|
|
@@ -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).
|
|
|
@@ -375,6 +376,9 @@ CODE
|
|
|
When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
|
|
|
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
|
|
|
|
|
|
+ - 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).
|
|
|
@@ -885,6 +889,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
|
|
|
@@ -911,27 +916,33 @@ static void UpdateViewportsNewFrame();
|
|
|
// [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); }
|
|
|
@@ -939,10 +950,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)
|
|
|
@@ -988,7 +998,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);
|
|
|
@@ -3018,6 +3028,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;
|
|
|
@@ -3116,20 +3127,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;
|
|
|
|
|
|
@@ -3284,7 +3297,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()
|
|
|
@@ -3293,7 +3306,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()
|
|
|
@@ -3330,13 +3343,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);
|
|
|
@@ -3541,7 +3562,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.HoveredRootWindow;
|
|
|
+ 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)
|
|
|
@@ -3684,7 +3705,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);
|
|
|
@@ -3778,7 +3799,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->RootWindow, modal_window))
|
|
|
clear_hovered_windows = true;
|
|
|
|
|
|
// Disabled mouse?
|
|
|
@@ -3806,7 +3827,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)
|
|
|
@@ -3841,7 +3862,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--)
|
|
|
@@ -3880,7 +3901,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;
|
|
|
@@ -4130,7 +4151,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();
|
|
|
@@ -4534,7 +4555,6 @@ static void FindHoveredWindow()
|
|
|
}
|
|
|
|
|
|
g.HoveredWindow = hovered_window;
|
|
|
- g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL;
|
|
|
g.HoveredWindowUnderMovingWindow = hovered_window_ignoring_moving_window;
|
|
|
}
|
|
|
|
|
|
@@ -4812,6 +4832,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);
|
|
|
@@ -5000,6 +5022,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
|
|
|
@@ -5373,9 +5397,9 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
|
|
|
if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindow == 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)
|
|
|
{
|
|
|
@@ -5430,7 +5454,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))
|
|
|
{
|
|
|
@@ -5706,9 +5730,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);
|
|
|
@@ -6358,11 +6379,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);
|
|
|
}
|
|
|
|
|
|
@@ -6417,6 +6439,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;
|
|
|
@@ -6540,30 +6563,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.HoveredRootWindow != g.CurrentWindow->RootWindow)
|
|
|
+ if (g.HoveredWindow->RootWindow != window->RootWindow)
|
|
|
return false;
|
|
|
break;
|
|
|
case ImGuiHoveredFlags_RootWindow:
|
|
|
- if (g.HoveredWindow != g.CurrentWindow->RootWindow)
|
|
|
+ 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;
|
|
|
}
|
|
|
@@ -7058,7 +7079,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);
|
|
|
@@ -7631,6 +7652,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;
|
|
|
|
|
|
@@ -7684,6 +7706,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;
|
|
|
@@ -8453,26 +8480,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)
|
|
|
@@ -8771,7 +8791,7 @@ void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags mov
|
|
|
static void ImGui::NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window)
|
|
|
{
|
|
|
ImGuiWindow* parent = nav_window;
|
|
|
- while (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;
|
|
|
@@ -8786,17 +8806,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 (layer == 0 && window->NavLastIds[0] != 0)
|
|
|
- ImGui::SetNavIDWithRectRel(window->NavLastIds[0], layer, 0, window->NavRectRel[0]);
|
|
|
+ if (window->NavLastIds[layer] != 0)
|
|
|
+ {
|
|
|
+ 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()
|
|
|
@@ -8814,12 +8840,12 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
|
|
|
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;
|
|
|
@@ -8907,17 +8933,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 );
|
|
|
@@ -8938,7 +8964,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;
|
|
|
@@ -8963,13 +8989,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;
|
|
|
@@ -8998,18 +9022,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)
|
|
|
+ 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)
|
|
|
{
|
|
|
@@ -9136,7 +9157,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));
|
|
|
@@ -9151,7 +9172,7 @@ static void ImGui::NavUpdate()
|
|
|
}
|
|
|
|
|
|
// For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items)
|
|
|
- ImRect nav_rect_rel = g.NavWindow ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0);
|
|
|
+ ImRect nav_rect_rel = g.NavWindow && !g.NavWindow->NavRectRel[g.NavLayer].IsInverted() ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0);
|
|
|
g.NavScoringRect = g.NavWindow ? ImRect(g.NavWindow->Pos + nav_rect_rel.Min, g.NavWindow->Pos + nav_rect_rel.Max) : ImRect(0, 0, 0, 0);
|
|
|
g.NavScoringRect.TranslateY(nav_scoring_rect_offset_y);
|
|
|
g.NavScoringRect.Min.x = ImMin(g.NavScoringRect.Min.x + 1.0f, g.NavScoringRect.Max.x);
|
|
|
@@ -9178,11 +9199,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
|
|
|
@@ -9245,7 +9267,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
|
|
|
@@ -9449,12 +9473,12 @@ static void ImGui::NavUpdateWindowing()
|
|
|
g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow; // FIXME-DOCK: Will need to use RootWindowDockStop
|
|
|
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));
|
|
|
@@ -9480,7 +9504,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
|
|
|
@@ -9502,9 +9526,9 @@ 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)
|
|
|
{
|
|
|
@@ -9555,8 +9579,10 @@ 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.
|
|
|
+ // Reinitialize navigation when entering menu bar with the Alt key.
|
|
|
const ImGuiNavLayer new_nav_layer = (g.NavWindow->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((int)g.NavLayer ^ 1) : ImGuiNavLayer_Main;
|
|
|
+ if (new_nav_layer == ImGuiNavLayer_Menu)
|
|
|
+ g.NavWindow->NavLastIds[new_nav_layer] = 0;
|
|
|
NavRestoreLayer(new_nav_layer);
|
|
|
}
|
|
|
}
|
|
|
@@ -9620,27 +9646,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))
|
|
|
@@ -9667,10 +9711,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();
|
|
|
@@ -9873,7 +9913,7 @@ 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));
|
|
|
@@ -9912,14 +9952,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);
|
|
|
@@ -9930,9 +9964,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.
|
|
|
@@ -10623,7 +10677,7 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
|
|
|
#endif
|
|
|
|
|
|
// Win32 API IME support (for Asian languages, etc.)
|
|
|
-#if defined(_WIN32) && !defined(__GNUC__) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
|
|
|
+#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
|
|
|
|
|
|
#include <imm.h>
|
|
|
#ifdef _MSC_VER
|
|
|
@@ -11007,7 +11061,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->RootWindow->Name : "NULL");
|
|
|
Text("HoveredWindowUnderMovingWindow: '%s'", g.HoveredWindowUnderMovingWindow ? g.HoveredWindowUnderMovingWindow->Name : "NULL");
|
|
|
Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL");
|
|
|
Unindent();
|
|
|
@@ -11195,7 +11249,7 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list,
|
|
|
{
|
|
|
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;
|
|
|
}
|
|
|
}
|
|
|
@@ -11222,7 +11276,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)
|
|
|
@@ -11292,7 +11346,7 @@ void ImGui::DebugNodeViewport(ImGuiViewportP* viewport)
|
|
|
viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y,
|
|
|
viewport->WorkOffsetMin.x, viewport->WorkOffsetMin.y, viewport->WorkOffsetMax.x, viewport->WorkOffsetMax.y);
|
|
|
BulletText("Flags: 0x%04X =%s%s%s", viewport->Flags,
|
|
|
- (flags & ImGuiViewportFlags_IsPlatformWindow) ? " IsPlatformWindow" : "",
|
|
|
+ (flags & ImGuiViewportFlags_IsPlatformWindow) ? " IsPlatformWindow" : "",
|
|
|
(flags & ImGuiViewportFlags_IsPlatformMonitor) ? " IsPlatformMonitor" : "",
|
|
|
(flags & ImGuiViewportFlags_OwnedByApp) ? " OwnedByApp" : "");
|
|
|
for (int layer_i = 0; layer_i < IM_ARRAYSIZE(viewport->DrawDataBuilder.Layers); layer_i++)
|