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
diff options
context:
space:
mode:
authorBartosz Taudul <wolf@nereid.pl>2021-03-15 23:13:01 +0300
committerBartosz Taudul <wolf@nereid.pl>2021-03-15 23:13:01 +0300
commit06b1214affc0c8099e885385fbb6b8424ad49bec (patch)
treeec9603c2636774ae9565419f7b3e2a52146783c2
parent753c007557989615b3bb02058ddf835299a7abe8 (diff)
Update ImGUI to 1.82 + docking.
-rw-r--r--imgui/imconfig.h8
-rw-r--r--imgui/imgui.cpp663
-rw-r--r--imgui/imgui.h226
-rw-r--r--imgui/imgui_demo.cpp128
-rw-r--r--imgui/imgui_draw.cpp316
-rw-r--r--imgui/imgui_internal.h143
-rw-r--r--imgui/imgui_tables.cpp42
-rw-r--r--imgui/imgui_widgets.cpp157
-rw-r--r--imgui/misc/freetype/imgui_freetype.cpp27
-rw-r--r--imgui/misc/freetype/imgui_freetype.h3
-rw-r--r--profiler/src/imgui_impl_glfw.cpp6
-rw-r--r--profiler/src/imgui_impl_opengl3.cpp3
12 files changed, 1060 insertions, 662 deletions
diff --git a/imgui/imconfig.h b/imgui/imconfig.h
index c5e1650a..39de21c6 100644
--- a/imgui/imconfig.h
+++ b/imgui/imconfig.h
@@ -20,7 +20,9 @@
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
-// Using dear imgui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
+// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
+// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
+// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
//#define IMGUI_API __declspec( dllexport )
//#define IMGUI_API __declspec( dllimport )
@@ -34,8 +36,8 @@
//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger window: ShowMetricsWindow() will be empty.
//---- Don't implement some functions to reduce linkage requirements.
-//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
-//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow.
+//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
+//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow. (imm32.lib/.a)
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
diff --git a/imgui/imgui.cpp b/imgui/imgui.cpp
index 1d5c88a1..1bf605ad 100644
--- a/imgui/imgui.cpp
+++ b/imgui/imgui.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.81
+// dear imgui, v1.82
// (main code and documentation)
// Help:
@@ -15,6 +15,7 @@
// - Glossary https://github.com/ocornut/imgui/wiki/Glossary
// - Wiki https://github.com/ocornut/imgui/wiki
// - Issues & support https://github.com/ocornut/imgui/issues
+// - Discussions https://github.com/ocornut/imgui/discussions
// Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
// See LICENSE.txt for copyright and licensing details (standard MIT License).
@@ -376,15 +377,34 @@ CODE
When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
- (Docking/Viewport Branch)
- - 2020/XX/XX (1.XX) - when multi-viewports are enabled, all positions will be in your natural OS coordinates space. It means that:
+(Docking/Viewport Branch)
+ - 2021/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.
- - 2020/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
-
-
+ - 2021/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
+
+
+ - 2021/03/12 (1.82) - upgraded ImDrawList::AddRect(), AddRectFilled(), PathRect() to use ImDrawFlags instead of ImDrawCornersFlags.
+ - ImDrawCornerFlags_TopLeft -> use ImDrawFlags_RoundCornersTopLeft
+ - ImDrawCornerFlags_BotRight -> use ImDrawFlags_RoundCornersBottomRight
+ - ImDrawCornerFlags_None -> use ImDrawFlags_RoundCornersNone etc.
+ flags now sanely defaults to 0 instead of 0x0F, consistent with all other flags in the API.
+ breaking: the default with rounding > 0.0f is now "round all corners" vs old implicit "round no corners":
+ - rounding == 0.0f + flags == 0 --> meant no rounding --> unchanged (common use)
+ - rounding > 0.0f + flags != 0 --> meant rounding --> unchanged (common use)
+ - rounding == 0.0f + flags != 0 --> meant no rounding --> unchanged (unlikely use)
+ - rounding > 0.0f + flags == 0 --> meant no rounding --> BREAKING (unlikely use): will now round all corners --> use ImDrawFlags_RoundCornersNone or rounding == 0.0f.
+ this ONLY matters for hard coded use of 0 + rounding > 0.0f. Use of named ImDrawFlags_RoundCornersNone (new) or ImDrawCornerFlags_None (old) are ok.
+ the old ImDrawCornersFlags used awkward default values of ~0 or 0xF (4 lower bits set) to signify "round all corners" and we sometimes encouraged using them as shortcuts.
+ legacy path still support use of hard coded ~0 or any value from 0x1 or 0xF. They will behave the same with legacy paths enabled (will assert otherwise).
+ - 2021/03/11 (1.82) - removed redirecting functions/enums names that were marked obsolete in 1.66 (September 2018):
+ - ImGui::SetScrollHere() -> use ImGui::SetScrollHereY()
+ - 2021/03/11 (1.82) - clarified that ImDrawList::PathArcTo(), ImDrawList::PathArcToFast() won't render with radius < 0.0f. Previously it sorts of accidentally worked but would generally lead to counter-clockwise paths and have an effect on anti-aliasing.
+ - 2021/03/10 (1.82) - upgraded ImDrawList::AddPolyline() and PathStroke() "bool closed" parameter to "ImDrawFlags flags". The matching ImDrawFlags_Closed value is guaranteed to always stay == 1 in the future.
+ - 2021/02/22 (1.82) - win32+mingw: Re-enabled IME functions by default even under MinGW. In July 2016, issue #738 had me incorrectly disable those default functions for MinGW. MinGW users should: either link with -limm32, either set their imconfig file with '#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS'.
+ - 2021/02/17 (1.82) - renamed rarely used style.CircleSegmentMaxError (old default = 1.60f) to style.CircleTessellationMaxError (new default = 0.30f) as the meaning of the value changed.
- 2021/02/03 (1.81) - renamed ListBoxHeader(const char* label, ImVec2 size) to BeginListBox(). Kept inline redirection function (will obsolete).
- removed ListBoxHeader(const char* label, int items_count, int height_in_items = -1) in favor of specifying size. Kept inline redirection function (will obsolete).
- renamed ListBoxFooter() to EndListBox(). Kept inline redirection function (will obsolete).
@@ -896,6 +916,7 @@ static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb
static ImVec2 NavCalcPreferredRefPos();
static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
+static void NavRestoreLayer(ImGuiNavLayer layer);
static int FindWindowFocusIndex(ImGuiWindow* window);
// Error Checking
@@ -934,27 +955,33 @@ static void UpdateViewportPlatformMonitor(ImGuiViewportP* viewport);
// [SECTION] CONTEXT AND MEMORY ALLOCATORS
//-----------------------------------------------------------------------------
+// DLL users:
+// - Heaps and globals are not shared across DLL boundaries!
+// - You will need to call SetCurrentContext() + SetAllocatorFunctions() for each static/DLL boundary you are calling from.
+// - Same apply for hot-reloading mechanisms that are reliant on reloading DLL (note that many hot-reloading mechanism works without DLL).
+// - Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
+// - Confused? In a debugger: add GImGui to your watch window and notice how its value changes depending on your current location (which DLL boundary you are in).
+
// Current context pointer. Implicitly used by all Dear ImGui functions. Always assumed to be != NULL.
-// ImGui::CreateContext() will automatically set this pointer if it is NULL. Change to a different context by calling ImGui::SetCurrentContext().
-// 1) Important: globals are not shared across DLL boundaries! If you use DLLs or any form of hot-reloading: you will need to call
-// SetCurrentContext() (with the pointer you got from CreateContext) from each unique static/DLL boundary, and after each hot-reloading.
-// In your debugger, add GImGui to your watch window and notice how its value changes depending on which location you are currently stepping into.
-// 2) Important: Dear ImGui functions are not thread-safe because of this pointer.
-// If you want thread-safety to allow N threads to access N different contexts, you can:
-// - Change this variable to use thread local storage so each thread can refer to a different context, in imconfig.h:
-// struct ImGuiContext;
-// extern thread_local ImGuiContext* MyImGuiTLS;
-// #define GImGui MyImGuiTLS
-// And then define MyImGuiTLS in one of your cpp file. Note that thread_local is a C++11 keyword, earlier C++ uses compiler-specific keyword.
-// - Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
-// - If you need a finite number of contexts, you may compile and use multiple instances of the ImGui code from different namespace.
+// - ImGui::CreateContext() will automatically set this pointer if it is NULL.
+// Change to a different context by calling ImGui::SetCurrentContext().
+// - Important: Dear ImGui functions are not thread-safe because of this pointer.
+// If you want thread-safety to allow N threads to access N different contexts:
+// - Change this variable to use thread local storage so each thread can refer to a different context, in your imconfig.h:
+// struct ImGuiContext;
+// extern thread_local ImGuiContext* MyImGuiTLS;
+// #define GImGui MyImGuiTLS
+// And then define MyImGuiTLS in one of your cpp file. Note that thread_local is a C++11 keyword, earlier C++ uses compiler-specific keyword.
+// - Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
+// - If you need a finite number of contexts, you may compile and use multiple instances of the ImGui code from different namespace.
+// - DLL users: read comments above.
#ifndef GImGui
ImGuiContext* GImGui = NULL;
#endif
// Memory Allocator functions. Use SetAllocatorFunctions() to change them.
-// If you use DLL hotreloading you might need to call SetAllocatorFunctions() after reloading code from this file.
-// Otherwise, you probably don't want to modify them mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction.
+// - You probably don't want to modify those mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction.
+// - DLL users: read comments above.
#ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS
static void* MallocWrapper(size_t size, void* user_data) { IM_UNUSED(user_data); return malloc(size); }
static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_data); free(ptr); }
@@ -962,10 +989,9 @@ static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_d
static void* MallocWrapper(size_t size, void* user_data) { IM_UNUSED(user_data); IM_UNUSED(size); IM_ASSERT(0); return NULL; }
static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_UNUSED(ptr); IM_ASSERT(0); }
#endif
-
-static void* (*GImAllocatorAllocFunc)(size_t size, void* user_data) = MallocWrapper;
-static void (*GImAllocatorFreeFunc)(void* ptr, void* user_data) = FreeWrapper;
-static void* GImAllocatorUserData = NULL;
+static ImGuiMemAllocFunc GImAllocatorAllocFunc = MallocWrapper;
+static ImGuiMemFreeFunc GImAllocatorFreeFunc = FreeWrapper;
+static void* GImAllocatorUserData = NULL;
//-----------------------------------------------------------------------------
// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO)
@@ -1011,7 +1037,7 @@ ImGuiStyle::ImGuiStyle()
AntiAliasedLinesUseTex = true; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering.
AntiAliasedFill = true; // Enable anti-aliased filled shapes (rounded rectangles, circles, etc.).
CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
- CircleSegmentMaxError = 1.60f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
+ CircleTessellationMaxError = 0.30f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
// Default theme
ImGui::StyleColorsDark(this);
@@ -2842,8 +2868,8 @@ 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, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
+ window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
+ window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
}
}
@@ -2854,8 +2880,8 @@ 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, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
+ window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
+ window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
}
}
@@ -2881,13 +2907,13 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl
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, 0, THICKNESS);
if (!fully_visible)
window->DrawList->PopClipRect();
}
if (flags & ImGuiNavHighlightFlags_TypeThin)
{
- window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, ~0, 1.0f);
+ window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, 1.0f);
}
}
@@ -3062,6 +3088,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
g.ActiveIdTimer = 0.0f;
g.ActiveIdHasBeenPressedBefore = false;
g.ActiveIdHasBeenEditedBefore = false;
+ g.ActiveIdMouseButton = -1;
if (id != 0)
{
g.LastActiveId = id;
@@ -3136,8 +3163,8 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFla
// FIXME-OPT: This could be cached/stored within the window.
ImGuiContext& g = *GImGui;
if (g.NavWindow)
- if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow)
- if (focused_root_window->WasActive && focused_root_window != window->RootWindow)
+ if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindowDockTree)
+ if (focused_root_window->WasActive && focused_root_window != window->RootWindowDockTree)
{
// For the purpose of those flags we differentiate "standard popup" from "modal popup"
// NB: The order of those two tests is important because Modal windows are also Popups.
@@ -3149,7 +3176,7 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFla
// Filter by viewport
if (window->Viewport != g.MouseViewport)
- if (g.MovingWindow == NULL || window->RootWindow != g.MovingWindow->RootWindow)
+ if (g.MovingWindow == NULL || window->RootWindowDockTree != g.MovingWindow->RootWindowDockTree)
return false;
return true;
@@ -3166,20 +3193,22 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
return IsItemFocused();
// Test for bounding box overlap, as updated as ItemAdd()
- if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
+ ImGuiItemStatusFlags status_flags = window->DC.LastItemStatusFlags;
+ if (!(status_flags & ImGuiItemStatusFlags_HoveredRect))
return false;
IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function
// Test if we are hovering the right window (our window could be behind another window)
- // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable to use IsItemHovered() after EndChild() itself.
- // Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was the test that has been running for a long while.
- //if (g.HoveredWindow != window)
- // return false;
- if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped))
- return false;
+ // [2021/03/02] Reworked / reverted the revert, finally. Note we want e.g. BeginGroup/ItemAdd/EndGroup to work as well. (#3851)
+ // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable
+ // to use IsItemHovered() after EndChild() itself. Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was
+ // the test that has been running for a long while.
+ if (g.HoveredWindow != window && (status_flags & ImGuiItemStatusFlags_HoveredWindow) == 0)
+ if ((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0)
+ return false;
// Test if another item is active (e.g. being dragged)
- if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
+ if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0)
if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
return false;
@@ -3274,18 +3303,18 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id)
// Process TAB/Shift-TAB to tab *OUT* of the currently focused item.
// (Note that we can always TAB out of a widget that doesn't allow tabbing in)
- if (g.ActiveId == id && g.FocusTabPressed && !IsActiveIdUsingKey(ImGuiKey_Tab) && g.FocusRequestNextWindow == NULL)
+ if (g.ActiveId == id && g.TabFocusPressed && !IsActiveIdUsingKey(ImGuiKey_Tab) && g.TabFocusRequestNextWindow == NULL)
{
- g.FocusRequestNextWindow = window;
- g.FocusRequestNextCounterTabStop = window->DC.FocusCounterTabStop + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items.
+ g.TabFocusRequestNextWindow = window;
+ g.TabFocusRequestNextCounterTabStop = window->DC.FocusCounterTabStop + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items.
}
// Handle focus requests
- if (g.FocusRequestCurrWindow == window)
+ if (g.TabFocusRequestCurrWindow == window)
{
- if (window->DC.FocusCounterRegular == g.FocusRequestCurrCounterRegular)
+ if (window->DC.FocusCounterRegular == g.TabFocusRequestCurrCounterRegular)
return true;
- if (is_tab_stop && window->DC.FocusCounterTabStop == g.FocusRequestCurrCounterTabStop)
+ if (is_tab_stop && window->DC.FocusCounterTabStop == g.TabFocusRequestCurrCounterTabStop)
{
g.NavJustTabbedId = id;
return true;
@@ -3334,7 +3363,7 @@ void* ImGui::MemAlloc(size_t size)
{
if (ImGuiContext* ctx = GImGui)
ctx->IO.MetricsActiveAllocations++;
- return GImAllocatorAllocFunc(size, GImAllocatorUserData);
+ return (*GImAllocatorAllocFunc)(size, GImAllocatorUserData);
}
// IM_FREE() == ImGui::MemFree()
@@ -3343,7 +3372,7 @@ void ImGui::MemFree(void* ptr)
if (ptr)
if (ImGuiContext* ctx = GImGui)
ctx->IO.MetricsActiveAllocations--;
- return GImAllocatorFreeFunc(ptr, GImAllocatorUserData);
+ return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData);
}
const char* ImGui::GetClipboardText()
@@ -3380,13 +3409,21 @@ void ImGui::SetCurrentContext(ImGuiContext* ctx)
#endif
}
-void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data)
+void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func, void* user_data)
{
GImAllocatorAllocFunc = alloc_func;
GImAllocatorFreeFunc = free_func;
GImAllocatorUserData = user_data;
}
+// This is provided to facilitate copying allocators from one static/DLL boundary to another (e.g. retrieve default allocator of your executable address space)
+void ImGui::GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func, void** p_user_data)
+{
+ *p_alloc_func = GImAllocatorAllocFunc;
+ *p_free_func = GImAllocatorFreeFunc;
+ *p_user_data = GImAllocatorUserData;
+}
+
ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas)
{
ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);
@@ -3527,10 +3564,10 @@ void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
SetActiveID(window->MoveId, window);
g.NavDisableHighlight = true;
g.ActiveIdNoClearOnFocusLoss = true;
- g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindow->Pos;
+ g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindowDockTree->Pos;
bool can_move_window = true;
- if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindow->Flags & ImGuiWindowFlags_NoMove))
+ if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindowDockTree->Flags & ImGuiWindowFlags_NoMove))
can_move_window = false;
if (ImGuiDockNode* node = window->DockNodeAsHost)
if (node->VisibleWindow && (node->VisibleWindow->Flags & ImGuiWindowFlags_NoMove))
@@ -3578,8 +3615,8 @@ void ImGui::UpdateMouseMovingWindowNewFrame()
// We actually want to move the root window. g.MovingWindow == window we clicked on (could be a child window).
// We track it to preserve Focus and so that generally ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency.
KeepAliveID(g.ActiveId);
- IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow);
- ImGuiWindow* moving_window = g.MovingWindow->RootWindow;
+ IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindowDockTree);
+ ImGuiWindow* moving_window = g.MovingWindow->RootWindowDockTree;
if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos))
{
ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset;
@@ -3643,7 +3680,7 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
{
// 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;
+ ImGuiWindow* root_window = g.HoveredWindow ? g.HoveredWindow->RootWindow : 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)
@@ -3809,7 +3846,7 @@ void ImGui::UpdateMouseWheel()
const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
const float scale = new_font_scale / window->FontWindowScale;
window->FontWindowScale = new_font_scale;
- if (!(window->Flags & ImGuiWindowFlags_ChildWindow))
+ if (window == window->RootWindow)
{
const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size;
SetWindowPos(window, window->Pos + offset, 0);
@@ -3858,32 +3895,32 @@ void ImGui::UpdateTabFocus()
ImGuiContext& g = *GImGui;
// Pressing TAB activate widget focus
- g.FocusTabPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab));
- if (g.ActiveId == 0 && g.FocusTabPressed)
+ g.TabFocusPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab));
+ if (g.ActiveId == 0 && g.TabFocusPressed)
{
// Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also
// manipulate the Next fields even, even though they will be turned into Curr fields by the code below.
- g.FocusRequestNextWindow = g.NavWindow;
- g.FocusRequestNextCounterRegular = INT_MAX;
+ g.TabFocusRequestNextWindow = g.NavWindow;
+ g.TabFocusRequestNextCounterRegular = INT_MAX;
if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
- g.FocusRequestNextCounterTabStop = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
+ g.TabFocusRequestNextCounterTabStop = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
else
- g.FocusRequestNextCounterTabStop = g.IO.KeyShift ? -1 : 0;
+ g.TabFocusRequestNextCounterTabStop = g.IO.KeyShift ? -1 : 0;
}
// Turn queued focus request into current one
- g.FocusRequestCurrWindow = NULL;
- g.FocusRequestCurrCounterRegular = g.FocusRequestCurrCounterTabStop = INT_MAX;
- if (g.FocusRequestNextWindow != NULL)
+ g.TabFocusRequestCurrWindow = NULL;
+ g.TabFocusRequestCurrCounterRegular = g.TabFocusRequestCurrCounterTabStop = INT_MAX;
+ if (g.TabFocusRequestNextWindow != NULL)
{
- ImGuiWindow* window = g.FocusRequestNextWindow;
- g.FocusRequestCurrWindow = window;
- if (g.FocusRequestNextCounterRegular != INT_MAX && window->DC.FocusCounterRegular != -1)
- g.FocusRequestCurrCounterRegular = ImModPositive(g.FocusRequestNextCounterRegular, window->DC.FocusCounterRegular + 1);
- if (g.FocusRequestNextCounterTabStop != INT_MAX && window->DC.FocusCounterTabStop != -1)
- g.FocusRequestCurrCounterTabStop = ImModPositive(g.FocusRequestNextCounterTabStop, window->DC.FocusCounterTabStop + 1);
- g.FocusRequestNextWindow = NULL;
- g.FocusRequestNextCounterRegular = g.FocusRequestNextCounterTabStop = INT_MAX;
+ ImGuiWindow* window = g.TabFocusRequestNextWindow;
+ g.TabFocusRequestCurrWindow = window;
+ if (g.TabFocusRequestNextCounterRegular != INT_MAX && window->DC.FocusCounterRegular != -1)
+ g.TabFocusRequestCurrCounterRegular = ImModPositive(g.TabFocusRequestNextCounterRegular, window->DC.FocusCounterRegular + 1);
+ if (g.TabFocusRequestNextCounterTabStop != INT_MAX && window->DC.FocusCounterTabStop != -1)
+ g.TabFocusRequestCurrCounterTabStop = ImModPositive(g.TabFocusRequestNextCounterTabStop, window->DC.FocusCounterTabStop + 1);
+ g.TabFocusRequestNextWindow = NULL;
+ g.TabFocusRequestNextCounterRegular = g.TabFocusRequestNextCounterTabStop = INT_MAX;
}
g.NavIdTabCounter = INT_MAX;
@@ -3904,7 +3941,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
// Modal windows prevents mouse from hovering behind them.
ImGuiWindow* modal_window = GetTopMostPopupModal();
- if (modal_window && g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window))
+ if (modal_window && g.HoveredWindow && !IsWindowChildOf(g.HoveredWindow->RootWindowDockTree, modal_window))
clear_hovered_windows = true;
// Disabled mouse?
@@ -3932,7 +3969,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
clear_hovered_windows = true;
if (clear_hovered_windows)
- g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL;
+ g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
// Update io.WantCaptureMouse for the user application (true = dispatch mouse info to imgui, false = dispatch mouse info to Dear ImGui + app)
if (g.WantCaptureMouseNextFrame != -1)
@@ -3967,7 +4004,7 @@ void ImGui::NewFrame()
{
IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
ImGuiContext& g = *GImGui;
-
+
// Remove pending delete hooks before frame start.
// This deferred removal avoid issues of removal while iterating the hook vector
for (int n = g.Hooks.Size - 1; n >= 0; n--)
@@ -4009,7 +4046,7 @@ void ImGui::NewFrame()
virtual_space.Add(g.Viewports[n]->GetMainRect());
g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4();
g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol;
- g.DrawListSharedData.SetCircleSegmentMaxError(g.Style.CircleSegmentMaxError);
+ g.DrawListSharedData.SetCircleTessellationMaxError(g.Style.CircleTessellationMaxError);
g.DrawListSharedData.InitialFlags = ImDrawListFlags_None;
if (g.Style.AntiAliasedLines)
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines;
@@ -4284,7 +4321,7 @@ void ImGui::Shutdown(ImGuiContext* context)
g.CurrentWindowStack.clear();
g.WindowsById.Clear();
g.NavWindow = NULL;
- g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL;
+ g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL;
g.MovingWindow = NULL;
g.ColorStack.clear();
@@ -4516,15 +4553,15 @@ static void ImGui::EndFrameDrawDimmedBackgrounds()
// Choose a draw list that will be front-most across all our children
// In the unlikely case that the window wasn't made active we can't rely on its drawlist and skip rendering all-together.
ImGuiWindow* window = g.NavWindowingTargetAnim;
- ImDrawList* draw_list = FindFrontMostVisibleChildWindow(window->RootWindow)->DrawList;
+ ImDrawList* draw_list = FindFrontMostVisibleChildWindow(window->RootWindowDockTree)->DrawList;
draw_list->PushClipRectFullScreen();
// Docking: draw modal whitening background on other nodes of a same dock tree
// For CTRL+TAB within a docking node we need to render the dimming background in 8 steps
// (Because the root node renders the background in one shot, in order to avoid flickering when a child dock node is not submitted)
- if (window->RootWindowDockStop->DockIsActive)
- if (window->RootWindow != window->RootWindowDockStop)
- RenderRectFilledWithHole(draw_list, window->RootWindow->Rect(), window->RootWindowDockStop->Rect(), GetColorU32(ImGuiCol_NavWindowingDimBg, g.DimBgRatio), g.Style.WindowRounding);
+ if (window->RootWindow->DockIsActive)
+ if (window->RootWindowDockTree != window->RootWindow)
+ RenderRectFilledWithHole(draw_list, window->RootWindowDockTree->Rect(), window->RootWindow->Rect(), GetColorU32(ImGuiCol_NavWindowingDimBg, g.DimBgRatio), g.Style.WindowRounding);
// Draw navigation selection/windowing rectangle border
float rounding = ImMax(window->WindowRounding, g.Style.WindowRounding);
@@ -4656,7 +4693,7 @@ void ImGui::Render()
// Add ImDrawList to render
ImGuiWindow* windows_to_render_top_most[2];
- windows_to_render_top_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL;
+ windows_to_render_top_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindowDockTree : NULL;
windows_to_render_top_most[1] = (g.NavWindowingTarget ? g.NavWindowingListWindow : NULL);
for (int n = 0; n != g.Windows.Size; n++)
{
@@ -4781,14 +4818,13 @@ static void FindHoveredWindow()
if (hovered_window == NULL)
hovered_window = window;
- if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindow != g.MovingWindow->RootWindow))
+ if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindowDockTree != g.MovingWindow->RootWindowDockTree))
hovered_window_ignoring_moving_window = window;
if (hovered_window && hovered_window_ignoring_moving_window)
break;
}
g.HoveredWindow = hovered_window;
- g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL;
g.HoveredWindowUnderMovingWindow = hovered_window_ignoring_moving_window;
if (g.MovingWindow)
@@ -5077,6 +5113,8 @@ bool ImGui::IsItemFocused()
return true;
}
+// Important: this can be useful but it is NOT equivalent to the behavior of e.g.Button()!
+// Most widgets have specific reactions based on mouse-up/down state, mouse position etc.
bool ImGui::IsItemClicked(ImGuiMouseButton mouse_button)
{
return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None);
@@ -5265,6 +5303,8 @@ void ImGui::EndChild()
// Not navigable into
ItemAdd(bb, 0);
}
+ if (g.HoveredWindow == window)
+ parent_window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
}
g.WithinEndChild = false;
g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
@@ -5385,9 +5425,10 @@ static ImGuiWindow* GetWindowForTitleAndMenuHeight(ImGuiWindow* window)
return (window->DockNodeAsHost && window->DockNodeAsHost->VisibleWindow) ? window->DockNodeAsHost->VisibleWindow : window;
}
-static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size)
+static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window, const ImVec2& size_desired)
{
ImGuiContext& g = *GImGui;
+ ImVec2 new_size = size_desired;
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)
{
// Using -1,-1 on either X/Y axis to preserve the current size.
@@ -5670,12 +5711,12 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
// Navigation resize (keyboard/gamepad)
- if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindow == window)
+ if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindowDockTree == window)
{
ImVec2 nav_resize_delta;
- if (g.NavInputSource == ImGuiInputSource_NavKeyboard && g.IO.KeyShift)
+ if (g.NavInputSource == ImGuiInputSource_Keyboard && g.IO.KeyShift)
nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down);
- if (g.NavInputSource == ImGuiInputSource_NavGamepad)
+ if (g.NavInputSource == ImGuiInputSource_Gamepad)
nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_Down);
if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f)
{
@@ -5721,7 +5762,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
float rounding = window->WindowRounding;
float border_size = window->WindowBorderSize;
if (border_size > 0.0f && !(window->Flags & ImGuiWindowFlags_NoBackground))
- window->DrawList->AddRect(window->Pos, window->Pos + window->Size, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
+ window->DrawList->AddRect(window->Pos, window->Pos + window->Size, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
int border_held = window->ResizeBorderHeld;
if (border_held != -1)
@@ -5730,7 +5771,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
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->PathStroke(GetColorU32(ImGuiCol_SeparatorActive), false, ImMax(2.0f, border_size)); // Thicker than usual
+ window->DrawList->PathStroke(GetColorU32(ImGuiCol_SeparatorActive), 0, ImMax(2.0f, border_size)); // Thicker than usual
}
if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
{
@@ -5800,7 +5841,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
if (override_alpha)
bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT);
}
- window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot);
+ window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
}
// Title bar
@@ -5809,7 +5850,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
{
ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
- window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawCornerFlags_Top);
+ window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawFlags_RoundCornersTop);
}
// Menu bar
@@ -5817,7 +5858,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
{
ImRect menu_bar_rect = window->MenuBarRect();
menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them.
- window->DrawList->AddRectFilled(menu_bar_rect.Min + ImVec2(window_border_size, 0), menu_bar_rect.Max - ImVec2(window_border_size, 0), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawCornerFlags_Top);
+ window->DrawList->AddRectFilled(menu_bar_rect.Min + ImVec2(window_border_size, 0), menu_bar_rect.Max - ImVec2(window_border_size, 0), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawFlags_RoundCornersTop);
if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
}
@@ -5955,12 +5996,12 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window)
{
window->ParentWindow = parent_window;
- window->RootWindow = window->RootWindowDockStop = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window;
+ window->RootWindow = window->RootWindowDockTree = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window;
if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
{
- window->RootWindow = parent_window->RootWindow;
+ window->RootWindowDockTree = parent_window->RootWindowDockTree;
if (!window->DockIsActive && !(parent_window->Flags & ImGuiWindowFlags_DockNodeHost))
- window->RootWindowDockStop = parent_window->RootWindowDockStop;
+ window->RootWindow = parent_window->RootWindow;
}
if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)))
window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight;
@@ -6076,9 +6117,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->PopupId = popup_ref.PopupId;
}
- if (window_just_appearing_after_hidden_for_resize && !(flags & ImGuiWindowFlags_ChildWindow))
- window->NavLastIds[0] = 0;
-
// Update ->RootWindow and others pointers (before any possible call to FocusWindow)
if (first_begin_of_the_frame)
UpdateWindowParentAndRootLinks(window, flags, parent_window);
@@ -6232,7 +6270,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
{
window->Collapsed = !window->Collapsed;
MarkIniSettingsDirty(window);
- FocusWindow(window);
}
}
else
@@ -6402,9 +6439,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
if (window->WindowClass.ViewportFlagsOverrideClear)
viewport_flags &= ~window->WindowClass.ViewportFlagsOverrideClear;
- // We also tell the backend that clearing the platform window won't be necessary, as our window is filling the viewport and we have disabled BgAlpha
+ // We can also tell the backend that clearing the platform window won't be necessary,
+ // as our window background is filling the viewport and we have disabled BgAlpha.
+ // FIXME: Work on support for per-viewport transparency (#2766)
if (!(flags & ImGuiWindowFlags_NoBackground))
- viewport_flags &= ~ImGuiViewportFlags_NoRendererClear;
+ viewport_flags |= ImGuiViewportFlags_NoRendererClear;
window->Viewport->Flags = viewport_flags;
}
@@ -6427,19 +6466,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
}
else if (window->ViewportOwned && g.PlatformIO.Monitors.Size > 0)
{
- if (window->Viewport->PlatformMonitor == -1)
- {
- // Fallback for "lost" window (e.g. a monitor disconnected): we move the window back over the main viewport
- const ImGuiViewport* main_viewport = GetMainViewport();
- SetWindowPos(window, main_viewport->Pos + style.DisplayWindowPadding, ImGuiCond_Always);
- }
- else
- {
- ImGuiPlatformMonitor& monitor = g.PlatformIO.Monitors[window->Viewport->PlatformMonitor];
- visibility_rect.Min = monitor.WorkPos + visibility_padding;
- visibility_rect.Max = monitor.WorkPos + monitor.WorkSize - visibility_padding;
- ClampWindowRect(window, visibility_rect);
- }
+ // Lost windows (e.g. a monitor disconnected) will naturally moved to the fallback/dummy monitor aka the main viewport.
+ const ImGuiPlatformMonitor* monitor = GetViewportPlatformMonitor(window->Viewport);
+ 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);
@@ -6582,7 +6613,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Draw modal or window list full viewport dimming background (for other viewports we'll render them in EndFrame)
ImGuiWindow* window_window_list = g.NavWindowingListWindow;
const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetTopMostPopupModal() && window->HiddenFramesCannotSkipItems <= 0;
- const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && ((window == g.NavWindowingTargetAnim->RootWindow) || (window == window_window_list && window_window_list->Viewport != g.NavWindowingTargetAnim->Viewport));
+ const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && ((window == g.NavWindowingTargetAnim->RootWindowDockTree) || (window == window_window_list && window_window_list->Viewport != g.NavWindowingTargetAnim->Viewport));
if (dim_bg_for_modal || dim_bg_for_window_list)
{
const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg, g.DimBgRatio);
@@ -6633,7 +6664,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
bb.Expand(-g.FontSize - 1.0f);
rounding = window->WindowRounding;
}
- window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), rounding, ~0, 3.0f);
+ window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), rounding, 0, 3.0f);
}
// UPDATE RECTANGLES (2- THOSE AFFECTED BY SCROLLING)
@@ -6706,7 +6737,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
if (want_focus)
{
FocusWindow(window);
- NavInitWindow(window, false);
+ NavInitWindow(window, false); // <-- this is in the way for us to be able to defer and sort reappearing FocusWindow() calls
}
// Close requested by platform window
@@ -6743,13 +6774,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Docking: Dragging a dockable window (or any of its child) turns it into a drag and drop source.
// We need to do this _before_ we overwrite window->DC.LastItemId below because BeginDockableDragDropSource() also overwrites it.
if ((g.MovingWindow == window) && (g.IO.ConfigDockingWithShift == g.IO.KeyShift))
- if ((window->RootWindow->Flags & ImGuiWindowFlags_NoDocking) == 0)
+ if ((window->RootWindowDockTree->Flags & ImGuiWindowFlags_NoDocking) == 0)
BeginDockableDragDropSource(window);
// Docking: Any dockable window can act as a target. For dock node hosts we call BeginDockableDragDropTarget() in DockNodeUpdate() instead.
if (g.DragDropActive && !(flags & ImGuiWindowFlags_NoDocking))
- if (g.MovingWindow == NULL || g.MovingWindow->RootWindow != window)
- if ((window == window->RootWindow) && !(window->Flags & ImGuiWindowFlags_DockNodeHost))
+ if (g.MovingWindow == NULL || g.MovingWindow->RootWindowDockTree != window)
+ if ((window == window->RootWindowDockTree) && !(window->Flags & ImGuiWindowFlags_DockNodeHost))
BeginDockableDragDropTarget(window);
}
@@ -6823,6 +6854,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Update the Hidden flag
window->Hidden = (window->HiddenFramesCanSkipItems > 0) || (window->HiddenFramesCannotSkipItems > 0) || (window->HiddenFramesForRenderOnly > 0);
+ // Disable inputs for requested number of frames
+ if (window->DisableInputsFrames > 0)
+ {
+ window->DisableInputsFrames--;
+ window->Flags |= ImGuiWindowFlags_NoInputs;
+ }
+
// Update the SkipItems flag, used to early out of all items functions (no layout required)
bool skip_items = false;
if (window->Collapsed || !window->Active || window->Hidden)
@@ -6894,7 +6932,7 @@ void ImGui::BringWindowToDisplayFront(ImGuiWindow* window)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* current_front_window = g.Windows.back();
- if (current_front_window == window || current_front_window->RootWindow == window) // Cheap early out (could be better)
+ if (current_front_window == window || current_front_window->RootWindowDockTree == window) // Cheap early out (could be better)
return;
for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the top-most window
if (g.Windows[i] == window)
@@ -6929,11 +6967,12 @@ void ImGui::FocusWindow(ImGuiWindow* window)
g.NavWindow = window;
if (window && g.NavDisableMouseHover)
g.NavMousePosDirty = true;
- g.NavInitRequest = false;
g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId
g.NavFocusScopeId = 0;
g.NavIdIsAlive = false;
g.NavLayer = ImGuiNavLayer_Main;
+ g.NavInitRequest = g.NavMoveRequest = false;
+ NavUpdateAnyRequestFlag();
//IMGUI_DEBUG_LOG("FocusWindow(\"%s\")\n", window ? window->Name : NULL);
}
@@ -6941,9 +6980,9 @@ void ImGui::FocusWindow(ImGuiWindow* window)
ClosePopupsOverWindow(window, false);
// Move the root window to the top of the pile
- IM_ASSERT(window == NULL || window->RootWindow != NULL);
- ImGuiWindow* focus_front_window = window ? window->RootWindowDockStop : NULL;
- ImGuiWindow* display_front_window = window ? window->RootWindow : NULL;
+ IM_ASSERT(window == NULL || window->RootWindowDockTree != NULL);
+ ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL;
+ ImGuiWindow* display_front_window = window ? window->RootWindowDockTree : NULL;
ImGuiDockNode* dock_node = window ? window->DockNode : NULL;
bool active_id_window_is_dock_node_host = (g.ActiveIdWindow && dock_node && dock_node->HostWindow == g.ActiveIdWindow);
@@ -6951,7 +6990,7 @@ void ImGui::FocusWindow(ImGuiWindow* window)
// - Focus a window while an InputText in another window is active, if focus happens before the old InputText can run.
// - When using Nav to activate menu items (due to timing of activating on press->new window appears->losing ActiveId)
// - Using dock host items (tab, collapse button) can trigger this before we redirect the ActiveIdWindow toward the child window.
- if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindowDockStop != focus_front_window)
+ if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != focus_front_window)
if (!g.ActiveIdNoClearOnFocusLoss && !active_id_window_is_dock_node_host)
ClearActiveID();
@@ -6985,7 +7024,7 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind
{
// We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user.
ImGuiWindow* window = g.WindowsFocusOrder[i];
- if (window != ignore_window && window->WasActive && window->RootWindowDockStop == window)
+ if (window != ignore_window && window->WasActive && window->RootWindow == window)
if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
{
// FIXME-DOCK: This is failing (lagging by one frame) for docked windows.
@@ -7000,6 +7039,7 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind
FocusWindow(NULL);
}
+// Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only.
void ImGui::SetCurrentFont(ImFont* font)
{
ImGuiContext& g = *GImGui;
@@ -7094,7 +7134,7 @@ void ImGui::PopTextWrapPos()
bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent)
{
- if (window->RootWindow == potential_parent)
+ if (window->RootWindowDockTree == potential_parent)
return true;
while (window != NULL)
{
@@ -7123,30 +7163,28 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
{
IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function
ImGuiContext& g = *GImGui;
+ if (g.HoveredWindow == NULL)
+ return false;
- if (flags & ImGuiHoveredFlags_AnyWindow)
- {
- if (g.HoveredWindow == NULL)
- return false;
- }
- else
+ if ((flags & ImGuiHoveredFlags_AnyWindow) == 0)
{
+ ImGuiWindow* window = g.CurrentWindow;
switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows))
{
case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows:
- if (g.HoveredWindow == NULL || g.HoveredWindow->RootWindowDockStop != g.CurrentWindow->RootWindowDockStop)
+ if (g.HoveredWindow->RootWindow != window->RootWindow)
return false;
break;
case ImGuiHoveredFlags_RootWindow:
- if (g.HoveredWindow != g.CurrentWindow->RootWindowDockStop)
+ if (g.HoveredWindow != window->RootWindow)
return false;
break;
case ImGuiHoveredFlags_ChildWindows:
- if (g.HoveredWindow == NULL || !IsWindowChildOf(g.HoveredWindow, g.CurrentWindow))
+ if (!IsWindowChildOf(g.HoveredWindow, window))
return false;
break;
default:
- if (g.HoveredWindow != g.CurrentWindow)
+ if (g.HoveredWindow != window)
return false;
break;
}
@@ -7171,9 +7209,9 @@ bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags)
switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows))
{
case ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows:
- return g.NavWindow && g.NavWindow->RootWindowDockStop == g.CurrentWindow->RootWindowDockStop;
+ return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow;
case ImGuiFocusedFlags_RootWindow:
- return g.NavWindow == g.CurrentWindow->RootWindowDockStop;
+ return g.NavWindow == g.CurrentWindow->RootWindow;
case ImGuiFocusedFlags_ChildWindows:
return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow);
default:
@@ -7198,7 +7236,7 @@ bool ImGui::IsWindowDocked()
// If you want a window to never be focused, you may use the e.g. NoInputs flag.
bool ImGui::IsWindowNavFocusable(ImGuiWindow* window)
{
- return window->WasActive && window == window->RootWindowDockStop && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
+ return window->WasActive && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
}
float ImGui::GetWindowWidth()
@@ -7521,9 +7559,9 @@ void ImGui::SetKeyboardFocusHere(int offset)
IM_ASSERT(offset >= -1); // -1 is allowed but not below
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
- g.FocusRequestNextWindow = window;
- g.FocusRequestNextCounterRegular = window->DC.FocusCounterRegular + 1 + offset;
- g.FocusRequestNextCounterTabStop = INT_MAX;
+ g.TabFocusRequestNextWindow = window;
+ g.TabFocusRequestNextCounterRegular = window->DC.FocusCounterRegular + 1 + offset;
+ g.TabFocusRequestNextCounterTabStop = INT_MAX;
}
void ImGui::SetItemDefaultFocus()
@@ -7690,7 +7728,7 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()?");
IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded() && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()?");
IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!");
- IM_ASSERT(g.Style.CircleSegmentMaxError > 0.0f && "Invalid style setting!");
+ IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0f && "Invalid style setting!");
IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting!"); // Allows us to avoid a few clamps in color computations
IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting.");
IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
@@ -8303,6 +8341,7 @@ void ImGui::BeginGroup()
group_data.BackupCurrLineSize = window->DC.CurrLineSize;
group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset;
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
+ group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
group_data.EmitItem = true;
@@ -8356,6 +8395,11 @@ void ImGui::EndGroup()
window->DC.LastItemId = g.ActiveIdPreviousFrame;
window->DC.LastItemRect = group_bb;
+ // Forward Hovered flag
+ const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive == false) && g.HoveredId != 0;
+ if (group_contains_curr_hovered_id)
+ window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
+
// Forward Edited flag
if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame)
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited;
@@ -8765,12 +8809,12 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to
// Trim the stack unless the popup is a direct parent of the reference window (the reference window is often the NavWindow)
// - With this stack of window, clicking/focusing Popup1 will close Popup2 and Popup3:
// Window -> Popup1 -> Popup2 -> Popup3
- // - Each popups may contain child windows, which is why we compare ->RootWindow!
+ // - Each popups may contain child windows, which is why we compare ->RootWindowDockTree!
// Window -> Popup1 -> Popup1_Child -> Popup2 -> Popup2_Child
bool ref_window_is_descendent_of_popup = false;
for (int n = popup_count_to_keep; n < g.OpenPopupStack.Size; n++)
if (ImGuiWindow* popup_window = g.OpenPopupStack[n].Window)
- if (popup_window->RootWindow == ref_window->RootWindow)
+ if (popup_window->RootWindowDockTree == ref_window->RootWindowDockTree)
{
ref_window_is_descendent_of_popup = true;
break;
@@ -9135,26 +9179,19 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
// [SECTION] KEYBOARD/GAMEPAD NAVIGATION
//-----------------------------------------------------------------------------
-// FIXME-NAV: The existence of SetNavID vs SetNavIDWithRectRel vs SetFocusID is incredibly messy and confusing,
-// and needs some explanation or serious refactoring.
-void ImGui::SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id)
+// FIXME-NAV: The existence of SetNavID vs SetFocusID properly needs to be clarified/reworked.
+void ImGui::SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel)
{
ImGuiContext& g = *GImGui;
- IM_ASSERT(g.NavWindow);
- IM_ASSERT(nav_layer == 0 || nav_layer == 1);
+ IM_ASSERT(g.NavWindow != NULL);
+ IM_ASSERT(nav_layer == ImGuiNavLayer_Main || nav_layer == ImGuiNavLayer_Menu);
g.NavId = id;
+ g.NavLayer = (ImGuiNavLayer)nav_layer;
g.NavFocusScopeId = focus_scope_id;
g.NavWindow->NavLastIds[nav_layer] = id;
-}
-
-void ImGui::SetNavIDWithRectRel(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel)
-{
- ImGuiContext& g = *GImGui;
- SetNavID(id, nav_layer, focus_scope_id);
g.NavWindow->NavRectRel[nav_layer] = rect_rel;
- g.NavMousePosDirty = true;
- g.NavDisableHighlight = false;
- g.NavDisableMouseHover = true;
+ //g.NavDisableHighlight = false;
+ //g.NavDisableMouseHover = g.NavMousePosDirty = true;
}
void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
@@ -9453,7 +9490,7 @@ void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags mov
static void ImGui::NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window)
{
ImGuiWindow* parent = nav_window;
- while (parent && parent->RootWindowDockStop != parent && (parent->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (parent->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
+ while (parent && parent->RootWindow != parent && (parent->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
parent = parent->ParentWindow;
if (parent && parent != nav_window)
parent->NavLastChildNavWindow = nav_window;
@@ -9471,17 +9508,23 @@ static ImGuiWindow* ImGui::NavRestoreLastChildNavWindow(ImGuiWindow* window)
return window;
}
-static void NavRestoreLayer(ImGuiNavLayer layer)
+void ImGui::NavRestoreLayer(ImGuiNavLayer layer)
{
ImGuiContext& g = *GImGui;
- g.NavLayer = layer;
- if (layer == 0)
- g.NavWindow = ImGui::NavRestoreLastChildNavWindow(g.NavWindow);
+ if (layer == ImGuiNavLayer_Main)
+ g.NavWindow = NavRestoreLastChildNavWindow(g.NavWindow);
ImGuiWindow* window = g.NavWindow;
if (window->NavLastIds[layer] != 0)
- ImGui::SetNavIDWithRectRel(window->NavLastIds[layer], layer, 0, g.NavWindow->NavRectRel[layer]);
+ {
+ SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
+ g.NavDisableHighlight = false;
+ g.NavDisableMouseHover = g.NavMousePosDirty = true;
+ }
else
- ImGui::NavInitWindow(window, true);
+ {
+ g.NavLayer = layer;
+ NavInitWindow(window, true);
+ }
}
static inline void ImGui::NavUpdateAnyRequestFlag()
@@ -9495,16 +9538,17 @@ static inline void ImGui::NavUpdateAnyRequestFlag()
// This needs to be called before we submit any widget (aka in or before Begin)
void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
{
+ // FIXME: ChildWindow test here is wrong for docking
ImGuiContext& g = *GImGui;
IM_ASSERT(window == g.NavWindow);
bool init_for_nav = false;
if (!(window->Flags & ImGuiWindowFlags_NoNavInputs))
- if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
+ if (window == window->RootWindow || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
init_for_nav = true;
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from NavInitWindow(), init_for_nav=%d, window=\"%s\", layer=%d\n", init_for_nav, window->Name, g.NavLayer);
if (init_for_nav)
{
- SetNavID(0, g.NavLayer, 0);
+ SetNavID(0, g.NavLayer, 0, ImRect());
g.NavInitRequest = true;
g.NavInitRequestFromMove = false;
g.NavInitResultId = 0;
@@ -9592,17 +9636,17 @@ static void ImGui::NavUpdate()
// (do it before we map Keyboard input!)
bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
- if (nav_gamepad_active && g.NavInputSource != ImGuiInputSource_NavGamepad)
+ if (nav_gamepad_active && g.NavInputSource != ImGuiInputSource_Gamepad)
{
if (io.NavInputs[ImGuiNavInput_Activate] > 0.0f || io.NavInputs[ImGuiNavInput_Input] > 0.0f || io.NavInputs[ImGuiNavInput_Cancel] > 0.0f || io.NavInputs[ImGuiNavInput_Menu] > 0.0f
|| io.NavInputs[ImGuiNavInput_DpadLeft] > 0.0f || io.NavInputs[ImGuiNavInput_DpadRight] > 0.0f || io.NavInputs[ImGuiNavInput_DpadUp] > 0.0f || io.NavInputs[ImGuiNavInput_DpadDown] > 0.0f)
- g.NavInputSource = ImGuiInputSource_NavGamepad;
+ g.NavInputSource = ImGuiInputSource_Gamepad;
}
// Update Keyboard->Nav inputs mapping
if (nav_keyboard_active)
{
- #define NAV_MAP_KEY(_KEY, _NAV_INPUT) do { if (IsKeyDown(io.KeyMap[_KEY])) { io.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_NavKeyboard; } } while (0)
+ #define NAV_MAP_KEY(_KEY, _NAV_INPUT) do { if (IsKeyDown(io.KeyMap[_KEY])) { io.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_Keyboard; } } while (0)
NAV_MAP_KEY(ImGuiKey_Space, ImGuiNavInput_Activate );
NAV_MAP_KEY(ImGuiKey_Enter, ImGuiNavInput_Input );
NAV_MAP_KEY(ImGuiKey_Escape, ImGuiNavInput_Cancel );
@@ -9623,7 +9667,7 @@ static void ImGui::NavUpdate()
io.NavInputsDownDuration[i] = (io.NavInputs[i] > 0.0f) ? (io.NavInputsDownDuration[i] < 0.0f ? 0.0f : io.NavInputsDownDuration[i] + io.DeltaTime) : -1.0f;
// Process navigation init request (select first/default focus)
- if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitRequestFromMove))
+ if (g.NavInitResultId != 0)
NavUpdateInitResult();
g.NavInitRequest = false;
g.NavInitRequestFromMove = false;
@@ -9648,13 +9692,11 @@ static void ImGui::NavUpdate()
{
// Set mouse position given our knowledge of the navigated item position from last frame
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
- {
if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow)
{
io.MousePos = io.MousePosPrev = NavCalcPreferredRefPos();
io.WantSetMousePos = true;
}
- }
g.NavMousePosDirty = false;
}
g.NavIdIsAlive = false;
@@ -9683,18 +9725,15 @@ static void ImGui::NavUpdate()
if (!IsActiveIdUsingNavInput(ImGuiNavInput_Cancel))
ClearActiveID();
}
- else if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow) && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow && g.NavWindow != g.NavWindow->RootWindowDockStop)
+ else if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow)
{
// Exit child window
ImGuiWindow* child_window = g.NavWindow;
ImGuiWindow* parent_window = g.NavWindow->ParentWindow;
IM_ASSERT(child_window->ChildId != 0);
+ ImRect child_rect = child_window->Rect();
FocusWindow(parent_window);
- SetNavID(child_window->ChildId, 0, 0);
- // Reassigning with same value, we're being explicit here.
- g.NavIdIsAlive = false; // -V1048
- if (g.NavDisableMouseHover)
- g.NavMousePosDirty = true;
+ SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, ImRect(child_rect.Min - parent_window->Pos, child_rect.Max - parent_window->Pos));
}
else if (g.OpenPopupStack.Size > 0)
{
@@ -9821,7 +9860,7 @@ static void ImGui::NavUpdate()
// When using gamepad, we project the reference nav bounding box into window visible area.
// This is to allow resuming navigation inside the visible area after doing a large amount of scrolling, since with gamepad every movements are relative
// (can't focus a visible object like we can with the mouse).
- if (g.NavMoveRequest && g.NavInputSource == ImGuiInputSource_NavGamepad && g.NavLayer == ImGuiNavLayer_Main)
+ if (g.NavMoveRequest && g.NavInputSource == ImGuiInputSource_Gamepad && 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));
@@ -9863,11 +9902,12 @@ static void ImGui::NavUpdateInitResult()
// Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called)
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", g.NavInitResultId, g.NavLayer, g.NavWindow->Name);
+ SetNavID(g.NavInitResultId, g.NavLayer, 0, g.NavInitResultRectRel);
if (g.NavInitRequestFromMove)
- SetNavIDWithRectRel(g.NavInitResultId, g.NavLayer, 0, g.NavInitResultRectRel);
- else
- SetNavID(g.NavInitResultId, g.NavLayer, 0);
- g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitResultRectRel;
+ {
+ g.NavDisableHighlight = false;
+ g.NavDisableMouseHover = g.NavMousePosDirty = true;
+ }
}
// Apply result from previous frame navigation directional move request
@@ -9930,7 +9970,9 @@ static void ImGui::NavUpdateMoveResult()
g.NavJustMovedToKeyMods = g.NavMoveRequestKeyMods;
}
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID, g.NavLayer, g.NavWindow->Name);
- SetNavIDWithRectRel(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel);
+ SetNavID(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel);
+ g.NavDisableHighlight = false;
+ g.NavDisableMouseHover = g.NavMousePosDirty = true;
}
// Handle PageUp/PageDown/Home/End keys
@@ -10131,15 +10173,15 @@ static void ImGui::NavUpdateWindowing()
if (start_windowing_with_gamepad || start_windowing_with_keyboard)
if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
{
- g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindowDockStop;
+ g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow;
g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f;
g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true;
- g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_NavKeyboard : ImGuiInputSource_NavGamepad;
+ g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad;
}
// Gamepad update
g.NavWindowingTimer += g.IO.DeltaTime;
- if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavGamepad)
+ if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Gamepad)
{
// Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise
g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
@@ -10165,7 +10207,7 @@ static void ImGui::NavUpdateWindowing()
}
// Keyboard: Focus
- if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavKeyboard)
+ if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Keyboard)
{
// Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise
g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f
@@ -10187,15 +10229,15 @@ static void ImGui::NavUpdateWindowing()
if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove))
{
ImVec2 move_delta;
- if (g.NavInputSource == ImGuiInputSource_NavKeyboard && !g.IO.KeyShift)
+ if (g.NavInputSource == ImGuiInputSource_Keyboard && !g.IO.KeyShift)
move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down);
- if (g.NavInputSource == ImGuiInputSource_NavGamepad)
+ if (g.NavInputSource == ImGuiInputSource_Gamepad)
move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down);
if (move_delta.x != 0.0f || move_delta.y != 0.0f)
{
const float NAV_MOVE_SPEED = 800.0f;
const float move_speed = ImFloor(NAV_MOVE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); // FIXME: Doesn't handle variable framerate very well
- ImGuiWindow* moving_window = g.NavWindowingTarget->RootWindow;
+ ImGuiWindow* moving_window = g.NavWindowingTarget->RootWindowDockTree;
SetWindowPos(moving_window, moving_window->Pos + move_delta * move_speed, ImGuiCond_Always);
MarkIniSettingsDirty(moving_window);
g.NavDisableMouseHover = true;
@@ -10203,7 +10245,7 @@ static void ImGui::NavUpdateWindowing()
}
// Apply final focus
- if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindowDockStop))
+ if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow))
{
ImGuiViewport* previous_viewport = g.NavWindow ? g.NavWindow->Viewport : NULL;
ClearActiveID();
@@ -10245,11 +10287,11 @@ static void ImGui::NavUpdateWindowing()
g.NavDisableHighlight = false;
g.NavDisableMouseHover = true;
- // When entering a regular menu bar with the Alt key, we always reinitialize the navigation ID. It however persist on docking tab tabs.
+ // Reinitialize navigation when entering menu bar with the Alt key. We make it persist on Docking Tab Bars.
const ImGuiNavLayer new_nav_layer = (g.NavWindow->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((int)g.NavLayer ^ 1) : ImGuiNavLayer_Main;
const bool preserve_layer_1_nav_id = (new_nav_window->DockNodeAsHost != NULL);
if (new_nav_layer == ImGuiNavLayer_Menu && !preserve_layer_1_nav_id)
- g.NavWindow->NavLastIds[ImGuiNavLayer_Menu] = 0;
+ g.NavWindow->NavLastIds[new_nav_layer] = 0;
NavRestoreLayer(new_nav_layer);
}
}
@@ -10315,27 +10357,45 @@ void ImGui::ClearDragDrop()
memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
}
-// Call when current ID is active.
// When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource()
+// If the item has an identifier:
+// - This assume/require the item to be activated (typically via ButtonBehavior).
+// - Therefore if you want to use this with a mouse button other than left mouse button, it is up to the item itself to activate with another button.
+// - We then pull and use the mouse button that was used to activate the item and use it to carry on the drag.
+// If the item has no identifier:
+// - Currently always assume left mouse button.
bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
+ // FIXME-DRAGDROP: While in the common-most "drag from non-zero active id" case we can tell the mouse button,
+ // in both SourceExtern and id==0 cases we may requires something else (explicit flags or some heuristic).
+ ImGuiMouseButton mouse_button = ImGuiMouseButton_Left;
+
bool source_drag_active = false;
ImGuiID source_id = 0;
ImGuiID source_parent_id = 0;
- ImGuiMouseButton mouse_button = ImGuiMouseButton_Left;
if (!(flags & ImGuiDragDropFlags_SourceExtern))
{
source_id = window->DC.LastItemId;
- if (source_id != 0 && g.ActiveId != source_id) // Early out for most common case
- return false;
- if (g.IO.MouseDown[mouse_button] == false)
- return false;
-
- if (source_id == 0)
+ if (source_id != 0)
+ {
+ // Common path: items with ID
+ if (g.ActiveId != source_id)
+ return false;
+ if (g.ActiveIdMouseButton != -1)
+ mouse_button = g.ActiveIdMouseButton;
+ if (g.IO.MouseDown[mouse_button] == false)
+ return false;
+ g.ActiveIdAllowOverlap = false;
+ }
+ else
{
+ // Uncommon path: items without ID
+ if (g.IO.MouseDown[mouse_button] == false)
+ return false;
+
// If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to:
// A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag, C) Swallow your programmer pride.
if (!(flags & ImGuiDragDropFlags_SourceAllowNullID))
@@ -10362,10 +10422,6 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
if (g.ActiveId == source_id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker.
g.ActiveIdAllowOverlap = is_hovered;
}
- else
- {
- g.ActiveIdAllowOverlap = false;
- }
if (g.ActiveId != source_id)
return false;
source_parent_id = window->IDStack.back();
@@ -10489,7 +10545,7 @@ bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id)
ImGuiWindow* window = g.CurrentWindow;
ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow;
- if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow)
+ if (hovered_window == NULL || window->RootWindowDockTree != hovered_window->RootWindowDockTree)
return false;
IM_ASSERT(id != 0);
if (!IsMouseHoveringRect(bb.Min, bb.Max) || (id == g.DragDropPayload.SourceId))
@@ -10518,7 +10574,7 @@ bool ImGui::BeginDragDropTarget()
if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
return false;
ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow;
- if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow)
+ if (hovered_window == NULL || window->RootWindowDockTree != hovered_window->RootWindowDockTree)
return false;
const ImRect& display_rect = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? window->DC.LastItemDisplayRect : window->DC.LastItemRect;
@@ -10568,11 +10624,11 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop
flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that lives for 1 frame)
if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview)
{
- // FIXME-DRAG: Settle on a proper default visuals for drop target.
+ // FIXME-DRAGDROP: 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));
- window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, ~0, 2.0f);
+ window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f);
if (push_clip_rect) window->DrawList->PopClipRect();
}
@@ -10607,14 +10663,8 @@ void ImGui::EndDragDropTarget()
//-----------------------------------------------------------------------------
// Pass text data straight to log (without being displayed)
-void ImGui::LogText(const char* fmt, ...)
+static inline void LogTextV(ImGuiContext& g, const char* fmt, va_list args)
{
- ImGuiContext& g = *GImGui;
- if (!g.LogEnabled)
- return;
-
- va_list args;
- va_start(args, fmt);
if (g.LogFile)
{
g.LogBuffer.Buf.resize(0);
@@ -10625,9 +10675,29 @@ void ImGui::LogText(const char* fmt, ...)
{
g.LogBuffer.appendfv(fmt, args);
}
+}
+
+void ImGui::LogText(const char* fmt, ...)
+{
+ ImGuiContext& g = *GImGui;
+ if (!g.LogEnabled)
+ return;
+
+ va_list args;
+ va_start(args, fmt);
+ LogTextV(g, fmt, args);
va_end(args);
}
+void ImGui::LogTextV(const char* fmt, va_list args)
+{
+ ImGuiContext& g = *GImGui;
+ if (!g.LogEnabled)
+ return;
+
+ LogTextV(g, fmt, args);
+}
+
// Internal version that takes a position to decide on newline placement and pad items according to their depth.
// We split text into individual lines to add current tree level padding
// FIXME: This code is a little complicated perhaps, considering simplifying the whole system.
@@ -11157,7 +11227,6 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
buf->appendf("Collapsed=%d\n", settings->Collapsed);
if (settings->DockId != 0)
{
- // Write DockId as 4 digits if possible. Automatic DockId are small numbers, but full explicit DockSpace() are full ImGuiID range.
if (settings->DockOrder == -1)
buf->appendf("DockId=0x%08X\n", settings->DockId);
else
@@ -11485,6 +11554,17 @@ static void ImGui::UpdateViewportsNewFrame()
viewport->DpiScale = new_dpi_scale;
}
+ // Update fallback monitor
+ if (g.PlatformIO.Monitors.Size == 0)
+ {
+ ImGuiPlatformMonitor* monitor = &g.FallbackMonitor;
+ monitor->MainPos = main_viewport->Pos;
+ monitor->MainSize = main_viewport->Size;
+ monitor->WorkPos = main_viewport->WorkPos;
+ monitor->WorkSize = main_viewport->WorkSize;
+ monitor->DpiScale = main_viewport->DpiScale;
+ }
+
if (!viewports_enabled)
{
g.MouseViewport = main_viewport;
@@ -11567,7 +11647,7 @@ ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const
flags |= ImGuiViewportFlags_IsPlatformWindow;
if (window != NULL)
{
- if (g.MovingWindow && g.MovingWindow->RootWindow == window)
+ if (g.MovingWindow && g.MovingWindow->RootWindowDockTree == window)
flags |= ImGuiViewportFlags_NoInputs | ImGuiViewportFlags_NoFocusOnAppearing;
if ((window->Flags & ImGuiWindowFlags_NoMouseInputs) && (window->Flags & ImGuiWindowFlags_NoNavInputs))
flags |= ImGuiViewportFlags_NoInputs;
@@ -11680,7 +11760,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
{
window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
}
- else if (g.MovingWindow && g.MovingWindow->RootWindow == window && IsMousePosValid())
+ else if (g.MovingWindow && g.MovingWindow->RootWindowDockTree == window && IsMousePosValid())
{
if (window->Viewport != NULL && window->Viewport->Window == window)
window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
@@ -11698,7 +11778,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
if (window->Viewport == NULL)
if (!UpdateTryMergeWindowIntoHostViewport(window, main_viewport))
window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
-
+
// Mark window as allowed to protrude outside of its viewport and into the current monitor
if (!lock_viewport)
{
@@ -11961,6 +12041,17 @@ static void ImGui::UpdateViewportPlatformMonitor(ImGuiViewportP* viewport)
viewport->PlatformMonitor = (short)FindPlatformMonitorForRect(viewport->GetMainRect());
}
+// Return value is always != NULL, but don't hold on it across frames.
+const ImGuiPlatformMonitor* ImGui::GetViewportPlatformMonitor(ImGuiViewport* viewport_p)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)viewport_p;
+ int monitor_idx = viewport->PlatformMonitor;
+ if (monitor_idx >= 0 || monitor_idx < g.PlatformIO.Monitors.Size)
+ return &g.PlatformIO.Monitors[monitor_idx];
+ return &g.FallbackMonitor;
+}
+
void ImGui::DestroyPlatformWindow(ImGuiViewportP* viewport)
{
ImGuiContext& g = *GImGui;
@@ -12120,14 +12211,14 @@ struct ImGuiDockNodeSettings
ImGuiID ID;
ImGuiID ParentNodeId;
ImGuiID ParentWindowId;
- ImGuiID SelectedWindowId;
+ ImGuiID SelectedTabId;
signed char SplitAxis;
char Depth;
ImGuiDockNodeFlags Flags; // NB: We save individual flags one by one in ascii format (ImGuiDockNodeFlags_SavedFlagsMask_)
ImVec2ih Pos;
ImVec2ih Size;
ImVec2ih SizeRef;
- ImGuiDockNodeSettings() { ID = ParentNodeId = ParentWindowId = SelectedWindowId = 0; SplitAxis = ImGuiAxis_None; Depth = 0; Flags = ImGuiDockNodeFlags_None; }
+ ImGuiDockNodeSettings() { memset(this, 0, sizeof(*this)); SplitAxis = ImGuiAxis_None; }
};
//-----------------------------------------------------------------------------
@@ -12327,8 +12418,8 @@ void ImGui::DockContextNewFrameUpdateDocking(ImGuiContext* ctx)
{
if (hovered_window->DockNodeAsHost)
g.HoveredDockNode = DockNodeTreeFindVisibleNodeByPos(hovered_window->DockNodeAsHost, g.IO.MousePos);
- else if (hovered_window->RootWindowDockStop->DockNode)
- g.HoveredDockNode = hovered_window->RootWindowDockStop->DockNode;
+ else if (hovered_window->RootWindow->DockNode)
+ g.HoveredDockNode = hovered_window->RootWindow->DockNode;
}
// Process Docking requests
@@ -12504,7 +12595,7 @@ static void ImGui::DockContextBuildNodesFromSettings(ImGuiContext* ctx, ImGuiDoc
node->ParentNode->ChildNodes[0] = node;
else if (node->ParentNode && node->ParentNode->ChildNodes[1] == NULL)
node->ParentNode->ChildNodes[1] = node;
- node->SelectedTabId = settings->SelectedWindowId;
+ node->SelectedTabId = settings->SelectedTabId;
node->SplitAxis = (ImGuiAxis)settings->SplitAxis;
node->LocalFlags |= (settings->Flags & ImGuiDockNodeFlags_SavedFlagsMask_);
@@ -12838,7 +12929,7 @@ ImGuiDockNode::ImGuiDockNode(ImGuiID id)
AuthorityForPos = AuthorityForSize = ImGuiDataAuthority_DockNode;
AuthorityForViewport = ImGuiDataAuthority_Auto;
IsVisible = true;
- IsFocused = HasCloseButton = HasWindowMenuButton = EnableCloseButton = false;
+ IsFocused = HasCloseButton = HasWindowMenuButton = false;
WantCloseAll = WantLockSizeOnce = WantMouseMove = WantHiddenTabBarUpdate = WantHiddenTabBarToggle = false;
MarkedForPosSizeWrite = false;
}
@@ -12924,7 +13015,7 @@ static void ImGui::DockNodeRemoveWindow(ImGuiDockNode* node, ImGuiWindow* window
{
ImGuiContext& g = *GImGui;
IM_ASSERT(window->DockNode == node);
- //IM_ASSERT(window->RootWindow == node->HostWindow);
+ //IM_ASSERT(window->RootWindowDockTree == node->HostWindow);
//IM_ASSERT(window->LastFrameActive < g.FrameCount); // We may call this from Begin()
IM_ASSERT(save_dock_id == 0 || save_dock_id == node->ID);
IMGUI_DEBUG_LOG_DOCKING("DockNodeRemoveWindow node 0x%08X window '%s'\n", node->ID, window->Name);
@@ -13148,6 +13239,7 @@ static void ImGui::DockNodeUpdateVisibleFlagAndInactiveChilds(ImGuiDockNode* nod
}
else
{
+ // FIXME-DOCKING: Missing policies for conflict resolution, hence the "Experimental" tag on this.
node->LocalFlags &= ~window->WindowClass.DockNodeFlagsOverrideClear;
node->LocalFlags |= window->WindowClass.DockNodeFlagsOverrideSet;
}
@@ -13272,7 +13364,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
node->State = ImGuiDockNodeState_HostWindowHiddenBecauseSingleWindow;
node->WantCloseAll = false;
node->WantCloseTabId = 0;
- node->HasCloseButton = node->HasWindowMenuButton = node->EnableCloseButton = false;
+ node->HasCloseButton = node->HasWindowMenuButton = false;
node->LastFrameActive = g.FrameCount;
if (node->WantMouseMove && node->Windows.Size == 1)
@@ -13307,6 +13399,19 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
const ImGuiDockNodeFlags node_flags = node->GetMergedFlags();
+ // Decide if the node will have a close button and a window menu button
+ node->HasWindowMenuButton = (node->Windows.Size > 0) && (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0;
+ node->HasCloseButton = false;
+ for (int window_n = 0; window_n < node->Windows.Size; window_n++)
+ {
+ // FIXME-DOCK: Setting DockIsActive here means that for single active window in a leaf node, DockIsActive will be cleared until the next Begin() call.
+ ImGuiWindow* window = node->Windows[window_n];
+ node->HasCloseButton |= window->HasCloseButton;
+ window->DockIsActive = (node->Windows.Size > 1);
+ }
+ if (node_flags & ImGuiDockNodeFlags_NoCloseButton)
+ node->HasCloseButton = false;
+
// Bind or create host window
ImGuiWindow* host_window = NULL;
bool beginned_into_host_window = false;
@@ -13314,25 +13419,11 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
{
// [Explicit root dockspace node]
IM_ASSERT(node->HostWindow);
- node->EnableCloseButton = false;
- node->HasCloseButton = (node_flags & ImGuiDockNodeFlags_NoCloseButton) == 0;
- node->HasWindowMenuButton = (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0;
host_window = node->HostWindow;
}
else
{
// [Automatic root or child nodes]
- node->EnableCloseButton = false;
- node->HasCloseButton = (node->Windows.Size > 0) && (node_flags & ImGuiDockNodeFlags_NoCloseButton) == 0;
- node->HasWindowMenuButton = (node->Windows.Size > 0) && (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0;
- for (int window_n = 0; window_n < node->Windows.Size; window_n++)
- {
- // FIXME-DOCK: Setting DockIsActive here means that for single active window in a leaf node, DockIsActive will be cleared until the next Begin() call.
- ImGuiWindow* window = node->Windows[window_n];
- window->DockIsActive = (node->Windows.Size > 1);
- node->EnableCloseButton |= window->HasCloseButton;
- }
-
if (node->IsRootNode() && node->IsVisible)
{
ImGuiWindow* ref_window = (node->Windows.Size > 0) ? node->Windows[0] : NULL;
@@ -13402,8 +13493,8 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
if (node->IsSplitNode())
IM_ASSERT(node->TabBar == NULL);
if (node->IsRootNode())
- if (g.NavWindow && g.NavWindow->RootWindowDockStop->DockNode && g.NavWindow->RootWindowDockStop->ParentWindow == host_window)
- node->LastFocusedNodeId = g.NavWindow->RootWindowDockStop->DockNode->ID;
+ if (g.NavWindow && g.NavWindow->RootWindow->DockNode && g.NavWindow->RootWindow->ParentWindow == host_window)
+ node->LastFocusedNodeId = g.NavWindow->RootWindow->DockNode->ID;
// We need to draw a background at the root level if requested by ImGuiDockNodeFlags_PassthruCentralNode, but we will only know the correct pos/size
// _after_ processing the resizing splitters. So we are using the DrawList channel splitting facility to submit drawing primitives out of order!
@@ -13483,7 +13574,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
// Draw payload drop target
if (host_window && node->IsVisible)
- if (node->IsRootNode() && (g.MovingWindow == NULL || g.MovingWindow->RootWindow != host_window))
+ if (node->IsRootNode() && (g.MovingWindow == NULL || g.MovingWindow->RootWindowDockTree != host_window))
BeginDockableDragDropTarget(host_window);
// We update this after DockNodeUpdateTabBar()
@@ -13564,7 +13655,7 @@ bool ImGui::DockNodeBeginAmendTabBar(ImGuiDockNode* node)
PushOverrideID(node->ID);
bool ret = BeginTabBarEx(node->TabBar, node->TabBar->BarRect, node->TabBar->Flags, node);
IM_UNUSED(ret);
- IM_ASSERT(ret);
+ IM_ASSERT(ret);
return true;
}
@@ -13592,7 +13683,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
ImGuiDockNode* root_node = DockNodeGetRootNode(node);
if (g.NavWindowingTarget)
is_focused = (g.NavWindowingTarget->DockNode == node);
- else if (g.NavWindow && g.NavWindow->RootWindowForTitleBarHighlight == host_window->RootWindow && root_node->LastFocusedNodeId == node->ID)
+ else if (g.NavWindow && g.NavWindow->RootWindowForTitleBarHighlight == host_window->RootWindowDockTree && root_node->LastFocusedNodeId == node->ID)
is_focused = true;
// Hidden tab bar will show a triangle on the upper-left (in Begin)
@@ -13638,7 +13729,6 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
const ImGuiDockNodeFlags node_flags = node->GetMergedFlags();
const bool has_window_menu_button = (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0 && (style.WindowMenuButtonPosition != ImGuiDir_None);
- const bool has_close_button = (node_flags & ImGuiDockNodeFlags_NoCloseButton) == 0;
// In a dock node, the Collapse Button turns into the Window Menu button.
// FIXME-DOCK FIXME-OPT: Could we recycle popups id across multiple dock nodes?
@@ -13659,7 +13749,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
for (int window_n = 0; window_n < node->Windows.Size; window_n++)
{
ImGuiWindow* window = node->Windows[window_n];
- if (g.NavWindow && g.NavWindow->RootWindowDockStop == window)
+ if (g.NavWindow && g.NavWindow->RootWindow == window)
tab_bar->SelectedTabId = window->ID;
if (TabBarFindTabByID(tab_bar, window->ID) == NULL)
TabBarAddTab(tab_bar, ImGuiTabItemFlags_Unsorted, window);
@@ -13669,7 +13759,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
if (is_focused)
node->LastFrameFocused = g.FrameCount;
ImU32 title_bar_col = GetColorU32(host_window->Collapsed ? ImGuiCol_TitleBgCollapsed : is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
- host_window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, host_window->WindowRounding, ImDrawCornerFlags_Top);
+ host_window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, host_window->WindowRounding, ImDrawFlags_RoundCornersTop);
// Docking/Collapse button
if (has_window_menu_button)
@@ -13748,7 +13838,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
window->DockTabItemRect = host_window->DC.LastItemRect;
// Update navigation ID on menu layer
- if (g.NavWindow && g.NavWindow->RootWindowDockStop == window && (window->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) == 0)
+ if (g.NavWindow && g.NavWindow->RootWindow == window && (window->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) == 0)
host_window->NavLastIds[1] = window->ID;
}
}
@@ -13764,12 +13854,15 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
// Close button (after VisibleWindow was updated)
// Note that VisibleWindow may have been overrided by CTRL+Tabbing, so VisibleWindow->ID may be != from tab_bar->SelectedTabId
- if (has_close_button && node->VisibleWindow)
+ const bool close_button_is_enabled = node->HasCloseButton && node->VisibleWindow && node->VisibleWindow->HasCloseButton;
+ const bool close_button_is_visible = node->HasCloseButton;
+ //const bool close_button_is_visible = close_button_is_enabled; // Most people would expect this behavior of not even showing the button (leaving a hole since we can't claim that space as other windows in the tba bar have one)
+ if (close_button_is_visible)
{
- if (!node->VisibleWindow->HasCloseButton)
+ if (!close_button_is_enabled)
{
PushItemFlag(ImGuiItemFlags_Disabled, true);
- PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_Text] * ImVec4(1.0f,1.0f,1.0f,0.5f));
+ PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_Text] * ImVec4(1.0f,1.0f,1.0f,0.4f));
}
const float button_sz = g.FontSize;
if (CloseButton(host_window->GetID("#CLOSE"), title_bar_rect.GetTR() + ImVec2(-style.FramePadding.x * 2.0f - button_sz, 0.0f)))
@@ -13780,7 +13873,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
}
//if (IsItemActive())
// focus_tab_id = tab_bar->SelectedTabId;
- if (!node->VisibleWindow->HasCloseButton)
+ if (!close_button_is_enabled)
{
PopStyleColor();
PopItemFlag();
@@ -15337,7 +15430,7 @@ void ImGui::BeginDockableDragDropSource(ImGuiWindow* window)
IM_ASSERT(g.MovingWindow == window);
window->DC.LastItemId = window->MoveId;
- window = window->RootWindow;
+ window = window->RootWindowDockTree;
IM_ASSERT((window->Flags & ImGuiWindowFlags_NoDocking) == 0);
bool is_drag_docking = (g.IO.ConfigDockingWithShift) || ImRect(0, 0, window->SizeFull.x, GetFrameHeight()).Contains(g.ActiveIdClickOffset);
if (is_drag_docking && BeginDragDropSource(ImGuiDragDropFlags_SourceNoPreviewTooltip | ImGuiDragDropFlags_SourceNoHoldToOpenOthers | ImGuiDragDropFlags_SourceAutoExpirePayload))
@@ -15356,7 +15449,7 @@ void ImGui::BeginDockableDragDropTarget(ImGuiWindow* window)
ImGuiContext* ctx = GImGui;
ImGuiContext& g = *ctx;
- //IM_ASSERT(window->RootWindow == window); // May also be a DockSpace
+ //IM_ASSERT(window->RootWindowDockTree == window); // May also be a DockSpace
IM_ASSERT((window->Flags & ImGuiWindowFlags_NoDocking) == 0);
if (!g.DragDropActive)
return;
@@ -15550,7 +15643,7 @@ static void ImGui::DockSettingsHandler_ReadLine(ImGuiContext* ctx, ImGuiSettings
if (sscanf(line, " HiddenTabBar=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_HiddenTabBar; }
if (sscanf(line, " NoWindowMenuButton=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_NoWindowMenuButton; }
if (sscanf(line, " NoCloseButton=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_NoCloseButton; }
- if (sscanf(line, " Selected=0x%08X%n", &node.SelectedWindowId,&r) == 1) { line += r; }
+ if (sscanf(line, " Selected=0x%08X%n", &node.SelectedTabId,&r) == 1) { line += r; }
if (node.ParentNodeId != 0)
if (ImGuiDockNodeSettings* parent_settings = DockSettingsFindNodeSettings(ctx, node.ParentNodeId))
node.Depth = parent_settings->Depth + 1;
@@ -15564,7 +15657,7 @@ static void DockSettingsHandler_DockNodeToSettings(ImGuiDockContext* dc, ImGuiDo
node_settings.ID = node->ID;
node_settings.ParentNodeId = node->ParentNode ? node->ParentNode->ID : 0;
node_settings.ParentWindowId = (node->IsDockSpace() && node->HostWindow && node->HostWindow->ParentWindow) ? node->HostWindow->ParentWindow->ID : 0;
- node_settings.SelectedWindowId = node->SelectedTabId;
+ node_settings.SelectedTabId = node->SelectedTabId;
node_settings.SplitAxis = (signed char)(node->IsSplitNode() ? node->SplitAxis : ImGuiAxis_None);
node_settings.Depth = (char)depth;
node_settings.Flags = (node->LocalFlags & ImGuiDockNodeFlags_SavedFlagsMask_);
@@ -15630,8 +15723,8 @@ static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettings
buf->appendf(" NoWindowMenuButton=1");
if (node_settings->Flags & ImGuiDockNodeFlags_NoCloseButton)
buf->appendf(" NoCloseButton=1");
- if (node_settings->SelectedWindowId)
- buf->appendf(" Selected=0x%08X", node_settings->SelectedWindowId);
+ if (node_settings->SelectedTabId)
+ buf->appendf(" Selected=0x%08X", node_settings->SelectedTabId);
#if IMGUI_DEBUG_INI_SETTINGS
// [DEBUG] Include comments in the .ini file to ease debugging
@@ -15992,7 +16085,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);
if (IsItemHovered())
- GetForegroundDrawList()->AddRect(table->OuterRect.Min - ImVec2(1, 1), table->OuterRect.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f);
+ GetForegroundDrawList()->AddRect(table->OuterRect.Min - ImVec2(1, 1), table->OuterRect.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
Indent();
char buf[128];
for (int rect_n = 0; rect_n < TRT_Count; rect_n++)
@@ -16007,7 +16100,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImFormatString(buf, IM_ARRAYSIZE(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) Col %d %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), column_n, trt_rects_names[rect_n]);
Selectable(buf);
if (IsItemHovered())
- GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f);
+ GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
}
}
else
@@ -16016,7 +16109,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImFormatString(buf, IM_ARRAYSIZE(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), trt_rects_names[rect_n]);
Selectable(buf);
if (IsItemHovered())
- GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f);
+ GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
}
}
Unindent();
@@ -16192,14 +16285,14 @@ void ImGui::ShowMetricsWindow(bool* p_open)
{
ImGuiDockNodeSettings* settings = &dc->NodesSettings[n];
const char* selected_tab_name = NULL;
- if (settings->SelectedWindowId)
+ if (settings->SelectedTabId)
{
- if (ImGuiWindow* window = FindWindowByID(settings->SelectedWindowId))
+ if (ImGuiWindow* window = FindWindowByID(settings->SelectedTabId))
selected_tab_name = window->Name;
- else if (ImGuiWindowSettings* window_settings = FindWindowSettings(settings->SelectedWindowId))
+ else if (ImGuiWindowSettings* window_settings = FindWindowSettings(settings->SelectedTabId))
selected_tab_name = window_settings->GetName();
}
- BulletText("Node %08X, Parent %08X, SelectedTab %08X ('%s')", settings->ID, settings->ParentNodeId, settings->SelectedWindowId, selected_tab_name ? selected_tab_name : settings->SelectedWindowId ? "N/A" : "");
+ BulletText("Node %08X, Parent %08X, SelectedTab %08X ('%s')", settings->ID, settings->ParentNodeId, settings->SelectedTabId, selected_tab_name ? selected_tab_name : settings->SelectedTabId ? "N/A" : "");
}
TreePop();
}
@@ -16221,7 +16314,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Text("WINDOWING");
Indent();
Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL");
- Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL");
+ Text("HoveredWindow->Root: '%s'", g.HoveredWindow ? g.HoveredWindow->RootWindowDockTree->Name : "NULL");
Text("HoveredWindowUnderMovingWindow: '%s'", g.HoveredWindowUnderMovingWindow ? g.HoveredWindowUnderMovingWindow->Name : "NULL");
Text("HoveredDockNode: 0x%08X", g.HoveredDockNode ? g.HoveredDockNode->ID : 0);
Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL");
@@ -16293,7 +16386,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, column_n);
ImU32 col = (table->HoveredColumnBody == column_n) ? IM_COL32(255, 255, 128, 255) : IM_COL32(255, 0, 128, 255);
float thickness = (table->HoveredColumnBody == column_n) ? 3.0f : 1.0f;
- draw_list->AddRect(r.Min, r.Max, col, 0.0f, ~0, thickness);
+ draw_list->AddRect(r.Min, r.Max, col, 0.0f, 0, thickness);
}
}
else
@@ -16480,7 +16573,7 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, con
{
ImDrawListFlags backup_flags = fg_draw_list->Flags;
fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles.
- fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), true, 1.0f);
+ fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f);
fg_draw_list->Flags = backup_flags;
}
}
@@ -16507,7 +16600,7 @@ void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, co
for (int n = 0; n < 3; n++, idx_n++)
vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos));
if (show_mesh)
- out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), true, 1.0f); // In yellow: mesh triangles
+ out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f); // In yellow: mesh triangles
}
// Draw bounding boxes
if (show_aabb)
@@ -16650,10 +16743,10 @@ void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label)
BulletText("DockId: 0x%04X, DockOrder: %d, Act: %d, Vis: %d", window->DockId, window->DockOrder, window->DockIsActive, window->DockTabIsVisible);
if (window->DockNode || window->DockNodeAsHost)
DebugNodeDockNode(window->DockNodeAsHost ? window->DockNodeAsHost : window->DockNode, window->DockNodeAsHost ? "DockNodeAsHost" : "DockNode");
- if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); }
- if (window->RootWindowDockStop != window->RootWindow) { DebugNodeWindow(window->RootWindowDockStop, "RootWindowDockStop"); }
- if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow, "ParentWindow"); }
- if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); }
+ if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); }
+ if (window->RootWindowDockTree != window->RootWindow) { DebugNodeWindow(window->RootWindowDockTree, "RootWindowDockTree"); }
+ if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow, "ParentWindow"); }
+ if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); }
if (window->ColumnsStorage.Size > 0 && TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size))
{
for (int n = 0; n < window->ColumnsStorage.Size; n++)
diff --git a/imgui/imgui.h b/imgui/imgui.h
index 48b71756..da8182c5 100644
--- a/imgui/imgui.h
+++ b/imgui/imgui.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.81
+// dear imgui, v1.82
// (headers)
// Help:
@@ -15,6 +15,7 @@
// - Glossary https://github.com/ocornut/imgui/wiki/Glossary
// - Wiki https://github.com/ocornut/imgui/wiki
// - Issues & support https://github.com/ocornut/imgui/issues
+// - Discussions https://github.com/ocornut/imgui/discussions
/*
@@ -27,12 +28,12 @@ Index of this file:
// [SECTION] ImGuiStyle
// [SECTION] ImGuiIO
// [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiWindowClass, ImGuiPayload, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs)
-// [SECTION] Obsolete functions
// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, ImColor)
-// [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawListFlags, ImDrawList, ImDrawData)
+// [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData)
// [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont)
// [SECTION] Viewports (ImGuiViewportFlags, ImGuiViewport)
// [SECTION] Platform interface for multi-viewport support (ImGuiPlatformIO, ImGuiPlatformMonitor)
+// [SECTION] Obsolete functions and types
*/
@@ -60,8 +61,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.81"
-#define IMGUI_VERSION_NUM 18100
+#define IMGUI_VERSION "1.82"
+#define IMGUI_VERSION_NUM 18200
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch
@@ -167,8 +168,8 @@ typedef int ImGuiMouseCursor; // -> enum ImGuiMouseCursor_ // Enum: A
typedef int ImGuiSortDirection; // -> enum ImGuiSortDirection_ // Enum: A sorting direction (ascending or descending)
typedef int ImGuiStyleVar; // -> enum ImGuiStyleVar_ // Enum: A variable identifier for styling
typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A color target for TableSetBgColor()
-typedef int ImDrawCornerFlags; // -> enum ImDrawCornerFlags_ // Flags: for ImDrawList::AddRect(), AddRectFilled() etc.
-typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: for ImDrawList
+typedef int ImDrawFlags; // -> enum ImDrawFlags_ // Flags: for ImDrawList functions
+typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: for ImDrawList instance
typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: for ImFontAtlas build
typedef int ImGuiBackendFlags; // -> enum ImGuiBackendFlags_ // Flags: for io.BackendFlags
typedef int ImGuiButtonFlags; // -> enum ImGuiButtonFlags_ // Flags: for InvisibleButton()
@@ -200,6 +201,8 @@ typedef void* ImTextureID; // User data for rendering backend to identi
typedef unsigned int ImGuiID; // A unique ID used by widgets, typically hashed from a stack of string.
typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); // Callback function for ImGui::InputText()
typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); // Callback function for ImGui::SetNextWindowSizeConstraints()
+typedef void* (*ImGuiMemAllocFunc)(size_t sz, void* user_data); // Function signature for ImGui::SetAllocatorFunctions()
+typedef void (*ImGuiMemFreeFunc)(void* ptr, void* user_data); // Function signature for ImGui::SetAllocatorFunctions()
// Character types
// (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display)
@@ -262,8 +265,9 @@ struct ImVec4
namespace ImGui
{
// Context creation and access
- // Each context create its own ImFontAtlas by default. You may instance one yourself and pass it to CreateContext() to share a font atlas between imgui contexts.
- // None of those functions is reliant on the current context.
+ // - Each context create its own ImFontAtlas by default. You may instance one yourself and pass it to CreateContext() to share a font atlas between contexts.
+ // - DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
+ // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for details.
IMGUI_API ImGuiContext* CreateContext(ImFontAtlas* shared_font_atlas = NULL);
IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = destroy current context
IMGUI_API ImGuiContext* GetCurrentContext();
@@ -711,7 +715,7 @@ namespace ImGui
// - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in
// some advanced use cases (e.g. adding custom widgets in header row).
// - Use TableSetupScrollFreeze() to lock columns/rows so they stay visible when scrolled.
- IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImU32 user_id = 0);
+ IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImGuiID user_id = 0);
IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled.
IMGUI_API void TableHeadersRow(); // submit all headers cells based on data provided to TableSetupColumn() + submit context menu
IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used)
@@ -721,7 +725,7 @@ namespace ImGui
// since last call, or the first time. Make sure to set 'SpecsDirty = false' after sorting, else you may
// wastefully sort your data every frame!
// - Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable().
- IMGUI_API ImGuiTableSortSpecs* TableGetSortSpecs(); // get latest sort specs for the table (NULL if not sorting).
+ IMGUI_API ImGuiTableSortSpecs* TableGetSortSpecs(); // get latest sort specs for the table (NULL if not sorting).
// Tables: Miscellaneous functions
// - Functions args 'int column_n' treat the default value of -1 as the same as passing the current column index.
IMGUI_API int TableGetColumnCount(); // return number of columns (value passed to BeginTable)
@@ -774,10 +778,14 @@ namespace ImGui
IMGUI_API void LogFinish(); // stop logging (close file, etc.)
IMGUI_API void LogButtons(); // helper to display buttons for logging to tty/file/clipboard
IMGUI_API void LogText(const char* fmt, ...) IM_FMTARGS(1); // pass text data straight to log (without being displayed)
+ IMGUI_API void LogTextV(const char* fmt, va_list args) IM_FMTLIST(1);
// Drag and Drop
- // - If you stop calling BeginDragDropSource() the payload is preserved however it won't have a preview tooltip (we currently display a fallback "..." tooltip as replacement)
- IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0); // call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource()
+ // - On source items, call BeginDragDropSource(), if it returns true also call SetDragDropPayload() + EndDragDropSource().
+ // - On target candidates, call BeginDragDropTarget(), if it returns true also call AcceptDragDropPayload() + EndDragDropTarget().
+ // - If you stop calling BeginDragDropSource() the payload is preserved however it won't have a preview tooltip (we currently display a fallback "..." tooltip, see #1725)
+ // - An item can be both drag source and drop target.
+ IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0); // call after submitting an item which may be dragged. when this return true, you can call SetDragDropPayload() + EndDragDropSource()
IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t sz, ImGuiCond cond = 0); // type is a user defined string of maximum 32 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui.
IMGUI_API void EndDragDropSource(); // only call EndDragDropSource() if BeginDragDropSource() returns true!
IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive a payload. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget()
@@ -796,12 +804,12 @@ namespace ImGui
IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget.
// Item/Widgets Utilities
- // - Most of the functions are referring to the last/previous item we submitted.
+ // - Most of the functions are referring to the previous Item that has been submitted.
// - See Demo Window under "Widgets->Querying Status" for an interactive visualization of most of those functions.
IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags = 0); // is the last item hovered? (and usable, aka not blocked by a popup, etc.). See ImGuiHoveredFlags for more options.
IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited. This will continuously return true while holding mouse button on an item. Items that don't interact will always return false)
IMGUI_API bool IsItemFocused(); // is the last item focused for keyboard/gamepad navigation?
- IMGUI_API bool IsItemClicked(ImGuiMouseButton mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) == IsMouseClicked(mouse_button) && IsItemHovered()
+ IMGUI_API bool IsItemClicked(ImGuiMouseButton mouse_button = 0); // is the last item hovered and mouse clicked on? (**) == IsMouseClicked(mouse_button) && IsItemHovered()Important. (**) this it NOT equivalent to the behavior of e.g. Button(). Read comments in function definition.
IMGUI_API bool IsItemVisible(); // is the last item visible? (items may be out of sight because of clipping/scrolling)
IMGUI_API bool IsItemEdited(); // did the last item modify its underlying value this frame? or was pressed? This is generally the same as the "bool" return value of many widgets.
IMGUI_API bool IsItemActivated(); // was the last item just made active (item was previously inactive).
@@ -895,9 +903,11 @@ namespace ImGui
IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro.
// Memory Allocators
- // - All those functions are not reliant on the current context.
- // - If you reload the contents of imgui.cpp at runtime, you may need to call SetCurrentContext() + SetAllocatorFunctions() again because we use global storage for those.
- IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = NULL);
+ // - Those functions are not reliant on the current context.
+ // - DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
+ // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
+ IMGUI_API void SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func, void* user_data = NULL);
+ IMGUI_API void GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func, void** p_user_data);
IMGUI_API void* MemAlloc(size_t size);
IMGUI_API void MemFree(void* ptr);
@@ -905,7 +915,6 @@ namespace ImGui
// Read comments around the ImGuiPlatformIO structure for more details.
// Note: You may use GetWindowViewport() to get the current viewport of the current window.
IMGUI_API ImGuiPlatformIO& GetPlatformIO(); // platform/renderer functions, for backend to setup + viewports list.
- IMGUI_API ImGuiViewport* GetMainViewport(); // return primary/default viewport. In the future in "no main platform window" mode we will direct this to primary monitor.
IMGUI_API void UpdatePlatformWindows(); // call in main loop. will call CreateWindow/ResizeWindow/etc. platform functions for each secondary viewport, and DestroyWindow for each inactive viewport.
IMGUI_API void RenderPlatformWindowsDefault(void* platform_render_arg = NULL, void* renderer_render_arg = NULL); // call in main loop. will call RenderWindow/SwapBuffers platform functions for each secondary viewport which doesn't have the ImGuiViewportFlags_Minimized flag set. May be reimplemented by user for custom rendering needs.
IMGUI_API void DestroyPlatformWindows(); // call DestroyWindow platform functions for all viewports. call from backend Shutdown() if you need to close platform windows before imgui shutdown. otherwise will be called by DestroyContext().
@@ -978,7 +987,7 @@ enum ImGuiInputTextFlags_
ImGuiInputTextFlags_AllowTabInput = 1 << 10, // Pressing TAB input a '\t' character into the text field
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11, // In multi-line mode, unfocus with Enter, add new line with Ctrl+Enter (default is opposite: unfocus with Ctrl+Enter, add line with Enter).
ImGuiInputTextFlags_NoHorizontalScroll = 1 << 12, // Disable following the cursor horizontally
- ImGuiInputTextFlags_AlwaysInsertMode = 1 << 13, // Insert mode
+ ImGuiInputTextFlags_AlwaysOverwrite = 1 << 13, // Overwrite mode
ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode
ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*'
ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID().
@@ -988,6 +997,11 @@ enum ImGuiInputTextFlags_
// [Internal]
ImGuiInputTextFlags_Multiline = 1 << 20, // For internal use by InputTextMultiline()
ImGuiInputTextFlags_NoMarkEdited = 1 << 21 // For internal use by functions using InputText() before reformatting data
+
+ // Obsolete names (will be removed soon)
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ , ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior
+#endif
};
// Flags for ImGui::TreeNodeEx(), ImGui::CollapsingHeader*()
@@ -1796,7 +1810,7 @@ struct ImGuiStyle
bool AntiAliasedLinesUseTex; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering. Latched at the beginning of the frame (copied to ImDrawList).
bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).
float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
- float CircleSegmentMaxError; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
+ float CircleTessellationMaxError; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
ImVec4 Colors[ImGuiCol_COUNT];
IMGUI_API ImGuiStyle();
@@ -2068,51 +2082,6 @@ struct ImGuiTableSortSpecs
};
//-----------------------------------------------------------------------------
-// [SECTION] Obsolete functions
-// (Will be removed! Read 'API BREAKING CHANGES' section in imgui.cpp for details)
-// Please keep your copy of dear imgui up to date! Occasionally set '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' in imconfig.h to stay ahead.
-//-----------------------------------------------------------------------------
-
-#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
-namespace ImGui
-{
- // OBSOLETED in 1.81 (from February 2021)
- IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // Helper to calculate size from items_count and height_in_items
- static inline bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0, 0)) { return BeginListBox(label, size); }
- static inline void ListBoxFooter() { EndListBox(); }
- // OBSOLETED in 1.79 (from August 2020)
- static inline void OpenPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry!
- // OBSOLETED in 1.78 (from June 2020)
- // Old drag/sliders functions that took a 'float power = 1.0' argument instead of flags.
- // For shared code, you can version check at compile-time with `#if IMGUI_VERSION_NUM >= 17704`.
- IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, float power);
- IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, float power);
- static inline bool DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, power); }
- static inline bool DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, power); }
- static inline bool DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, power); }
- static inline bool DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, power); }
- IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power);
- IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, const char* format, float power);
- static inline bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, float power) { return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, power); }
- static inline bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, float power) { return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, power); }
- static inline bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, float power) { return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, power); }
- static inline bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, float power) { return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, power); }
- // OBSOLETED in 1.77 (from June 2020)
- 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 April 2019)
- static inline void TreeAdvanceToLabelPos() { SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()); }
- // OBSOLETED in 1.71 (from June 2019)
- static inline void SetNextTreeNodeOpen(bool open, ImGuiCond cond = 0) { SetNextItemOpen(open, cond); }
- // OBSOLETED in 1.70 (from May 2019)
- static inline float GetContentRegionAvailWidth() { return GetContentRegionAvail().x; }
- // OBSOLETED in 1.69 (from Mar 2019)
- static inline ImDrawList* GetOverlayDrawList() { return GetForegroundDrawList(); }
- // OBSOLETED in 1.66 (from Sep 2018)
- static inline void SetScrollHere(float center_ratio=0.5f){ SetScrollHereY(center_ratio); }
-}
-#endif
-
-//-----------------------------------------------------------------------------
// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, ImColor)
//-----------------------------------------------------------------------------
@@ -2415,21 +2384,27 @@ struct ImDrawListSplitter
IMGUI_API void SetCurrentChannel(ImDrawList* draw_list, int channel_idx);
};
-enum ImDrawCornerFlags_
+// Flags for ImDrawList functions
+// (Legacy: bit 0 must always correspond to ImDrawFlags_Closed to be backward compatible with old API using a bool. Bits 1..3 must be unused)
+enum ImDrawFlags_
{
- ImDrawCornerFlags_None = 0,
- ImDrawCornerFlags_TopLeft = 1 << 0, // 0x1
- ImDrawCornerFlags_TopRight = 1 << 1, // 0x2
- ImDrawCornerFlags_BotLeft = 1 << 2, // 0x4
- ImDrawCornerFlags_BotRight = 1 << 3, // 0x8
- ImDrawCornerFlags_Top = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_TopRight, // 0x3
- ImDrawCornerFlags_Bot = ImDrawCornerFlags_BotLeft | ImDrawCornerFlags_BotRight, // 0xC
- ImDrawCornerFlags_Left = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotLeft, // 0x5
- ImDrawCornerFlags_Right = ImDrawCornerFlags_TopRight | ImDrawCornerFlags_BotRight, // 0xA
- ImDrawCornerFlags_All = 0xF // In your function calls you may use ~0 (= all bits sets) instead of ImDrawCornerFlags_All, as a convenience
+ ImDrawFlags_None = 0,
+ ImDrawFlags_Closed = 1 << 0, // PathStroke(), AddPolyline(): specify that shape should be closed (Important: this is always == 1 for legacy reason)
+ ImDrawFlags_RoundCornersTopLeft = 1 << 4, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-left corner only (when rounding > 0.0f, we default to all corners). Was 0x01.
+ ImDrawFlags_RoundCornersTopRight = 1 << 5, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-right corner only (when rounding > 0.0f, we default to all corners). Was 0x02.
+ ImDrawFlags_RoundCornersBottomLeft = 1 << 6, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-left corner only (when rounding > 0.0f, we default to all corners). Was 0x04.
+ ImDrawFlags_RoundCornersBottomRight = 1 << 7, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-right corner only (when rounding > 0.0f, we default to all corners). Wax 0x08.
+ ImDrawFlags_RoundCornersNone = 1 << 8, // AddRect(), AddRectFilled(), PathRect(): disable rounding on all corners (when rounding > 0.0f). This is NOT zero, NOT an implicit flag!
+ ImDrawFlags_RoundCornersTop = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight,
+ ImDrawFlags_RoundCornersBottom = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
+ ImDrawFlags_RoundCornersLeft = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersTopLeft,
+ ImDrawFlags_RoundCornersRight = ImDrawFlags_RoundCornersBottomRight | ImDrawFlags_RoundCornersTopRight,
+ ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
+ ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified.
+ ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone
};
-// Flags for ImDrawList. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly.
+// Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly.
// It is however possible to temporarily alter flags between calls to ImDrawList:: functions.
enum ImDrawListFlags_
{
@@ -2489,8 +2464,8 @@ struct ImDrawList
// In future versions we will use textures to provide cheaper and higher-quality circles.
// Use AddNgon() and AddNgonFilled() functions if you need to guaranteed a specific number of sides.
IMGUI_API void AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness = 1.0f);
- IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size), rounding_corners_flags: 4 bits corresponding to which corner to round
- IMGUI_API void AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All); // a: upper-left, b: lower-right (== upper-left + size)
+ IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size)
+ IMGUI_API void AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0); // a: upper-left, b: lower-right (== upper-left + size)
IMGUI_API void AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left);
IMGUI_API void AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness = 1.0f);
IMGUI_API void AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col);
@@ -2502,7 +2477,7 @@ struct ImDrawList
IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments);
IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL);
- IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, bool closed, float thickness);
+ IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); // Note: Anti-aliased filling requires points to be in clockwise order.
IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0); // Cubic Bezier (4 control points)
IMGUI_API void AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments = 0); // Quadratic Bezier (3 control points)
@@ -2513,19 +2488,19 @@ struct ImDrawList
// - "uv_min" and "uv_max" represent the normalized texture coordinates to use for those corners. Using (0,0)->(1,1) texture coordinates will generally display the entire texture.
IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min = ImVec2(0, 0), const ImVec2& uv_max = ImVec2(1, 1), ImU32 col = IM_COL32_WHITE);
IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1 = ImVec2(0, 0), const ImVec2& uv2 = ImVec2(1, 0), const ImVec2& uv3 = ImVec2(1, 1), const ImVec2& uv4 = ImVec2(0, 1), ImU32 col = IM_COL32_WHITE);
- IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All);
+ IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags = 0);
// 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 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);
+ inline void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, flags, thickness); _Path.Size = 0; }
+ IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 0);
IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle
IMGUI_API void PathBezierCubicCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0); // Cubic Bezier (4 control points)
IMGUI_API void PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3, int num_segments = 0); // Quadratic Bezier (3 control points)
- IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All);
+ IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, ImDrawFlags flags = 0);
// Advanced
IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles.
@@ -2566,6 +2541,9 @@ struct ImDrawList
IMGUI_API void _OnChangedClipRect();
IMGUI_API void _OnChangedTextureID();
IMGUI_API void _OnChangedVtxOffset();
+ IMGUI_API int _CalcCircleAutoSegmentCount(float radius) const;
+ IMGUI_API void _PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step);
+ IMGUI_API void _PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments);
};
// All draw data to render a Dear ImGui frame
@@ -2735,11 +2713,12 @@ struct ImFontAtlas
//-------------------------------------------
// You can request arbitrary rectangles to be packed into the atlas, for your own purposes.
- // 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.md for more details about using colorful icons.
- // Note: this API may be redesigned later in order to support multi-monitor varying DPI settings.
+ // - After calling Build(), you can query the rectangle position and render your pixels.
+ // - If you render colored output, set 'atlas->TexPixelsUseColors = true' as this may help some backends decide of prefered texture format.
+ // - 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.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));
ImFontAtlasCustomRect* GetCustomRectByIndex(int index) { IM_ASSERT(index >= 0); return &CustomRects[index]; }
@@ -2752,14 +2731,15 @@ struct ImFontAtlas
// Members
//-------------------------------------------
- bool Locked; // Marked as Locked by ImGui::NewFrame() so attempt to modify the atlas will assert.
ImFontAtlasFlags Flags; // Build flags (see ImFontAtlasFlags_)
ImTextureID TexID; // User data to refer to the texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure.
int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height.
int TexGlyphPadding; // Padding between glyphs within texture in pixels. Defaults to 1. If your rendering method doesn't rely on bilinear filtering you may set this to 0.
+ bool Locked; // Marked as Locked by ImGui::NewFrame() so attempt to modify the atlas will assert.
// [Internal]
// NB: Access texture data via GetTexData*() calls! Which will setup a default font for you.
+ bool TexPixelsUseColors; // Tell whether our texture data is known to use colors (rather than just alpha channel), in order to help backend select a format.
unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight
unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4
int TexWidth; // Texture width calculated during Build().
@@ -2872,7 +2852,7 @@ struct ImGuiViewport
{
ImGuiID ID; // Unique identifier for the viewport
ImGuiViewportFlags Flags; // See ImGuiViewportFlags_
- ImVec2 Pos; // Main Area: Position of the viewport (Dear Imgui coordinates are the same as OS desktop/native coordinates)
+ ImVec2 Pos; // Main Area: Position of the viewport (Dear ImGui coordinates are the same as OS desktop/native coordinates)
ImVec2 Size; // Main Area: Size of the viewport.
ImVec2 WorkPos; // Work Area: Position of the viewport minus task bars, menus bars, status bars (>= Pos)
ImVec2 WorkSize; // Work Area: Size of the viewport minus task bars, menu bars, status bars (<= Size)
@@ -2981,7 +2961,7 @@ struct ImGuiPlatformIO
bool (*Platform_GetWindowFocus)(ImGuiViewport* vp); // . . U . . //
bool (*Platform_GetWindowMinimized)(ImGuiViewport* vp); // N . . . . // Get platform window minimized state. When minimized, we generally won't attempt to get/set size and contents will be culled more easily
void (*Platform_SetWindowTitle)(ImGuiViewport* vp, const char* str); // . . U . . // Set platform window title (given an UTF-8 string)
- void (*Platform_SetWindowAlpha)(ImGuiViewport* vp, float alpha); // . . U . . // (Optional) Setup window transparency
+ void (*Platform_SetWindowAlpha)(ImGuiViewport* vp, float alpha); // . . U . . // (Optional) Setup global transparency (not per-pixel transparency)
void (*Platform_UpdateWindow)(ImGuiViewport* vp); // . . U . . // (Optional) Called by UpdatePlatformWindows(). Optional hook to allow the platform backend from doing general book-keeping every frame.
void (*Platform_RenderWindow)(ImGuiViewport* vp, void* render_arg); // . . . R . // (Optional) Main rendering (platform side! This is often unused, or just setting a "current" context for OpenGL bindings). 'render_arg' is the value passed to RenderPlatformWindowsDefault().
void (*Platform_SwapBuffers)(ImGuiViewport* vp, void* render_arg); // . . . R . // (Optional) Call Present/SwapBuffers (platform side! This is often unused!). 'render_arg' is the value passed to RenderPlatformWindowsDefault().
@@ -3023,6 +3003,66 @@ struct ImGuiPlatformMonitor
};
//-----------------------------------------------------------------------------
+// [SECTION] Obsolete functions and types
+// (Will be removed! Read 'API BREAKING CHANGES' section in imgui.cpp for details)
+// Please keep your copy of dear imgui up to date! Occasionally set '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' in imconfig.h to stay ahead.
+//-----------------------------------------------------------------------------
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+namespace ImGui
+{
+ // OBSOLETED in 1.81 (from February 2021)
+ IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // Helper to calculate size from items_count and height_in_items
+ static inline bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0, 0)) { return BeginListBox(label, size); }
+ static inline void ListBoxFooter() { EndListBox(); }
+ // OBSOLETED in 1.79 (from August 2020)
+ static inline void OpenPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry!
+ // OBSOLETED in 1.78 (from June 2020)
+ // Old drag/sliders functions that took a 'float power = 1.0' argument instead of flags.
+ // For shared code, you can version check at compile-time with `#if IMGUI_VERSION_NUM >= 17704`.
+ IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, float power);
+ IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, float power);
+ static inline bool DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, power); }
+ static inline bool DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, power); }
+ static inline bool DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, power); }
+ static inline bool DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, power); }
+ IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power);
+ IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, const char* format, float power);
+ static inline bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, float power) { return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, power); }
+ static inline bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, float power) { return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, power); }
+ static inline bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, float power) { return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, power); }
+ static inline bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, float power) { return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, power); }
+ // OBSOLETED in 1.77 (from June 2020)
+ 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 April 2019)
+ static inline void TreeAdvanceToLabelPos() { SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()); }
+ // OBSOLETED in 1.71 (from June 2019)
+ static inline void SetNextTreeNodeOpen(bool open, ImGuiCond cond = 0) { SetNextItemOpen(open, cond); }
+ // OBSOLETED in 1.70 (from May 2019)
+ static inline float GetContentRegionAvailWidth() { return GetContentRegionAvail().x; }
+ // OBSOLETED in 1.69 (from Mar 2019)
+ static inline ImDrawList* GetOverlayDrawList() { return GetForegroundDrawList(); }
+}
+
+// OBSOLETED in 1.82 (from Mars 2021): flags for AddRect(), AddRectFilled(), AddImageRounded(), PathRect()
+typedef ImDrawFlags ImDrawCornerFlags;
+enum ImDrawCornerFlags_
+{
+ ImDrawCornerFlags_None = ImDrawFlags_RoundCornersNone, // Was == 0 prior to 1.82, this is now == ImDrawFlags_RoundCornersNone which is != 0 and not implicit
+ ImDrawCornerFlags_TopLeft = ImDrawFlags_RoundCornersTopLeft, // Was == 0x01 (1 << 0) prior to 1.82. Order matches ImDrawFlags_NoRoundCorner* flag (we exploit this internally).
+ ImDrawCornerFlags_TopRight = ImDrawFlags_RoundCornersTopRight, // Was == 0x02 (1 << 1) prior to 1.82.
+ ImDrawCornerFlags_BotLeft = ImDrawFlags_RoundCornersBottomLeft, // Was == 0x04 (1 << 2) prior to 1.82.
+ ImDrawCornerFlags_BotRight = ImDrawFlags_RoundCornersBottomRight, // Was == 0x08 (1 << 3) prior to 1.82.
+ ImDrawCornerFlags_All = ImDrawFlags_RoundCornersAll, // Was == 0x0F prior to 1.82
+ ImDrawCornerFlags_Top = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_TopRight,
+ ImDrawCornerFlags_Bot = ImDrawCornerFlags_BotLeft | ImDrawCornerFlags_BotRight,
+ ImDrawCornerFlags_Left = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotLeft,
+ ImDrawCornerFlags_Right = ImDrawCornerFlags_TopRight | ImDrawCornerFlags_BotRight
+};
+
+#endif // #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+
+//-----------------------------------------------------------------------------
#if defined(__clang__)
#pragma clang diagnostic pop
diff --git a/imgui/imgui_demo.cpp b/imgui/imgui_demo.cpp
index 96cf24d1..0eeda824 100644
--- a/imgui/imgui_demo.cpp
+++ b/imgui/imgui_demo.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.81
+// dear imgui, v1.82
// (demo code)
// Help:
@@ -136,6 +136,16 @@ Index of this file:
#define vsnprintf _vsnprintf
#endif
+// Format specifiers, printing 64-bit hasn't been decently standardized...
+// In a real application you should be using PRId64 and PRIu64 from <inttypes.h> (non-windows) and on Windows define them yourself.
+#ifdef _MSC_VER
+#define IM_PRId64 "I64d"
+#define IM_PRIu64 "I64u"
+#else
+#define IM_PRId64 "lld"
+#define IM_PRIu64 "llu"
+#endif
+
// Helpers macros
// We normally try to not use many helpers in imgui_demo.cpp in order to make code easier to copy and paste,
// but making an exception here as those are largely simplifying code...
@@ -967,7 +977,7 @@ static void ShowDemoWindowWidgets()
// so you can safely copy & paste garbled characters into another application.
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. "
+ "Call io.Fonts->AddFontFromFileTTF() manually to load extra character ranges. "
"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)");
@@ -1972,12 +1982,12 @@ static void ShowDemoWindowWidgets()
ImGui::SliderScalar("slider u32 low", ImGuiDataType_U32, &u32_v, &u32_zero, &u32_fifty,"%u");
ImGui::SliderScalar("slider u32 high", ImGuiDataType_U32, &u32_v, &u32_hi_a, &u32_hi_b, "%u");
ImGui::SliderScalar("slider u32 full", ImGuiDataType_U32, &u32_v, &u32_min, &u32_max, "%u");
- ImGui::SliderScalar("slider s64 low", ImGuiDataType_S64, &s64_v, &s64_zero, &s64_fifty,"%I64d");
- ImGui::SliderScalar("slider s64 high", ImGuiDataType_S64, &s64_v, &s64_hi_a, &s64_hi_b, "%I64d");
- ImGui::SliderScalar("slider s64 full", ImGuiDataType_S64, &s64_v, &s64_min, &s64_max, "%I64d");
- ImGui::SliderScalar("slider u64 low", ImGuiDataType_U64, &u64_v, &u64_zero, &u64_fifty,"%I64u ms");
- ImGui::SliderScalar("slider u64 high", ImGuiDataType_U64, &u64_v, &u64_hi_a, &u64_hi_b, "%I64u ms");
- ImGui::SliderScalar("slider u64 full", ImGuiDataType_U64, &u64_v, &u64_min, &u64_max, "%I64u ms");
+ ImGui::SliderScalar("slider s64 low", ImGuiDataType_S64, &s64_v, &s64_zero, &s64_fifty,"%" IM_PRId64);
+ ImGui::SliderScalar("slider s64 high", ImGuiDataType_S64, &s64_v, &s64_hi_a, &s64_hi_b, "%" IM_PRId64);
+ ImGui::SliderScalar("slider s64 full", ImGuiDataType_S64, &s64_v, &s64_min, &s64_max, "%" IM_PRId64);
+ ImGui::SliderScalar("slider u64 low", ImGuiDataType_U64, &u64_v, &u64_zero, &u64_fifty,"%" IM_PRIu64 " ms");
+ ImGui::SliderScalar("slider u64 high", ImGuiDataType_U64, &u64_v, &u64_hi_a, &u64_hi_b, "%" IM_PRIu64 " ms");
+ ImGui::SliderScalar("slider u64 full", ImGuiDataType_U64, &u64_v, &u64_min, &u64_max, "%" IM_PRIu64 " ms");
ImGui::SliderScalar("slider float low", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one);
ImGui::SliderScalar("slider float low log", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one, "%.10f", ImGuiSliderFlags_Logarithmic);
ImGui::SliderScalar("slider float high", ImGuiDataType_Float, &f32_v, &f32_lo_a, &f32_hi_a, "%e");
@@ -1986,12 +1996,12 @@ static void ShowDemoWindowWidgets()
ImGui::SliderScalar("slider double high", ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams");
ImGui::Text("Sliders (reverse)");
- ImGui::SliderScalar("slider s8 reverse", ImGuiDataType_S8, &s8_v, &s8_max, &s8_min, "%d");
- ImGui::SliderScalar("slider u8 reverse", ImGuiDataType_U8, &u8_v, &u8_max, &u8_min, "%u");
+ ImGui::SliderScalar("slider s8 reverse", ImGuiDataType_S8, &s8_v, &s8_max, &s8_min, "%d");
+ ImGui::SliderScalar("slider u8 reverse", ImGuiDataType_U8, &u8_v, &u8_max, &u8_min, "%u");
ImGui::SliderScalar("slider s32 reverse", ImGuiDataType_S32, &s32_v, &s32_fifty, &s32_zero, "%d");
ImGui::SliderScalar("slider u32 reverse", ImGuiDataType_U32, &u32_v, &u32_fifty, &u32_zero, "%u");
- ImGui::SliderScalar("slider s64 reverse", ImGuiDataType_S64, &s64_v, &s64_fifty, &s64_zero, "%I64d");
- ImGui::SliderScalar("slider u64 reverse", ImGuiDataType_U64, &u64_v, &u64_fifty, &u64_zero, "%I64u ms");
+ ImGui::SliderScalar("slider s64 reverse", ImGuiDataType_S64, &s64_v, &s64_fifty, &s64_zero, "%" IM_PRId64);
+ ImGui::SliderScalar("slider u64 reverse", ImGuiDataType_U64, &u64_v, &u64_fifty, &u64_zero, "%" IM_PRIu64 " ms");
static bool inputs_step = true;
ImGui::Text("Inputs");
@@ -4913,6 +4923,9 @@ static void ShowDemoWindowTables()
ImGui::TreePop();
}
+ // In this example we'll expose most table flags and settings.
+ // For specific flags and settings refer to the corresponding section for more detailed explanation.
+ // This section is mostly useful to experiment with combining certain flags or settings with each others.
//ImGui::SetNextItemOpen(true, ImGuiCond_Once); // [DEBUG]
if (open_action != -1)
ImGui::SetNextItemOpen(open_action != 0);
@@ -5051,7 +5064,7 @@ static void ShowDemoWindowTables()
ImGui::TreePop();
}
- // Recreate/reset item list if we changed the number of items
+ // Update item list if we changed the number of items
static ImVector<MyItem> items;
static ImVector<int> selection;
static bool items_need_sort = false;
@@ -5073,6 +5086,7 @@ static void ShowDemoWindowTables()
ImVec2 table_scroll_cur, table_scroll_max; // For debug display
const ImDrawList* table_draw_list = NULL; // "
+ // Submit table
const float inner_width_to_use = (flags & ImGuiTableFlags_ScrollX) ? inner_width_with_scroll : 0.0f;
if (ImGui::BeginTable("table_advanced", 6, flags, outer_size_enabled ? outer_size_value : ImVec2(0, 0), inner_width_to_use))
{
@@ -5131,9 +5145,9 @@ static void ShowDemoWindowTables()
const bool item_is_selected = selection.contains(item->ID);
ImGui::PushID(item->ID);
ImGui::TableNextRow(ImGuiTableRowFlags_None, row_min_height);
- ImGui::TableNextColumn();
// For the demo purpose we can select among different type of items submitted in the first column
+ ImGui::TableSetColumnIndex(0);
char label[32];
sprintf(label, "%04d", item->ID);
if (contents_type == CT_Text)
@@ -5164,14 +5178,14 @@ static void ShowDemoWindowTables()
}
}
- if (ImGui::TableNextColumn())
+ if (ImGui::TableSetColumnIndex(1))
ImGui::TextUnformatted(item->Name);
// Here we demonstrate marking our data set as needing to be sorted again if we modified a quantity,
// and we are currently sorting on the column showing the Quantity.
// To avoid triggering a sort while holding the button, we only trigger it when the button has been released.
// You will probably need a more advanced system in your code if you want to automatically sort when a specific entry changes.
- if (ImGui::TableNextColumn())
+ if (ImGui::TableSetColumnIndex(2))
{
if (ImGui::SmallButton("Chop")) { item->Quantity += 1; }
if (sorts_specs_using_quantity && ImGui::IsItemDeactivated()) { items_need_sort = true; }
@@ -5180,16 +5194,16 @@ static void ShowDemoWindowTables()
if (sorts_specs_using_quantity && ImGui::IsItemDeactivated()) { items_need_sort = true; }
}
- if (ImGui::TableNextColumn())
+ if (ImGui::TableSetColumnIndex(3))
ImGui::Text("%d", item->Quantity);
- ImGui::TableNextColumn();
+ ImGui::TableSetColumnIndex(4);
if (show_wrapped_text)
ImGui::TextWrapped("Lorem ipsum dolor sit amet");
else
ImGui::Text("Lorem ipsum dolor sit amet");
- if (ImGui::TableNextColumn())
+ if (ImGui::TableSetColumnIndex(5))
ImGui::Text("1234");
ImGui::PopID();
@@ -5456,29 +5470,34 @@ static void ShowDemoWindowMisc()
ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos);
ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible);
- // Display Keyboard/Mouse state
- if (ImGui::TreeNode("Keyboard, Mouse & Navigation State"))
+ // Display Mouse state
+ if (ImGui::TreeNode("Mouse State"))
{
if (ImGui::IsMousePosValid())
ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
else
ImGui::Text("Mouse pos: <INVALID>");
ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
- ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
- ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
- ImGui::Text("Mouse dblclick:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
- ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
+ ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDown(i)) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
+ ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
+ ImGui::Text("Mouse dblclick:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)){ ImGui::SameLine(); ImGui::Text("b%d", i); }
+ ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
+ ImGui::Text("Pen Pressure: %.1f", io.PenPressure); // Note: currently unused
+ ImGui::TreePop();
+ }
- ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (0x%X) (%.02f secs)", i, i, io.KeysDownDuration[i]); }
- ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); }
- ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); }
+ // Display Keyboard/Mouse state
+ if (ImGui::TreeNode("Keyboard & Navigation State"))
+ {
+ ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyDown(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X) (%.02f secs)", i, i, io.KeysDownDuration[i]); }
+ ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); }
+ ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); }
ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
- ImGui::Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine(); ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.
+ ImGui::Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine(); ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.
- ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputs[i]); }
+ ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f (%.02f secs)", i, io.NavInputs[i], io.NavInputsDownDuration[i]); }
ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); }
- ImGui::Text("NavInputs duration:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputsDownDuration[i]); }
ImGui::Button("Hovering me sets the\nkeyboard capture flag");
if (ImGui::IsItemHovered())
@@ -5487,7 +5506,6 @@ static void ShowDemoWindowMisc()
ImGui::Button("Holding me clears the\nthe keyboard capture flag");
if (ImGui::IsItemActive())
ImGui::CaptureKeyboardFromApp(false);
-
ImGui::TreePop();
}
@@ -6108,22 +6126,42 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
// When editing the "Circle Segment Max Error" value, draw a preview of its effect on auto-tessellated circles.
- ImGui::DragFloat("Circle Segment Max Error", &style.CircleSegmentMaxError, 0.01f, 0.10f, 10.0f, "%.2f");
+ ImGui::DragFloat("Circle Tessellation Max Error", &style.CircleTessellationMaxError , 0.005f, 0.10f, 5.0f, "%.2f", ImGuiSliderFlags_AlwaysClamp);
if (ImGui::IsItemActive())
{
ImGui::SetNextWindowPos(ImGui::GetCursorScreenPos());
ImGui::BeginTooltip();
- ImVec2 p = ImGui::GetCursorScreenPos();
+ ImGui::TextUnformatted("(R = radius, N = number of segments)");
+ ImGui::Spacing();
ImDrawList* draw_list = ImGui::GetWindowDrawList();
- float RAD_MIN = 10.0f, RAD_MAX = 80.0f;
- float off_x = 10.0f;
- for (int n = 0; n < 7; n++)
+ const float min_widget_width = ImGui::CalcTextSize("N: MMM\nR: MMM").x;
+ for (int n = 0; n < 8; n++)
{
- const float rad = RAD_MIN + (RAD_MAX - RAD_MIN) * (float)n / (7.0f - 1.0f);
- draw_list->AddCircle(ImVec2(p.x + off_x + rad, p.y + RAD_MAX), rad, ImGui::GetColorU32(ImGuiCol_Text), 0);
- off_x += 10.0f + rad * 2.0f;
+ const float RAD_MIN = 5.0f;
+ const float RAD_MAX = 70.0f;
+ const float rad = RAD_MIN + (RAD_MAX - RAD_MIN) * (float)n / (8.0f - 1.0f);
+
+ ImGui::BeginGroup();
+
+ ImGui::Text("R: %.f\nN: %d", rad, draw_list->_CalcCircleAutoSegmentCount(rad));
+
+ const float canvas_width = IM_MAX(min_widget_width, rad * 2.0f);
+ const float offset_x = floorf(canvas_width * 0.5f);
+ const float offset_y = floorf(RAD_MAX);
+
+ const ImVec2 p1 = ImGui::GetCursorScreenPos();
+ draw_list->AddCircle(ImVec2(p1.x + offset_x, p1.y + offset_y), rad, ImGui::GetColorU32(ImGuiCol_Text));
+ ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
+
+ /*
+ const ImVec2 p2 = ImGui::GetCursorScreenPos();
+ draw_list->AddCircleFilled(ImVec2(p2.x + offset_x, p2.y + offset_y), rad, ImGui::GetColorU32(ImGuiCol_Text));
+ ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
+ */
+
+ ImGui::EndGroup();
+ ImGui::SameLine();
}
- ImGui::Dummy(ImVec2(off_x, RAD_MAX * 2.0f));
ImGui::EndTooltip();
}
ImGui::SameLine();
@@ -7248,9 +7286,7 @@ static void ShowExampleAppCustomRendering(bool* p_open)
const ImVec2 p = ImGui::GetCursorScreenPos();
const ImU32 col = ImColor(colf);
const float spacing = 10.0f;
- const ImDrawCornerFlags corners_none = 0;
- const ImDrawCornerFlags corners_all = ImDrawCornerFlags_All;
- const ImDrawCornerFlags corners_tl_br = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotRight;
+ const ImDrawFlags corners_tl_br = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBottomRight;
const float rounding = sz / 5.0f;
const int circle_segments = circle_segments_override ? circle_segments_override_v : 0;
const int curve_segments = curve_segments_override ? curve_segments_override_v : 0;
@@ -7262,8 +7298,8 @@ static void ShowExampleAppCustomRendering(bool* p_open)
float th = (n == 0) ? 1.0f : thickness;
draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // N-gon
draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th); x += sz + spacing; // Circle
- draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, corners_none, th); x += sz + spacing; // Square
- draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_all, th); x += sz + spacing; // Square with all rounded corners
+ draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, ImDrawFlags_None, th); x += sz + spacing; // Square
+ draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, ImDrawFlags_None, th); x += sz + spacing; // Square with all rounded corners
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners
draw_list->AddTriangle(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col, th);x += sz + spacing; // Triangle
//draw_list->AddTriangle(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col, th);x+= sz*0.4f + spacing; // Thin triangle
diff --git a/imgui/imgui_draw.cpp b/imgui/imgui_draw.cpp
index f08c3620..138abc1e 100644
--- a/imgui/imgui_draw.cpp
+++ b/imgui/imgui_draw.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.81
+// dear imgui, v1.82
// (drawing and font code)
/*
@@ -380,19 +380,22 @@ ImDrawListSharedData::ImDrawListSharedData()
const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(ArcFastVtx);
ArcFastVtx[i] = ImVec2(ImCos(a), ImSin(a));
}
+ ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError);
}
-void ImDrawListSharedData::SetCircleSegmentMaxError(float max_error)
+void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error)
{
if (CircleSegmentMaxError == max_error)
return;
+
+ IM_ASSERT(max_error > 0.0f);
CircleSegmentMaxError = max_error;
for (int i = 0; i < IM_ARRAYSIZE(CircleSegmentCounts); i++)
{
const float radius = (float)i;
- const int segment_count = (i > 0) ? IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError) : 0;
- CircleSegmentCounts[i] = (ImU8)ImMin(segment_count, 255);
+ CircleSegmentCounts[i] = (ImU8)((i > 0) ? IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError) : 0);
}
+ ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError);
}
// Initialize before use in a new frame. We always have a command ready in the buffer.
@@ -549,6 +552,16 @@ void ImDrawList::_OnChangedVtxOffset()
curr_cmd->VtxOffset = _CmdHeader.VtxOffset;
}
+int ImDrawList::_CalcCircleAutoSegmentCount(float radius) const
+{
+ // Automatic segment count
+ const int radius_idx = (int)(radius + 0.999999f); // ceil to never reduce accuracy
+ if (radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts))
+ return _Data->CircleSegmentCounts[radius_idx]; // Use cached value
+ else
+ return IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError);
+}
+
// 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)
{
@@ -686,11 +699,12 @@ void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, c
// TODO: Thickness anti-aliased lines cap are missing their AA fringe.
// We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds.
-void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, bool closed, float thickness)
+void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, ImDrawFlags flags, float thickness)
{
if (points_count < 2)
return;
+ const bool closed = (flags & ImDrawFlags_Closed) != 0;
const ImVec2 opaque_uv = _Data->TexUvWhitePixel;
const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw
const bool thick_line = (thickness > _FringeScale);
@@ -1022,33 +1036,88 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun
}
}
-void ImDrawList::PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12)
+void ImDrawList::_PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step)
{
- if (radius == 0.0f)
+ if (radius <= 0.0f)
{
_Path.push_back(center);
return;
}
- IM_ASSERT(a_min_of_12 <= a_max_of_12);
+ IM_ASSERT(a_min_sample <= a_max_sample);
- // For legacy reason the PathArcToFast() always takes angles where 2*PI is represented by 12,
- // but it is possible to set IM_DRAWLIST_ARCFAST_TESSELATION_MULTIPLIER to a higher value. This should compile to a no-op otherwise.
-#if IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER != 1
- a_min_of_12 *= IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER;
- a_max_of_12 *= IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER;
-#endif
+ // Calculate arc auto segment step size
+ if (a_step <= 0)
+ a_step = IM_DRAWLIST_ARCFAST_SAMPLE_MAX / _CalcCircleAutoSegmentCount(radius);
+
+ // Make sure we never do steps larger than one quarter of the circle
+ a_step = ImClamp(a_step, 1, IM_DRAWLIST_ARCFAST_TABLE_SIZE / 4);
- _Path.reserve(_Path.Size + (a_max_of_12 - a_min_of_12 + 1));
- for (int a = a_min_of_12; a <= a_max_of_12; a++)
+ // Normalize a_min_sample to always start lie in [0..IM_DRAWLIST_ARCFAST_SAMPLE_MAX] range.
+ if (a_min_sample < 0)
{
- const ImVec2& c = _Data->ArcFastVtx[a % IM_ARRAYSIZE(_Data->ArcFastVtx)];
- _Path.push_back(ImVec2(center.x + c.x * radius, center.y + c.y * radius));
+ int normalized_sample = a_min_sample % IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+ if (normalized_sample < 0)
+ normalized_sample += IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+ a_max_sample += (normalized_sample - a_min_sample);
+ a_min_sample = normalized_sample;
}
+
+ const int sample_range = a_max_sample - a_min_sample;
+ const int a_next_step = a_step;
+
+ int samples = sample_range + 1;
+ bool extra_max_sample = false;
+ if (a_step > 1)
+ {
+ samples = sample_range / a_step + 1;
+ const int overstep = sample_range % a_step;
+
+ if (overstep > 0)
+ {
+ extra_max_sample = true;
+ samples++;
+
+ // When we have overstep to avoid awkwardly looking one long line and one tiny one at the end,
+ // distribute first step range evenly between them by reducing first step size.
+ if (sample_range > 0)
+ a_step -= (a_step - overstep) / 2;
+ }
+ }
+
+ _Path.resize(_Path.Size + samples);
+ ImVec2* out_ptr = _Path.Data + (_Path.Size - samples);
+
+ int sample_index = a_min_sample;
+ for (int a = a_min_sample; a <= a_max_sample; a += a_step, sample_index += a_step, a_step = a_next_step)
+ {
+ // a_step is clamped to IM_DRAWLIST_ARCFAST_SAMPLE_MAX, so we have guaranteed that it will not wrap over range twice or more
+ if (sample_index >= IM_DRAWLIST_ARCFAST_SAMPLE_MAX)
+ sample_index -= IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+
+ const ImVec2 s = _Data->ArcFastVtx[sample_index];
+ out_ptr->x = center.x + s.x * radius;
+ out_ptr->y = center.y + s.y * radius;
+ out_ptr++;
+ }
+
+ if (extra_max_sample)
+ {
+ int normalized_max_sample = a_max_sample % IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+ if (normalized_max_sample < 0)
+ normalized_max_sample += IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+
+ const ImVec2 s = _Data->ArcFastVtx[normalized_max_sample];
+ out_ptr->x = center.x + s.x * radius;
+ out_ptr->y = center.y + s.y * radius;
+ out_ptr++;
+ }
+
+ IM_ASSERT_PARANOID(_Path.Data + _Path.Size == out_ptr);
}
-void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments)
+void ImDrawList::_PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments)
{
- if (radius == 0.0f)
+ if (radius <= 0.0f)
{
_Path.push_back(center);
return;
@@ -1065,6 +1134,64 @@ void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, floa
}
}
+// 0: East, 3: South, 6: West, 9: North, 12: East
+void ImDrawList::PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12)
+{
+ if (radius <= 0.0f)
+ {
+ _Path.push_back(center);
+ return;
+ }
+ IM_ASSERT(a_min_of_12 <= a_max_of_12);
+ _PathArcToFastEx(center, radius, a_min_of_12 * IM_DRAWLIST_ARCFAST_SAMPLE_MAX / 12, a_max_of_12 * IM_DRAWLIST_ARCFAST_SAMPLE_MAX / 12, 0);
+}
+
+void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments)
+{
+ if (radius <= 0.0f)
+ {
+ _Path.push_back(center);
+ return;
+ }
+ IM_ASSERT(a_min <= a_max);
+
+ if (num_segments > 0)
+ {
+ _PathArcToN(center, radius, a_min, a_max, num_segments);
+ return;
+ }
+
+ // Automatic segment count
+ if (radius <= _Data->ArcFastRadiusCutoff)
+ {
+ // We are going to use precomputed values for mid samples.
+ // Determine first and last sample in lookup table that belong to the arc.
+ const int a_min_sample = (int)ImCeil(IM_DRAWLIST_ARCFAST_SAMPLE_MAX * a_min / (IM_PI * 2.0f));
+ const int a_max_sample = (int)( IM_DRAWLIST_ARCFAST_SAMPLE_MAX * a_max / (IM_PI * 2.0f));
+ const int a_mid_samples = ImMax(a_max_sample - a_min_sample, 0);
+
+ const float a_min_segment_angle = a_min_sample * IM_PI * 2.0f / IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+ const float a_max_segment_angle = a_max_sample * IM_PI * 2.0f / IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+ const bool a_emit_start = (a_min_segment_angle - a_min) > 0.0f;
+ const bool a_emit_end = (a_max - a_max_segment_angle) > 0.0f;
+
+ _Path.reserve(_Path.Size + (a_mid_samples + 1 + (a_emit_start ? 1 : 0) + (a_emit_end ? 1 : 0)));
+ if (a_emit_start)
+ _Path.push_back(ImVec2(center.x + ImCos(a_min) * radius, center.y + ImSin(a_min) * radius));
+ if (a_max_sample >= a_min_sample)
+ _PathArcToFastEx(center, radius, a_min_sample, a_max_sample, 0);
+ if (a_emit_end)
+ _Path.push_back(ImVec2(center.x + ImCos(a_max) * radius, center.y + ImSin(a_max) * radius));
+ }
+ else
+ {
+ const float arc_length = a_max - a_min;
+ const int circle_segment_count = _CalcCircleAutoSegmentCount(radius);
+ const int arc_segment_count = ImMax((int)ImCeil(circle_segment_count * arc_length / (IM_PI * 2.0f)), (int)(2.0f * IM_PI / arc_length));
+ _PathArcToN(center, radius, a_min, a_max, arc_segment_count);
+ }
+}
+
ImVec2 ImBezierCubicCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, float t)
{
float u = 1.0f - t;
@@ -1158,12 +1285,47 @@ void ImDrawList::PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3,
}
}
-void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDrawCornerFlags rounding_corners)
+IM_STATIC_ASSERT(ImDrawFlags_RoundCornersTopLeft == (1 << 4));
+static inline ImDrawFlags FixRectCornerFlags(ImDrawFlags flags)
+{
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ // Legacy Support for hard coded ~0 (used to be a suggested equivalent to ImDrawCornerFlags_All)
+ // ~0 --> ImDrawFlags_RoundCornersAll or 0
+ if (flags == ~0)
+ return ImDrawFlags_RoundCornersAll;
+
+ // Legacy Support for hard coded 0x01 to 0x0F (matching 15 out of 16 old flags combinations)
+ // 0x01 --> ImDrawFlags_RoundCornersTopLeft (VALUE 0x01 OVERLAPS ImDrawFlags_Closed but ImDrawFlags_Closed is never valid in this path!)
+ // 0x02 --> ImDrawFlags_RoundCornersTopRight
+ // 0x03 --> ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight
+ // 0x04 --> ImDrawFlags_RoundCornersBotLeft
+ // 0x05 --> ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBotLeft
+ // ...
+ // 0x0F --> ImDrawFlags_RoundCornersAll or 0
+ // (See all values in ImDrawCornerFlags_)
+ if (flags >= 0x01 && flags <= 0x0F)
+ return (flags << 4);
+
+ // We cannot support hard coded 0x00 with 'float rounding > 0.0f' --> replace with ImDrawFlags_RoundCornersNone or use 'float rounding = 0.0f'
+#endif
+
+ // If this triggers, please update your code replacing hardcoded values with new ImDrawFlags_RoundCorners* values.
+ // Note that ImDrawFlags_Closed (== 0x01) is an invalid flag for AddRect(), AddRectFilled(), PathRect() etc...
+ IM_ASSERT((flags & 0x0F) == 0 && "Misuse of legacy hardcoded ImDrawCornerFlags values!");
+
+ if ((flags & ImDrawFlags_RoundCornersMask_) == 0)
+ flags |= ImDrawFlags_RoundCornersAll;
+
+ return flags;
+}
+
+void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDrawFlags flags)
{
- rounding = ImMin(rounding, ImFabs(b.x - a.x) * ( ((rounding_corners & ImDrawCornerFlags_Top) == ImDrawCornerFlags_Top) || ((rounding_corners & ImDrawCornerFlags_Bot) == ImDrawCornerFlags_Bot) ? 0.5f : 1.0f ) - 1.0f);
- rounding = ImMin(rounding, ImFabs(b.y - a.y) * ( ((rounding_corners & ImDrawCornerFlags_Left) == ImDrawCornerFlags_Left) || ((rounding_corners & ImDrawCornerFlags_Right) == ImDrawCornerFlags_Right) ? 0.5f : 1.0f ) - 1.0f);
+ flags = FixRectCornerFlags(flags);
+ rounding = ImMin(rounding, ImFabs(b.x - a.x) * ( ((flags & ImDrawFlags_RoundCornersTop) == ImDrawFlags_RoundCornersTop) || ((flags & ImDrawFlags_RoundCornersBottom) == ImDrawFlags_RoundCornersBottom) ? 0.5f : 1.0f ) - 1.0f);
+ rounding = ImMin(rounding, ImFabs(b.y - a.y) * ( ((flags & ImDrawFlags_RoundCornersLeft) == ImDrawFlags_RoundCornersLeft) || ((flags & ImDrawFlags_RoundCornersRight) == ImDrawFlags_RoundCornersRight) ? 0.5f : 1.0f ) - 1.0f);
- if (rounding <= 0.0f || rounding_corners == 0)
+ if (rounding <= 0.0f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone)
{
PathLineTo(a);
PathLineTo(ImVec2(b.x, a.y));
@@ -1172,10 +1334,10 @@ void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDr
}
else
{
- const float rounding_tl = (rounding_corners & ImDrawCornerFlags_TopLeft) ? rounding : 0.0f;
- const float rounding_tr = (rounding_corners & ImDrawCornerFlags_TopRight) ? rounding : 0.0f;
- const float rounding_br = (rounding_corners & ImDrawCornerFlags_BotRight) ? rounding : 0.0f;
- const float rounding_bl = (rounding_corners & ImDrawCornerFlags_BotLeft) ? rounding : 0.0f;
+ const float rounding_tl = (flags & ImDrawFlags_RoundCornersTopLeft) ? rounding : 0.0f;
+ const float rounding_tr = (flags & ImDrawFlags_RoundCornersTopRight) ? rounding : 0.0f;
+ const float rounding_br = (flags & ImDrawFlags_RoundCornersBottomRight) ? rounding : 0.0f;
+ const float rounding_bl = (flags & ImDrawFlags_RoundCornersBottomLeft) ? rounding : 0.0f;
PathArcToFast(ImVec2(a.x + rounding_tl, a.y + rounding_tl), rounding_tl, 6, 9);
PathArcToFast(ImVec2(b.x - rounding_tr, a.y + rounding_tr), rounding_tr, 9, 12);
PathArcToFast(ImVec2(b.x - rounding_br, b.y - rounding_br), rounding_br, 0, 3);
@@ -1189,35 +1351,35 @@ void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float th
return;
PathLineTo(p1 + ImVec2(0.5f, 0.5f));
PathLineTo(p2 + ImVec2(0.5f, 0.5f));
- PathStroke(col, false, thickness);
+ PathStroke(col, 0, thickness);
}
// p_min = upper-left, p_max = lower-right
// Note we don't render 1 pixels sized rectangles properly.
-void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners, float thickness)
+void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags, float thickness)
{
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, flags);
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.
- PathStroke(col, true, thickness);
+ PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.49f, 0.49f), rounding, flags); // Better looking lower-right corner and rounded non-AA shapes.
+ PathStroke(col, ImDrawFlags_Closed, thickness);
}
-void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners)
+void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags)
{
if ((col & IM_COL32_A_MASK) == 0)
return;
- if (rounding > 0.0f)
+ if (rounding <= 0.0f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone)
{
- PathRect(p_min, p_max, rounding, rounding_corners);
- PathFillConvex(col);
+ PrimReserve(6, 4);
+ PrimRect(p_min, p_max, col);
}
else
{
- PrimReserve(6, 4);
- PrimRect(p_min, p_max, col);
+ PathRect(p_min, p_max, rounding, flags);
+ PathFillConvex(col);
}
}
@@ -1246,7 +1408,7 @@ void ImDrawList::AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, c
PathLineTo(p2);
PathLineTo(p3);
PathLineTo(p4);
- PathStroke(col, true, thickness);
+ PathStroke(col, ImDrawFlags_Closed, thickness);
}
void ImDrawList::AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col)
@@ -1269,7 +1431,7 @@ void ImDrawList::AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p
PathLineTo(p1);
PathLineTo(p2);
PathLineTo(p3);
- PathStroke(col, true, thickness);
+ PathStroke(col, ImDrawFlags_Closed, thickness);
}
void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col)
@@ -1292,11 +1454,7 @@ void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int nu
if (num_segments <= 0)
{
// Automatic segment count
- const int radius_idx = (int)radius;
- if (radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts))
- num_segments = _Data->CircleSegmentCounts[radius_idx]; // Use cached value
- else
- num_segments = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError);
+ num_segments = _CalcCircleAutoSegmentCount(radius);
}
else
{
@@ -1310,7 +1468,7 @@ void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int nu
PathArcToFast(center, radius - 0.5f, 0, 12 - 1);
else
PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1);
- PathStroke(col, true, thickness);
+ PathStroke(col, ImDrawFlags_Closed, thickness);
}
void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments)
@@ -1322,11 +1480,7 @@ void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col,
if (num_segments <= 0)
{
// Automatic segment count
- const int radius_idx = (int)radius;
- if (radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts))
- num_segments = _Data->CircleSegmentCounts[radius_idx]; // Use cached value
- else
- num_segments = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError);
+ num_segments = _CalcCircleAutoSegmentCount(radius);
}
else
{
@@ -1352,7 +1506,7 @@ void ImDrawList::AddNgon(const ImVec2& center, float radius, ImU32 col, int num_
// Because we are filling a closed shape we remove 1 from the count of segments/points
const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments;
PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1);
- PathStroke(col, true, thickness);
+ PathStroke(col, ImDrawFlags_Closed, thickness);
}
// Guaranteed to honor 'num_segments'
@@ -1375,7 +1529,7 @@ void ImDrawList::AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2
PathLineTo(p1);
PathBezierCubicCurveTo(p2, p3, p4, num_segments);
- PathStroke(col, false, thickness);
+ PathStroke(col, 0, thickness);
}
// Quadratic Bezier takes 3 controls points
@@ -1386,7 +1540,7 @@ void ImDrawList::AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const Im
PathLineTo(p1);
PathBezierQuadraticCurveTo(p2, p3, num_segments);
- PathStroke(col, false, thickness);
+ PathStroke(col, 0, thickness);
}
void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
@@ -1455,23 +1609,24 @@ void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, con
PopTextureID();
}
-void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners)
+void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags)
{
if ((col & IM_COL32_A_MASK) == 0)
return;
- if (rounding <= 0.0f || (rounding_corners & ImDrawCornerFlags_All) == 0)
+ flags = FixRectCornerFlags(flags);
+ if (rounding <= 0.0f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone)
{
AddImage(user_texture_id, p_min, p_max, uv_min, uv_max, col);
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);
int vert_start_idx = VtxBuffer.Size;
- PathRect(p_min, p_max, rounding, rounding_corners);
+ PathRect(p_min, p_max, rounding, flags);
PathFillConvex(col);
int vert_end_idx = VtxBuffer.Size;
ImGui::ShadeVertsLinearUV(this, vert_start_idx, vert_end_idx, p_min, p_max, uv_min, uv_max, true);
@@ -1829,6 +1984,7 @@ void ImFontAtlas::ClearTexData()
IM_FREE(TexPixelsRGBA32);
TexPixelsAlpha8 = NULL;
TexPixelsRGBA32 = NULL;
+ TexPixelsUseColors = false;
}
void ImFontAtlas::ClearFonts()
@@ -3590,7 +3746,7 @@ void ImGui::RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float
draw_list->PathLineTo(ImVec2(bx - third, by - third));
draw_list->PathLineTo(ImVec2(bx, by));
draw_list->PathLineTo(ImVec2(bx + third * 2.0f, by - third * 2.0f));
- draw_list->PathStroke(col, false, thickness);
+ draw_list->PathStroke(col, 0, thickness);
}
void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow)
@@ -3710,27 +3866,29 @@ void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect
const bool fill_R = (inner.Max.x < outer.Max.x);
const bool fill_U = (inner.Min.y > outer.Min.y);
const bool fill_D = (inner.Max.y < outer.Max.y);
- if (fill_L) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Min.y), ImVec2(inner.Min.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawCornerFlags_TopLeft) | (fill_D ? 0 : ImDrawCornerFlags_BotLeft));
- if (fill_R) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Min.y), ImVec2(outer.Max.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawCornerFlags_TopRight) | (fill_D ? 0 : ImDrawCornerFlags_BotRight));
- if (fill_U) draw_list->AddRectFilled(ImVec2(inner.Min.x, outer.Min.y), ImVec2(inner.Max.x, inner.Min.y), col, rounding, (fill_L ? 0 : ImDrawCornerFlags_TopLeft) | (fill_R ? 0 : ImDrawCornerFlags_TopRight));
- if (fill_D) draw_list->AddRectFilled(ImVec2(inner.Min.x, inner.Max.y), ImVec2(inner.Max.x, outer.Max.y), col, rounding, (fill_L ? 0 : ImDrawCornerFlags_BotLeft) | (fill_R ? 0 : ImDrawCornerFlags_BotRight));
- if (fill_L && fill_U) draw_list->AddRectFilled(ImVec2(outer.Min.x, outer.Min.y), ImVec2(inner.Min.x, inner.Min.y), col, rounding, ImDrawCornerFlags_TopLeft);
- if (fill_R && fill_U) draw_list->AddRectFilled(ImVec2(inner.Max.x, outer.Min.y), ImVec2(outer.Max.x, inner.Min.y), col, rounding, ImDrawCornerFlags_TopRight);
- if (fill_L && fill_D) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Max.y), ImVec2(inner.Min.x, outer.Max.y), col, rounding, ImDrawCornerFlags_BotLeft);
- if (fill_R && fill_D) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Max.y), ImVec2(outer.Max.x, outer.Max.y), col, rounding, ImDrawCornerFlags_BotRight);
+ if (fill_L) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Min.y), ImVec2(inner.Min.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomLeft));
+ if (fill_R) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Min.y), ImVec2(outer.Max.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawFlags_RoundCornersTopRight) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomRight));
+ if (fill_U) draw_list->AddRectFilled(ImVec2(inner.Min.x, outer.Min.y), ImVec2(inner.Max.x, inner.Min.y), col, rounding, (fill_L ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersTopRight));
+ if (fill_D) draw_list->AddRectFilled(ImVec2(inner.Min.x, inner.Max.y), ImVec2(inner.Max.x, outer.Max.y), col, rounding, (fill_L ? 0 : ImDrawFlags_RoundCornersBottomLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersBottomRight));
+ if (fill_L && fill_U) draw_list->AddRectFilled(ImVec2(outer.Min.x, outer.Min.y), ImVec2(inner.Min.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersTopLeft);
+ if (fill_R && fill_U) draw_list->AddRectFilled(ImVec2(inner.Max.x, outer.Min.y), ImVec2(outer.Max.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersTopRight);
+ if (fill_L && fill_D) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Max.y), ImVec2(inner.Min.x, outer.Max.y), col, rounding, ImDrawFlags_RoundCornersBottomLeft);
+ if (fill_R && fill_D) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Max.y), ImVec2(outer.Max.x, outer.Max.y), col, rounding, ImDrawFlags_RoundCornersBottomRight);
}
// Helper for ColorPicker4()
// NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that.
// Spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding altogether.
// FIXME: uses ImGui::GetColorU32
-void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, int rounding_corners_flags)
+void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, ImDrawFlags flags)
{
+ if ((flags & ImDrawFlags_RoundCornersMask_) == 0)
+ flags = ImDrawFlags_RoundCornersDefault_;
if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF)
{
- ImU32 col_bg1 = ImGui::GetColorU32(ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col));
- ImU32 col_bg2 = ImGui::GetColorU32(ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col));
- draw_list->AddRectFilled(p_min, p_max, col_bg1, rounding, rounding_corners_flags);
+ ImU32 col_bg1 = GetColorU32(ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col));
+ ImU32 col_bg2 = GetColorU32(ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col));
+ draw_list->AddRectFilled(p_min, p_max, col_bg1, rounding, flags);
int yi = 0;
for (float y = p_min.y + grid_off.y; y < p_max.y; y += grid_step, yi++)
@@ -3743,17 +3901,19 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p
float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x);
if (x2 <= x1)
continue;
- int rounding_corners_flags_cell = 0;
- if (y1 <= p_min.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopRight; }
- if (y2 >= p_max.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotRight; }
- rounding_corners_flags_cell &= rounding_corners_flags;
- draw_list->AddRectFilled(ImVec2(x1, y1), ImVec2(x2, y2), col_bg2, rounding_corners_flags_cell ? rounding : 0.0f, rounding_corners_flags_cell);
+ ImDrawFlags cell_flags = ImDrawFlags_RoundCornersNone;
+ if (y1 <= p_min.y) { if (x1 <= p_min.x) cell_flags |= ImDrawFlags_RoundCornersTopLeft; if (x2 >= p_max.x) cell_flags |= ImDrawFlags_RoundCornersTopRight; }
+ if (y2 >= p_max.y) { if (x1 <= p_min.x) cell_flags |= ImDrawFlags_RoundCornersBottomLeft; if (x2 >= p_max.x) cell_flags |= ImDrawFlags_RoundCornersBottomRight; }
+
+ // Combine flags
+ cell_flags = (flags == ImDrawFlags_RoundCornersNone || cell_flags == ImDrawFlags_RoundCornersNone) ? ImDrawFlags_RoundCornersNone : (cell_flags & flags);
+ draw_list->AddRectFilled(ImVec2(x1, y1), ImVec2(x2, y2), col_bg2, rounding, cell_flags);
}
}
}
else
{
- draw_list->AddRectFilled(p_min, p_max, col, rounding, rounding_corners_flags);
+ draw_list->AddRectFilled(p_min, p_max, col, rounding, flags);
}
}
diff --git a/imgui/imgui_internal.h b/imgui/imgui_internal.h
index de249335..599823f3 100644
--- a/imgui/imgui_internal.h
+++ b/imgui/imgui_internal.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.81
+// dear imgui, v1.82
// (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!
@@ -188,9 +188,9 @@ namespace ImStb
// Debug Logging for selected systems. Remove the '((void)0) //' to enable.
//#define IMGUI_DEBUG_LOG_POPUP IMGUI_DEBUG_LOG // Enable log
+//#define IMGUI_DEBUG_LOG_NAV IMGUI_DEBUG_LOG // Enable log
//#define IMGUI_DEBUG_LOG_VIEWPORT IMGUI_DEBUG_LOG // Enable log
//#define IMGUI_DEBUG_LOG_DOCKING IMGUI_DEBUG_LOG // Enable log
-//#define IMGUI_DEBUG_LOG_NAV IMGUI_DEBUG_LOG // Enable log
#define IMGUI_DEBUG_LOG_POPUP(...) ((void)0) // Disable log
#define IMGUI_DEBUG_LOG_NAV(...) ((void)0) // Disable log
#define IMGUI_DEBUG_LOG_VIEWPORT(...) ((void)0) // Disable log
@@ -226,6 +226,7 @@ namespace ImStb
#define IM_NEWLINE "\n"
#endif
#define IM_TABSIZE (4)
+#define IM_MEMALIGN(_OFF,_ALIGN) (((_OFF) + (_ALIGN - 1)) & ~(_ALIGN - 1)) // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8
#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose
#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255
#define IM_FLOOR(_VAL) ((float)(int)(_VAL)) // ImFloor() is not inlined in MSVC debug builds
@@ -460,6 +461,7 @@ struct IMGUI_API ImRect
ImVec2 GetSize() const { return ImVec2(Max.x - Min.x, Max.y - Min.y); }
float GetWidth() const { return Max.x - Min.x; }
float GetHeight() const { return Max.y - Min.y; }
+ float GetArea() const { return (Max.x - Min.x) * (Max.y - Min.y); }
ImVec2 GetTL() const { return Min; } // Top-left
ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right
ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left
@@ -556,20 +558,22 @@ struct ImSpan
// Helper: ImSpanAllocator<>
// Facilitate storing multiple chunks into a single large block (the "arena")
+// - Usage: call Reserve() N times, allocate GetArenaSizeInBytes() worth, pass it to SetArenaBasePtr(), call GetSpan() N times to retrieve the aligned ranges.
template<int CHUNKS>
struct ImSpanAllocator
{
char* BasePtr;
- int TotalSize;
- int CurrSpan;
+ int CurrOff;
+ int CurrIdx;
int Offsets[CHUNKS];
+ int Sizes[CHUNKS];
ImSpanAllocator() { memset(this, 0, sizeof(*this)); }
- inline void ReserveBytes(int n, size_t sz) { IM_ASSERT(n == CurrSpan && n < CHUNKS); IM_UNUSED(n); Offsets[CurrSpan++] = TotalSize; TotalSize += (int)sz; }
- inline int GetArenaSizeInBytes() { return TotalSize; }
+ inline void Reserve(int n, size_t sz, int a=4) { IM_ASSERT(n == CurrIdx && n < CHUNKS); CurrOff = IM_MEMALIGN(CurrOff, a); Offsets[n] = CurrOff; Sizes[n] = (int)sz; CurrIdx++; CurrOff += (int)sz; }
+ inline int GetArenaSizeInBytes() { return CurrOff; }
inline void SetArenaBasePtr(void* base_ptr) { BasePtr = (char*)base_ptr; }
- inline void* GetSpanPtrBegin(int n) { IM_ASSERT(n >= 0 && n < CHUNKS && CurrSpan == CHUNKS); return (void*)(BasePtr + Offsets[n]); }
- inline void* GetSpanPtrEnd(int n) { IM_ASSERT(n >= 0 && n < CHUNKS && CurrSpan == CHUNKS); return (n + 1 < CHUNKS) ? BasePtr + Offsets[n + 1] : (void*)(BasePtr + TotalSize); }
+ inline void* GetSpanPtrBegin(int n) { IM_ASSERT(n >= 0 && n < CHUNKS && CurrIdx == CHUNKS); return (void*)(BasePtr + Offsets[n]); }
+ inline void* GetSpanPtrEnd(int n) { IM_ASSERT(n >= 0 && n < CHUNKS && CurrIdx == CHUNKS); return (void*)(BasePtr + Offsets[n] + Sizes[n]); }
template<typename T>
inline void GetSpan(int n, ImSpan<T>* span) { span->set((T*)GetSpanPtrBegin(n), (T*)GetSpanPtrEnd(n)); }
};
@@ -603,7 +607,7 @@ struct IMGUI_API ImPool
// Helper: ImChunkStream<>
// Build and iterate a contiguous stream of variable-sized structures.
// This is used by Settings to store persistent data while reducing allocation count.
-// We store the chunk size first, and align the final size on 4 bytes boundaries (this what the '(X + 3) & ~3' statement is for)
+// We store the chunk size first, and align the final size on 4 bytes boundaries.
// The tedious/zealous amount of casting is to avoid -Wcast-align warnings.
template<typename T>
struct IMGUI_API ImChunkStream
@@ -613,7 +617,7 @@ struct IMGUI_API ImChunkStream
void clear() { Buf.clear(); }
bool empty() const { return Buf.Size == 0; }
int size() const { return Buf.Size; }
- T* alloc_chunk(size_t sz) { size_t HDR_SZ = 4; sz = ((HDR_SZ + sz) + 3u) & ~3u; int off = Buf.Size; Buf.resize(off + (int)sz); ((int*)(void*)(Buf.Data + off))[0] = (int)sz; return (T*)(void*)(Buf.Data + off + (int)HDR_SZ); }
+ T* alloc_chunk(size_t sz) { size_t HDR_SZ = 4; sz = IM_MEMALIGN(HDR_SZ + sz, 4u); int off = Buf.Size; Buf.resize(off + (int)sz); ((int*)(void*)(Buf.Data + off))[0] = (int)sz; return (T*)(void*)(Buf.Data + off + (int)HDR_SZ); }
T* begin() { size_t HDR_SZ = 4; if (!Buf.Data) return NULL; return (T*)(void*)(Buf.Data + HDR_SZ); }
T* next_chunk(T* p) { size_t HDR_SZ = 4; IM_ASSERT(p >= begin() && p < end()); p = (T*)(void*)((char*)(void*)p + chunk_size(p)); if (p == (T*)(void*)((char*)end() + HDR_SZ)) return (T*)0; IM_ASSERT(p < end()); return p; }
int chunk_size(const T* p) { return ((const int*)p)[-1]; }
@@ -629,15 +633,30 @@ struct IMGUI_API ImChunkStream
//-----------------------------------------------------------------------------
// ImDrawList: Helper function to calculate a circle's segment count given its radius and a "maximum error" value.
-// FIXME: the minimum number of auto-segment may be undesirably high for very small radiuses (e.g. 1.0f)
-#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN 12
+// Estimation of number of circle segment based on error is derived using method described in https://stackoverflow.com/a/2244088/15194693
+// Number of segments (N) is calculated using equation:
+// N = ceil ( pi / acos(1 - error / r) ) where r > 0, error <= r
+// Our equation is significantly simpler that one in the post thanks for choosing segment that is
+// perpendicular to X axis. Follow steps in the article from this starting condition and you will
+// will get this result.
+//
+// Rendering circles with an odd number of segments, while mathematically correct will produce
+// asymmetrical results on the raster grid. Therefore we're rounding N to next even number (7->8, 8->8, 9->10 etc.)
+//
+#define IM_ROUNDUP_TO_EVEN(_V) ((((_V) + 1) / 2) * 2)
+#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN 4
#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX 512
-#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(_RAD,_MAXERROR) ImClamp((int)((IM_PI * 2.0f) / ImAcos(((_RAD) - (_MAXERROR)) / (_RAD))), IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX)
+#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(_RAD,_MAXERROR) ImClamp(IM_ROUNDUP_TO_EVEN((int)ImCeil(IM_PI / ImAcos(1 - ImMin((_MAXERROR), (_RAD)) / (_RAD)))), IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX)
+
+// Raw equation from IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC rewritten for 'r' and 'error'.
+#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(_N,_MAXERROR) ((_MAXERROR) / (1 - ImCos(IM_PI / ImMax((float)(_N), IM_PI))))
+#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_ERROR(_N,_RAD) ((1 - ImCos(IM_PI / ImMax((float)(_N), IM_PI))) / (_RAD))
-// ImDrawList: You may set this to higher values (e.g. 2 or 3) to increase tessellation of fast rounded corners path.
-#ifndef IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER
-#define IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER 1
+// ImDrawList: Lookup table size for adaptive arc drawing, cover full circle.
+#ifndef IM_DRAWLIST_ARCFAST_TABLE_SIZE
+#define IM_DRAWLIST_ARCFAST_TABLE_SIZE 48 // Number of samples in lookup table.
#endif
+#define IM_DRAWLIST_ARCFAST_SAMPLE_MAX IM_DRAWLIST_ARCFAST_TABLE_SIZE // Sample index _PathArcToFastEx() for 360 angle.
// Data shared between all ImDrawList instances
// You may want to create your own instance of this if you want to use ImDrawList completely without ImGui. In that case, watch out for future changes to this structure.
@@ -652,12 +671,13 @@ struct IMGUI_API ImDrawListSharedData
ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards)
// [Internal] Lookup tables
- ImVec2 ArcFastVtx[12 * IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER]; // FIXME: Bake rounded corners fill/borders in atlas
+ ImVec2 ArcFastVtx[IM_DRAWLIST_ARCFAST_TABLE_SIZE]; // Sample points on the quarter of the circle.
+ float ArcFastRadiusCutoff; // Cutoff radius after which arc drawing will fallback to slower PathArcTo()
ImU8 CircleSegmentCounts[64]; // Precomputed segment count for given radius before we calculate it dynamically (to avoid calculation overhead)
const ImVec4* TexUvLines; // UV of anti-aliased lines in the atlas
ImDrawListSharedData();
- void SetCircleSegmentMaxError(float max_error);
+ void SetCircleTessellationMaxError(float max_error);
};
struct ImDrawDataBuilder
@@ -695,12 +715,13 @@ enum ImGuiItemStatusFlags_
{
ImGuiItemStatusFlags_None = 0,
ImGuiItemStatusFlags_HoveredRect = 1 << 0,
- ImGuiItemStatusFlags_HasDisplayRect = 1 << 1,
+ ImGuiItemStatusFlags_HasDisplayRect = 1 << 1, // LastItemDisplayRect is valid
ImGuiItemStatusFlags_Edited = 1 << 2, // Value exposed by item was edited in the current frame (should match the bool return value of most widgets)
ImGuiItemStatusFlags_ToggledSelection = 1 << 3, // Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected" because reporting the change allows us to handle clipping with less issues.
ImGuiItemStatusFlags_ToggledOpen = 1 << 4, // Set when TreeNode() reports toggling their open state.
ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag.
- ImGuiItemStatusFlags_Deactivated = 1 << 6 // Only valid if ImGuiItemStatusFlags_HasDeactivated is set.
+ ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set.
+ ImGuiItemStatusFlags_HoveredWindow = 1 << 7 // Override the HoveredWindow test to allow cross-window hover testing.
#ifdef IMGUI_ENABLE_TEST_ENGINE
, // [imgui_tests only]
@@ -815,9 +836,9 @@ enum ImGuiInputSource
{
ImGuiInputSource_None = 0,
ImGuiInputSource_Mouse,
- ImGuiInputSource_Nav,
- ImGuiInputSource_NavKeyboard, // Only used occasionally for storage, not tested/handled by most code
- ImGuiInputSource_NavGamepad, // "
+ ImGuiInputSource_Keyboard,
+ ImGuiInputSource_Gamepad,
+ ImGuiInputSource_Nav, // Stored in g.ActiveIdSource only
ImGuiInputSource_COUNT
};
@@ -922,7 +943,7 @@ struct ImGuiStyleMod
};
// Stacked storage data for BeginGroup()/EndGroup()
-struct ImGuiGroupData
+struct IMGUI_API ImGuiGroupData
{
ImGuiID WindowID;
ImVec2 BackupCursorPos;
@@ -933,6 +954,7 @@ struct ImGuiGroupData
float BackupCurrLineTextBaseOffset;
ImGuiID BackupActiveIdIsAlive;
bool BackupActiveIdPreviousFrameIsAlive;
+ bool BackupHoveredIdIsAlive;
bool EmitItem;
};
@@ -1202,7 +1224,7 @@ enum ImGuiDockNodeState
};
// sizeof() 116~160
-struct ImGuiDockNode
+struct IMGUI_API ImGuiDockNode
{
ImGuiID ID;
ImGuiDockNodeFlags SharedFlags; // Flags shared by all nodes of a same dockspace hierarchy (inherited from the root node)
@@ -1233,9 +1255,8 @@ struct ImGuiDockNode
ImGuiDataAuthority AuthorityForViewport :3;
bool IsVisible :1; // Set to false when the node is hidden (usually disabled as it has no active window)
bool IsFocused :1;
- bool HasCloseButton :1;
+ bool HasCloseButton :1; // Provide space for a close button (if any of the docked window has one). Note that button may be hidden on window without one.
bool HasWindowMenuButton :1;
- bool EnableCloseButton :1;
bool WantCloseAll :1; // Set when closing all tabs at once.
bool WantLockSizeOnce :1;
bool WantMouseMove :1; // After a node extraction we need to transition toward moving the newly created host window
@@ -1459,17 +1480,16 @@ struct ImGuiContext
// Windows state
ImVector<ImGuiWindow*> Windows; // Windows, sorted in display order, back to front
- ImVector<ImGuiWindow*> WindowsFocusOrder; // Windows, sorted in focus order, back to front. (FIXME: We could only store root windows here! Need to sort out the Docking equivalent which is RootWindowDockStop and is unfortunately a little more dynamic)
+ ImVector<ImGuiWindow*> WindowsFocusOrder; // Windows, sorted in focus order, back to front. (FIXME: We could only store root windows here!)
ImVector<ImGuiWindow*> WindowsTempSortBuffer; // Temporary buffer used in EndFrame() to reorder windows so parents are kept before their child
ImVector<ImGuiWindow*> CurrentWindowStack;
ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow*
int WindowsActiveCount; // Number of unique windows submitted by frame
ImGuiWindow* CurrentWindow; // Window being drawn into
ImGuiWindow* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs.
- ImGuiWindow* HoveredRootWindow; // == HoveredWindow ? HoveredWindow->RootWindow : NULL, merely a shortcut to avoid null test in some situation.
ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set.
ImGuiDockNode* HoveredDockNode; // Hovered dock node.
- ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actual window that is moved is generally MovingWindow->RootWindow.
+ ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actual window that is moved is generally MovingWindow->RootWindowDockTree.
ImGuiWindow* WheelingWindow; // Track the window we started mouse-wheeling on. Until a timer elapse or mouse has moved, generally keep scrolling the same window even if during the course of scrolling the mouse ends up hovering a child window.
ImVec2 WheelingWindowRefMousePos;
float WheelingWindowTimer;
@@ -1528,6 +1548,7 @@ struct ImGuiContext
ImGuiViewportP* MouseViewport;
ImGuiViewportP* MouseLastHoveredViewport; // Last known viewport that was hovered by mouse (even if we are not hovering any viewport any more) + honoring the _NoInputs flag.
ImGuiID PlatformLastFocusedViewportId;
+ ImGuiPlatformMonitor FallbackMonitor; // Virtual monitor used as fallback if backend doesn't provide monitor information.
int ViewportFrontMostStampCount; // Every time the front-most window changes, we stamp its viewport with an incrementing counter
// Gamepad/keyboard Navigation
@@ -1578,13 +1599,13 @@ struct ImGuiContext
bool NavWindowingToggleLayer;
// Legacy Focus/Tabbing system (older than Nav, active even if Nav is disabled, misnamed. FIXME-NAV: This needs a redesign!)
- ImGuiWindow* FocusRequestCurrWindow; //
- ImGuiWindow* FocusRequestNextWindow; //
- int FocusRequestCurrCounterRegular; // Any item being requested for focus, stored as an index (we on layout to be stable between the frame pressing TAB and the next frame, semi-ouch)
- int FocusRequestCurrCounterTabStop; // Tab item being requested for focus, stored as an index
- int FocusRequestNextCounterRegular; // Stored for next frame
- int FocusRequestNextCounterTabStop; // "
- bool FocusTabPressed; //
+ ImGuiWindow* TabFocusRequestCurrWindow; //
+ ImGuiWindow* TabFocusRequestNextWindow; //
+ int TabFocusRequestCurrCounterRegular; // Any item being requested for focus, stored as an index (we on layout to be stable between the frame pressing TAB and the next frame, semi-ouch)
+ int TabFocusRequestCurrCounterTabStop; // Tab item being requested for focus, stored as an index
+ int TabFocusRequestNextCounterRegular; // Stored for next frame
+ int TabFocusRequestNextCounterTabStop; // "
+ bool TabFocusPressed; //
// Render
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
@@ -1710,7 +1731,6 @@ struct ImGuiContext
WindowsActiveCount = 0;
CurrentWindow = NULL;
HoveredWindow = NULL;
- HoveredRootWindow = NULL;
HoveredWindowUnderMovingWindow = NULL;
HoveredDockNode = NULL;
MovingWindow = NULL;
@@ -1738,7 +1758,7 @@ struct ImGuiContext
ActiveIdClickOffset = ImVec2(-1, -1);
ActiveIdWindow = NULL;
ActiveIdSource = ImGuiInputSource_None;
- ActiveIdMouseButton = 0;
+ ActiveIdMouseButton = -1;
ActiveIdPreviousFrame = 0;
ActiveIdPreviousFrameIsAlive = false;
ActiveIdPreviousFrameHasBeenEditedBefore = false;
@@ -1781,10 +1801,10 @@ struct ImGuiContext
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
NavWindowingToggleLayer = false;
- FocusRequestCurrWindow = FocusRequestNextWindow = NULL;
- FocusRequestCurrCounterRegular = FocusRequestCurrCounterTabStop = INT_MAX;
- FocusRequestNextCounterRegular = FocusRequestNextCounterTabStop = INT_MAX;
- FocusTabPressed = false;
+ TabFocusRequestCurrWindow = TabFocusRequestNextWindow = NULL;
+ TabFocusRequestCurrCounterRegular = TabFocusRequestCurrCounterTabStop = INT_MAX;
+ TabFocusRequestNextCounterRegular = TabFocusRequestNextCounterTabStop = INT_MAX;
+ TabFocusPressed = false;
DimBgRatio = 0.0f;
MouseCursor = ImGuiMouseCursor_Arrow;
@@ -1961,6 +1981,7 @@ struct IMGUI_API ImGuiWindow
ImS8 HiddenFramesCanSkipItems; // Hide the window for N frames
ImS8 HiddenFramesCannotSkipItems; // Hide the window for N frames while allowing items to be submitted so we can measure their size
ImS8 HiddenFramesForRenderOnly; // Hide the window until frame N at Render() time only
+ ImS8 DisableInputsFrames; // Disable window interactions for N frames
ImGuiCond SetWindowPosAllowFlags : 8; // store acceptable condition flags for SetNextWindowPos() use.
ImGuiCond SetWindowSizeAllowFlags : 8; // store acceptable condition flags for SetNextWindowSize() use.
ImGuiCond SetWindowCollapsedAllowFlags : 8; // store acceptable condition flags for SetNextWindowCollapsed() use.
@@ -1996,8 +2017,8 @@ struct IMGUI_API ImGuiWindow
ImDrawList* DrawList; // == &DrawListInst (for backward compatibility reason with code using imgui_internal.h we keep this a pointer)
ImDrawList DrawListInst;
ImGuiWindow* ParentWindow; // If we are a child _or_ popup window, this is pointing to our parent. Otherwise NULL.
- ImGuiWindow* RootWindow; // Point to ourself or first ancestor that is not a child window == Top-level window.
- ImGuiWindow* RootWindowDockStop; // Point to ourself or first ancestor that is not a child window. Doesn't cross through dock nodes. We use this so IsWindowFocused() can behave consistently regardless of docking state.
+ ImGuiWindow* RootWindow; // Point to ourself or first ancestor that is not a child window. Doesn't cross through dock nodes. We use this so IsWindowFocused() can behave consistently regardless of docking state.
+ ImGuiWindow* RootWindowDockTree; // Point to ourself or first ancestor that is not a child window. Cross through dock nodes.
ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active.
ImGuiWindow* RootWindowForNav; // Point to ourself or first ancestor which doesn't have the NavFlattened flag.
@@ -2096,13 +2117,13 @@ struct ImGuiTabItem
};
// Storage for a tab bar (sizeof() 152 bytes)
-struct ImGuiTabBar
+struct IMGUI_API ImGuiTabBar
{
ImVector<ImGuiTabItem> Tabs;
ImGuiTabBarFlags Flags;
ImGuiID ID; // Zero for tab-bars used by docking
ImGuiID SelectedTabId; // Selected tab/window
- ImGuiID NextSelectedTabId;
+ ImGuiID NextSelectedTabId; // Next selected tab/window. Will also trigger a scrolling animation
ImGuiID VisibleTabId; // Can occasionally be != SelectedTabId (e.g. when previewing contents for CTRL+TAB preview)
int CurrFrameVisible;
int PrevFrameVisible;
@@ -2309,9 +2330,10 @@ struct ImGuiTable
ImGuiTableColumnIdx HeldHeaderColumn; // Index of column header being held.
ImGuiTableColumnIdx ReorderColumn; // Index of column being reordered. (not cleared)
ImGuiTableColumnIdx ReorderColumnDir; // -1 or +1
+ ImGuiTableColumnIdx LeftMostEnabledColumn; // Index of left-most non-hidden column.
+ ImGuiTableColumnIdx RightMostEnabledColumn; // Index of right-most non-hidden column.
ImGuiTableColumnIdx LeftMostStretchedColumn; // Index of left-most stretched column.
ImGuiTableColumnIdx RightMostStretchedColumn; // Index of right-most stretched column.
- ImGuiTableColumnIdx RightMostEnabledColumn; // Index of right-most non-hidden column.
ImGuiTableColumnIdx ContextPopupColumn; // Column right-clicked on, of -1 if opening context menu from a neutral/empty spot
ImGuiTableColumnIdx FreezeRowsRequest; // Requested frozen rows count
ImGuiTableColumnIdx FreezeRowsCount; // Actual frozen row count (== FreezeRowsRequest, or == 0 when no scrolling offset)
@@ -2437,9 +2459,10 @@ namespace ImGui
IMGUI_API void CallContextHooks(ImGuiContext* context, ImGuiContextHookType type);
// Viewports
- IMGUI_API void TranslateWindowsInViewport(ImGuiViewportP* viewport, const ImVec2& old_pos, const ImVec2& new_pos);
- IMGUI_API void ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale);
- IMGUI_API void DestroyPlatformWindow(ImGuiViewportP* viewport);
+ IMGUI_API void TranslateWindowsInViewport(ImGuiViewportP* viewport, const ImVec2& old_pos, const ImVec2& new_pos);
+ IMGUI_API void ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale);
+ IMGUI_API void DestroyPlatformWindow(ImGuiViewportP* viewport);
+ const ImGuiPlatformMonitor* GetViewportPlatformMonitor(ImGuiViewport* viewport);
// Settings
IMGUI_API void MarkIniSettingsDirty();
@@ -2520,8 +2543,7 @@ namespace ImGui
IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f);
IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate);
IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again.
- IMGUI_API void SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id);
- IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel);
+ IMGUI_API void SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel);
// Focus Scope (WIP)
// This is generally used to identify a selection set (multiple of which may be in the same window), as selection
@@ -2619,6 +2641,7 @@ namespace ImGui
IMGUI_API void TablePopBackgroundChannel();
// Tables: Internals
+ inline ImGuiTable* GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; }
IMGUI_API ImGuiTable* TableFindByID(ImGuiID id);
IMGUI_API bool BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f);
IMGUI_API void TableBeginInitMemory(ImGuiTable* table, int columns_count);
@@ -2682,7 +2705,7 @@ namespace ImGui
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);
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
- IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, int rounding_corners_flags = ~0);
+ IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_TypeDefault); // Navigation highlight
IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text.
@@ -2709,7 +2732,7 @@ namespace ImGui
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 ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float avail_v, float contents_v, ImDrawFlags flags);
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);
@@ -2817,11 +2840,11 @@ IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table
//-----------------------------------------------------------------------------
#ifdef IMGUI_ENABLE_TEST_ENGINE
-extern void ImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx, const ImRect& bb, ImGuiID id);
-extern void ImGuiTestEngineHook_ItemInfo(ImGuiContext* ctx, ImGuiID id, const char* label, ImGuiItemStatusFlags flags);
-extern void ImGuiTestEngineHook_IdInfo(ImGuiContext* ctx, ImGuiDataType data_type, ImGuiID id, const void* data_id);
-extern void ImGuiTestEngineHook_IdInfo(ImGuiContext* ctx, ImGuiDataType data_type, ImGuiID id, const void* data_id, const void* data_id_end);
-extern void ImGuiTestEngineHook_Log(ImGuiContext* ctx, const char* fmt, ...);
+extern void ImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx, const ImRect& bb, ImGuiID id);
+extern void ImGuiTestEngineHook_ItemInfo(ImGuiContext* ctx, ImGuiID id, const char* label, ImGuiItemStatusFlags flags);
+extern void ImGuiTestEngineHook_IdInfo(ImGuiContext* ctx, ImGuiDataType data_type, ImGuiID id, const void* data_id);
+extern void ImGuiTestEngineHook_IdInfo(ImGuiContext* ctx, ImGuiDataType data_type, ImGuiID id, const void* data_id, const void* data_id_end);
+extern void ImGuiTestEngineHook_Log(ImGuiContext* ctx, const char* fmt, ...);
#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _BB, _ID) // Register item bounding box
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional)
#define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log
diff --git a/imgui/imgui_tables.cpp b/imgui/imgui_tables.cpp
index 61a84f9f..b6d11749 100644
--- a/imgui/imgui_tables.cpp
+++ b/imgui/imgui_tables.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.81
+// dear imgui, v1.82
// (tables and columns code)
/*
@@ -166,7 +166,7 @@ Index of this file:
// - Case B: column is clipped / out of sight (because of scrolling or parent ClipRect): TableNextColumn() return false as a hint but we still allow layout output.
// - Case C: column is hidden explicitly by the user (e.g. via the context menu, or _DefaultHide column flag, etc.).
//
-// [A] [B] [C]
+// [A] [B] [C]
// TableNextColumn(): true false false -> [userland] when TableNextColumn() / TableSetColumnIndex() return false, user can skip submitting items but only if the column doesn't contribute to row height.
// SkipItems: false false true -> [internal] when SkipItems is true, most widgets will early out if submitted, resulting is no layout output.
// ClipRect: normal zero-width zero-width -> [internal] when ClipRect is zero, ItemAdd() will return false and most widgets will early out mid-way.
@@ -272,12 +272,7 @@ inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags, ImGuiWindow* outer_w
flags |= ImGuiTableFlags_NoSavedSettings;
// Inherit _NoSavedSettings from top-level window (child windows always have _NoSavedSettings set)
-#ifdef IMGUI_HAS_DOCK
- ImGuiWindow* window_for_settings = outer_window->RootWindowDockStop;
-#else
- ImGuiWindow* window_for_settings = outer_window->RootWindow;
-#endif
- if (window_for_settings->Flags & ImGuiWindowFlags_NoSavedSettings)
+ if (outer_window->RootWindow->Flags & ImGuiWindowFlags_NoSavedSettings)
flags |= ImGuiTableFlags_NoSavedSettings;
return flags;
@@ -538,9 +533,9 @@ void ImGui::TableBeginInitMemory(ImGuiTable* table, int columns_count)
{
// Allocate single buffer for our arrays
ImSpanAllocator<3> span_allocator;
- span_allocator.ReserveBytes(0, columns_count * sizeof(ImGuiTableColumn));
- span_allocator.ReserveBytes(1, columns_count * sizeof(ImGuiTableColumnIdx));
- span_allocator.ReserveBytes(2, columns_count * sizeof(ImGuiTableCellData));
+ span_allocator.Reserve(0, columns_count * sizeof(ImGuiTableColumn));
+ span_allocator.Reserve(1, columns_count * sizeof(ImGuiTableColumnIdx));
+ span_allocator.Reserve(2, columns_count * sizeof(ImGuiTableCellData), 4);
table->RawData = IM_ALLOC(span_allocator.GetArenaSizeInBytes());
memset(table->RawData, 0, span_allocator.GetArenaSizeInBytes());
span_allocator.SetArenaBasePtr(table->RawData);
@@ -635,7 +630,7 @@ static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, I
{
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiTableColumnFlags_WidthMask_)); // Check that only 1 of each set is used.
}
-
+
// Resize
if ((table->Flags & ImGuiTableFlags_Resizable) == 0)
flags |= ImGuiTableColumnFlags_NoResize;
@@ -687,13 +682,14 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
table->ColumnsEnabledCount = 0;
table->EnabledMaskByIndex = 0x00;
table->EnabledMaskByDisplayOrder = 0x00;
+ table->LeftMostEnabledColumn = -1;
table->MinColumnWidth = ImMax(1.0f, g.Style.FramePadding.x * 1.0f); // g.Style.ColumnsMinSpacing; // FIXME-TABLE
// [Part 1] Apply/lock Enabled and Order states. Calculate auto/ideal width for columns. Count fixed/stretch columns.
// Process columns in their visible orders as we are building the Prev/Next indices.
int count_fixed = 0; // Number of columns that have fixed sizing policies
int count_stretch = 0; // Number of columns that have stretch sizing policies
- int last_visible_column_idx = -1;
+ int prev_visible_column_idx = -1;
bool has_auto_fit_request = false;
bool has_resizable = false;
float stretch_sum_width_auto = 0.0f;
@@ -741,14 +737,16 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
}
// Mark as enabled and link to previous/next enabled column
- column->PrevEnabledColumn = (ImGuiTableColumnIdx)last_visible_column_idx;
+ column->PrevEnabledColumn = (ImGuiTableColumnIdx)prev_visible_column_idx;
column->NextEnabledColumn = -1;
- if (last_visible_column_idx != -1)
- table->Columns[last_visible_column_idx].NextEnabledColumn = (ImGuiTableColumnIdx)column_n;
+ if (prev_visible_column_idx != -1)
+ table->Columns[prev_visible_column_idx].NextEnabledColumn = (ImGuiTableColumnIdx)column_n;
+ else
+ table->LeftMostEnabledColumn = (ImGuiTableColumnIdx)column_n;
column->IndexWithinEnabledSet = table->ColumnsEnabledCount++;
table->EnabledMaskByIndex |= (ImU64)1 << column_n;
table->EnabledMaskByDisplayOrder |= (ImU64)1 << column->DisplayOrder;
- last_visible_column_idx = column_n;
+ prev_visible_column_idx = column_n;
IM_ASSERT(column->IndexWithinEnabledSet <= column->DisplayOrder);
// Calculate ideal/auto column width (that's the width required for all contents to be visible without clipping)
@@ -778,8 +776,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
}
if ((table->Flags & ImGuiTableFlags_Sortable) && table->SortSpecsCount == 0 && !(table->Flags & ImGuiTableFlags_SortTristate))
table->IsSortSpecsDirty = true;
- table->RightMostEnabledColumn = (ImGuiTableColumnIdx)last_visible_column_idx;
- IM_ASSERT(table->RightMostEnabledColumn >= 0);
+ table->RightMostEnabledColumn = (ImGuiTableColumnIdx)prev_visible_column_idx;
+ IM_ASSERT(table->LeftMostEnabledColumn >= 0 && table->RightMostEnabledColumn >= 0);
// [Part 2] Disable child window clipping while fitting columns. This is not strictly necessary but makes it possible
// to avoid the column fitting having to wait until the first visible frame of the child container (may or not be a good thing).
@@ -805,7 +803,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// Apply same widths policy
float width_auto = column->WidthAuto;
if (table_sizing_policy == ImGuiTableFlags_SizingFixedSame && (column->AutoFitQueue != 0x00 || !column_is_resizable))
- width_auto = fixed_max_width_auto;
+ width_auto = fixed_max_width_auto;
// Apply automatic width
// Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!)
@@ -2364,7 +2362,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
if ((merge_group_n & 2) != 0 && (table->Flags & ImGuiTableFlags_NoHostExtendY) == 0)
merge_clip_rect.Max.y = ImMax(merge_clip_rect.Max.y, host_rect.Max.y);
#if 0
- GetOverlayDrawList()->AddRect(merge_group->ClipRect.Min, merge_group->ClipRect.Max, IM_COL32(255, 0, 0, 200), 0.0f, ~0, 1.0f);
+ GetOverlayDrawList()->AddRect(merge_group->ClipRect.Min, merge_group->ClipRect.Max, IM_COL32(255, 0, 0, 200), 0.0f, 0, 1.0f);
GetOverlayDrawList()->AddLine(merge_group->ClipRect.Min, merge_clip_rect.Min, IM_COL32(255, 100, 0, 200));
GetOverlayDrawList()->AddLine(merge_group->ClipRect.Max, merge_clip_rect.Max, IM_COL32(255, 100, 0, 200));
#endif
@@ -2477,7 +2475,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
const ImU32 outer_col = table->BorderColorStrong;
if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter)
{
- inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, ~0, border_size);
+ inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, 0, border_size);
}
else if (table->Flags & ImGuiTableFlags_BordersOuterV)
{
diff --git a/imgui/imgui_widgets.cpp b/imgui/imgui_widgets.cpp
index b6175368..b9b2b77b 100644
--- a/imgui/imgui_widgets.cpp
+++ b/imgui/imgui_widgets.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.81
+// dear imgui, v1.82
// (widgets code)
/*
@@ -500,7 +500,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
flags |= ImGuiButtonFlags_PressedOnDefault_;
ImGuiWindow* backup_hovered_window = g.HoveredWindow;
- const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window->RootWindow;
+ const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredWindow && g.HoveredWindow->RootWindowDockTree == window->RootWindowDockTree;
if (flatten_hovered_children)
g.HoveredWindow = window;
@@ -782,22 +782,30 @@ bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir)
}
// Button to close a window
-bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)//, float size)
+bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
- // We intentionally allow interaction when clipped so that a mechanical Alt,Right,Validate sequence close a window.
- // (this isn't the regular behavior of buttons, but it doesn't affect the user much because navigation tends to keep items visible).
+ // Tweak 1: Shrink hit-testing area if button covers an abnormally large proportion of the visible region. That's in order to facilitate moving the window away. (#3825)
+ // This may better be applied as a general hit-rect reduction mechanism for all widgets to ensure the area to move window is always accessible?
const ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f);
- bool is_clipped = !ItemAdd(bb, id);
+ ImRect bb_interact = bb;
+ const float area_to_visible_ratio = window->OuterRectClipped.GetArea() / bb.GetArea();
+ if (area_to_visible_ratio < 1.5f)
+ bb_interact.Expand(ImFloor(bb_interact.GetSize() * -0.25f));
+
+ // Tweak 2: We intentionally allow interaction when clipped so that a mechanical Alt,Right,Activate sequence can always close a window.
+ // (this isn't the regular behavior of buttons, but it doesn't affect the user much because navigation tends to keep items visible).
+ bool is_clipped = !ItemAdd(bb_interact, id);
bool hovered, held;
- bool pressed = ButtonBehavior(bb, id, &hovered, &held);
+ bool pressed = ButtonBehavior(bb_interact, id, &hovered, &held);
if (is_clipped)
return pressed;
// Render
+ // FIXME: Clarify this mess
ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered);
ImVec2 center = bb.GetCenter();
if (hovered)
@@ -873,19 +881,19 @@ void ImGui::Scrollbar(ImGuiAxis axis)
// Calculate scrollbar bounding box
ImRect bb = GetWindowScrollbarRect(window, axis);
- ImDrawCornerFlags rounding_corners = 0;
+ ImDrawFlags rounding_corners = ImDrawFlags_RoundCornersNone;
if (axis == ImGuiAxis_X)
{
- rounding_corners |= ImDrawCornerFlags_BotLeft;
+ rounding_corners |= ImDrawFlags_RoundCornersBottomLeft;
if (!window->ScrollbarY)
- rounding_corners |= ImDrawCornerFlags_BotRight;
+ rounding_corners |= ImDrawFlags_RoundCornersBottomRight;
}
else
{
if ((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar))
- rounding_corners |= ImDrawCornerFlags_TopRight;
+ rounding_corners |= ImDrawFlags_RoundCornersTopRight;
if (!window->ScrollbarX)
- rounding_corners |= ImDrawCornerFlags_BotRight;
+ rounding_corners |= ImDrawFlags_RoundCornersBottomRight;
}
float size_avail = window->InnerRect.Max[axis] - window->InnerRect.Min[axis];
float size_contents = window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f;
@@ -898,7 +906,7 @@ void ImGui::Scrollbar(ImGuiAxis axis)
// - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar
// - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal.
// Still, the code should probably be made simpler..
-bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float size_avail_v, float size_contents_v, ImDrawCornerFlags rounding_corners)
+bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float size_avail_v, float size_contents_v, ImDrawFlags flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
@@ -978,7 +986,7 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa
// Render
const ImU32 bg_col = GetColorU32(ImGuiCol_ScrollbarBg);
const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab, alpha);
- window->DrawList->AddRectFilled(bb_frame.Min, bb_frame.Max, bg_col, window->WindowRounding, rounding_corners);
+ window->DrawList->AddRectFilled(bb_frame.Min, bb_frame.Max, bg_col, window->WindowRounding, flags);
ImRect grab_rect;
if (axis == ImGuiAxis_X)
grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y);
@@ -1578,12 +1586,12 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
const float value_x2 = ImMax(frame_bb.Min.x, frame_bb.Max.x - arrow_size);
RenderNavHighlight(frame_bb, id);
if (!(flags & ImGuiComboFlags_NoPreview))
- window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(value_x2, frame_bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Left);
+ window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(value_x2, frame_bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft);
if (!(flags & ImGuiComboFlags_NoArrowButton))
{
ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
ImU32 text_col = GetColorU32(ImGuiCol_Text);
- window->DrawList->AddRectFilled(ImVec2(value_x2, frame_bb.Min.y), frame_bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Right);
+ window->DrawList->AddRectFilled(ImVec2(value_x2, frame_bb.Min.y), frame_bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight);
if (value_x2 + arrow_size - style.FramePadding.x <= frame_bb.Max.x)
RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f);
}
@@ -2076,12 +2084,35 @@ static const char* ImAtoi(const char* src, TYPE* output)
return src;
}
+// Sanitize format
+// - Zero terminate so extra characters after format (e.g. "%f123") don't confuse atof/atoi
+// - stb_sprintf.h supports several new modifiers which format numbers in a way that also makes them incompatible atof/atoi.
+static void SanitizeFormatString(const char* fmt, char* fmt_out, size_t fmt_out_size)
+{
+ const char* fmt_end = ImParseFormatFindEnd(fmt);
+ IM_ASSERT((size_t)(fmt_end - fmt + 1) < fmt_out_size); // Format is too long, let us know if this happens to you!
+ while (fmt < fmt_end)
+ {
+ char c = *(fmt++);
+ if (c != '\'' && c != '$' && c != '_') // Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '.
+ *(fmt_out++) = c;
+ }
+ *fmt_out = 0; // Zero-terminate
+}
+
template<typename TYPE, typename SIGNEDTYPE>
TYPE ImGui::RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, TYPE v)
{
const char* fmt_start = ImParseFormatFindStart(format);
if (fmt_start[0] != '%' || fmt_start[1] == '%') // Don't apply if the value is not visible in the format string
return v;
+
+ // Sanitize format
+ char fmt_sanitized[32];
+ SanitizeFormatString(fmt_start, fmt_sanitized, IM_ARRAYSIZE(fmt_sanitized));
+ fmt_start = fmt_sanitized;
+
+ // Format value with our rounding, and read back
char v_str[64];
ImFormatString(v_str, IM_ARRAYSIZE(v_str), fmt_start, v);
const char* p = v_str;
@@ -2119,9 +2150,9 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
{
ImGuiContext& g = *GImGui;
const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
- const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
const bool is_clamped = (v_min < v_max);
- const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) && is_decimal;
+ const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) != 0;
+ const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
// Default tweak speed
if (v_speed == 0.0f && is_clamped && (v_max - v_min < FLT_MAX))
@@ -2139,7 +2170,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
}
else if (g.ActiveIdSource == ImGuiInputSource_Nav)
{
- int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0;
+ const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f / 10.0f, 10.0f)[axis];
v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision));
}
@@ -2179,7 +2210,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
if (is_logarithmic)
{
// When using logarithmic sliders, we need to clamp to avoid hitting zero, but our choice of clamp value greatly affects slider precision. We attempt to use the specified precision to estimate a good lower bound.
- const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 1;
+ const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 1;
logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision);
// Convert to parametric space, apply delta, convert back
@@ -2217,9 +2248,9 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
// Clamp values (+ handle overflow/wrap-around for integer types)
if (*v != v_cur && is_clamped)
{
- if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f && !is_decimal))
+ if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f && !is_floating_point))
v_cur = v_min;
- if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0f && !is_decimal))
+ if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0f && !is_floating_point))
v_cur = v_max;
}
@@ -2610,7 +2641,7 @@ TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, T
{
if (v_min == v_max)
return v_min;
- const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
+ const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
TYPE result;
if (is_logarithmic)
@@ -2658,7 +2689,7 @@ TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, T
else
{
// Linear slider
- if (is_decimal)
+ if (is_floating_point)
{
result = ImLerp(v_min, v_max, t);
}
@@ -2691,14 +2722,14 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
const ImGuiStyle& style = g.Style;
const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
- const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
- const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) && is_decimal;
+ const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) != 0;
+ const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
const float grab_padding = 2.0f;
const float slider_sz = (bb.Max[axis] - bb.Min[axis]) - grab_padding * 2.0f;
float grab_sz = style.GrabMinSize;
SIGNEDTYPE v_range = (v_min < v_max ? v_max - v_min : v_min - v_max);
- if (!is_decimal && v_range >= 0) // v_range < 0 may happen on integer overflows
+ if (!is_floating_point && v_range >= 0) // v_range < 0 may happen on integer overflows
grab_sz = ImMax((float)(slider_sz / (v_range + 1)), style.GrabMinSize); // For integer sliders: if possible have the grab size represent 1 unit
grab_sz = ImMin(grab_sz, slider_sz);
const float slider_usable_sz = slider_sz - grab_sz;
@@ -2710,7 +2741,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
if (is_logarithmic)
{
// When using logarithmic sliders, we need to clamp to avoid hitting zero, but our choice of clamp value greatly affects slider precision. We attempt to use the specified precision to estimate a good lower bound.
- const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 1;
+ const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 1;
logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision);
zero_deadzone_halfsize = (style.LogSliderDeadzone * 0.5f) / ImMax(slider_usable_sz, 1.0f);
}
@@ -2748,7 +2779,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
float input_delta = (axis == ImGuiAxis_X) ? input_delta2.x : -input_delta2.y;
if (input_delta != 0.0f)
{
- const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0;
+ const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
if (decimal_precision > 0)
{
input_delta /= 100.0f; // Gamepad/keyboard tweak speeds in % of slider bounds
@@ -3293,7 +3324,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, p_data, NULL);
if (p_clamp_min || p_clamp_max)
{
- if (DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0)
+ if (p_clamp_min && p_clamp_max && DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0)
ImSwap(p_clamp_min, p_clamp_max);
DataTypeClamp(data_type, p_data, p_clamp_min, p_clamp_max);
}
@@ -3903,11 +3934,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
ImGuiInputTextState* state = GetInputTextState(id);
const bool focus_requested = FocusableItemRegister(window, id);
- const bool focus_requested_by_code = focus_requested && (g.FocusRequestCurrWindow == window && g.FocusRequestCurrCounterRegular == window->DC.FocusCounterRegular);
+ const bool focus_requested_by_code = focus_requested && (g.TabFocusRequestCurrWindow == window && g.TabFocusRequestCurrCounterRegular == window->DC.FocusCounterRegular);
const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
const bool user_clicked = hovered && io.MouseClicked[0];
- const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_NavKeyboard));
+ const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard));
const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
@@ -3956,8 +3987,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (!is_multiline && focus_requested_by_code)
select_all = true;
}
- if (flags & ImGuiInputTextFlags_AlwaysInsertMode)
- state->Stb.insert_mode = 1;
+ if (flags & ImGuiInputTextFlags_AlwaysOverwrite)
+ state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863)
if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.KeyCtrl)))
select_all = true;
}
@@ -5210,7 +5241,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps;
const int vert_start_idx = draw_list->VtxBuffer.Size;
draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc);
- draw_list->PathStroke(col_white, false, wheel_thickness);
+ draw_list->PathStroke(col_white, 0, wheel_thickness);
const int vert_end_idx = draw_list->VtxBuffer.Size;
// Paint colors over existing vertices
@@ -5336,8 +5367,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, ImDrawFlags_RoundCornersRight);
+ window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawFlags_RoundCornersLeft);
}
else
{
@@ -5346,7 +5377,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
if (col_source.w < 1.0f)
RenderColorRectWithAlphaCheckerboard(window->DrawList, bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding);
else
- window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding, ImDrawCornerFlags_All);
+ window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding);
}
RenderNavHighlight(bb, id);
if ((flags & ImGuiColorEditFlags_NoBorder) == 0)
@@ -5892,7 +5923,7 @@ void ImGui::TreePop()
if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
if (g.NavIdIsAlive && (window->DC.TreeJumpToParentOnPopMask & tree_depth_mask))
{
- SetNavID(window->IDStack.back(), g.NavLayer, 0);
+ SetNavID(window->IDStack.back(), g.NavLayer, 0, ImRect());
NavMoveRequestCancel();
}
window->DC.TreeJumpToParentOnPopMask &= tree_depth_mask - 1;
@@ -6080,8 +6111,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
{
if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
{
+ SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, ImRect(bb.Min - window->Pos, bb.Max - window->Pos));
g.NavDisableHighlight = true;
- SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent);
}
}
if (pressed)
@@ -6199,6 +6230,7 @@ void ImGui::EndListBox()
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) && "Mismatched BeginListBox/EndListBox calls. Did you test the return value of BeginListBox?");
+ IM_UNUSED(window);
EndChildFrame();
EndGroup(); // This is only required to be able to do IsItemXXX query on the whole ListBox including label
@@ -6559,9 +6591,9 @@ void ImGui::EndMenuBar()
const ImGuiNavLayer layer = ImGuiNavLayer_Menu;
IM_ASSERT(window->DC.NavLayerActiveMaskNext & (1 << layer)); // Sanity check
FocusWindow(window);
- SetNavIDWithRectRel(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
- g.NavLayer = layer;
+ SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection.
+ g.NavDisableMouseHover = g.NavMousePosDirty = true;
g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;
NavMoveRequestCancel();
}
@@ -6592,7 +6624,7 @@ bool ImGui::BeginMainMenuBar()
if (menu_bar_window == NULL || menu_bar_window->BeginCount == 0)
{
// Set window position
- // We don't attempt to calculate our height ahead, as it depends on the per-viewport font size.
+ // We don't attempt to calculate our height ahead, as it depends on the per-viewport font size.
// However menu-bar will affect the minimum window size so we'll get the right height.
ImVec2 menu_bar_pos = viewport->Pos + viewport->CurrWorkOffsetMin;
ImVec2 menu_bar_size = ImVec2(viewport->Size.x - viewport->CurrWorkOffsetMin.x + viewport->CurrWorkOffsetMax.x, 1.0f);
@@ -6910,7 +6942,7 @@ namespace ImGui
static ImU32 TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label, ImGuiWindow* docked_window);
static float TabBarCalcMaxTabWidth();
static float TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling);
- static void TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, ImGuiTabBarSection* sections);
+ static void TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGuiTabBarSection* sections);
static ImGuiTabItem* TabBarScrollingButtons(ImGuiTabBar* tab_bar);
static ImGuiTabItem* TabBarTabListPopupButton(ImGuiTabBar* tab_bar);
}
@@ -7128,12 +7160,12 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
sections[1].Spacing = sections[1].TabCount > 0 && sections[2].TabCount > 0 ? g.Style.ItemInnerSpacing.x : 0.0f;
// Setup next selected tab
- ImGuiID scroll_track_selected_tab_id = 0;
+ ImGuiID scroll_to_tab_id = 0;
if (tab_bar->NextSelectedTabId)
{
tab_bar->SelectedTabId = tab_bar->NextSelectedTabId;
tab_bar->NextSelectedTabId = 0;
- scroll_track_selected_tab_id = tab_bar->SelectedTabId;
+ scroll_to_tab_id = tab_bar->SelectedTabId;
}
// Process order change request (we could probably process it when requested but it's just saner to do it in a single spot).
@@ -7141,7 +7173,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
{
if (TabBarProcessReorder(tab_bar))
if (tab_bar->ReorderRequestTabId == tab_bar->SelectedTabId)
- scroll_track_selected_tab_id = tab_bar->ReorderRequestTabId;
+ scroll_to_tab_id = tab_bar->ReorderRequestTabId;
tab_bar->ReorderRequestTabId = 0;
}
@@ -7149,7 +7181,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
const bool tab_list_popup_button = (tab_bar->Flags & ImGuiTabBarFlags_TabListPopupButton) != 0;
if (tab_list_popup_button)
if (ImGuiTabItem* tab_to_select = TabBarTabListPopupButton(tab_bar)) // NB: Will alter BarRect.Min.x!
- scroll_track_selected_tab_id = tab_bar->SelectedTabId = tab_to_select->ID;
+ scroll_to_tab_id = tab_bar->SelectedTabId = tab_to_select->ID;
// Leading/Trailing tabs will be shrink only if central one aren't visible anymore, so layout the shrink data as: leading, trailing, central
// (whereas our tabs are stored as: leading, central, trailing)
@@ -7169,8 +7201,8 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
most_recently_selected_tab = tab;
if (tab->ID == tab_bar->SelectedTabId)
found_selected_tab_id = true;
- if (scroll_track_selected_tab_id == 0 && g.NavJustMovedToId == tab->ID)
- scroll_track_selected_tab_id = tab->ID;
+ if (scroll_to_tab_id == 0 && g.NavJustMovedToId == tab->ID)
+ scroll_to_tab_id = tab->ID;
// Refresh tab width immediately, otherwise changes of style e.g. style.FramePadding.x would noticeably lag in the tab bar.
// Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet,
@@ -7201,11 +7233,11 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
// Horizontal scrolling buttons
// (note that TabBarScrollButtons() will alter BarRect.Max.x)
if ((tab_bar->WidthAllTabsIdeal > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll))
- if (ImGuiTabItem* scroll_track_selected_tab = TabBarScrollingButtons(tab_bar))
+ if (ImGuiTabItem* scroll_and_select_tab = TabBarScrollingButtons(tab_bar))
{
- scroll_track_selected_tab_id = scroll_track_selected_tab->ID;
- if (!(scroll_track_selected_tab->Flags & ImGuiTabItemFlags_Button))
- tab_bar->SelectedTabId = scroll_track_selected_tab_id;
+ scroll_to_tab_id = scroll_and_select_tab->ID;
+ if ((scroll_and_select_tab->Flags & ImGuiTabItemFlags_Button) == 0)
+ tab_bar->SelectedTabId = scroll_to_tab_id;
}
// Shrink widths if full tabs don't fit in their allocated space
@@ -7269,7 +7301,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
if (found_selected_tab_id == false)
tab_bar->SelectedTabId = 0;
if (tab_bar->SelectedTabId == 0 && tab_bar->NextSelectedTabId == 0 && most_recently_selected_tab != NULL)
- scroll_track_selected_tab_id = tab_bar->SelectedTabId = most_recently_selected_tab->ID;
+ scroll_to_tab_id = tab_bar->SelectedTabId = most_recently_selected_tab->ID;
// Lock in visible tab
tab_bar->VisibleTabId = tab_bar->SelectedTabId;
@@ -7277,12 +7309,11 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
// CTRL+TAB can override visible tab temporarily
if (g.NavWindowingTarget != NULL && g.NavWindowingTarget->DockNode && g.NavWindowingTarget->DockNode->TabBar == tab_bar)
- tab_bar->VisibleTabId = scroll_track_selected_tab_id = g.NavWindowingTarget->ID;
+ tab_bar->VisibleTabId = scroll_to_tab_id = g.NavWindowingTarget->ID;
// Update scrolling
- if (scroll_track_selected_tab_id)
- if (ImGuiTabItem* scroll_track_selected_tab = TabBarFindTabByID(tab_bar, scroll_track_selected_tab_id))
- TabBarScrollToTab(tab_bar, scroll_track_selected_tab, sections);
+ if (scroll_to_tab_id != 0)
+ TabBarScrollToTab(tab_bar, scroll_to_tab_id, sections);
tab_bar->ScrollingAnim = TabBarScrollClamp(tab_bar, tab_bar->ScrollingAnim);
tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget);
if (tab_bar->ScrollingAnim != tab_bar->ScrollingTarget)
@@ -7412,8 +7443,12 @@ static float ImGui::TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling)
return ImMax(scrolling, 0.0f);
}
-static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, ImGuiTabBarSection* sections)
+// Note: we may scroll to tab that are not selected! e.g. using keyboard arrow keys
+static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGuiTabBarSection* sections)
{
+ ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id);
+ if (tab == NULL)
+ return;
if (tab->Flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing))
return;
@@ -7983,7 +8018,7 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI
draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding + 0.5f, y1 + rounding + 0.5f), rounding, 6, 9);
draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding - 0.5f, y1 + rounding + 0.5f), rounding, 9, 12);
draw_list->PathLineTo(ImVec2(bb.Max.x - 0.5f, y2));
- draw_list->PathStroke(GetColorU32(ImGuiCol_Border), false, g.Style.TabBorderSize);
+ draw_list->PathStroke(GetColorU32(ImGuiCol_Border), 0, g.Style.TabBorderSize);
}
}
diff --git a/imgui/misc/freetype/imgui_freetype.cpp b/imgui/misc/freetype/imgui_freetype.cpp
index db1b68e5..c4120778 100644
--- a/imgui/misc/freetype/imgui_freetype.cpp
+++ b/imgui/misc/freetype/imgui_freetype.cpp
@@ -6,6 +6,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
+// 2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs.
+// 2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a prefered texture format.
// 2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+).
// 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'.
// renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas().
@@ -105,7 +107,7 @@ namespace
FT_Int OffsetX; // The distance from the origin ("pen position") to the left of the glyph.
FT_Int OffsetY; // The distance from the origin to the top of the glyph. This is usually a value < 0.
float AdvanceX; // The distance from the origin to the origin of the next glyph. This is usually a value > 0.
- bool IsColored;
+ bool IsColored; // The glyph is colored
};
// Font parameters and metrics.
@@ -151,12 +153,13 @@ namespace
if (error != 0)
return false;
- memset(&Info, 0, sizeof(Info));
- SetPixelHeight((uint32_t)cfg.SizePixels);
-
// Convert to FreeType flags (NB: Bold and Oblique are processed separately)
UserFlags = cfg.FontBuilderFlags | extra_font_builder_flags;
- LoadFlags = FT_LOAD_NO_BITMAP;
+
+ LoadFlags = 0;
+ if ((UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) == 0)
+ LoadFlags |= FT_LOAD_NO_BITMAP;
+
if (UserFlags & ImGuiFreeTypeBuilderFlags_NoHinting)
LoadFlags |= FT_LOAD_NO_HINTING;
if (UserFlags & ImGuiFreeTypeBuilderFlags_NoAutoHint)
@@ -178,6 +181,9 @@ namespace
if (UserFlags & ImGuiFreeTypeBuilderFlags_LoadColor)
LoadFlags |= FT_LOAD_COLOR;
+ memset(&Info, 0, sizeof(Info));
+ SetPixelHeight((uint32_t)cfg.SizePixels);
+
return true;
}
@@ -196,7 +202,7 @@ namespace
// is a maximum height of an any given glyph, i.e. it's the sum of font's ascender and descender. Seems strange to me.
// NB: FT_Set_Pixel_Sizes() doesn't seem to get us the same result.
FT_Size_RequestRec req;
- req.type = FT_SIZE_REQUEST_TYPE_REAL_DIM;
+ req.type = (UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM;
req.width = 0;
req.height = (uint32_t)pixel_height * 64;
req.horiResolution = 0;
@@ -224,7 +230,7 @@ namespace
// Need an outline for this to work
FT_GlyphSlot slot = Face->glyph;
- IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE);
+ IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP);
// Apply convenience transform (this is not picking from real "Bold"/"Italic" fonts! Merely applying FreeType helper transform. Oblique == Slanting)
if (UserFlags & ImGuiFreeTypeBuilderFlags_Bold)
@@ -605,6 +611,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
// 8. Copy rasterized font characters back into the main texture
// 9. Setup ImFont and glyphs for runtime
+ bool tex_use_colors = false;
for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
{
ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
@@ -668,13 +675,15 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
float v1 = (ty + info.Height) / (float)atlas->TexHeight;
dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX);
- IM_ASSERT(dst_font->Glyphs.back().Codepoint == src_glyph.Codepoint);
+ ImFontGlyph* dst_glyph = &dst_font->Glyphs.back();
+ IM_ASSERT(dst_glyph->Codepoint == src_glyph.Codepoint);
if (src_glyph.Info.IsColored)
- dst_font->Glyphs.back().Colored = true;
+ dst_glyph->Colored = tex_use_colors = true;
}
src_tmp.Rects = NULL;
}
+ atlas->TexPixelsUseColors = tex_use_colors;
// Cleanup
for (int buf_i = 0; buf_i < buf_bitmap_buffers.Size; buf_i++)
diff --git a/imgui/misc/freetype/imgui_freetype.h b/imgui/misc/freetype/imgui_freetype.h
index d570f83a..713e4639 100644
--- a/imgui/misc/freetype/imgui_freetype.h
+++ b/imgui/misc/freetype/imgui_freetype.h
@@ -26,7 +26,8 @@ enum ImGuiFreeTypeBuilderFlags
ImGuiFreeTypeBuilderFlags_Bold = 1 << 5, // Styling: Should we artificially embolden the font?
ImGuiFreeTypeBuilderFlags_Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style?
ImGuiFreeTypeBuilderFlags_Monochrome = 1 << 7, // Disable anti-aliasing. Combine this with MonoHinting for best results!
- ImGuiFreeTypeBuilderFlags_LoadColor = 1 << 8 // Enable FreeType color-layered glyphs
+ ImGuiFreeTypeBuilderFlags_LoadColor = 1 << 8, // Enable FreeType color-layered glyphs
+ ImGuiFreeTypeBuilderFlags_Bitmap = 1 << 9 // Enable FreeType bitmap glyphs
};
namespace ImGuiFreeType
diff --git a/profiler/src/imgui_impl_glfw.cpp b/profiler/src/imgui_impl_glfw.cpp
index 3344b7bd..b8b7f912 100644
--- a/profiler/src/imgui_impl_glfw.cpp
+++ b/profiler/src/imgui_impl_glfw.cpp
@@ -179,7 +179,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
#endif
io.BackendPlatformName = "imgui_impl_glfw";
- // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
+ // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB;
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
@@ -567,7 +567,7 @@ static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
glfwWindowHint(GLFW_VISIBLE, false);
glfwWindowHint(GLFW_FOCUSED, false);
#if GLFW_HAS_FOCUS_ON_SHOW
- glfwWindowHint(GLFW_FOCUS_ON_SHOW, false);
+ glfwWindowHint(GLFW_FOCUS_ON_SHOW, false);
#endif
glfwWindowHint(GLFW_DECORATED, (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? false : true);
#if GLFW_HAS_WINDOW_TOPMOST
@@ -773,7 +773,7 @@ static void ImGui_ImplGlfw_SwapBuffers(ImGuiViewport* viewport, void*)
//--------------------------------------------------------------------------------------------------------
// We provide a Win32 implementation because this is such a common issue for IME users
-#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(__GNUC__)
+#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
#define HAS_WIN32_IME 1
#include <imm.h>
#ifdef _MSC_VER
diff --git a/profiler/src/imgui_impl_opengl3.cpp b/profiler/src/imgui_impl_opengl3.cpp
index f0d54676..f6883c51 100644
--- a/profiler/src/imgui_impl_opengl3.cpp
+++ b/profiler/src/imgui_impl_opengl3.cpp
@@ -15,6 +15,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
+// 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer.
// 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state.
// 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state.
// 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x)
@@ -258,7 +259,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);