1058#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
1059#define _CRT_SECURE_NO_WARNINGS
1062#ifndef IMGUI_DEFINE_MATH_OPERATORS
1063#define IMGUI_DEFINE_MATH_OPERATORS
1067#ifndef IMGUI_DISABLE
1068#include "imgui_internal.h"
1075#if defined(_WIN32) && !defined(_MSC_VER) && !defined(IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
1076#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
1080#if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && defined(IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
1081#define IMGUI_DISABLE_WIN32_FUNCTIONS
1083#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
1084#ifndef WIN32_LEAN_AND_MEAN
1085#define WIN32_LEAN_AND_MEAN
1095#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP || WINAPI_FAMILY == WINAPI_FAMILY_GAMES)
1097#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
1098#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
1099#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
1104#if defined(__APPLE__)
1105#include <TargetConditionals.h>
1110#pragma warning (disable: 4127)
1111#pragma warning (disable: 4996)
1112#if defined(_MSC_VER) && _MSC_VER >= 1922
1113#pragma warning (disable: 5054)
1115#pragma warning (disable: 26451)
1116#pragma warning (disable: 26495)
1117#pragma warning (disable: 26812)
1121#if defined(__clang__)
1122#if __has_warning("-Wunknown-warning-option")
1123#pragma clang diagnostic ignored "-Wunknown-warning-option"
1125#pragma clang diagnostic ignored "-Wunknown-pragmas"
1126#pragma clang diagnostic ignored "-Wold-style-cast"
1127#pragma clang diagnostic ignored "-Wfloat-equal"
1128#pragma clang diagnostic ignored "-Wformat-nonliteral"
1129#pragma clang diagnostic ignored "-Wexit-time-destructors"
1130#pragma clang diagnostic ignored "-Wglobal-constructors"
1131#pragma clang diagnostic ignored "-Wsign-conversion"
1132#pragma clang diagnostic ignored "-Wformat-pedantic"
1133#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"
1134#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
1135#pragma clang diagnostic ignored "-Wdouble-promotion"
1136#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
1137#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
1138#elif defined(__GNUC__)
1140#pragma GCC diagnostic ignored "-Wpragmas"
1141#pragma GCC diagnostic ignored "-Wunused-function"
1142#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
1143#pragma GCC diagnostic ignored "-Wformat"
1144#pragma GCC diagnostic ignored "-Wdouble-promotion"
1145#pragma GCC diagnostic ignored "-Wconversion"
1146#pragma GCC diagnostic ignored "-Wformat-nonliteral"
1147#pragma GCC diagnostic ignored "-Wstrict-overflow"
1148#pragma GCC diagnostic ignored "-Wclass-memaccess"
1152#define IMGUI_DEBUG_NAV_SCORING 0
1153#define IMGUI_DEBUG_NAV_RECTS 0
1156static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f;
1157static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f;
1159static const float NAV_ACTIVATE_HIGHLIGHT_TIMER = 0.10f;
1162static const float WINDOWS_HOVER_PADDING = 4.0f;
1163static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f;
1164static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 0.70f;
1167static const ImVec2 TOOLTIP_DEFAULT_OFFSET_MOUSE = ImVec2(16, 10);
1168static const ImVec2 TOOLTIP_DEFAULT_OFFSET_TOUCH = ImVec2(0, -20);
1169static const ImVec2 TOOLTIP_DEFAULT_PIVOT_TOUCH = ImVec2(0.5f, 1.0f);
1172static const float DOCKING_TRANSPARENT_PAYLOAD_ALPHA = 0.50f;
1178static void SetCurrentWindow(ImGuiWindow* window);
1179static ImGuiWindow* CreateNewWindow(
const char* name, ImGuiWindowFlags flags);
1180static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window);
1182static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
1185static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*);
1186static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*,
const char* name);
1187static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
void* entry,
const char* line);
1188static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*);
1189static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf);
1192static const char* Platform_GetClipboardTextFn_DefaultImpl(ImGuiContext* ctx);
1193static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext* ctx,
const char* text);
1194static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data);
1195static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext* ctx,
const char* path);
1200static void ItemHandleShortcut(ImGuiID
id);
1203static void NavUpdate();
1204static void NavUpdateWindowing();
1205static void NavUpdateWindowingOverlay();
1206static void NavUpdateCancelRequest();
1207static void NavUpdateCreateMoveRequest();
1208static void NavUpdateCreateTabbingRequest();
1209static float NavUpdatePageUpPageDown();
1210static inline void NavUpdateAnyRequestFlag();
1211static void NavUpdateCreateWrappingRequest();
1212static void NavEndFrame();
1213static bool NavScoreItem(ImGuiNavItemData* result);
1214static void NavApplyItemToResult(ImGuiNavItemData* result);
1215static void NavProcessItem();
1216static void NavProcessItemForTabbingRequest(ImGuiID
id, ImGuiItemFlags item_flags, ImGuiNavMoveFlags move_flags);
1217static ImGuiInputSource NavCalcPreferredRefPosSource();
1218static ImVec2 NavCalcPreferredRefPos();
1219static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
1220static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
1221static void NavRestoreLayer(ImGuiNavLayer layer);
1222static int FindWindowFocusIndex(ImGuiWindow* window);
1225static void ErrorCheckNewFrameSanityChecks();
1226static void ErrorCheckEndFrameSanityChecks();
1227static void UpdateDebugToolItemPicker();
1228static void UpdateDebugToolStackQueries();
1229static void UpdateDebugToolFlashStyleColor();
1232static void UpdateKeyboardInputs();
1233static void UpdateMouseInputs();
1234static void UpdateMouseWheel();
1235static void UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt);
1238static void UpdateSettings();
1239static int UpdateWindowManualResize(ImGuiWindow* window,
const ImVec2& size_auto_fit,
int* border_hovered,
int* border_held,
int resize_grip_count, ImU32 resize_grip_col[4],
const ImRect& visibility_rect);
1240static void RenderWindowOuterBorders(ImGuiWindow* window);
1241static void RenderWindowDecorations(ImGuiWindow* window,
const ImRect& title_bar_rect,
bool title_bar_is_highlight,
bool handle_borders_and_resize_grips,
int resize_grip_count,
const ImU32 resize_grip_col[4],
float resize_grip_draw_size);
1242static void RenderWindowTitleBarContents(ImGuiWindow* window,
const ImRect& title_bar_rect,
const char* name,
bool* p_open);
1243static void RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col);
1244static void RenderDimmedBackgrounds();
1245static void SetLastItemDataForWindow(ImGuiWindow* window,
const ImRect& rect);
1249static ImGuiViewportP* AddUpdateViewport(ImGuiWindow* window, ImGuiID
id,
const ImVec2& platform_pos,
const ImVec2& size, ImGuiViewportFlags flags);
1250static void DestroyViewport(ImGuiViewportP* viewport);
1251static void UpdateViewportsNewFrame();
1252static void UpdateViewportsEndFrame();
1253static void WindowSelectViewport(ImGuiWindow* window);
1254static void WindowSyncOwnedViewport(ImGuiWindow* window, ImGuiWindow* parent_window_in_stack);
1255static bool UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* host_viewport);
1256static bool UpdateTryMergeWindowIntoHostViewports(ImGuiWindow* window);
1257static bool GetWindowAlwaysWantOwnViewport(ImGuiWindow* window);
1258static int FindPlatformMonitorForPos(
const ImVec2& pos);
1259static int FindPlatformMonitorForRect(
const ImRect& r);
1260static void UpdateViewportPlatformMonitor(ImGuiViewportP* viewport);
1295#ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS
1296static void* MallocWrapper(
size_t size,
void* user_data) { IM_UNUSED(user_data);
return malloc(size); }
1297static void FreeWrapper(
void* ptr,
void* user_data) { IM_UNUSED(user_data); free(ptr); }
1299static void* MallocWrapper(
size_t size,
void* user_data) { IM_UNUSED(user_data); IM_UNUSED(size); IM_ASSERT(0);
return NULL; }
1300static void FreeWrapper(
void* ptr,
void* user_data) { IM_UNUSED(user_data); IM_UNUSED(ptr); IM_ASSERT(0); }
1302static ImGuiMemAllocFunc GImAllocatorAllocFunc = MallocWrapper;
1303static ImGuiMemFreeFunc GImAllocatorFreeFunc = FreeWrapper;
1304static void* GImAllocatorUserData = NULL;
1310ImGuiStyle::ImGuiStyle()
1313 DisabledAlpha = 0.60f;
1314 WindowPadding = ImVec2(8,8);
1315 WindowRounding = 0.0f;
1316 WindowBorderSize = 1.0f;
1317 WindowMinSize = ImVec2(32,32);
1318 WindowTitleAlign = ImVec2(0.0f,0.5f);
1319 WindowMenuButtonPosition = ImGuiDir_Left;
1320 ChildRounding = 0.0f;
1321 ChildBorderSize = 1.0f;
1322 PopupRounding = 0.0f;
1323 PopupBorderSize = 1.0f;
1324 FramePadding = ImVec2(4,3);
1325 FrameRounding = 0.0f;
1326 FrameBorderSize = 0.0f;
1327 ItemSpacing = ImVec2(8,4);
1328 ItemInnerSpacing = ImVec2(4,4);
1329 CellPadding = ImVec2(4,2);
1330 TouchExtraPadding = ImVec2(0,0);
1331 IndentSpacing = 21.0f;
1332 ColumnsMinSpacing = 6.0f;
1333 ScrollbarSize = 14.0f;
1334 ScrollbarRounding = 9.0f;
1335 GrabMinSize = 12.0f;
1336 GrabRounding = 0.0f;
1337 LogSliderDeadzone = 4.0f;
1339 TabBorderSize = 0.0f;
1340 TabMinWidthForCloseButton = 0.0f;
1341 TabBarBorderSize = 1.0f;
1342 TabBarOverlineSize = 2.0f;
1343 TableAngledHeadersAngle = 35.0f * (IM_PI / 180.0f);
1344 TableAngledHeadersTextAlign = ImVec2(0.5f,0.0f);
1345 ColorButtonPosition = ImGuiDir_Right;
1346 ButtonTextAlign = ImVec2(0.5f,0.5f);
1347 SelectableTextAlign = ImVec2(0.0f,0.0f);
1348 SeparatorTextBorderSize = 3.0f;
1349 SeparatorTextAlign = ImVec2(0.0f,0.5f);
1350 SeparatorTextPadding = ImVec2(20.0f,3.f);
1351 DisplayWindowPadding = ImVec2(19,19);
1352 DisplaySafeAreaPadding = ImVec2(3,3);
1353 DockingSeparatorSize = 2.0f;
1354 MouseCursorScale = 1.0f;
1355 AntiAliasedLines =
true;
1356 AntiAliasedLinesUseTex =
true;
1357 AntiAliasedFill =
true;
1358 CurveTessellationTol = 1.25f;
1359 CircleTessellationMaxError = 0.30f;
1362 HoverStationaryDelay = 0.15f;
1363 HoverDelayShort = 0.15f;
1364 HoverDelayNormal = 0.40f;
1365 HoverFlagsForTooltipMouse = ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_AllowWhenDisabled;
1366 HoverFlagsForTooltipNav = ImGuiHoveredFlags_NoSharedDelay | ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_AllowWhenDisabled;
1369 ImGui::StyleColorsDark(
this);
1374void ImGuiStyle::ScaleAllSizes(
float scale_factor)
1376 WindowPadding = ImTrunc(WindowPadding * scale_factor);
1377 WindowRounding = ImTrunc(WindowRounding * scale_factor);
1378 WindowMinSize = ImTrunc(WindowMinSize * scale_factor);
1379 ChildRounding = ImTrunc(ChildRounding * scale_factor);
1380 PopupRounding = ImTrunc(PopupRounding * scale_factor);
1381 FramePadding = ImTrunc(FramePadding * scale_factor);
1382 FrameRounding = ImTrunc(FrameRounding * scale_factor);
1383 ItemSpacing = ImTrunc(ItemSpacing * scale_factor);
1384 ItemInnerSpacing = ImTrunc(ItemInnerSpacing * scale_factor);
1385 CellPadding = ImTrunc(CellPadding * scale_factor);
1386 TouchExtraPadding = ImTrunc(TouchExtraPadding * scale_factor);
1387 IndentSpacing = ImTrunc(IndentSpacing * scale_factor);
1388 ColumnsMinSpacing = ImTrunc(ColumnsMinSpacing * scale_factor);
1389 ScrollbarSize = ImTrunc(ScrollbarSize * scale_factor);
1390 ScrollbarRounding = ImTrunc(ScrollbarRounding * scale_factor);
1391 GrabMinSize = ImTrunc(GrabMinSize * scale_factor);
1392 GrabRounding = ImTrunc(GrabRounding * scale_factor);
1393 LogSliderDeadzone = ImTrunc(LogSliderDeadzone * scale_factor);
1394 TabRounding = ImTrunc(TabRounding * scale_factor);
1395 TabMinWidthForCloseButton = (TabMinWidthForCloseButton != FLT_MAX) ? ImTrunc(TabMinWidthForCloseButton * scale_factor) : FLT_MAX;
1396 TabBarOverlineSize = ImTrunc(TabBarOverlineSize * scale_factor);
1397 SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor);
1398 DockingSeparatorSize = ImTrunc(DockingSeparatorSize * scale_factor);
1399 DisplayWindowPadding = ImTrunc(DisplayWindowPadding * scale_factor);
1400 DisplaySafeAreaPadding = ImTrunc(DisplaySafeAreaPadding * scale_factor);
1401 MouseCursorScale = ImTrunc(MouseCursorScale * scale_factor);
1407 memset(
this, 0,
sizeof(*
this));
1408 IM_STATIC_ASSERT(IM_ARRAYSIZE(ImGuiIO::MouseDown) == ImGuiMouseButton_COUNT && IM_ARRAYSIZE(ImGuiIO::MouseClicked) == ImGuiMouseButton_COUNT);
1411 ConfigFlags = ImGuiConfigFlags_None;
1412 BackendFlags = ImGuiBackendFlags_None;
1413 DisplaySize = ImVec2(-1.0f, -1.0f);
1414 DeltaTime = 1.0f / 60.0f;
1415 IniSavingRate = 5.0f;
1416 IniFilename =
"imgui.ini";
1417 LogFilename =
"imgui_log.txt";
1418#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
1419 for (
int i = 0; i < ImGuiKey_COUNT; i++)
1425 FontGlobalScale = 1.0f;
1427 FontAllowUserScaling =
false;
1428 DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
1431 ConfigNavSwapGamepadButtons =
false;
1432 ConfigNavMoveSetMousePos =
false;
1433 ConfigNavCaptureKeyboard =
true;
1434 ConfigNavEscapeClearFocusItem =
true;
1435 ConfigNavEscapeClearFocusWindow =
false;
1436 ConfigNavCursorVisibleAuto =
true;
1437 ConfigNavCursorVisibleAlways =
false;
1440 ConfigDockingNoSplit =
false;
1441 ConfigDockingWithShift =
false;
1442 ConfigDockingAlwaysTabBar =
false;
1443 ConfigDockingTransparentPayload =
false;
1446 ConfigViewportsNoAutoMerge =
false;
1447 ConfigViewportsNoTaskBarIcon =
false;
1448 ConfigViewportsNoDecoration =
true;
1449 ConfigViewportsNoDefaultParent =
false;
1452 MouseDrawCursor =
false;
1454 ConfigMacOSXBehaviors =
true;
1456 ConfigMacOSXBehaviors =
false;
1458 ConfigInputTrickleEventQueue =
true;
1459 ConfigInputTextCursorBlink =
true;
1460 ConfigInputTextEnterKeepActive =
false;
1461 ConfigDragClickToInputText =
false;
1462 ConfigWindowsResizeFromEdges =
true;
1463 ConfigWindowsMoveFromTitleBarOnly =
false;
1464 ConfigScrollbarScrollByPage =
true;
1465 ConfigMemoryCompactTimer = 60.0f;
1466 ConfigDebugIsDebuggerPresent =
false;
1467 ConfigDebugHighlightIdConflicts =
true;
1468 ConfigDebugBeginReturnValueOnce =
false;
1469 ConfigDebugBeginReturnValueLoop =
false;
1471 ConfigErrorRecovery =
true;
1472 ConfigErrorRecoveryEnableAssert =
true;
1473 ConfigErrorRecoveryEnableDebugLog =
true;
1474 ConfigErrorRecoveryEnableTooltip =
true;
1477 MouseDoubleClickTime = 0.30f;
1478 MouseDoubleClickMaxDist = 6.0f;
1479 MouseDragThreshold = 6.0f;
1480 KeyRepeatDelay = 0.275f;
1481 KeyRepeatRate = 0.050f;
1485 BackendPlatformName = BackendRendererName = NULL;
1486 BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL;
1489 MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
1490 MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX);
1491 MouseSource = ImGuiMouseSource_Mouse;
1492 for (
int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
1493 for (
int i = 0; i < IM_ARRAYSIZE(KeysData); i++) { KeysData[i].DownDuration = KeysData[i].DownDurationPrev = -1.0f; }
1494 AppAcceptingEvents =
true;
1495 BackendUsingLegacyKeyArrays = (ImS8)-1;
1496 BackendUsingLegacyNavInputArray =
true;
1503void ImGuiIO::AddInputCharacter(
unsigned int c)
1505 IM_ASSERT(Ctx != NULL);
1506 ImGuiContext&
g = *Ctx;
1507 if (c == 0 || !AppAcceptingEvents)
1511 e.Type = ImGuiInputEventType_Text;
1512 e.Source = ImGuiInputSource_Keyboard;
1513 e.EventId =
g.InputEventsNextEventId++;
1515 g.InputEventsQueue.push_back(e);
1520void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c)
1522 if ((c == 0 && InputQueueSurrogate == 0) || !AppAcceptingEvents)
1525 if ((c & 0xFC00) == 0xD800)
1527 if (InputQueueSurrogate != 0)
1528 AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID);
1529 InputQueueSurrogate = c;
1534 if (InputQueueSurrogate != 0)
1536 if ((c & 0xFC00) != 0xDC00)
1538 AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID);
1542#if IM_UNICODE_CODEPOINT_MAX == 0xFFFF
1543 cp = IM_UNICODE_CODEPOINT_INVALID;
1545 cp = (ImWchar)(((InputQueueSurrogate - 0xD800) << 10) + (c - 0xDC00) + 0x10000);
1549 InputQueueSurrogate = 0;
1551 AddInputCharacter((
unsigned)cp);
1554void ImGuiIO::AddInputCharactersUTF8(
const char* utf8_chars)
1556 if (!AppAcceptingEvents)
1558 while (*utf8_chars != 0)
1562 AddInputCharacter(c);
1567void ImGuiIO::ClearEventsQueue()
1569 IM_ASSERT(Ctx != NULL);
1570 ImGuiContext&
g = *Ctx;
1571 g.InputEventsQueue.clear();
1575void ImGuiIO::ClearInputKeys()
1577#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
1578 memset(KeysDown, 0,
sizeof(KeysDown));
1580 for (
int n = 0; n < IM_ARRAYSIZE(KeysData); n++)
1582 if (ImGui::IsMouseKey((ImGuiKey)(n + ImGuiKey_KeysData_OFFSET)))
1584 KeysData[n].Down =
false;
1585 KeysData[n].DownDuration = -1.0f;
1586 KeysData[n].DownDurationPrev = -1.0f;
1588 KeyCtrl = KeyShift = KeyAlt = KeySuper =
false;
1589 KeyMods = ImGuiMod_None;
1590 InputQueueCharacters.resize(0);
1593void ImGuiIO::ClearInputMouse()
1595 for (ImGuiKey key = ImGuiKey_Mouse_BEGIN; key < ImGuiKey_Mouse_END; key = (ImGuiKey)(key + 1))
1597 ImGuiKeyData* key_data = &KeysData[key - ImGuiKey_KeysData_OFFSET];
1598 key_data->Down =
false;
1599 key_data->DownDuration = -1.0f;
1600 key_data->DownDurationPrev = -1.0f;
1602 MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
1603 for (
int n = 0; n < IM_ARRAYSIZE(MouseDown); n++)
1605 MouseDown[n] =
false;
1606 MouseDownDuration[n] = MouseDownDurationPrev[n] = -1.0f;
1608 MouseWheel = MouseWheelH = 0.0f;
1613#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
1614void ImGuiIO::ClearInputCharacters()
1616 InputQueueCharacters.resize(0);
1620static ImGuiInputEvent* FindLatestInputEvent(ImGuiContext* ctx, ImGuiInputEventType type,
int arg = -1)
1622 ImGuiContext&
g = *ctx;
1623 for (
int n =
g.InputEventsQueue.Size - 1; n >= 0; n--)
1625 ImGuiInputEvent*
e = &
g.InputEventsQueue[n];
1626 if (
e->Type != type)
1628 if (type == ImGuiInputEventType_Key &&
e->Key.Key != arg)
1630 if (type == ImGuiInputEventType_MouseButton &&
e->MouseButton.Button != arg)
1643void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key,
bool down,
float analog_value)
1646 IM_ASSERT(Ctx != NULL);
1647 if (key == ImGuiKey_None || !AppAcceptingEvents)
1649 ImGuiContext&
g = *Ctx;
1650 IM_ASSERT(ImGui::IsNamedKeyOrMod(key));
1651 IM_ASSERT(ImGui::IsAliasKey(key) ==
false);
1654 if (
g.IO.ConfigMacOSXBehaviors)
1656 if (key == ImGuiMod_Super) { key = ImGuiMod_Ctrl; }
1657 else if (key == ImGuiMod_Ctrl) { key = ImGuiMod_Super; }
1658 else if (key == ImGuiKey_LeftSuper) { key = ImGuiKey_LeftCtrl; }
1659 else if (key == ImGuiKey_RightSuper){ key = ImGuiKey_RightCtrl; }
1660 else if (key == ImGuiKey_LeftCtrl) { key = ImGuiKey_LeftSuper; }
1661 else if (key == ImGuiKey_RightCtrl) { key = ImGuiKey_RightSuper; }
1665#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
1666 IM_ASSERT((BackendUsingLegacyKeyArrays == -1 || BackendUsingLegacyKeyArrays == 0) &&
"Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
1667 if (BackendUsingLegacyKeyArrays == -1)
1668 for (
int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++)
1669 IM_ASSERT(KeyMap[n] == -1 &&
"Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
1670 BackendUsingLegacyKeyArrays = 0;
1672 if (ImGui::IsGamepadKey(key))
1673 BackendUsingLegacyNavInputArray =
false;
1676 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_Key, (
int)key);
1677 const ImGuiKeyData* key_data = ImGui::GetKeyData(&
g, key);
1678 const bool latest_key_down = latest_event ? latest_event->Key.Down : key_data->Down;
1679 const float latest_key_analog = latest_event ? latest_event->Key.AnalogValue : key_data->AnalogValue;
1680 if (latest_key_down == down && latest_key_analog == analog_value)
1685 e.Type = ImGuiInputEventType_Key;
1686 e.Source = ImGui::IsGamepadKey(key) ? ImGuiInputSource_Gamepad : ImGuiInputSource_Keyboard;
1687 e.EventId =
g.InputEventsNextEventId++;
1690 e.Key.AnalogValue = analog_value;
1691 g.InputEventsQueue.push_back(e);
1694void ImGuiIO::AddKeyEvent(ImGuiKey key,
bool down)
1696 if (!AppAcceptingEvents)
1698 AddKeyAnalogEvent(key, down, down ? 1.0f : 0.0f);
1704void ImGuiIO::SetKeyEventNativeData(ImGuiKey key,
int native_keycode,
int native_scancode,
int native_legacy_index)
1706 if (key == ImGuiKey_None)
1708 IM_ASSERT(ImGui::IsNamedKey(key));
1709 IM_ASSERT(native_legacy_index == -1 || ImGui::IsLegacyKey((ImGuiKey)native_legacy_index));
1710 IM_UNUSED(native_keycode);
1711 IM_UNUSED(native_scancode);
1714#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
1715 const int legacy_key = (native_legacy_index != -1) ? native_legacy_index : native_keycode;
1716 if (!ImGui::IsLegacyKey((ImGuiKey)legacy_key))
1718 KeyMap[legacy_key] = key;
1719 KeyMap[key] = legacy_key;
1722 IM_UNUSED(native_legacy_index);
1727void ImGuiIO::SetAppAcceptingEvents(
bool accepting_events)
1729 AppAcceptingEvents = accepting_events;
1733void ImGuiIO::AddMousePosEvent(
float x,
float y)
1735 IM_ASSERT(Ctx != NULL);
1736 ImGuiContext&
g = *Ctx;
1737 if (!AppAcceptingEvents)
1741 ImVec2 pos((x > -FLT_MAX) ? ImFloor(x) : x, (y > -FLT_MAX) ? ImFloor(y) : y);
1744 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_MousePos);
1745 const ImVec2 latest_pos = latest_event ? ImVec2(latest_event->MousePos.PosX, latest_event->MousePos.PosY) :
g.IO.MousePos;
1746 if (latest_pos.x == pos.x && latest_pos.y == pos.y)
1750 e.Type = ImGuiInputEventType_MousePos;
1751 e.Source = ImGuiInputSource_Mouse;
1752 e.EventId =
g.InputEventsNextEventId++;
1753 e.MousePos.PosX = pos.x;
1754 e.MousePos.PosY = pos.y;
1755 e.MousePos.MouseSource =
g.InputEventsNextMouseSource;
1756 g.InputEventsQueue.push_back(e);
1759void ImGuiIO::AddMouseButtonEvent(
int mouse_button,
bool down)
1761 IM_ASSERT(Ctx != NULL);
1762 ImGuiContext&
g = *Ctx;
1763 IM_ASSERT(mouse_button >= 0 && mouse_button < ImGuiMouseButton_COUNT);
1764 if (!AppAcceptingEvents)
1768 if (ConfigMacOSXBehaviors && mouse_button == 0 && MouseCtrlLeftAsRightClick)
1773 MouseCtrlLeftAsRightClick =
false;
1777 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_MouseButton, (
int)mouse_button);
1778 const bool latest_button_down = latest_event ? latest_event->MouseButton.Down :
g.IO.MouseDown[mouse_button];
1779 if (latest_button_down == down)
1785 if (ConfigMacOSXBehaviors && mouse_button == 0 && down)
1787 const ImGuiInputEvent* latest_super_event = FindLatestInputEvent(&
g, ImGuiInputEventType_Key, (
int)ImGuiMod_Super);
1788 if (latest_super_event ? latest_super_event->Key.Down :
g.IO.KeySuper)
1790 IMGUI_DEBUG_LOG_IO(
"[io] Super+Left Click aliased into Right Click\n");
1791 MouseCtrlLeftAsRightClick =
true;
1792 AddMouseButtonEvent(1,
true);
1798 e.Type = ImGuiInputEventType_MouseButton;
1799 e.Source = ImGuiInputSource_Mouse;
1800 e.EventId =
g.InputEventsNextEventId++;
1801 e.MouseButton.Button = mouse_button;
1802 e.MouseButton.Down = down;
1803 e.MouseButton.MouseSource =
g.InputEventsNextMouseSource;
1804 g.InputEventsQueue.push_back(e);
1808void ImGuiIO::AddMouseWheelEvent(
float wheel_x,
float wheel_y)
1810 IM_ASSERT(Ctx != NULL);
1811 ImGuiContext&
g = *Ctx;
1814 if (!AppAcceptingEvents || (wheel_x == 0.0f && wheel_y == 0.0f))
1818 e.Type = ImGuiInputEventType_MouseWheel;
1819 e.Source = ImGuiInputSource_Mouse;
1820 e.EventId =
g.InputEventsNextEventId++;
1821 e.MouseWheel.WheelX = wheel_x;
1822 e.MouseWheel.WheelY = wheel_y;
1823 e.MouseWheel.MouseSource =
g.InputEventsNextMouseSource;
1824 g.InputEventsQueue.push_back(e);
1829void ImGuiIO::AddMouseSourceEvent(ImGuiMouseSource source)
1831 IM_ASSERT(Ctx != NULL);
1832 ImGuiContext&
g = *Ctx;
1833 g.InputEventsNextMouseSource = source;
1836void ImGuiIO::AddMouseViewportEvent(ImGuiID viewport_id)
1838 IM_ASSERT(Ctx != NULL);
1839 ImGuiContext&
g = *Ctx;
1841 if (!AppAcceptingEvents)
1845 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_MouseViewport);
1846 const ImGuiID latest_viewport_id = latest_event ? latest_event->MouseViewport.HoveredViewportID :
g.IO.MouseHoveredViewport;
1847 if (latest_viewport_id == viewport_id)
1851 e.Type = ImGuiInputEventType_MouseViewport;
1852 e.Source = ImGuiInputSource_Mouse;
1853 e.MouseViewport.HoveredViewportID = viewport_id;
1854 g.InputEventsQueue.push_back(e);
1857void ImGuiIO::AddFocusEvent(
bool focused)
1859 IM_ASSERT(Ctx != NULL);
1860 ImGuiContext&
g = *Ctx;
1863 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_Focus);
1864 const bool latest_focused = latest_event ? latest_event->AppFocused.Focused : !
g.IO.AppFocusLost;
1865 if (latest_focused == focused || (ConfigDebugIgnoreFocusLoss && !focused))
1869 e.Type = ImGuiInputEventType_Focus;
1870 e.EventId =
g.InputEventsNextEventId++;
1871 e.AppFocused.Focused = focused;
1872 g.InputEventsQueue.push_back(e);
1875ImGuiPlatformIO::ImGuiPlatformIO()
1878 memset(
this, 0,
sizeof(*
this));
1879 Platform_LocaleDecimalPoint =
'.';
1888 IM_ASSERT(num_segments > 0);
1891 float p_closest_dist2 = FLT_MAX;
1892 float t_step = 1.0f / (float)num_segments;
1893 for (
int i_step = 1; i_step <= num_segments; i_step++)
1897 float dist2 = ImLengthSqr(p - p_line);
1898 if (dist2 < p_closest_dist2)
1901 p_closest_dist2 = dist2;
1909static void ImBezierCubicClosestPointCasteljauStep(
const ImVec2& p, ImVec2& p_closest, ImVec2& p_last,
float& p_closest_dist2,
float x1,
float y1,
float x2,
float y2,
float x3,
float y3,
float x4,
float y4,
float tess_tol,
int level)
1913 float d2 = ((x2 - x4) * dy - (y2 - y4) * dx);
1914 float d3 = ((x3 - x4) * dy - (y3 - y4) * dx);
1915 d2 = (d2 >= 0) ? d2 : -d2;
1916 d3 = (d3 >= 0) ? d3 : -d3;
1917 if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy))
1919 ImVec2 p_current(x4, y4);
1921 float dist2 = ImLengthSqr(p - p_line);
1922 if (dist2 < p_closest_dist2)
1925 p_closest_dist2 = dist2;
1929 else if (level < 10)
1931 float x12 = (x1 + x2)*0.5f, y12 = (y1 + y2)*0.5f;
1932 float x23 = (x2 + x3)*0.5f, y23 = (y2 + y3)*0.5f;
1933 float x34 = (x3 + x4)*0.5f, y34 = (y3 + y4)*0.5f;
1934 float x123 = (x12 + x23)*0.5f, y123 = (y12 + y23)*0.5f;
1935 float x234 = (x23 + x34)*0.5f, y234 = (y23 + y34)*0.5f;
1936 float x1234 = (x123 + x234)*0.5f, y1234 = (y123 + y234)*0.5f;
1937 ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1);
1938 ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1);
1946 IM_ASSERT(tess_tol > 0.0f);
1949 float p_closest_dist2 = FLT_MAX;
1950 ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, p1.x, p1.y, p2.x, p2.y,
p3.x,
p3.y,
p4.x,
p4.y, tess_tol, 0);
1957 ImVec2 ab_dir = b - a;
1958 float dot = ap.x * ab_dir.x + ap.y * ab_dir.y;
1961 float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y;
1962 if (dot > ab_len_sqr)
1964 return a + ab_dir * dot / ab_len_sqr;
1969 bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f;
1970 bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f;
1971 bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f;
1972 return ((b1 == b2) && (b2 == b3));
1980 const float denom = v0.x * v1.y - v1.x * v0.y;
1981 out_v = (v2.x * v1.y - v1.x * v2.y) / denom;
1982 out_w = (v0.x * v2.y - v2.x * v0.y) / denom;
1983 out_u = 1.0f - out_v - out_w;
1991 float dist2_ab = ImLengthSqr(p - proj_ab);
1992 float dist2_bc = ImLengthSqr(p - proj_bc);
1993 float dist2_ca = ImLengthSqr(p - proj_ca);
1994 float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca));
2010 while ((d = ImToUpper(*str2) - ImToUpper(*str1)) == 0 && *str1) { str1++; str2++; }
2017 while (count > 0 && (d = ImToUpper(*str2) - ImToUpper(*str1)) == 0 && *str1) { str1++; str2++; count--; }
2026 strncpy(dst, src, count - 1);
2032 size_t len = strlen(str);
2033 void* buf = IM_ALLOC(len + 1);
2034 return (
char*)memcpy(buf, (
const void*)str, len + 1);
2039 size_t dst_buf_size = p_dst_size ? *p_dst_size : strlen(dst) + 1;
2040 size_t src_size = strlen(src) + 1;
2041 if (dst_buf_size < src_size)
2044 dst = (
char*)IM_ALLOC(src_size);
2046 *p_dst_size = src_size;
2048 return (
char*)memcpy(dst, (
const void*)src, src_size);
2053 const char* p = (
const char*)memchr(str, (
int)c, str_end - str);
2068 const char* p = (
const char*)memchr(str,
'\n', str_end - str);
2069 return p ? p : str_end;
2072const char*
ImStrbol(
const char* buf_mid_line,
const char* buf_begin)
2074 while (buf_mid_line > buf_begin && buf_mid_line[-1] !=
'\n')
2076 return buf_mid_line;
2079const char*
ImStristr(
const char* haystack,
const char* haystack_end,
const char* needle,
const char* needle_end)
2082 needle_end = needle + strlen(needle);
2084 const char un0 = (char)ImToUpper(*needle);
2085 while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))
2087 if (ImToUpper(*haystack) == un0)
2089 const char* b = needle + 1;
2090 for (
const char* a = haystack + 1; b < needle_end; a++, b++)
2091 if (ImToUpper(*a) != ImToUpper(*b))
2093 if (b == needle_end)
2105 while (p[0] ==
' ' || p[0] ==
'\t')
2110 while (p > p_start && (p[-1] ==
' ' || p[-1] ==
'\t'))
2113 memmove(buf, p_start, p - p_start);
2114 buf[p - p_start] = 0;
2119 while (str[0] ==
' ' || str[0] ==
'\t')
2127#ifndef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
2133#ifdef IMGUI_USE_STB_SPRINTF
2134#ifndef IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION
2135#define STB_SPRINTF_IMPLEMENTATION
2137#ifdef IMGUI_STB_SPRINTF_FILENAME
2138#include IMGUI_STB_SPRINTF_FILENAME
2140#include "stb_sprintf.h"
2144#if defined(_MSC_VER) && !defined(vsnprintf)
2145#define vsnprintf _vsnprintf
2151 va_start(args, fmt);
2152#ifdef IMGUI_USE_STB_SPRINTF
2153 int w = stbsp_vsnprintf(buf, (
int)buf_size, fmt, args);
2155 int w = vsnprintf(buf, buf_size, fmt, args);
2160 if (w == -1 || w >= (
int)buf_size)
2161 w = (int)buf_size - 1;
2168#ifdef IMGUI_USE_STB_SPRINTF
2169 int w = stbsp_vsnprintf(buf, (
int)buf_size, fmt, args);
2171 int w = vsnprintf(buf, buf_size, fmt, args);
2175 if (w == -1 || w >= (
int)buf_size)
2176 w = (int)buf_size - 1;
2185 va_start(args, fmt);
2197 if (fmt[0] ==
'%' && fmt[1] ==
's' && fmt[2] == 0)
2199 const char* buf = va_arg(args,
const char*);
2203 if (out_buf_end) { *out_buf_end = buf + strlen(buf); }
2205 else if (fmt[0] ==
'%' && fmt[1] ==
'.' && fmt[2] ==
'*' && fmt[3] ==
's' && fmt[4] == 0)
2207 int buf_len = va_arg(args,
int);
2208 const char* buf = va_arg(args,
const char*);
2212 buf_len = ImMin(buf_len, 6);
2215 *out_buf_end = buf + buf_len;
2220 *out_buf =
g.TempBuffer.Data;
2221 if (out_buf_end) { *out_buf_end =
g.TempBuffer.Data + buf_len; }
2228static const ImU32 GCrc32LookupTable[256] =
2230 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,
2231 0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,
2232 0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,
2233 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,
2234 0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01,
2235 0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,
2236 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,
2237 0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD,
2238 0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
2239 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,
2240 0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79,
2241 0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,
2242 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,
2243 0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,
2244 0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,
2245 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D,
2251ImGuiID
ImHashData(
const void* data_p,
size_t data_size, ImGuiID seed)
2254 const unsigned char* data = (
const unsigned char*)data_p;
2255 const ImU32* crc32_lut = GCrc32LookupTable;
2256 while (data_size-- != 0)
2257 crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *data++];
2267ImGuiID
ImHashStr(
const char* data_p,
size_t data_size, ImGuiID seed)
2271 const unsigned char* data = (
const unsigned char*)data_p;
2272 const ImU32* crc32_lut = GCrc32LookupTable;
2275 while (data_size-- != 0)
2277 unsigned char c = *data++;
2278 if (c ==
'#' && data_size >= 2 && data[0] ==
'#' && data[1] ==
'#')
2280 crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
2285 while (
unsigned char c = *data++)
2287 if (c ==
'#' && data[0] ==
'#' && data[1] ==
'#')
2289 crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
2300#ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
2304#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(__CYGWIN__) && !defined(__GNUC__)
2307 const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
2308 const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
2312 wchar_t local_temp_stack[FILENAME_MAX];
2313 ImVector<wchar_t> local_temp_heap;
2314 if (filename_wsize + mode_wsize > IM_ARRAYSIZE(local_temp_stack))
2315 local_temp_heap.resize(filename_wsize + mode_wsize);
2316 wchar_t* filename_wbuf = local_temp_heap.Data ? local_temp_heap.Data : local_temp_stack;
2317 wchar_t* mode_wbuf = filename_wbuf + filename_wsize;
2318 ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, filename_wbuf, filename_wsize);
2319 ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, mode_wbuf, mode_wsize);
2320 return ::_wfopen(filename_wbuf, mode_wbuf);
2322 return fopen(filename, mode);
2328ImU64
ImFileGetSize(ImFileHandle f) {
long off = 0, sz = 0;
return ((off = ftell(f)) != -1 && !fseek(f, 0, SEEK_END) && (sz = ftell(f)) != -1 && !fseek(f, off, SEEK_SET)) ? (ImU64)sz : (ImU64)-1; }
2329ImU64
ImFileRead(
void* data, ImU64 sz, ImU64 count, ImFileHandle f) {
return fread(data, (
size_t)sz, (
size_t)count, f); }
2330ImU64
ImFileWrite(
const void* data, ImU64 sz, ImU64 count, ImFileHandle f) {
return fwrite(data, (
size_t)sz, (
size_t)count, f); }
2336void*
ImFileLoadToMemory(
const char* filename,
const char* mode,
size_t* out_file_size,
int padding_bytes)
2338 IM_ASSERT(filename && mode);
2343 if ((f =
ImFileOpen(filename, mode)) == NULL)
2347 if (file_size == (
size_t)-1)
2353 void* file_data = IM_ALLOC(file_size + padding_bytes);
2354 if (file_data == NULL)
2359 if (
ImFileRead(file_data, 1, file_size, f) != file_size)
2365 if (padding_bytes > 0)
2366 memset((
void*)(((
char*)file_data) + file_size), 0, (
size_t)padding_bytes);
2370 *out_file_size = file_size;
2379IM_MSVC_RUNTIME_CHECKS_OFF
2386 static const char lengths[32] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0 };
2387 static const int masks[] = { 0x00, 0x7f, 0x1f, 0x0f, 0x07 };
2388 static const uint32_t mins[] = { 0x400000, 0, 0x80, 0x800, 0x10000 };
2389 static const int shiftc[] = { 0, 18, 12, 6, 0 };
2390 static const int shifte[] = { 0, 6, 4, 2, 0 };
2391 int len = lengths[*(
const unsigned char*)in_text >> 3];
2392 int wanted = len + (len ? 0 : 1);
2394 if (in_text_end == NULL)
2395 in_text_end = in_text + wanted;
2400 s[0] = in_text + 0 < in_text_end ? in_text[0] : 0;
2401 s[1] = in_text + 1 < in_text_end ? in_text[1] : 0;
2402 s[2] = in_text + 2 < in_text_end ? in_text[2] : 0;
2403 s[3] = in_text + 3 < in_text_end ? in_text[3] : 0;
2406 *out_char = (uint32_t)(s[0] & masks[len]) << 18;
2407 *out_char |= (uint32_t)(s[1] & 0x3f) << 12;
2408 *out_char |= (uint32_t)(s[2] & 0x3f) << 6;
2409 *out_char |= (uint32_t)(s[3] & 0x3f) << 0;
2410 *out_char >>= shiftc[len];
2414 e = (*out_char < mins[len]) << 6;
2415 e |= ((*out_char >> 11) == 0x1b) << 7;
2416 e |= (*out_char > IM_UNICODE_CODEPOINT_MAX) << 8;
2417 e |= (s[1] & 0xc0) >> 2;
2418 e |= (s[2] & 0xc0) >> 4;
2429 wanted = ImMin(wanted, !!s[0] + !!s[1] + !!s[2] + !!s[3]);
2430 *out_char = IM_UNICODE_CODEPOINT_INVALID;
2436int ImTextStrFromUtf8(ImWchar* buf,
int buf_size,
const char* in_text,
const char* in_text_end,
const char** in_text_remaining)
2438 ImWchar* buf_out = buf;
2439 ImWchar* buf_end = buf + buf_size;
2440 while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
2444 *buf_out++ = (ImWchar)c;
2447 if (in_text_remaining)
2448 *in_text_remaining = in_text;
2449 return (
int)(buf_out - buf);
2455 while ((!in_text_end || in_text < in_text_end) && *in_text)
2465static inline int ImTextCharToUtf8_inline(
char* buf,
int buf_size,
unsigned int c)
2474 if (buf_size < 2)
return 0;
2475 buf[0] = (char)(0xc0 + (c >> 6));
2476 buf[1] = (char)(0x80 + (c & 0x3f));
2481 if (buf_size < 3)
return 0;
2482 buf[0] = (char)(0xe0 + (c >> 12));
2483 buf[1] = (char)(0x80 + ((c >> 6) & 0x3f));
2484 buf[2] = (char)(0x80 + ((c ) & 0x3f));
2489 if (buf_size < 4)
return 0;
2490 buf[0] = (char)(0xf0 + (c >> 18));
2491 buf[1] = (char)(0x80 + ((c >> 12) & 0x3f));
2492 buf[2] = (char)(0x80 + ((c >> 6) & 0x3f));
2493 buf[3] = (char)(0x80 + ((c ) & 0x3f));
2502 int count = ImTextCharToUtf8_inline(out_buf, 5, c);
2510 unsigned int unused = 0;
2516 if (c < 0x80)
return 1;
2517 if (c < 0x800)
return 2;
2518 if (c < 0x10000)
return 3;
2519 if (c <= 0x10FFFF)
return 4;
2523int ImTextStrToUtf8(
char* out_buf,
int out_buf_size,
const ImWchar* in_text,
const ImWchar* in_text_end)
2525 char* buf_p = out_buf;
2526 const char* buf_end = out_buf + out_buf_size;
2527 while (buf_p < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
2529 unsigned int c = (
unsigned int)(*in_text++);
2533 buf_p += ImTextCharToUtf8_inline(buf_p, (
int)(buf_end - buf_p - 1), c);
2536 return (
int)(buf_p - out_buf);
2541 int bytes_count = 0;
2542 while ((!in_text_end || in_text < in_text_end) && *in_text)
2544 unsigned int c = (
unsigned int)(*in_text++);
2555 while (in_text_curr > in_text_start)
2558 if ((*in_text_curr & 0xC0) != 0x80)
2559 return in_text_curr;
2561 return in_text_start;
2566 if (in_text_end == NULL)
2567 in_text_end = in_text + strlen(in_text);
2569 while (in_text < in_text_end)
2571 const char* line_end = (
const char*)memchr(in_text,
'\n', in_text_end - in_text);
2572 in_text = line_end ? line_end + 1 : in_text_end;
2578IM_MSVC_RUNTIME_CHECKS_RESTORE
2587 float t = ((col_b >> IM_COL32_A_SHIFT) & 0xFF) / 255.f;
2588 int r = ImLerp((
int)(col_a >> IM_COL32_R_SHIFT) & 0xFF, (
int)(col_b >> IM_COL32_R_SHIFT) & 0xFF,
t);
2589 int g = ImLerp((
int)(col_a >> IM_COL32_G_SHIFT) & 0xFF, (
int)(col_b >> IM_COL32_G_SHIFT) & 0xFF,
t);
2590 int b = ImLerp((
int)(col_a >> IM_COL32_B_SHIFT) & 0xFF, (
int)(col_b >> IM_COL32_B_SHIFT) & 0xFF,
t);
2591 return IM_COL32(r,
g, b, 0xFF);
2594ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in)
2596 float s = 1.0f / 255.0f;
2598 ((in >> IM_COL32_R_SHIFT) & 0xFF) * s,
2599 ((in >> IM_COL32_G_SHIFT) & 0xFF) * s,
2600 ((in >> IM_COL32_B_SHIFT) & 0xFF) * s,
2601 ((in >> IM_COL32_A_SHIFT) & 0xFF) * s);
2604ImU32 ImGui::ColorConvertFloat4ToU32(
const ImVec4& in)
2607 out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT;
2608 out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT;
2609 out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT;
2610 out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT;
2616void ImGui::ColorConvertRGBtoHSV(
float r,
float g,
float b,
float& out_h,
float& out_s,
float& out_v)
2630 const float chroma = r - (
g < b ?
g : b);
2631 out_h = ImFabs(K + (
g - b) / (6.f * chroma + 1e-20f));
2632 out_s = chroma / (r + 1e-20f);
2638void ImGui::ColorConvertHSVtoRGB(
float h,
float s,
float v,
float& out_r,
float& out_g,
float& out_b)
2643 out_r = out_g = out_b = v;
2647 h = ImFmod(h, 1.0f) / (60.0f / 360.0f);
2649 float f = h - (float)i;
2650 float p = v * (1.0f - s);
2651 float q = v * (1.0f - s * f);
2652 float t = v * (1.0f - s * (1.0f - f));
2656 case 0: out_r = v; out_g =
t; out_b = p;
break;
2657 case 1: out_r = q; out_g = v; out_b = p;
break;
2658 case 2: out_r = p; out_g = v; out_b =
t;
break;
2659 case 3: out_r = p; out_g = q; out_b = v;
break;
2660 case 4: out_r =
t; out_g = p; out_b = v;
break;
2661 case 5:
default: out_r = v; out_g = p; out_b = q;
break;
2671ImGuiStoragePair*
ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStoragePair* in_end, ImGuiID key)
2673 ImGuiStoragePair* in_p = in_begin;
2674 for (
size_t count = (
size_t)(in_end - in_p); count > 0; )
2676 size_t count2 = count >> 1;
2677 ImGuiStoragePair* mid = in_p + count2;
2681 count -= count2 + 1;
2691IM_MSVC_RUNTIME_CHECKS_OFF
2692static int IMGUI_CDECL PairComparerByID(
const void* lhs,
const void* rhs)
2695 ImGuiID lhs_v = ((
const ImGuiStoragePair*)lhs)->key;
2696 ImGuiID rhs_v = ((
const ImGuiStoragePair*)rhs)->key;
2697 return (lhs_v > rhs_v ? +1 : lhs_v < rhs_v ? -1 : 0);
2701void ImGuiStorage::BuildSortByKey()
2703 ImQsort(Data.Data, (
size_t)Data.Size,
sizeof(ImGuiStoragePair), PairComparerByID);
2706int ImGuiStorage::GetInt(ImGuiID key,
int default_val)
const
2708 ImGuiStoragePair* it =
ImLowerBound(
const_cast<ImGuiStoragePair*
>(Data.Data),
const_cast<ImGuiStoragePair*
>(Data.Data + Data.Size), key);
2709 if (it == Data.Data + Data.Size || it->key != key)
2714bool ImGuiStorage::GetBool(ImGuiID key,
bool default_val)
const
2716 return GetInt(key, default_val ? 1 : 0) != 0;
2719float ImGuiStorage::GetFloat(ImGuiID key,
float default_val)
const
2721 ImGuiStoragePair* it =
ImLowerBound(
const_cast<ImGuiStoragePair*
>(Data.Data),
const_cast<ImGuiStoragePair*
>(Data.Data + Data.Size), key);
2722 if (it == Data.Data + Data.Size || it->key != key)
2727void* ImGuiStorage::GetVoidPtr(ImGuiID key)
const
2729 ImGuiStoragePair* it =
ImLowerBound(
const_cast<ImGuiStoragePair*
>(Data.Data),
const_cast<ImGuiStoragePair*
>(Data.Data + Data.Size), key);
2730 if (it == Data.Data + Data.Size || it->key != key)
2736int* ImGuiStorage::GetIntRef(ImGuiID key,
int default_val)
2738 ImGuiStoragePair* it =
ImLowerBound(Data.Data, Data.Data + Data.Size, key);
2739 if (it == Data.Data + Data.Size || it->key != key)
2740 it = Data.insert(it, ImGuiStoragePair(key, default_val));
2744bool* ImGuiStorage::GetBoolRef(ImGuiID key,
bool default_val)
2746 return (
bool*)GetIntRef(key, default_val ? 1 : 0);
2749float* ImGuiStorage::GetFloatRef(ImGuiID key,
float default_val)
2751 ImGuiStoragePair* it =
ImLowerBound(Data.Data, Data.Data + Data.Size, key);
2752 if (it == Data.Data + Data.Size || it->key != key)
2753 it = Data.insert(it, ImGuiStoragePair(key, default_val));
2757void** ImGuiStorage::GetVoidPtrRef(ImGuiID key,
void* default_val)
2759 ImGuiStoragePair* it =
ImLowerBound(Data.Data, Data.Data + Data.Size, key);
2760 if (it == Data.Data + Data.Size || it->key != key)
2761 it = Data.insert(it, ImGuiStoragePair(key, default_val));
2766void ImGuiStorage::SetInt(ImGuiID key,
int val)
2768 ImGuiStoragePair* it =
ImLowerBound(Data.Data, Data.Data + Data.Size, key);
2769 if (it == Data.Data + Data.Size || it->key != key)
2770 Data.insert(it, ImGuiStoragePair(key, val));
2775void ImGuiStorage::SetBool(ImGuiID key,
bool val)
2777 SetInt(key, val ? 1 : 0);
2780void ImGuiStorage::SetFloat(ImGuiID key,
float val)
2782 ImGuiStoragePair* it =
ImLowerBound(Data.Data, Data.Data + Data.Size, key);
2783 if (it == Data.Data + Data.Size || it->key != key)
2784 Data.insert(it, ImGuiStoragePair(key, val));
2789void ImGuiStorage::SetVoidPtr(ImGuiID key,
void* val)
2791 ImGuiStoragePair* it =
ImLowerBound(Data.Data, Data.Data + Data.Size, key);
2792 if (it == Data.Data + Data.Size || it->key != key)
2793 Data.insert(it, ImGuiStoragePair(key, val));
2798void ImGuiStorage::SetAllInt(
int v)
2800 for (
int i = 0; i < Data.Size; i++)
2803IM_MSVC_RUNTIME_CHECKS_RESTORE
2810ImGuiTextFilter::ImGuiTextFilter(
const char* default_filter)
2816 ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf));
2821bool ImGuiTextFilter::Draw(
const char* label,
float width)
2824 ImGui::SetNextItemWidth(width);
2825 bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
2828 return value_changed;
2831void ImGuiTextFilter::ImGuiTextRange::split(
char separator, ImVector<ImGuiTextRange>* out)
const
2835 const char* we = wb;
2838 if (*we == separator)
2840 out->push_back(ImGuiTextRange(wb, we));
2846 out->push_back(ImGuiTextRange(wb, we));
2849void ImGuiTextFilter::Build()
2852 ImGuiTextRange input_range(InputBuf, InputBuf + strlen(InputBuf));
2853 input_range.split(
',', &Filters);
2856 for (ImGuiTextRange& f : Filters)
2858 while (f.b < f.e && ImCharIsBlankA(f.b[0]))
2860 while (f.e > f.b && ImCharIsBlankA(f.e[-1]))
2869bool ImGuiTextFilter::PassFilter(
const char* text,
const char* text_end)
const
2871 if (Filters.Size == 0)
2875 text = text_end =
"";
2877 for (
const ImGuiTextRange& f : Filters)
2884 if (
ImStristr(text, text_end, f.b + 1, f.e) != NULL)
2890 if (
ImStristr(text, text_end, f.b, f.e) != NULL)
2909#if defined(__GNUC__) || defined(__clang__)
2910#define va_copy(dest, src) __builtin_va_copy(dest, src)
2912#define va_copy(dest, src) (dest = src)
2916char ImGuiTextBuffer::EmptyString[1] = { 0 };
2918void ImGuiTextBuffer::append(
const char* str,
const char* str_end)
2920 int len = str_end ? (int)(str_end - str) : (int)strlen(str);
2923 const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
2924 const int needed_sz = write_off + len;
2925 if (write_off + len >= Buf.Capacity)
2927 int new_capacity = Buf.Capacity * 2;
2928 Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity);
2931 Buf.resize(needed_sz);
2932 memcpy(&Buf[write_off - 1], str, (
size_t)len);
2933 Buf[write_off - 1 + len] = 0;
2936void ImGuiTextBuffer::appendf(
const char* fmt, ...)
2939 va_start(args, fmt);
2940 appendfv(fmt, args);
2945void ImGuiTextBuffer::appendfv(
const char* fmt, va_list args)
2958 const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
2959 const int needed_sz = write_off + len;
2960 if (write_off + len >= Buf.Capacity)
2962 int new_capacity = Buf.Capacity * 2;
2963 Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity);
2966 Buf.resize(needed_sz);
2967 ImFormatStringV(&Buf[write_off - 1], (
size_t)len + 1, fmt, args_copy);
2971void ImGuiTextIndex::append(
const char* base,
int old_size,
int new_size)
2973 IM_ASSERT(old_size >= 0 && new_size >= old_size && new_size >= EndOffset);
2974 if (old_size == new_size)
2976 if (EndOffset == 0 || base[EndOffset - 1] ==
'\n')
2977 LineOffsets.push_back(EndOffset);
2978 const char* base_end = base + new_size;
2979 for (
const char* p = base + old_size; (p = (
const char*)memchr(p,
'\n', base_end - p)) != 0; )
2981 LineOffsets.push_back((
int)(intptr_t)(p - base));
2982 EndOffset = ImMax(EndOffset, new_size);
2991static bool GetSkipItemForListClipping()
2994 return (
g.CurrentTable ?
g.CurrentTable->HostSkipItems :
g.CurrentWindow->SkipItems);
2997static void ImGuiListClipper_SortAndFuseRanges(ImVector<ImGuiListClipperRange>&
ranges,
int offset = 0)
2999 if (
ranges.Size - offset <= 1)
3003 for (
int sort_end =
ranges.Size - offset - 1; sort_end > 0; --sort_end)
3004 for (
int i = offset; i < sort_end + offset; ++i)
3009 for (
int i = 1 + offset; i <
ranges.Size; i++)
3011 IM_ASSERT(!
ranges[i].PosToIndexConvert && !
ranges[i - 1].PosToIndexConvert);
3021static void ImGuiListClipper_SeekCursorAndSetupPrevLine(
float pos_y,
float line_height)
3027 ImGuiWindow* window =
g.CurrentWindow;
3028 float off_y = pos_y - window->DC.CursorPos.y;
3029 window->DC.CursorPos.y = pos_y;
3030 window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, pos_y -
g.Style.ItemSpacing.y);
3031 window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height;
3032 window->DC.PrevLineSize.y = (line_height -
g.Style.ItemSpacing.y);
3033 if (ImGuiOldColumns* columns = window->DC.CurrentColumns)
3034 columns->LineMinY = window->DC.CursorPos.y;
3035 if (ImGuiTable* table =
g.CurrentTable)
3037 if (table->IsInsideRow)
3038 ImGui::TableEndRow(table);
3039 table->RowPosY2 = window->DC.CursorPos.y;
3040 const int row_increase = (int)((off_y / line_height) + 0.5f);
3042 table->RowBgColorCounter += row_increase;
3046ImGuiListClipper::ImGuiListClipper()
3048 memset(
this, 0,
sizeof(*
this));
3051ImGuiListClipper::~ImGuiListClipper()
3056void ImGuiListClipper::Begin(
int items_count,
float items_height)
3059 Ctx = ImGui::GetCurrentContext();
3061 ImGuiContext&
g = *Ctx;
3062 ImGuiWindow* window =
g.CurrentWindow;
3063 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Begin(%d,%.2f) in '%s'\n", items_count, items_height, window->Name);
3065 if (ImGuiTable* table =
g.CurrentTable)
3066 if (table->IsInsideRow)
3067 ImGui::TableEndRow(table);
3069 StartPosY = window->DC.CursorPos.y;
3070 ItemsHeight = items_height;
3071 ItemsCount = items_count;
3076 if (++
g.ClipperTempDataStacked >
g.ClipperTempData.Size)
3077 g.ClipperTempData.resize(
g.ClipperTempDataStacked, ImGuiListClipperData());
3078 ImGuiListClipperData* data = &
g.ClipperTempData[
g.ClipperTempDataStacked - 1];
3080 data->LossynessOffset = window->DC.CursorStartPosLossyness.y;
3082 StartSeekOffsetY = data->LossynessOffset;
3085void ImGuiListClipper::End()
3087 if (ImGuiListClipperData* data = (ImGuiListClipperData*)TempData)
3090 ImGuiContext&
g = *Ctx;
3091 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: End() in '%s'\n",
g.CurrentWindow->Name);
3092 if (ItemsCount >= 0 && ItemsCount < INT_MAX && DisplayStart >= 0)
3093 SeekCursorForItem(ItemsCount);
3096 IM_ASSERT(data->ListClipper ==
this);
3097 data->StepNo = data->Ranges.Size;
3098 if (--
g.ClipperTempDataStacked > 0)
3100 data = &
g.ClipperTempData[
g.ClipperTempDataStacked - 1];
3101 data->ListClipper->TempData = data;
3108void ImGuiListClipper::IncludeItemsByIndex(
int item_begin,
int item_end)
3110 ImGuiListClipperData* data = (ImGuiListClipperData*)TempData;
3111 IM_ASSERT(DisplayStart < 0);
3112 IM_ASSERT(item_begin <= item_end);
3113 if (item_begin < item_end)
3114 data->Ranges.push_back(ImGuiListClipperRange::FromIndices(item_begin, item_end));
3119void ImGuiListClipper::SeekCursorForItem(
int item_n)
3124 float pos_y = (float)((
double)StartPosY + StartSeekOffsetY + (double)item_n * ItemsHeight);
3125 ImGuiListClipper_SeekCursorAndSetupPrevLine(pos_y, ItemsHeight);
3128static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
3130 ImGuiContext&
g = *clipper->Ctx;
3131 ImGuiWindow* window =
g.CurrentWindow;
3132 ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData;
3133 IM_ASSERT(data != NULL &&
"Called ImGuiListClipper::Step() too many times, or before ImGuiListClipper::Begin() ?");
3135 ImGuiTable* table =
g.CurrentTable;
3136 if (table && table->IsInsideRow)
3137 ImGui::TableEndRow(table);
3140 if (clipper->ItemsCount == 0 || GetSkipItemForListClipping())
3145 if (data->StepNo == 0 && table != NULL && !table->IsUnfrozenRows)
3147 clipper->DisplayStart = data->ItemsFrozen;
3148 clipper->DisplayEnd = ImMin(data->ItemsFrozen + 1, clipper->ItemsCount);
3149 if (clipper->DisplayStart < clipper->DisplayEnd)
3150 data->ItemsFrozen++;
3155 bool calc_clipping =
false;
3156 if (data->StepNo == 0)
3158 clipper->StartPosY = window->DC.CursorPos.y;
3159 if (clipper->ItemsHeight <= 0.0f)
3162 data->Ranges.push_front(ImGuiListClipperRange::FromIndices(data->ItemsFrozen, data->ItemsFrozen + 1));
3163 clipper->DisplayStart = ImMax(data->Ranges[0].Min, data->ItemsFrozen);
3164 clipper->DisplayEnd = ImMin(data->Ranges[0].Max, clipper->ItemsCount);
3168 calc_clipping =
true;
3172 if (clipper->ItemsHeight <= 0.0f)
3174 IM_ASSERT(data->StepNo == 1);
3176 IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y);
3178 clipper->ItemsHeight = (window->DC.CursorPos.y - clipper->StartPosY) / (
float)(clipper->DisplayEnd - clipper->DisplayStart);
3179 bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision(clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y);
3180 if (affected_by_floating_point_precision)
3181 clipper->ItemsHeight = window->DC.PrevLineSize.y +
g.Style.ItemSpacing.y;
3182 if (clipper->ItemsHeight == 0.0f && clipper->ItemsCount == INT_MAX)
3184 IM_ASSERT(clipper->ItemsHeight > 0.0f &&
"Unable to calculate item height! First item hasn't moved the cursor vertically!");
3185 calc_clipping =
true;
3189 const int already_submitted = clipper->DisplayEnd;
3193 clipper->StartSeekOffsetY = (double)data->LossynessOffset - data->ItemsFrozen * (
double)clipper->ItemsHeight;
3198 data->Ranges.push_back(ImGuiListClipperRange::FromIndices(0, clipper->ItemsCount));
3203 const bool is_nav_request = (
g.NavMoveScoringItems &&
g.NavWindow &&
g.NavWindow->RootWindowForNav == window->RootWindowForNav);
3205 data->Ranges.push_back(ImGuiListClipperRange::FromPositions(
g.NavScoringNoClipRect.Min.y,
g.NavScoringNoClipRect.Max.y, 0, 0));
3206 if (is_nav_request && (
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) &&
g.NavTabbingDir == -1)
3207 data->Ranges.push_back(ImGuiListClipperRange::FromIndices(clipper->ItemsCount - 1, clipper->ItemsCount));
3210 ImRect nav_rect_abs = ImGui::WindowRectRelToAbs(window, window->NavRectRel[0]);
3211 if (
g.NavId != 0 && window->NavLastIds[0] ==
g.NavId)
3212 data->Ranges.push_back(ImGuiListClipperRange::FromPositions(nav_rect_abs.Min.y, nav_rect_abs.Max.y, 0, 0));
3215 float min_y = window->ClipRect.Min.y;
3216 float max_y = window->ClipRect.Max.y;
3219 ImGuiBoxSelectState* bs = &
g.BoxSelectState;
3220 if (bs->IsActive && bs->Window == window)
3225 min_y -=
g.Style.ItemSpacing.y;
3226 max_y +=
g.Style.ItemSpacing.y;
3230 data->Ranges.push_back(ImGuiListClipperRange::FromPositions(bs->UnclipRect.Min.y, bs->UnclipRect.Max.y, 0, 0));
3233 const int off_min = (is_nav_request &&
g.NavMoveClipDir == ImGuiDir_Up) ? -1 : 0;
3234 const int off_max = (is_nav_request &&
g.NavMoveClipDir == ImGuiDir_Down) ? 1 : 0;
3235 data->Ranges.push_back(ImGuiListClipperRange::FromPositions(min_y, max_y, off_min, off_max));
3242 for (ImGuiListClipperRange& range : data->Ranges)
3243 if (range.PosToIndexConvert)
3245 int m1 = (int)(((
double)range.Min - window->DC.CursorPos.y - data->LossynessOffset) / clipper->ItemsHeight);
3246 int m2 = (int)((((
double)range.Max - window->DC.CursorPos.y - data->LossynessOffset) / clipper->ItemsHeight) + 0.999999f);
3247 range.Min = ImClamp(already_submitted + m1 + range.PosToIndexOffsetMin, already_submitted, clipper->ItemsCount - 1);
3248 range.Max = ImClamp(already_submitted + m2 + range.PosToIndexOffsetMax, range.Min + 1, clipper->ItemsCount);
3249 range.PosToIndexConvert =
false;
3251 ImGuiListClipper_SortAndFuseRanges(data->Ranges, data->StepNo);
3255 while (data->StepNo < data->Ranges.Size)
3257 clipper->DisplayStart = ImMax(data->Ranges[data->StepNo].Min, already_submitted);
3258 clipper->DisplayEnd = ImMin(data->Ranges[data->StepNo].Max, clipper->ItemsCount);
3259 if (clipper->DisplayStart > already_submitted)
3260 clipper->SeekCursorForItem(clipper->DisplayStart);
3262 if (clipper->DisplayStart == clipper->DisplayEnd && data->StepNo < data->Ranges.Size)
3269 if (clipper->ItemsCount < INT_MAX)
3270 clipper->SeekCursorForItem(clipper->ItemsCount);
3275bool ImGuiListClipper::Step()
3277 ImGuiContext&
g = *Ctx;
3278 bool need_items_height = (ItemsHeight <= 0.0f);
3279 bool ret = ImGuiListClipper_StepInternal(
this);
3280 if (ret && (DisplayStart == DisplayEnd))
3282 if (
g.CurrentTable &&
g.CurrentTable->IsUnfrozenRows ==
false)
3283 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): inside frozen table row.\n");
3284 if (need_items_height && ItemsHeight > 0.0f)
3285 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): computed ItemsHeight: %.2f.\n", ItemsHeight);
3288 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): display %d to %d.\n", DisplayStart, DisplayEnd);
3292 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): End.\n");
3302ImGuiStyle& ImGui::GetStyle()
3304 IM_ASSERT(
GImGui != NULL &&
"No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
3308ImU32 ImGui::GetColorU32(ImGuiCol idx,
float alpha_mul)
3310 ImGuiStyle& style =
GImGui->Style;
3311 ImVec4 c = style.Colors[idx];
3312 c.w *= style.Alpha * alpha_mul;
3313 return ColorConvertFloat4ToU32(c);
3316ImU32 ImGui::GetColorU32(
const ImVec4& col)
3318 ImGuiStyle& style =
GImGui->Style;
3321 return ColorConvertFloat4ToU32(c);
3324const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx)
3326 ImGuiStyle& style =
GImGui->Style;
3327 return style.Colors[idx];
3330ImU32 ImGui::GetColorU32(ImU32 col,
float alpha_mul)
3332 ImGuiStyle& style =
GImGui->Style;
3333 alpha_mul *= style.Alpha;
3334 if (alpha_mul >= 1.0f)
3336 ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
3337 a = (ImU32)(a * alpha_mul);
3338 return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT);
3342void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col)
3345 ImGuiColorMod backup;
3347 backup.BackupValue =
g.Style.Colors[idx];
3348 g.ColorStack.push_back(backup);
3349 if (
g.DebugFlashStyleColorIdx != idx)
3350 g.Style.Colors[idx] = ColorConvertU32ToFloat4(col);
3353void ImGui::PushStyleColor(ImGuiCol idx,
const ImVec4& col)
3356 ImGuiColorMod backup;
3358 backup.BackupValue =
g.Style.Colors[idx];
3359 g.ColorStack.push_back(backup);
3360 if (
g.DebugFlashStyleColorIdx != idx)
3361 g.Style.Colors[idx] = col;
3364void ImGui::PopStyleColor(
int count)
3367 if (
g.ColorStack.Size < count)
3369 IM_ASSERT_USER_ERROR(0,
"Calling PopStyleColor() too many times!");
3370 count =
g.ColorStack.Size;
3374 ImGuiColorMod& backup =
g.ColorStack.back();
3375 g.Style.Colors[backup.Col] = backup.BackupValue;
3376 g.ColorStack.pop_back();
3381static const ImGuiCol GWindowDockStyleColors[ImGuiWindowDockStyleCol_COUNT] =
3383 ImGuiCol_Text, ImGuiCol_TabHovered, ImGuiCol_Tab, ImGuiCol_TabSelected, ImGuiCol_TabSelectedOverline, ImGuiCol_TabDimmed, ImGuiCol_TabDimmedSelected, ImGuiCol_TabDimmedSelectedOverline,
3386static const ImGuiDataVarInfo GStyleVarInfo[] =
3388 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, Alpha) },
3389 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, DisabledAlpha) },
3390 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowPadding) },
3391 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, WindowRounding) },
3392 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, WindowBorderSize) },
3393 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowMinSize) },
3394 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowTitleAlign) },
3395 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ChildRounding) },
3396 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ChildBorderSize) },
3397 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, PopupRounding) },
3398 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, PopupBorderSize) },
3399 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, FramePadding) },
3400 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, FrameRounding) },
3401 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, FrameBorderSize) },
3402 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ItemSpacing) },
3403 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ItemInnerSpacing) },
3404 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, IndentSpacing) },
3405 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, CellPadding) },
3406 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ScrollbarSize) },
3407 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ScrollbarRounding) },
3408 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, GrabMinSize) },
3409 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, GrabRounding) },
3410 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabRounding) },
3411 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBorderSize) },
3412 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBarBorderSize) },
3413 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBarOverlineSize) },
3414 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersAngle)},
3415 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersTextAlign)},
3416 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) },
3417 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) },
3418 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, SeparatorTextBorderSize)},
3419 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SeparatorTextAlign) },
3420 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SeparatorTextPadding) },
3421 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, DockingSeparatorSize) },
3424const ImGuiDataVarInfo* ImGui::GetStyleVarInfo(ImGuiStyleVar idx)
3426 IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT);
3428 return &GStyleVarInfo[idx];
3431void ImGui::PushStyleVar(ImGuiStyleVar idx,
float val)
3434 const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx);
3435 if (var_info->Type != ImGuiDataType_Float || var_info->Count != 1)
3437 IM_ASSERT_USER_ERROR(0,
"Calling PushStyleVar() variant with wrong type!");
3440 float* pvar = (
float*)var_info->GetVarPtr(&
g.Style);
3441 g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
3445void ImGui::PushStyleVarX(ImGuiStyleVar idx,
float val_x)
3448 const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx);
3449 if (var_info->Type != ImGuiDataType_Float || var_info->Count != 2)
3451 IM_ASSERT_USER_ERROR(0,
"Calling PushStyleVar() variant with wrong type!");
3454 ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&
g.Style);
3455 g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
3459void ImGui::PushStyleVarY(ImGuiStyleVar idx,
float val_y)
3462 const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx);
3463 if (var_info->Type != ImGuiDataType_Float || var_info->Count != 2)
3465 IM_ASSERT_USER_ERROR(0,
"Calling PushStyleVar() variant with wrong type!");
3468 ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&
g.Style);
3469 g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
3473void ImGui::PushStyleVar(ImGuiStyleVar idx,
const ImVec2& val)
3476 const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx);
3477 if (var_info->Type != ImGuiDataType_Float || var_info->Count != 2)
3479 IM_ASSERT_USER_ERROR(0,
"Calling PushStyleVar() variant with wrong type!");
3482 ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&
g.Style);
3483 g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
3487void ImGui::PopStyleVar(
int count)
3490 if (
g.StyleVarStack.Size < count)
3492 IM_ASSERT_USER_ERROR(0,
"Calling PopStyleVar() too many times!");
3493 count =
g.StyleVarStack.Size;
3498 ImGuiStyleMod& backup =
g.StyleVarStack.back();
3499 const ImGuiDataVarInfo* info = GetStyleVarInfo(backup.VarIdx);
3500 void* data = info->GetVarPtr(&
g.Style);
3501 if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((
float*)data)[0] = backup.BackupFloat[0]; }
3502 else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((
float*)data)[0] = backup.BackupFloat[0]; ((
float*)data)[1] = backup.BackupFloat[1]; }
3503 g.StyleVarStack.pop_back();
3508const char* ImGui::GetStyleColorName(ImGuiCol idx)
3513 case ImGuiCol_Text:
return "Text";
3514 case ImGuiCol_TextDisabled:
return "TextDisabled";
3515 case ImGuiCol_WindowBg:
return "WindowBg";
3516 case ImGuiCol_ChildBg:
return "ChildBg";
3517 case ImGuiCol_PopupBg:
return "PopupBg";
3518 case ImGuiCol_Border:
return "Border";
3519 case ImGuiCol_BorderShadow:
return "BorderShadow";
3520 case ImGuiCol_FrameBg:
return "FrameBg";
3521 case ImGuiCol_FrameBgHovered:
return "FrameBgHovered";
3522 case ImGuiCol_FrameBgActive:
return "FrameBgActive";
3523 case ImGuiCol_TitleBg:
return "TitleBg";
3524 case ImGuiCol_TitleBgActive:
return "TitleBgActive";
3525 case ImGuiCol_TitleBgCollapsed:
return "TitleBgCollapsed";
3526 case ImGuiCol_MenuBarBg:
return "MenuBarBg";
3527 case ImGuiCol_ScrollbarBg:
return "ScrollbarBg";
3528 case ImGuiCol_ScrollbarGrab:
return "ScrollbarGrab";
3529 case ImGuiCol_ScrollbarGrabHovered:
return "ScrollbarGrabHovered";
3530 case ImGuiCol_ScrollbarGrabActive:
return "ScrollbarGrabActive";
3531 case ImGuiCol_CheckMark:
return "CheckMark";
3532 case ImGuiCol_SliderGrab:
return "SliderGrab";
3533 case ImGuiCol_SliderGrabActive:
return "SliderGrabActive";
3534 case ImGuiCol_Button:
return "Button";
3535 case ImGuiCol_ButtonHovered:
return "ButtonHovered";
3536 case ImGuiCol_ButtonActive:
return "ButtonActive";
3537 case ImGuiCol_Header:
return "Header";
3538 case ImGuiCol_HeaderHovered:
return "HeaderHovered";
3539 case ImGuiCol_HeaderActive:
return "HeaderActive";
3540 case ImGuiCol_Separator:
return "Separator";
3541 case ImGuiCol_SeparatorHovered:
return "SeparatorHovered";
3542 case ImGuiCol_SeparatorActive:
return "SeparatorActive";
3543 case ImGuiCol_ResizeGrip:
return "ResizeGrip";
3544 case ImGuiCol_ResizeGripHovered:
return "ResizeGripHovered";
3545 case ImGuiCol_ResizeGripActive:
return "ResizeGripActive";
3546 case ImGuiCol_TabHovered:
return "TabHovered";
3547 case ImGuiCol_Tab:
return "Tab";
3548 case ImGuiCol_TabSelected:
return "TabSelected";
3549 case ImGuiCol_TabSelectedOverline:
return "TabSelectedOverline";
3550 case ImGuiCol_TabDimmed:
return "TabDimmed";
3551 case ImGuiCol_TabDimmedSelected:
return "TabDimmedSelected";
3552 case ImGuiCol_TabDimmedSelectedOverline:
return "TabDimmedSelectedOverline";
3553 case ImGuiCol_DockingPreview:
return "DockingPreview";
3554 case ImGuiCol_DockingEmptyBg:
return "DockingEmptyBg";
3555 case ImGuiCol_PlotLines:
return "PlotLines";
3556 case ImGuiCol_PlotLinesHovered:
return "PlotLinesHovered";
3557 case ImGuiCol_PlotHistogram:
return "PlotHistogram";
3558 case ImGuiCol_PlotHistogramHovered:
return "PlotHistogramHovered";
3559 case ImGuiCol_TableHeaderBg:
return "TableHeaderBg";
3560 case ImGuiCol_TableBorderStrong:
return "TableBorderStrong";
3561 case ImGuiCol_TableBorderLight:
return "TableBorderLight";
3562 case ImGuiCol_TableRowBg:
return "TableRowBg";
3563 case ImGuiCol_TableRowBgAlt:
return "TableRowBgAlt";
3564 case ImGuiCol_TextLink:
return "TextLink";
3565 case ImGuiCol_TextSelectedBg:
return "TextSelectedBg";
3566 case ImGuiCol_DragDropTarget:
return "DragDropTarget";
3567 case ImGuiCol_NavCursor:
return "NavCursor";
3568 case ImGuiCol_NavWindowingHighlight:
return "NavWindowingHighlight";
3569 case ImGuiCol_NavWindowingDimBg:
return "NavWindowingDimBg";
3570 case ImGuiCol_ModalWindowDimBg:
return "ModalWindowDimBg";
3584const char* ImGui::FindRenderedTextEnd(
const char* text,
const char* text_end)
3586 const char* text_display_end = text;
3588 text_end = (
const char*)-1;
3590 while (text_display_end < text_end && *text_display_end !=
'\0' && (text_display_end[0] !=
'#' || text_display_end[1] !=
'#'))
3592 return text_display_end;
3597void ImGui::RenderText(ImVec2 pos,
const char* text,
const char* text_end,
bool hide_text_after_hash)
3600 ImGuiWindow* window =
g.CurrentWindow;
3603 const char* text_display_end;
3604 if (hide_text_after_hash)
3606 text_display_end = FindRenderedTextEnd(text, text_end);
3611 text_end = text + strlen(text);
3612 text_display_end = text_end;
3615 if (text != text_display_end)
3617 window->DrawList->AddText(
g.Font,
g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
3619 LogRenderedText(&pos, text, text_display_end);
3623void ImGui::RenderTextWrapped(ImVec2 pos,
const char* text,
const char* text_end,
float wrap_width)
3626 ImGuiWindow* window =
g.CurrentWindow;
3629 text_end = text + strlen(text);
3631 if (text != text_end)
3633 window->DrawList->AddText(
g.Font,
g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width);
3635 LogRenderedText(&pos, text, text_end);
3644void ImGui::RenderTextClippedEx(ImDrawList* draw_list,
const ImVec2& pos_min,
const ImVec2& pos_max,
const char* text,
const char* text_display_end,
const ImVec2* text_size_if_known,
const ImVec2& align,
const ImRect* clip_rect)
3647 ImVec2 pos = pos_min;
3648 const ImVec2 text_size = text_size_if_known ? *text_size_if_known :
CalcTextSize(text, text_display_end,
false, 0.0f);
3650 const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min;
3651 const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max;
3652 bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y);
3654 need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y);
3657 if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x);
3658 if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y);
3663 ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y);
3664 draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect);
3668 draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL);
3672void ImGui::RenderTextClipped(
const ImVec2& pos_min,
const ImVec2& pos_max,
const char* text,
const char* text_end,
const ImVec2* text_size_if_known,
const ImVec2& align,
const ImRect* clip_rect)
3675 const char* text_display_end = FindRenderedTextEnd(text, text_end);
3676 const int text_len = (int)(text_display_end - text);
3681 ImGuiWindow* window =
g.CurrentWindow;
3682 RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect);
3684 LogRenderedText(&pos_min, text, text_display_end);
3690void ImGui::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_full,
const ImVec2* text_size_if_known)
3693 if (text_end_full == NULL)
3694 text_end_full = FindRenderedTextEnd(text);
3695 const ImVec2 text_size = text_size_if_known ? *text_size_if_known :
CalcTextSize(text, text_end_full,
false, 0.0f);
3701 if (text_size.x > pos_max.x - pos_min.x)
3708 const ImFont* font = draw_list->_Data->Font;
3709 const float font_size = draw_list->_Data->FontSize;
3710 const float font_scale = draw_list->_Data->FontScale;
3711 const char* text_end_ellipsis = NULL;
3712 const float ellipsis_width = font->EllipsisWidth * font_scale;
3715 const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_width) - pos_min.x, 1.0f);
3716 float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
3717 if (text == text_end_ellipsis && text_end_ellipsis < text_end_full)
3721 text_size_clipped_x = font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text, text_end_ellipsis).x;
3723 while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1]))
3726 text_end_ellipsis--;
3727 text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x;
3731 RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f));
3732 ImVec2 ellipsis_pos = ImTrunc(ImVec2(pos_min.x + text_size_clipped_x, pos_min.y));
3733 if (ellipsis_pos.x + ellipsis_width <= ellipsis_max_x)
3734 for (
int i = 0; i < font->EllipsisCharCount; i++, ellipsis_pos.x += font->EllipsisCharStep * font_scale)
3735 font->RenderChar(draw_list, font_size, ellipsis_pos, GetColorU32(ImGuiCol_Text), font->EllipsisChar);
3739 RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_full, &text_size, ImVec2(0.0f, 0.0f));
3743 LogRenderedText(&pos_min, text, text_end_full);
3747void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col,
bool borders,
float rounding)
3750 ImGuiWindow* window =
g.CurrentWindow;
3751 window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
3752 const float border_size =
g.Style.FrameBorderSize;
3753 if (borders && border_size > 0.0f)
3755 window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
3756 window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
3760void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max,
float rounding)
3763 ImGuiWindow* window =
g.CurrentWindow;
3764 const float border_size =
g.Style.FrameBorderSize;
3765 if (border_size > 0.0f)
3767 window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
3768 window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
3772void ImGui::RenderNavCursor(
const ImRect& bb, ImGuiID
id, ImGuiNavRenderCursorFlags flags)
3777 if (!
g.NavCursorVisible && !(flags & ImGuiNavRenderCursorFlags_AlwaysDraw))
3779 if (
id ==
g.LastItemData.ID && (
g.LastItemData.ItemFlags & ImGuiItemFlags_NoNav))
3781 ImGuiWindow* window =
g.CurrentWindow;
3782 if (window->DC.NavHideHighlightOneFrame)
3785 float rounding = (flags & ImGuiNavRenderCursorFlags_NoRounding) ? 0.0f :
g.Style.FrameRounding;
3786 ImRect display_rect = bb;
3787 display_rect.ClipWith(window->ClipRect);
3788 const float thickness = 2.0f;
3789 if (flags & ImGuiNavRenderCursorFlags_Compact)
3791 window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, 0, thickness);
3795 const float distance = 3.0f + thickness * 0.5f;
3796 display_rect.Expand(ImVec2(distance, distance));
3797 bool fully_visible = window->ClipRect.Contains(display_rect);
3799 window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
3800 window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, 0, thickness);
3802 window->DrawList->PopClipRect();
3806void ImGui::RenderMouseCursor(ImVec2 base_pos,
float base_scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow)
3809 if (mouse_cursor <= ImGuiMouseCursor_None || mouse_cursor >= ImGuiMouseCursor_COUNT)
3810 mouse_cursor = ImGuiMouseCursor_Arrow;
3811 ImFontAtlas* font_atlas =
g.DrawListSharedData.Font->ContainerAtlas;
3812 for (ImGuiViewportP* viewport :
g.Viewports)
3815 ImVec2 offset,
size, uv[4];
3816 if (!font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2]))
3818 const ImVec2 pos = base_pos - offset;
3819 const float scale = base_scale * viewport->DpiScale;
3820 if (!viewport->GetMainRect().Overlaps(ImRect(pos, pos + ImVec2(
size.x + 2,
size.y + 2) * scale)))
3822 ImDrawList* draw_list = GetForegroundDrawList(viewport);
3823 ImTextureID tex_id = font_atlas->TexID;
3824 draw_list->PushTextureID(tex_id);
3825 draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow);
3826 draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow);
3827 draw_list->AddImage(tex_id, pos, pos + size * scale, uv[2], uv[3], col_border);
3828 draw_list->AddImage(tex_id, pos, pos + size * scale, uv[0], uv[1], col_fill);
3829 draw_list->PopTextureID();
3839ImGuiContext* ImGui::GetCurrentContext()
3844void ImGui::SetCurrentContext(ImGuiContext* ctx)
3846#ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC
3847 IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx);
3853void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func,
void* user_data)
3855 GImAllocatorAllocFunc = alloc_func;
3856 GImAllocatorFreeFunc = free_func;
3857 GImAllocatorUserData = user_data;
3861void ImGui::GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func,
void** p_user_data)
3863 *p_alloc_func = GImAllocatorAllocFunc;
3864 *p_free_func = GImAllocatorFreeFunc;
3865 *p_user_data = GImAllocatorUserData;
3868ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas)
3870 ImGuiContext* prev_ctx = GetCurrentContext();
3871 ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);
3872 SetCurrentContext(ctx);
3874 if (prev_ctx != NULL)
3875 SetCurrentContext(prev_ctx);
3879void ImGui::DestroyContext(ImGuiContext* ctx)
3881 ImGuiContext* prev_ctx = GetCurrentContext();
3884 SetCurrentContext(ctx);
3886 SetCurrentContext((prev_ctx != ctx) ? prev_ctx : NULL);
3891static const ImGuiLocEntry GLocalizationEntriesEnUS[] =
3893 { ImGuiLocKey_VersionStr,
"Dear ImGui " IMGUI_VERSION
" (" IM_STRINGIFY(IMGUI_VERSION_NUM)
")" },
3894 { ImGuiLocKey_TableSizeOne,
"Size column to fit###SizeOne" },
3895 { ImGuiLocKey_TableSizeAllFit,
"Size all columns to fit###SizeAll" },
3896 { ImGuiLocKey_TableSizeAllDefault,
"Size all columns to default###SizeAll" },
3897 { ImGuiLocKey_TableResetOrder,
"Reset order###ResetOrder" },
3898 { ImGuiLocKey_WindowingMainMenuBar,
"(Main menu bar)" },
3899 { ImGuiLocKey_WindowingPopup,
"(Popup)" },
3900 { ImGuiLocKey_WindowingUntitled,
"(Untitled)" },
3901 { ImGuiLocKey_OpenLink_s,
"Open '%s'" },
3902 { ImGuiLocKey_CopyLink,
"Copy Link###CopyLink" },
3903 { ImGuiLocKey_DockingHideTabBar,
"Hide tab bar###HideTabBar" },
3904 { ImGuiLocKey_DockingHoldShiftToDock,
"Hold SHIFT to enable Docking window." },
3905 { ImGuiLocKey_DockingDragToUndockOrMoveNode,
"Click and drag to move or undock whole node." },
3908ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
3911 InputTextState.Ctx =
this;
3913 Initialized =
false;
3914 ConfigFlagsCurrFrame = ConfigFlagsLastFrame = ImGuiConfigFlags_None;
3915 FontAtlasOwnedByContext = shared_font_atlas ? false :
true;
3917 FontSize = FontBaseSize = FontScale = CurrentDpiScale = 0.0f;
3918 IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
3921 FrameCountEnded = FrameCountPlatformEnded = FrameCountRendered = -1;
3922 WithinFrameScope = WithinFrameScopeWithImplicitWindow = WithinEndChild =
false;
3923 GcCompactAll =
false;
3924 TestEngineHookItems =
false;
3926 memset(ContextName, 0,
sizeof(ContextName));
3928 InputEventsNextMouseSource = ImGuiMouseSource_Mouse;
3929 InputEventsNextEventId = 1;
3931 WindowsActiveCount = 0;
3932 CurrentWindow = NULL;
3933 HoveredWindow = NULL;
3934 HoveredWindowUnderMovingWindow = NULL;
3935 HoveredWindowBeforeClear = NULL;
3936 MovingWindow = NULL;
3937 WheelingWindow = NULL;
3938 WheelingWindowStartFrame = WheelingWindowScrolledFrame = -1;
3939 WheelingWindowReleaseTimer = 0.0f;
3941 DebugDrawIdConflicts = 0;
3942 DebugHookIdInfo = 0;
3943 HoveredId = HoveredIdPreviousFrame = 0;
3944 HoveredIdPreviousFrameItemCount = 0;
3945 HoveredIdAllowOverlap =
false;
3946 HoveredIdIsDisabled =
false;
3947 HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
3948 ItemUnclipByLog =
false;
3950 ActiveIdIsAlive = 0;
3951 ActiveIdTimer = 0.0f;
3952 ActiveIdIsJustActivated =
false;
3953 ActiveIdAllowOverlap =
false;
3954 ActiveIdNoClearOnFocusLoss =
false;
3955 ActiveIdHasBeenPressedBefore =
false;
3956 ActiveIdHasBeenEditedBefore =
false;
3957 ActiveIdHasBeenEditedThisFrame =
false;
3958 ActiveIdFromShortcut =
false;
3959 ActiveIdClickOffset = ImVec2(-1, -1);
3960 ActiveIdWindow = NULL;
3961 ActiveIdSource = ImGuiInputSource_None;
3962 ActiveIdMouseButton = -1;
3963 ActiveIdPreviousFrame = 0;
3964 ActiveIdPreviousFrameIsAlive =
false;
3965 ActiveIdPreviousFrameHasBeenEditedBefore =
false;
3966 ActiveIdPreviousFrameWindow = NULL;
3968 LastActiveIdTimer = 0.0f;
3970 LastKeyboardKeyPressTime = LastKeyModsChangeTime = LastKeyModsChangeFromNoneTime = -1.0;
3972 ActiveIdUsingNavDirMask = 0x00;
3973 ActiveIdUsingAllKeyboardKeys =
false;
3975 CurrentFocusScopeId = 0;
3976 CurrentItemFlags = ImGuiItemFlags_None;
3977 DebugShowGroupRects =
false;
3979 CurrentViewport = NULL;
3980 MouseViewport = MouseLastHoveredViewport = NULL;
3981 PlatformLastFocusedViewportId = 0;
3982 ViewportCreatedCount = PlatformWindowsCreatedCount = 0;
3983 ViewportFocusedStampCount = 0;
3985 NavCursorVisible =
false;
3986 NavHighlightItemUnderNav =
false;
3987 NavMousePosDirty =
false;
3988 NavIdIsAlive =
false;
3991 NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
3992 NavLayer = ImGuiNavLayer_Main;
3993 NavNextActivateId = 0;
3994 NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
3995 NavHighlightActivatedId = 0;
3996 NavHighlightActivatedTimer = 0.0f;
3997 NavInputSource = ImGuiInputSource_Keyboard;
3998 NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
3999 NavCursorHideFrames = 0;
4001 NavAnyRequest =
false;
4002 NavInitRequest =
false;
4003 NavInitRequestFromMove =
false;
4004 NavMoveSubmitted =
false;
4005 NavMoveScoringItems =
false;
4006 NavMoveForwardToNextFrame =
false;
4007 NavMoveFlags = ImGuiNavMoveFlags_None;
4008 NavMoveScrollFlags = ImGuiScrollFlags_None;
4009 NavMoveKeyMods = ImGuiMod_None;
4010 NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None;
4011 NavScoringDebugCount = 0;
4013 NavTabbingCounter = 0;
4015 NavJustMovedFromFocusScopeId = NavJustMovedToId = NavJustMovedToFocusScopeId = 0;
4016 NavJustMovedToKeyMods = ImGuiMod_None;
4017 NavJustMovedToIsTabbing =
false;
4018 NavJustMovedToHasSelectionData =
false;
4022 ConfigNavWindowingKeyNext = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiKey_Tab);
4023 ConfigNavWindowingKeyPrev = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab);
4024 NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
4025 NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
4026 NavWindowingToggleLayer =
false;
4027 NavWindowingToggleKey = ImGuiKey_None;
4031 DragDropActive = DragDropWithinSource = DragDropWithinTarget =
false;
4032 DragDropSourceFlags = ImGuiDragDropFlags_None;
4033 DragDropSourceFrameCount = -1;
4034 DragDropMouseButton = -1;
4035 DragDropTargetId = 0;
4036 DragDropAcceptFlags = ImGuiDragDropFlags_None;
4037 DragDropAcceptIdCurrRectSurface = 0.0f;
4038 DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0;
4039 DragDropAcceptFrameCount = -1;
4040 DragDropHoldJustPressedId = 0;
4041 memset(DragDropPayloadBufLocal, 0,
sizeof(DragDropPayloadBufLocal));
4043 ClipperTempDataStacked = 0;
4045 CurrentTable = NULL;
4046 TablesTempDataStacked = 0;
4047 CurrentTabBar = NULL;
4048 CurrentMultiSelect = NULL;
4049 MultiSelectTempDataStacked = 0;
4051 HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId = 0;
4052 HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f;
4054 MouseCursor = ImGuiMouseCursor_Arrow;
4055 MouseStationaryTimer = 0.0f;
4058 memset(&DataTypeZeroValue, 0,
sizeof(DataTypeZeroValue));
4059 BeginMenuDepth = BeginComboDepth = 0;
4060 ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
4061 ColorEditCurrentID = ColorEditSavedID = 0;
4062 ColorEditSavedHue = ColorEditSavedSat = 0.0f;
4063 ColorEditSavedColor = 0;
4064 WindowResizeRelativeMode =
false;
4065 ScrollbarSeekMode = 0;
4066 ScrollbarClickDeltaToGrabCenter = 0.0f;
4067 SliderGrabClickOffset = 0.0f;
4068 SliderCurrentAccum = 0.0f;
4069 SliderCurrentAccumDirty =
false;
4070 DragCurrentAccumDirty =
false;
4071 DragCurrentAccum = 0.0f;
4072 DragSpeedDefaultRatio = 1.0f / 100.0f;
4073 DisabledAlphaBackup = 0.0f;
4074 DisabledStackSize = 0;
4075 TooltipOverrideCount = 0;
4076 TooltipPreviousWindow = NULL;
4078 PlatformImeData.InputPos = ImVec2(0.0f, 0.0f);
4079 PlatformImeDataPrev.InputPos = ImVec2(-1.0f, -1.0f);
4080 PlatformImeViewport = 0;
4082 DockNodeWindowMenuHandler = NULL;
4084 SettingsLoaded =
false;
4085 SettingsDirtyTimer = 0.0f;
4088 memset(LocalizationTable, 0,
sizeof(LocalizationTable));
4091 LogType = ImGuiLogType_None;
4092 LogNextPrefix = LogNextSuffix = NULL;
4094 LogLinePosY = FLT_MAX;
4095 LogLineFirstItem =
false;
4097 LogDepthToExpand = LogDepthToExpandDefault = 2;
4099 ErrorCallback = NULL;
4100 ErrorCallbackUserData = NULL;
4102 ErrorCountCurrentFrame = 0;
4103 StackSizesInBeginForCurrentWindow = NULL;
4105 DebugDrawIdConflictsCount = 0;
4106 DebugLogFlags = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_OutputToTTY;
4108 DebugLogSkippedErrors = 0;
4109 DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
4110 DebugLogAutoDisableFrames = 0;
4111 DebugLocateFrames = 0;
4112 DebugBeginReturnValueCullDepth = -1;
4113 DebugItemPickerActive =
false;
4114 DebugItemPickerMouseButton = ImGuiMouseButton_Left;
4115 DebugItemPickerBreakId = 0;
4116 DebugFlashStyleColorTime = 0.0f;
4117 DebugFlashStyleColorIdx = ImGuiCol_COUNT;
4118 DebugHoveredDockNode = NULL;
4121 DebugBreakInWindow = 0;
4122 DebugBreakInTable = 0;
4123 DebugBreakInLocateId =
false;
4124 DebugBreakKeyChord = ImGuiKey_Pause;
4125 DebugBreakInShortcutRouting = ImGuiKey_None;
4127 memset(FramerateSecPerFrame, 0,
sizeof(FramerateSecPerFrame));
4128 FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0;
4129 FramerateSecPerFrameAccum = 0.0f;
4130 WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;
4131 memset(TempKeychordName, 0,
sizeof(TempKeychordName));
4134void ImGui::Initialize()
4137 IM_ASSERT(!
g.Initialized && !
g.SettingsLoaded);
4141 ImGuiSettingsHandler ini_handler;
4142 ini_handler.TypeName =
"Window";
4143 ini_handler.TypeHash =
ImHashStr(
"Window");
4144 ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll;
4145 ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen;
4146 ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine;
4147 ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll;
4148 ini_handler.WriteAllFn = WindowSettingsHandler_WriteAll;
4149 AddSettingsHandler(&ini_handler);
4151 TableSettingsAddSettingsHandler();
4154 LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_ARRAYSIZE(GLocalizationEntriesEnUS));
4157 g.PlatformIO.Platform_GetClipboardTextFn = Platform_GetClipboardTextFn_DefaultImpl;
4158 g.PlatformIO.Platform_SetClipboardTextFn = Platform_SetClipboardTextFn_DefaultImpl;
4159 g.PlatformIO.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl;
4160 g.PlatformIO.Platform_SetImeDataFn = Platform_SetImeDataFn_DefaultImpl;
4163 ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)();
4166 viewport->PlatformWindowCreated =
true;
4167 viewport->Flags = ImGuiViewportFlags_OwnedByApp;
4168 g.Viewports.push_back(viewport);
4169 g.TempBuffer.resize(1024 * 3 + 1, 0);
4170 g.ViewportCreatedCount++;
4171 g.PlatformIO.Viewports.push_back(
g.Viewports[0]);
4174 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
4175 if ((key >= ImGuiKey_0 && key <= ImGuiKey_9) || (key >= ImGuiKey_A && key <= ImGuiKey_Z) || (key >= ImGuiKey_Keypad0 && key <= ImGuiKey_Keypad9)
4176 || key == ImGuiKey_Tab || key == ImGuiKey_Space || key == ImGuiKey_Apostrophe || key == ImGuiKey_Comma || key == ImGuiKey_Minus || key == ImGuiKey_Period
4177 || key == ImGuiKey_Slash || key == ImGuiKey_Semicolon || key == ImGuiKey_Equal || key == ImGuiKey_LeftBracket || key == ImGuiKey_RightBracket || key == ImGuiKey_GraveAccent
4178 || key == ImGuiKey_KeypadDecimal || key == ImGuiKey_KeypadDivide || key == ImGuiKey_KeypadMultiply || key == ImGuiKey_KeypadSubtract || key == ImGuiKey_KeypadAdd || key == ImGuiKey_KeypadEqual)
4179 g.KeysMayBeCharInput.SetBit(key);
4181#ifdef IMGUI_HAS_DOCK
4183 DockContextInitialize(&
g);
4186 g.Initialized =
true;
4190void ImGui::Shutdown()
4193 IM_ASSERT_USER_ERROR(
g.IO.BackendPlatformUserData == NULL,
"Forgot to shutdown Platform backend?");
4194 IM_ASSERT_USER_ERROR(
g.IO.BackendRendererUserData == NULL,
"Forgot to shutdown Renderer backend?");
4197 if (
g.IO.Fonts &&
g.FontAtlasOwnedByContext)
4199 g.IO.Fonts->Locked =
false;
4200 IM_DELETE(
g.IO.Fonts);
4203 g.DrawListSharedData.TempBuffer.clear();
4210 if (
g.SettingsLoaded &&
g.IO.IniFilename != NULL)
4211 SaveIniSettingsToDisk(
g.IO.IniFilename);
4214 DestroyPlatformWindows();
4217 DockContextShutdown(&
g);
4219 CallContextHooks(&
g, ImGuiContextHookType_Shutdown);
4222 g.Windows.clear_delete();
4223 g.WindowsFocusOrder.clear();
4224 g.WindowsTempSortBuffer.clear();
4225 g.CurrentWindow = NULL;
4226 g.CurrentWindowStack.clear();
4227 g.WindowsById.Clear();
4229 g.HoveredWindow =
g.HoveredWindowUnderMovingWindow = NULL;
4230 g.ActiveIdWindow =
g.ActiveIdPreviousFrameWindow = NULL;
4231 g.MovingWindow = NULL;
4233 g.KeysRoutingTable.Clear();
4235 g.ColorStack.clear();
4236 g.StyleVarStack.clear();
4237 g.FontStack.clear();
4238 g.OpenPopupStack.clear();
4239 g.BeginPopupStack.clear();
4240 g.TreeNodeStack.clear();
4242 g.CurrentViewport =
g.MouseViewport =
g.MouseLastHoveredViewport = NULL;
4243 g.Viewports.clear_delete();
4246 g.CurrentTabBarStack.clear();
4247 g.ShrinkWidthBuffer.clear();
4249 g.ClipperTempData.clear_destruct();
4252 g.TablesTempData.clear_destruct();
4253 g.DrawChannelsTempMergeBuffer.clear();
4255 g.MultiSelectStorage.Clear();
4256 g.MultiSelectTempData.clear_destruct();
4258 g.ClipboardHandlerData.clear();
4259 g.MenusIdSubmittedThisFrame.clear();
4260 g.InputTextState.ClearFreeMemory();
4261 g.InputTextDeactivatedState.ClearFreeMemory();
4263 g.SettingsWindows.clear();
4264 g.SettingsHandlers.clear();
4268#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
4269 if (
g.LogFile != stdout)
4274 g.LogBuffer.clear();
4275 g.DebugLogBuf.clear();
4276 g.DebugLogIndex.clear();
4278 g.Initialized =
false;
4282ImGuiID ImGui::AddContextHook(ImGuiContext* ctx,
const ImGuiContextHook* hook)
4284 ImGuiContext&
g = *ctx;
4285 IM_ASSERT(hook->Callback != NULL && hook->HookId == 0 && hook->Type != ImGuiContextHookType_PendingRemoval_);
4286 g.Hooks.push_back(*hook);
4287 g.Hooks.back().HookId = ++
g.HookIdNext;
4288 return g.HookIdNext;
4292void ImGui::RemoveContextHook(ImGuiContext* ctx, ImGuiID hook_id)
4294 ImGuiContext&
g = *ctx;
4295 IM_ASSERT(hook_id != 0);
4296 for (ImGuiContextHook& hook :
g.Hooks)
4297 if (hook.HookId == hook_id)
4298 hook.Type = ImGuiContextHookType_PendingRemoval_;
4303void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type)
4305 ImGuiContext&
g = *ctx;
4306 for (ImGuiContextHook& hook :
g.Hooks)
4307 if (hook.Type == hook_type)
4308 hook.Callback(&
g, &hook);
4317ImGuiWindow::ImGuiWindow(ImGuiContext* ctx,
const char* name) : DrawListInst(NULL)
4319 memset(
this, 0,
sizeof(*
this));
4322 NameBufLen = (int)strlen(name) + 1;
4324 IDStack.push_back(ID);
4325 ViewportAllowPlatformMonitorExtend = -1;
4326 ViewportPos = ImVec2(FLT_MAX, FLT_MAX);
4327 MoveId = GetID(
"#MOVE");
4328 TabId = GetID(
"#TAB");
4329 ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
4330 ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
4331 AutoFitFramesX = AutoFitFramesY = -1;
4332 AutoPosLastDirection = ImGuiDir_None;
4333 SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = SetWindowDockAllowFlags = 0;
4334 SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX);
4335 LastFrameActive = -1;
4336 LastFrameJustFocused = -1;
4337 LastTimeActive = -1.0f;
4338 FontWindowScale = FontDpiScale = 1.0f;
4339 SettingsOffset = -1;
4341 DrawList = &DrawListInst;
4342 DrawList->_Data = &Ctx->DrawListSharedData;
4343 DrawList->_OwnerName = Name;
4344 NavPreferredScoringPosRel[0] = NavPreferredScoringPosRel[1] = ImVec2(FLT_MAX, FLT_MAX);
4345 IM_PLACEMENT_NEW(&WindowClass) ImGuiWindowClass();
4348ImGuiWindow::~ImGuiWindow()
4350 IM_ASSERT(DrawList == &DrawListInst);
4352 ColumnsStorage.clear_destruct();
4355static void SetCurrentWindow(ImGuiWindow* window)
4358 g.CurrentWindow = window;
4359 g.StackSizesInBeginForCurrentWindow =
g.CurrentWindow ? &
g.CurrentWindowStack.back().StackSizesInBegin : NULL;
4360 g.CurrentTable = window && window->DC.CurrentTableIdx != -1 ?
g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL;
4363 g.FontSize =
g.DrawListSharedData.FontSize = window->CalcFontSize();
4364 g.FontScale =
g.DrawListSharedData.FontScale =
g.FontSize /
g.Font->FontSize;
4365 ImGui::NavUpdateCurrentWindowIsScrollPushableX();
4369void ImGui::GcCompactTransientMiscBuffers()
4372 g.ItemFlagsStack.clear();
4373 g.GroupStack.clear();
4374 g.MultiSelectTempDataStacked = 0;
4375 g.MultiSelectTempData.clear_destruct();
4376 TableGcCompactSettings();
4383void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window)
4385 window->MemoryCompacted =
true;
4386 window->MemoryDrawListIdxCapacity = window->DrawList->IdxBuffer.Capacity;
4387 window->MemoryDrawListVtxCapacity = window->DrawList->VtxBuffer.Capacity;
4388 window->IDStack.clear();
4389 window->DrawList->_ClearFreeMemory();
4390 window->DC.ChildWindows.clear();
4391 window->DC.ItemWidthStack.clear();
4392 window->DC.TextWrapPosStack.clear();
4395void ImGui::GcAwakeTransientWindowBuffers(ImGuiWindow* window)
4399 window->MemoryCompacted =
false;
4400 window->DrawList->IdxBuffer.reserve(window->MemoryDrawListIdxCapacity);
4401 window->DrawList->VtxBuffer.reserve(window->MemoryDrawListVtxCapacity);
4402 window->MemoryDrawListIdxCapacity = window->MemoryDrawListVtxCapacity = 0;
4405void ImGui::SetActiveID(ImGuiID
id, ImGuiWindow* window)
4410 if (
g.ActiveId != 0)
4415 if (
g.MovingWindow != NULL &&
g.ActiveId ==
g.MovingWindow->MoveId)
4417 IMGUI_DEBUG_LOG_ACTIVEID(
"SetActiveID() cancel MovingWindow\n");
4418 g.MovingWindow = NULL;
4424 if (
g.InputTextState.ID ==
g.ActiveId)
4425 InputTextDeactivateHook(
g.ActiveId);
4429 g.ActiveIdIsJustActivated = (
g.ActiveId !=
id);
4430 if (
g.ActiveIdIsJustActivated)
4432 IMGUI_DEBUG_LOG_ACTIVEID(
"SetActiveID() old:0x%08X (window \"%s\") -> new:0x%08X (window \"%s\")\n",
g.ActiveId,
g.ActiveIdWindow ?
g.ActiveIdWindow->Name :
"",
id, window ? window->Name :
"");
4433 g.ActiveIdTimer = 0.0f;
4434 g.ActiveIdHasBeenPressedBefore =
false;
4435 g.ActiveIdHasBeenEditedBefore =
false;
4436 g.ActiveIdMouseButton = -1;
4439 g.LastActiveId =
id;
4440 g.LastActiveIdTimer = 0.0f;
4444 g.ActiveIdAllowOverlap =
false;
4445 g.ActiveIdNoClearOnFocusLoss =
false;
4446 g.ActiveIdWindow = window;
4447 g.ActiveIdHasBeenEditedThisFrame =
false;
4448 g.ActiveIdFromShortcut =
false;
4451 g.ActiveIdIsAlive =
id;
4452 g.ActiveIdSource = (
g.NavActivateId ==
id ||
g.NavJustMovedToId ==
id) ?
g.NavInputSource : ImGuiInputSource_Mouse;
4453 IM_ASSERT(
g.ActiveIdSource != ImGuiInputSource_None);
4458 g.ActiveIdUsingNavDirMask = 0x00;
4459 g.ActiveIdUsingAllKeyboardKeys =
false;
4462void ImGui::ClearActiveID()
4464 SetActiveID(0, NULL);
4467void ImGui::SetHoveredID(ImGuiID
id)
4471 g.HoveredIdAllowOverlap =
false;
4472 if (
id != 0 &&
g.HoveredIdPreviousFrame !=
id)
4473 g.HoveredIdTimer =
g.HoveredIdNotActiveTimer = 0.0f;
4476ImGuiID ImGui::GetHoveredID()
4479 return g.HoveredId ?
g.HoveredId :
g.HoveredIdPreviousFrame;
4482void ImGui::MarkItemEdited(ImGuiID
id)
4487 if (
g.LastItemData.ItemFlags & ImGuiItemFlags_NoMarkEdited)
4489 if (
g.ActiveId ==
id ||
g.ActiveId == 0)
4491 g.ActiveIdHasBeenEditedThisFrame =
true;
4492 g.ActiveIdHasBeenEditedBefore =
true;
4497 IM_ASSERT(
g.DragDropActive ||
g.ActiveId ==
id ||
g.ActiveId == 0 ||
g.ActiveIdPreviousFrame ==
id || (
g.CurrentMultiSelect != NULL &&
g.BoxSelectState.IsActive));
4500 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
4503bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
4509 if (ImGuiWindow* focused_root_window =
g.NavWindow->RootWindowDockTree)
4510 if (focused_root_window->WasActive && focused_root_window != window->RootWindowDockTree)
4514 bool want_inhibit =
false;
4515 if (focused_root_window->Flags & ImGuiWindowFlags_Modal)
4516 want_inhibit =
true;
4517 else if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup))
4518 want_inhibit =
true;
4522 if (!IsWindowWithinBeginStackOf(window->RootWindow, focused_root_window))
4527 if (window->Viewport !=
g.MouseViewport)
4528 if (
g.MovingWindow == NULL || window->RootWindowDockTree !=
g.MovingWindow->RootWindowDockTree)
4534static inline float CalcDelayFromHoveredFlags(ImGuiHoveredFlags flags)
4537 if (flags & ImGuiHoveredFlags_DelayNormal)
4538 return g.Style.HoverDelayNormal;
4539 if (flags & ImGuiHoveredFlags_DelayShort)
4540 return g.Style.HoverDelayShort;
4544static ImGuiHoveredFlags ApplyHoverFlagsForTooltip(ImGuiHoveredFlags user_flags, ImGuiHoveredFlags shared_flags)
4547 if (user_flags & (ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal))
4548 shared_flags &= ~(ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal);
4549 return user_flags | shared_flags;
4555bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
4558 ImGuiWindow* window =
g.CurrentWindow;
4559 IM_ASSERT_USER_ERROR((flags & ~ImGuiHoveredFlags_AllowedMaskForIsItemHovered) == 0,
"Invalid flags for IsItemHovered()!");
4561 if (
g.NavHighlightItemUnderNav &&
g.NavCursorVisible && !(flags & ImGuiHoveredFlags_NoNavOverride))
4563 if (!IsItemFocused())
4565 if ((
g.LastItemData.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
4568 if (flags & ImGuiHoveredFlags_ForTooltip)
4569 flags = ApplyHoverFlagsForTooltip(flags,
g.Style.HoverFlagsForTooltipNav);
4574 ImGuiItemStatusFlags status_flags =
g.LastItemData.StatusFlags;
4575 if (!(status_flags & ImGuiItemStatusFlags_HoveredRect))
4578 if (flags & ImGuiHoveredFlags_ForTooltip)
4579 flags = ApplyHoverFlagsForTooltip(flags,
g.Style.HoverFlagsForTooltipMouse);
4587 if (
g.HoveredWindow != window && (status_flags & ImGuiItemStatusFlags_HoveredWindow) == 0)
4588 if ((flags & ImGuiHoveredFlags_AllowWhenOverlappedByWindow) == 0)
4592 const ImGuiID
id =
g.LastItemData.ID;
4593 if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0)
4594 if (
g.ActiveId != 0 &&
g.ActiveId !=
id && !
g.ActiveIdAllowOverlap)
4595 if (
g.ActiveId != window->MoveId &&
g.ActiveId != window->TabId)
4600 if (!IsWindowContentHoverable(window, flags) && !(
g.LastItemData.ItemFlags & ImGuiItemFlags_NoWindowHoverableCheck))
4604 if ((
g.LastItemData.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
4610 if (
id == window->MoveId && window->WriteAccessed)
4614 if ((
g.LastItemData.ItemFlags & ImGuiItemFlags_AllowOverlap) &&
id != 0)
4615 if ((flags & ImGuiHoveredFlags_AllowWhenOverlappedByItem) == 0)
4616 if (
g.HoveredIdPreviousFrame !=
g.LastItemData.ID)
4622 const float delay = CalcDelayFromHoveredFlags(flags);
4623 if (delay > 0.0f || (flags & ImGuiHoveredFlags_Stationary))
4625 ImGuiID hover_delay_id = (
g.LastItemData.ID != 0) ?
g.LastItemData.ID : window->GetIDFromPos(
g.LastItemData.Rect.Min);
4626 if ((flags & ImGuiHoveredFlags_NoSharedDelay) && (
g.HoverItemDelayIdPreviousFrame != hover_delay_id))
4627 g.HoverItemDelayTimer = 0.0f;
4628 g.HoverItemDelayId = hover_delay_id;
4633 if ((flags & ImGuiHoveredFlags_Stationary) != 0 &&
g.HoverItemUnlockedStationaryId != hover_delay_id)
4636 if (
g.HoverItemDelayTimer < delay)
4649bool ImGui::ItemHoverable(
const ImRect& bb, ImGuiID
id, ImGuiItemFlags item_flags)
4652 ImGuiWindow* window =
g.CurrentWindow;
4655#ifndef IMGUI_DISABLE_DEBUG_TOOLS
4656 if (
id != 0 &&
g.HoveredIdPreviousFrame ==
id && (item_flags & ImGuiItemFlags_AllowDuplicateId) == 0)
4658 g.HoveredIdPreviousFrameItemCount++;
4659 if (
g.DebugDrawIdConflicts ==
id)
4660 window->DrawList->AddRect(bb.Min - ImVec2(1,1), bb.Max + ImVec2(1,1), IM_COL32(255, 0, 0, 255), 0.0f, ImDrawFlags_None, 2.0f);
4664 if (
g.HoveredWindow != window)
4666 if (!IsMouseHoveringRect(bb.Min, bb.Max))
4669 if (
g.HoveredId != 0 &&
g.HoveredId !=
id && !
g.HoveredIdAllowOverlap)
4671 if (
g.ActiveId != 0 &&
g.ActiveId !=
id && !
g.ActiveIdAllowOverlap)
4672 if (!
g.ActiveIdFromShortcut)
4676 if (!(item_flags & ImGuiItemFlags_NoWindowHoverableCheck) && !IsWindowContentHoverable(window, ImGuiHoveredFlags_None))
4678 g.HoveredIdIsDisabled =
true;
4687 if (
g.DragDropActive &&
g.DragDropPayload.SourceId ==
id && !(
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoDisableHover))
4694 if (item_flags & ImGuiItemFlags_AllowOverlap)
4696 g.HoveredIdAllowOverlap =
true;
4697 if (
g.HoveredIdPreviousFrame !=
id)
4703 if (
id ==
g.LastItemData.ID && (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasShortcut) &&
g.ActiveId !=
id)
4704 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_DelayNormal))
4705 SetTooltip(
"%s", GetKeyChordName(
g.LastItemData.Shortcut));
4709 if (item_flags & ImGuiItemFlags_Disabled)
4712 if (
g.ActiveId ==
id &&
id != 0)
4714 g.HoveredIdIsDisabled =
true;
4718#ifndef IMGUI_DISABLE_DEBUG_TOOLS
4725 if (
g.DebugItemPickerActive &&
g.HoveredIdPreviousFrame ==
id)
4726 GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
4727 if (
g.DebugItemPickerBreakId ==
id)
4732 if (
g.NavHighlightItemUnderNav && (item_flags & ImGuiItemFlags_NoNavDisableMouseHover) == 0)
4740bool ImGui::IsClippedEx(
const ImRect& bb, ImGuiID
id)
4743 ImGuiWindow* window =
g.CurrentWindow;
4744 if (!bb.Overlaps(window->ClipRect))
4745 if (
id == 0 || (
id !=
g.ActiveId &&
id !=
g.ActiveIdPreviousFrame &&
id !=
g.NavId &&
id !=
g.NavActivateId))
4746 if (!
g.ItemUnclipByLog)
4753void ImGui::SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags item_flags,
const ImRect& item_rect)
4756 g.LastItemData.ID = item_id;
4757 g.LastItemData.ItemFlags = in_flags;
4758 g.LastItemData.StatusFlags = item_flags;
4759 g.LastItemData.Rect =
g.LastItemData.NavRect = item_rect;
4762float ImGui::CalcWrapWidthForPos(
const ImVec2& pos,
float wrap_pos_x)
4764 if (wrap_pos_x < 0.0f)
4768 ImGuiWindow* window =
g.CurrentWindow;
4769 if (wrap_pos_x == 0.0f)
4776 wrap_pos_x = window->WorkRect.Max.x;
4778 else if (wrap_pos_x > 0.0f)
4780 wrap_pos_x += window->Pos.x - window->Scroll.x;
4783 return ImMax(wrap_pos_x - pos.x, 1.0f);
4787void* ImGui::MemAlloc(
size_t size)
4789 void* ptr = (*GImAllocatorAllocFunc)(
size, GImAllocatorUserData);
4790#ifndef IMGUI_DISABLE_DEBUG_TOOLS
4791 if (ImGuiContext* ctx =
GImGui)
4792 DebugAllocHook(&ctx->DebugAllocInfo, ctx->FrameCount, ptr, size);
4798void ImGui::MemFree(
void* ptr)
4800#ifndef IMGUI_DISABLE_DEBUG_TOOLS
4802 if (ImGuiContext* ctx =
GImGui)
4803 DebugAllocHook(&ctx->DebugAllocInfo, ctx->FrameCount, ptr, (
size_t)-1);
4805 return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData);
4809void ImGui::DebugAllocHook(ImGuiDebugAllocInfo* info,
int frame_count,
void* ptr,
size_t size)
4811 ImGuiDebugAllocEntry* entry = &info->LastEntriesBuf[info->LastEntriesIdx];
4813 if (entry->FrameCount != frame_count)
4815 info->LastEntriesIdx = (info->LastEntriesIdx + 1) % IM_ARRAYSIZE(info->LastEntriesBuf);
4816 entry = &info->LastEntriesBuf[info->LastEntriesIdx];
4817 entry->FrameCount = frame_count;
4818 entry->AllocCount = entry->FreeCount = 0;
4820 if (size != (
size_t)-1)
4822 entry->AllocCount++;
4823 info->TotalAllocCount++;
4829 info->TotalFreeCount++;
4834const char* ImGui::GetClipboardText()
4837 return g.PlatformIO.Platform_GetClipboardTextFn ?
g.PlatformIO.Platform_GetClipboardTextFn(&
g) :
"";
4840void ImGui::SetClipboardText(
const char* text)
4843 if (
g.PlatformIO.Platform_SetClipboardTextFn != NULL)
4844 g.PlatformIO.Platform_SetClipboardTextFn(&
g, text);
4847const char* ImGui::GetVersion()
4849 return IMGUI_VERSION;
4852ImGuiIO& ImGui::GetIO()
4854 IM_ASSERT(
GImGui != NULL &&
"No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
4859ImGuiIO& ImGui::GetIOEx(ImGuiContext* ctx)
4861 IM_ASSERT(ctx != NULL);
4865ImGuiPlatformIO& ImGui::GetPlatformIO()
4867 IM_ASSERT(
GImGui != NULL &&
"No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext()?");
4868 return GImGui->PlatformIO;
4872ImDrawData* ImGui::GetDrawData()
4875 ImGuiViewportP* viewport =
g.Viewports[0];
4876 return viewport->DrawDataP.Valid ? &viewport->DrawDataP : NULL;
4879double ImGui::GetTime()
4884int ImGui::GetFrameCount()
4886 return GImGui->FrameCount;
4889static ImDrawList* GetViewportBgFgDrawList(ImGuiViewportP* viewport,
size_t drawlist_no,
const char* drawlist_name)
4893 IM_ASSERT(drawlist_no < IM_ARRAYSIZE(viewport->BgFgDrawLists));
4894 ImDrawList* draw_list = viewport->BgFgDrawLists[drawlist_no];
4895 if (draw_list == NULL)
4897 draw_list = IM_NEW(ImDrawList)(&
g.DrawListSharedData);
4898 draw_list->_OwnerName = drawlist_name;
4899 viewport->BgFgDrawLists[drawlist_no] = draw_list;
4903 if (viewport->BgFgDrawListsLastFrame[drawlist_no] !=
g.FrameCount)
4905 draw_list->_ResetForNewFrame();
4906 draw_list->PushTextureID(
g.IO.Fonts->TexID);
4907 draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size,
false);
4908 viewport->BgFgDrawListsLastFrame[drawlist_no] =
g.FrameCount;
4913ImDrawList* ImGui::GetBackgroundDrawList(ImGuiViewport* viewport)
4915 if (viewport == NULL)
4916 viewport =
GImGui->CurrentWindow->Viewport;
4917 return GetViewportBgFgDrawList((ImGuiViewportP*)viewport, 0,
"##Background");
4920ImDrawList* ImGui::GetForegroundDrawList(ImGuiViewport* viewport)
4922 if (viewport == NULL)
4923 viewport =
GImGui->CurrentWindow->Viewport;
4924 return GetViewportBgFgDrawList((ImGuiViewportP*)viewport, 1,
"##Foreground");
4927ImDrawListSharedData* ImGui::GetDrawListSharedData()
4929 return &
GImGui->DrawListSharedData;
4932void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
4938 FocusWindow(window);
4939 SetActiveID(window->MoveId, window);
4940 if (
g.IO.ConfigNavCursorVisibleAuto)
4941 g.NavCursorVisible =
false;
4942 g.ActiveIdClickOffset =
g.IO.MouseClickedPos[0] - window->RootWindowDockTree->Pos;
4943 g.ActiveIdNoClearOnFocusLoss =
true;
4944 SetActiveIdUsingAllKeyboardKeys();
4946 bool can_move_window =
true;
4947 if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindowDockTree->Flags & ImGuiWindowFlags_NoMove))
4948 can_move_window =
false;
4949 if (ImGuiDockNode* node = window->DockNodeAsHost)
4950 if (node->VisibleWindow && (node->VisibleWindow->Flags & ImGuiWindowFlags_NoMove))
4951 can_move_window =
false;
4952 if (can_move_window)
4953 g.MovingWindow = window;
4957void ImGui::StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* node,
bool undock)
4960 bool can_undock_node =
false;
4961 if (undock && node != NULL && node->VisibleWindow && (node->VisibleWindow->Flags & ImGuiWindowFlags_NoMove) == 0 && (node->MergedFlags & ImGuiDockNodeFlags_NoUndocking) == 0)
4966 ImGuiDockNode* root_node = DockNodeGetRootNode(node);
4967 if (root_node->OnlyNodeWithWindows != node || root_node->CentralNode != NULL)
4968 can_undock_node =
true;
4971 const bool clicked = IsMouseClicked(0);
4972 const bool dragging = IsMouseDragging(0);
4973 if (can_undock_node && dragging)
4974 DockContextQueueUndockNode(&
g, node);
4975 else if (!can_undock_node && (clicked || dragging) &&
g.MovingWindow != window)
4976 StartMouseMovingWindow(window);
4984void ImGui::UpdateMouseMovingWindowNewFrame()
4987 if (
g.MovingWindow != NULL)
4991 KeepAliveID(
g.ActiveId);
4992 IM_ASSERT(
g.MovingWindow &&
g.MovingWindow->RootWindowDockTree);
4993 ImGuiWindow* moving_window =
g.MovingWindow->RootWindowDockTree;
4996 const bool window_disappared = (!moving_window->WasActive && !moving_window->Active);
4997 if (
g.IO.MouseDown[0] && IsMousePosValid(&
g.IO.MousePos) && !window_disappared)
4999 ImVec2 pos =
g.IO.MousePos -
g.ActiveIdClickOffset;
5000 if (moving_window->Pos.x != pos.x || moving_window->Pos.y != pos.y)
5002 SetWindowPos(moving_window, pos, ImGuiCond_Always);
5003 if (moving_window->Viewport && moving_window->ViewportOwned)
5005 moving_window->Viewport->Pos = pos;
5006 moving_window->Viewport->UpdateWorkRect();
5009 FocusWindow(
g.MovingWindow);
5013 if (!window_disappared)
5017 if (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
5018 UpdateTryMergeWindowIntoHostViewport(moving_window,
g.MouseViewport);
5021 if (moving_window->Viewport && !IsDragDropPayloadBeingAccepted())
5022 g.MouseViewport = moving_window->Viewport;
5025 if (moving_window->Viewport)
5026 moving_window->Viewport->Flags &= ~ImGuiViewportFlags_NoInputs;
5029 g.MovingWindow = NULL;
5036 if (
g.ActiveIdWindow &&
g.ActiveIdWindow->MoveId ==
g.ActiveId)
5038 KeepAliveID(
g.ActiveId);
5039 if (!
g.IO.MouseDown[0])
5048void ImGui::UpdateMouseMovingWindowEndFrame()
5051 if (
g.ActiveId != 0 || (
g.HoveredId != 0 && !
g.HoveredIdIsDisabled))
5055 if (
g.NavWindow &&
g.NavWindow->Appearing)
5060 if (
g.IO.MouseClicked[0])
5064 ImGuiWindow* root_window =
g.HoveredWindow ?
g.HoveredWindow->RootWindow : NULL;
5065 const bool is_closed_popup = root_window && (root_window->Flags & ImGuiWindowFlags_Popup) && !IsPopupOpen(root_window->PopupId, ImGuiPopupFlags_AnyPopupLevel);
5067 if (root_window != NULL && !is_closed_popup)
5069 StartMouseMovingWindow(
g.HoveredWindow);
5072 if (
g.IO.ConfigWindowsMoveFromTitleBarOnly)
5073 if (!(root_window->Flags & ImGuiWindowFlags_NoTitleBar) || root_window->DockIsActive)
5074 if (!root_window->TitleBarRect().Contains(
g.IO.MouseClickedPos[0]))
5075 g.MovingWindow = NULL;
5079 if (
g.HoveredIdIsDisabled)
5080 g.MovingWindow = NULL;
5082 else if (root_window == NULL &&
g.NavWindow != NULL)
5085 FocusWindow(NULL, ImGuiFocusRequestFlags_UnlessBelowModal);
5092 if (
g.IO.MouseClicked[1] &&
g.HoveredId == 0)
5096 ImGuiWindow* modal = GetTopMostPopupModal();
5097 bool hovered_window_above_modal =
g.HoveredWindow && (modal == NULL || IsWindowAbove(
g.HoveredWindow, modal));
5098 ClosePopupsOverWindow(hovered_window_above_modal ?
g.HoveredWindow : modal, true);
5104static void TranslateWindow(ImGuiWindow* window,
const ImVec2& delta)
5106 window->Pos += delta;
5107 window->ClipRect.Translate(delta);
5108 window->OuterRectClipped.Translate(delta);
5109 window->InnerRect.Translate(delta);
5110 window->DC.CursorPos += delta;
5111 window->DC.CursorStartPos += delta;
5112 window->DC.CursorMaxPos += delta;
5113 window->DC.IdealMaxPos += delta;
5116static void ScaleWindow(ImGuiWindow* window,
float scale)
5118 ImVec2 origin = window->Viewport->Pos;
5119 window->Pos = ImFloor((window->Pos - origin) * scale + origin);
5120 window->Size = ImTrunc(window->Size * scale);
5121 window->SizeFull = ImTrunc(window->SizeFull * scale);
5122 window->ContentSize = ImTrunc(window->ContentSize * scale);
5125static bool IsWindowActiveAndVisible(ImGuiWindow* window)
5127 return (window->Active) && (!window->Hidden);
5131void ImGui::UpdateHoveredWindowAndCaptureFlags()
5138 g.WindowsHoverPadding = ImMax(
g.Style.TouchExtraPadding, ImVec2(WINDOWS_HOVER_PADDING, WINDOWS_HOVER_PADDING));
5144 bool clear_hovered_windows =
false;
5145 FindHoveredWindowEx(
g.IO.MousePos,
false, &
g.HoveredWindow, &
g.HoveredWindowUnderMovingWindow);
5146 IM_ASSERT(
g.HoveredWindow == NULL ||
g.HoveredWindow ==
g.MovingWindow ||
g.HoveredWindow->Viewport ==
g.MouseViewport);
5147 g.HoveredWindowBeforeClear =
g.HoveredWindow;
5150 ImGuiWindow* modal_window = GetTopMostPopupModal();
5151 if (modal_window &&
g.HoveredWindow && !IsWindowWithinBeginStackOf(
g.HoveredWindow->RootWindow, modal_window))
5152 clear_hovered_windows =
true;
5155 if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)
5156 clear_hovered_windows =
true;
5160 const bool has_open_popup = (
g.OpenPopupStack.Size > 0);
5161 const bool has_open_modal = (modal_window != NULL);
5162 int mouse_earliest_down = -1;
5163 bool mouse_any_down =
false;
5164 for (
int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
5166 if (io.MouseClicked[i])
5168 io.MouseDownOwned[i] = (
g.HoveredWindow != NULL) || has_open_popup;
5169 io.MouseDownOwnedUnlessPopupClose[i] = (
g.HoveredWindow != NULL) || has_open_modal;
5171 mouse_any_down |= io.MouseDown[i];
5172 if (io.MouseDown[i] || io.MouseReleased[i])
5173 if (mouse_earliest_down == -1 || io.MouseClickedTime[i] < io.MouseClickedTime[mouse_earliest_down])
5174 mouse_earliest_down = i;
5176 const bool mouse_avail = (mouse_earliest_down == -1) || io.MouseDownOwned[mouse_earliest_down];
5177 const bool mouse_avail_unless_popup_close = (mouse_earliest_down == -1) || io.MouseDownOwnedUnlessPopupClose[mouse_earliest_down];
5181 const bool mouse_dragging_extern_payload =
g.DragDropActive && (
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0;
5182 if (!mouse_avail && !mouse_dragging_extern_payload)
5183 clear_hovered_windows =
true;
5185 if (clear_hovered_windows)
5186 g.HoveredWindow =
g.HoveredWindowUnderMovingWindow = NULL;
5190 if (
g.WantCaptureMouseNextFrame != -1)
5192 io.WantCaptureMouse = io.WantCaptureMouseUnlessPopupClose = (
g.WantCaptureMouseNextFrame != 0);
5196 io.WantCaptureMouse = (mouse_avail && (
g.HoveredWindow != NULL || mouse_any_down)) || has_open_popup;
5197 io.WantCaptureMouseUnlessPopupClose = (mouse_avail_unless_popup_close && (
g.HoveredWindow != NULL || mouse_any_down)) || has_open_modal;
5201 io.WantCaptureKeyboard =
false;
5202 if ((io.ConfigFlags & ImGuiConfigFlags_NoKeyboard) == 0)
5204 if ((
g.ActiveId != 0) || (modal_window != NULL))
5205 io.WantCaptureKeyboard =
true;
5206 else if (io.NavActive && (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && io.ConfigNavCaptureKeyboard)
5207 io.WantCaptureKeyboard =
true;
5209 if (
g.WantCaptureKeyboardNextFrame != -1)
5210 io.WantCaptureKeyboard = (
g.WantCaptureKeyboardNextFrame != 0);
5213 io.WantTextInput = (
g.WantTextInputNextFrame != -1) ? (
g.WantTextInputNextFrame != 0) :
false;
5217static void SetupDrawListSharedData()
5220 ImRect virtual_space(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
5221 for (ImGuiViewportP* viewport :
g.Viewports)
5222 virtual_space.Add(viewport->GetMainRect());
5223 g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4();
5224 g.DrawListSharedData.CurveTessellationTol =
g.Style.CurveTessellationTol;
5225 g.DrawListSharedData.SetCircleTessellationMaxError(
g.Style.CircleTessellationMaxError);
5226 g.DrawListSharedData.InitialFlags = ImDrawListFlags_None;
5227 if (
g.Style.AntiAliasedLines)
5228 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines;
5229 if (
g.Style.AntiAliasedLinesUseTex && !(
g.IO.Fonts->Flags & ImFontAtlasFlags_NoBakedLines))
5230 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLinesUseTex;
5231 if (
g.Style.AntiAliasedFill)
5232 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill;
5233 if (
g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)
5234 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset;
5237void ImGui::NewFrame()
5239 IM_ASSERT(
GImGui != NULL &&
"No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
5244 for (
int n =
g.Hooks.Size - 1; n >= 0; n--)
5245 if (
g.Hooks[n].Type == ImGuiContextHookType_PendingRemoval_)
5246 g.Hooks.erase(&
g.Hooks[n]);
5248 CallContextHooks(&
g, ImGuiContextHookType_NewFramePre);
5251 g.ConfigFlagsLastFrame =
g.ConfigFlagsCurrFrame;
5252 ErrorCheckNewFrameSanityChecks();
5253 g.ConfigFlagsCurrFrame =
g.IO.ConfigFlags;
5258 g.Time +=
g.IO.DeltaTime;
5259 g.WithinFrameScope =
true;
5261 g.TooltipOverrideCount = 0;
5262 g.WindowsActiveCount = 0;
5263 g.MenusIdSubmittedThisFrame.resize(0);
5266 g.FramerateSecPerFrameAccum +=
g.IO.DeltaTime -
g.FramerateSecPerFrame[
g.FramerateSecPerFrameIdx];
5267 g.FramerateSecPerFrame[
g.FramerateSecPerFrameIdx] =
g.IO.DeltaTime;
5268 g.FramerateSecPerFrameIdx = (
g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(
g.FramerateSecPerFrame);
5269 g.FramerateSecPerFrameCount = ImMin(
g.FramerateSecPerFrameCount + 1, IM_ARRAYSIZE(
g.FramerateSecPerFrame));
5270 g.IO.Framerate = (
g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (
g.FramerateSecPerFrameAccum / (
float)
g.FramerateSecPerFrameCount)) : FLT_MAX;
5273 g.InputEventsTrail.resize(0);
5274 UpdateInputEvents(
g.IO.ConfigInputTrickleEventQueue);
5277 UpdateViewportsNewFrame();
5281 g.IO.Fonts->Locked =
true;
5282 SetupDrawListSharedData();
5283 SetCurrentFont(GetDefaultFont());
5284 IM_ASSERT(
g.Font->IsLoaded());
5287 for (ImGuiViewportP* viewport :
g.Viewports)
5289 viewport->DrawData = NULL;
5290 viewport->DrawDataP.Valid =
false;
5294 if (
g.DragDropActive &&
g.DragDropPayload.SourceId ==
g.ActiveId)
5295 KeepAliveID(
g.DragDropPayload.SourceId);
5298 if (!
g.IO.ConfigDebugHighlightIdConflicts || !
g.IO.KeyCtrl)
5299 g.DebugDrawIdConflicts = 0;
5300 if (
g.IO.ConfigDebugHighlightIdConflicts &&
g.HoveredIdPreviousFrameItemCount > 1)
5301 g.DebugDrawIdConflicts =
g.HoveredIdPreviousFrame;
5304 if (!
g.HoveredIdPreviousFrame)
5305 g.HoveredIdTimer = 0.0f;
5306 if (!
g.HoveredIdPreviousFrame || (
g.HoveredId &&
g.ActiveId ==
g.HoveredId))
5307 g.HoveredIdNotActiveTimer = 0.0f;
5309 g.HoveredIdTimer +=
g.IO.DeltaTime;
5310 if (
g.HoveredId &&
g.ActiveId !=
g.HoveredId)
5311 g.HoveredIdNotActiveTimer +=
g.IO.DeltaTime;
5312 g.HoveredIdPreviousFrame =
g.HoveredId;
5313 g.HoveredIdPreviousFrameItemCount = 0;
5315 g.HoveredIdAllowOverlap =
false;
5316 g.HoveredIdIsDisabled =
false;
5321 if (
g.ActiveId != 0 &&
g.ActiveIdIsAlive !=
g.ActiveId &&
g.ActiveIdPreviousFrame ==
g.ActiveId)
5323 IMGUI_DEBUG_LOG_ACTIVEID(
"NewFrame(): ClearActiveID() because it isn't marked alive anymore!\n");
5329 g.ActiveIdTimer +=
g.IO.DeltaTime;
5330 g.LastActiveIdTimer +=
g.IO.DeltaTime;
5331 g.ActiveIdPreviousFrame =
g.ActiveId;
5332 g.ActiveIdPreviousFrameWindow =
g.ActiveIdWindow;
5333 g.ActiveIdPreviousFrameHasBeenEditedBefore =
g.ActiveIdHasBeenEditedBefore;
5334 g.ActiveIdIsAlive = 0;
5335 g.ActiveIdHasBeenEditedThisFrame =
false;
5336 g.ActiveIdPreviousFrameIsAlive =
false;
5337 g.ActiveIdIsJustActivated =
false;
5338 if (
g.TempInputId != 0 &&
g.ActiveId !=
g.TempInputId)
5340 if (
g.ActiveId == 0)
5342 g.ActiveIdUsingNavDirMask = 0x00;
5343 g.ActiveIdUsingAllKeyboardKeys =
false;
5349 if (
g.HoverItemDelayId != 0 &&
g.MouseStationaryTimer >=
g.Style.HoverStationaryDelay)
5350 g.HoverItemUnlockedStationaryId =
g.HoverItemDelayId;
5351 else if (
g.HoverItemDelayId == 0)
5352 g.HoverItemUnlockedStationaryId = 0;
5353 if (
g.HoveredWindow != NULL &&
g.MouseStationaryTimer >=
g.Style.HoverStationaryDelay)
5354 g.HoverWindowUnlockedStationaryId =
g.HoveredWindow->ID;
5355 else if (
g.HoveredWindow == NULL)
5356 g.HoverWindowUnlockedStationaryId = 0;
5359 g.HoverItemDelayIdPreviousFrame =
g.HoverItemDelayId;
5360 if (
g.HoverItemDelayId != 0)
5362 g.HoverItemDelayTimer +=
g.IO.DeltaTime;
5363 g.HoverItemDelayClearTimer = 0.0f;
5364 g.HoverItemDelayId = 0;
5366 else if (
g.HoverItemDelayTimer > 0.0f)
5370 g.HoverItemDelayClearTimer +=
g.IO.DeltaTime;
5371 if (
g.HoverItemDelayClearTimer >= ImMax(0.25f,
g.IO.DeltaTime * 2.0f))
5372 g.HoverItemDelayTimer =
g.HoverItemDelayClearTimer = 0.0f;
5376 g.DragDropAcceptIdPrev =
g.DragDropAcceptIdCurr;
5377 g.DragDropAcceptIdCurr = 0;
5378 g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
5379 g.DragDropWithinSource =
false;
5380 g.DragDropWithinTarget =
false;
5381 g.DragDropHoldJustPressedId = 0;
5382 g.TooltipPreviousWindow = NULL;
5389 UpdateKeyboardInputs();
5400 UpdateMouseInputs();
5404 DockContextNewFrameUpdateUndocking(&
g);
5407 IM_ASSERT(
g.WindowsFocusOrder.Size <=
g.Windows.Size);
5408 const float memory_compact_start_time = (
g.GcCompactAll ||
g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)
g.Time -
g.IO.ConfigMemoryCompactTimer;
5409 for (ImGuiWindow* window :
g.Windows)
5411 window->WasActive = window->Active;
5412 window->Active =
false;
5413 window->WriteAccessed =
false;
5414 window->BeginCountPreviousFrame = window->BeginCount;
5415 window->BeginCount = 0;
5418 if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
5419 GcCompactTransientWindowBuffers(window);
5425 UpdateHoveredWindowAndCaptureFlags();
5428 UpdateMouseMovingWindowNewFrame();
5431 if (GetTopMostPopupModal() != NULL || (
g.NavWindowingTarget != NULL &&
g.NavWindowingHighlightAlpha > 0.0f))
5432 g.DimBgRatio = ImMin(
g.DimBgRatio +
g.IO.DeltaTime * 6.0f, 1.0f);
5434 g.DimBgRatio = ImMax(
g.DimBgRatio -
g.IO.DeltaTime * 10.0f, 0.0f);
5436 g.MouseCursor = ImGuiMouseCursor_Arrow;
5437 g.WantCaptureMouseNextFrame =
g.WantCaptureKeyboardNextFrame =
g.WantTextInputNextFrame = -1;
5440 g.PlatformImeDataPrev =
g.PlatformImeData;
5441 g.PlatformImeData.WantVisible =
false;
5447 for (
int i = 0; i <
g.TablesLastTimeActive.Size; i++)
5448 if (
g.TablesLastTimeActive[i] >= 0.0f &&
g.TablesLastTimeActive[i] < memory_compact_start_time)
5449 TableGcCompactTransientBuffers(
g.Tables.GetByIndex(i));
5450 for (ImGuiTableTempData& table_temp_data :
g.TablesTempData)
5451 if (table_temp_data.LastTimeActive >= 0.0f && table_temp_data.LastTimeActive < memory_compact_start_time)
5452 TableGcCompactTransientBuffers(&table_temp_data);
5454 GcCompactTransientMiscBuffers();
5455 g.GcCompactAll =
false;
5458 if (
g.NavWindow && !
g.NavWindow->WasActive)
5459 FocusTopMostWindowUnderOne(NULL, NULL, NULL, ImGuiFocusRequestFlags_RestoreFocusedChild);
5463 g.CurrentWindowStack.resize(0);
5464 g.BeginPopupStack.resize(0);
5465 g.ItemFlagsStack.resize(0);
5466 g.ItemFlagsStack.push_back(ImGuiItemFlags_AutoClosePopups);
5467 g.CurrentItemFlags =
g.ItemFlagsStack.back();
5468 g.GroupStack.resize(0);
5471 DockContextNewFrameUpdateDocking(&
g);
5474#ifndef IMGUI_DISABLE_DEBUG_TOOLS
5475 UpdateDebugToolItemPicker();
5476 UpdateDebugToolStackQueries();
5477 UpdateDebugToolFlashStyleColor();
5478 if (
g.DebugLocateFrames > 0 && --
g.DebugLocateFrames == 0)
5480 g.DebugLocateId = 0;
5481 g.DebugBreakInLocateId =
false;
5483 if (
g.DebugLogAutoDisableFrames > 0 && --
g.DebugLogAutoDisableFrames == 0)
5485 DebugLog(
"(Debug Log: Auto-disabled some ImGuiDebugLogFlags after 2 frames)\n");
5486 g.DebugLogFlags &= ~g.DebugLogAutoDisableFlags;
5487 g.DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
5494 g.WithinFrameScopeWithImplicitWindow =
true;
5495 SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
5496 Begin(
"Debug##Default");
5497 IM_ASSERT(
g.CurrentWindow->IsFallbackWindow ==
true);
5500 g.ErrorCountCurrentFrame = 0;
5501 ErrorRecoveryStoreState(&
g.StackSizesInNewFrame);
5505#ifndef IMGUI_DISABLE_DEBUG_TOOLS
5506 if (
g.IO.ConfigDebugBeginReturnValueLoop)
5507 g.DebugBeginReturnValueCullDepth = (
g.DebugBeginReturnValueCullDepth == -1) ? 0 : ((
g.DebugBeginReturnValueCullDepth + ((
g.FrameCount % 4) == 0 ? 1 : 0)) % 10);
5509 g.DebugBeginReturnValueCullDepth = -1;
5512 CallContextHooks(&
g, ImGuiContextHookType_NewFramePost);
5516static int IMGUI_CDECL ChildWindowComparer(
const void* lhs,
const void* rhs)
5518 const ImGuiWindow*
const a = *(
const ImGuiWindow*
const *)lhs;
5519 const ImGuiWindow*
const b = *(
const ImGuiWindow*
const *)rhs;
5520 if (
int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup))
5522 if (
int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip))
5524 return (a->BeginOrderWithinParent - b->BeginOrderWithinParent);
5527static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window)
5529 out_sorted_windows->push_back(window);
5532 int count = window->DC.ChildWindows.Size;
5533 ImQsort(window->DC.ChildWindows.Data, (
size_t)count,
sizeof(ImGuiWindow*), ChildWindowComparer);
5534 for (
int i = 0; i <
count; i++)
5536 ImGuiWindow* child = window->DC.ChildWindows[i];
5538 AddWindowToSortBuffer(out_sorted_windows, child);
5543static void AddWindowToDrawData(ImGuiWindow* window,
int layer)
5546 ImGuiViewportP* viewport = window->Viewport;
5547 IM_ASSERT(viewport != NULL);
5548 g.IO.MetricsRenderWindows++;
5549 if (window->DrawList->_Splitter._Count > 1)
5550 window->DrawList->ChannelsMerge();
5551 ImGui::AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[layer], window->DrawList);
5552 for (ImGuiWindow* child : window->DC.ChildWindows)
5553 if (IsWindowActiveAndVisible(child))
5554 AddWindowToDrawData(child, layer);
5557static inline int GetWindowDisplayLayer(ImGuiWindow* window)
5559 return (window->Flags & ImGuiWindowFlags_Tooltip) ? 1 : 0;
5563static inline void AddRootWindowToDrawData(ImGuiWindow* window)
5565 AddWindowToDrawData(window, GetWindowDisplayLayer(window));
5568static void FlattenDrawDataIntoSingleLayer(ImDrawDataBuilder* builder)
5570 int n = builder->Layers[0]->Size;
5572 for (
int i = 1; i < IM_ARRAYSIZE(builder->Layers); i++)
5573 full_size += builder->Layers[i]->Size;
5574 builder->Layers[0]->resize(full_size);
5575 for (
int layer_n = 1; layer_n < IM_ARRAYSIZE(builder->Layers); layer_n++)
5577 ImVector<ImDrawList*>* layer = builder->Layers[layer_n];
5580 memcpy(builder->Layers[0]->Data + n, layer->Data, layer->Size *
sizeof(ImDrawList*));
5586static void InitViewportDrawData(ImGuiViewportP* viewport)
5588 ImGuiIO& io = ImGui::GetIO();
5589 ImDrawData* draw_data = &viewport->DrawDataP;
5591 viewport->DrawData = draw_data;
5592 viewport->DrawDataBuilder.Layers[0] = &draw_data->CmdLists;
5593 viewport->DrawDataBuilder.Layers[1] = &viewport->DrawDataBuilder.LayerData1;
5594 viewport->DrawDataBuilder.Layers[0]->resize(0);
5595 viewport->DrawDataBuilder.Layers[1]->resize(0);
5602 const bool is_minimized = (viewport->Flags & ImGuiViewportFlags_IsMinimized) != 0;
5604 draw_data->Valid =
true;
5605 draw_data->CmdListsCount = 0;
5606 draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0;
5607 draw_data->DisplayPos = viewport->Pos;
5608 draw_data->DisplaySize = is_minimized ? ImVec2(0.0f, 0.0f) : viewport->Size;
5609 draw_data->FramebufferScale = io.DisplayFramebufferScale;
5610 draw_data->OwnerViewport = viewport;
5621void ImGui::PushClipRect(
const ImVec2& clip_rect_min,
const ImVec2& clip_rect_max,
bool intersect_with_current_clip_rect)
5623 ImGuiWindow* window = GetCurrentWindow();
5624 window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect);
5625 window->ClipRect = window->DrawList->_ClipRectStack.back();
5628void ImGui::PopClipRect()
5630 ImGuiWindow* window = GetCurrentWindow();
5631 window->DrawList->PopClipRect();
5632 window->ClipRect = window->DrawList->_ClipRectStack.back();
5635static ImGuiWindow* FindFrontMostVisibleChildWindow(ImGuiWindow* window)
5637 for (
int n = window->DC.ChildWindows.Size - 1; n >= 0; n--)
5638 if (IsWindowActiveAndVisible(window->DC.ChildWindows[n]))
5639 return FindFrontMostVisibleChildWindow(window->DC.ChildWindows[n]);
5643static void ImGui::RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col)
5645 if ((col & IM_COL32_A_MASK) == 0)
5648 ImGuiViewportP* viewport = window->Viewport;
5649 ImRect viewport_rect = viewport->GetMainRect();
5655 ImDrawList* draw_list = window->RootWindowDockTree->DrawList;
5656 draw_list->ChannelsMerge();
5657 if (draw_list->CmdBuffer.Size == 0)
5658 draw_list->AddDrawCmd();
5659 draw_list->PushClipRect(viewport_rect.Min - ImVec2(1, 1), viewport_rect.Max + ImVec2(1, 1),
false);
5660 draw_list->AddRectFilled(viewport_rect.Min, viewport_rect.Max, col);
5661 ImDrawCmd cmd = draw_list->CmdBuffer.back();
5662 IM_ASSERT(cmd.ElemCount == 6);
5663 draw_list->CmdBuffer.pop_back();
5664 draw_list->CmdBuffer.push_front(cmd);
5665 draw_list->AddDrawCmd();
5666 draw_list->PopClipRect();
5670 if (window->RootWindow->DockIsActive)
5672 ImDrawList* draw_list = FindFrontMostVisibleChildWindow(window->RootWindowDockTree)->DrawList;
5673 draw_list->ChannelsMerge();
5674 if (draw_list->CmdBuffer.Size == 0)
5675 draw_list->AddDrawCmd();
5676 draw_list->PushClipRect(viewport_rect.Min, viewport_rect.Max,
false);
5677 RenderRectFilledWithHole(draw_list, window->RootWindowDockTree->Rect(), window->RootWindow->Rect(), col, 0.0f);
5678 draw_list->PopClipRect();
5682ImGuiWindow* ImGui::FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* parent_window)
5685 ImGuiWindow* bottom_most_visible_window = parent_window;
5686 for (
int i = FindWindowDisplayIndex(parent_window); i >= 0; i--)
5688 ImGuiWindow* window =
g.Windows[i];
5689 if (window->Flags & ImGuiWindowFlags_ChildWindow)
5691 if (!IsWindowWithinBeginStackOf(window, parent_window))
5693 if (IsWindowActiveAndVisible(window) && GetWindowDisplayLayer(window) <= GetWindowDisplayLayer(parent_window))
5694 bottom_most_visible_window = window;
5696 return bottom_most_visible_window;
5701static void ImGui::RenderDimmedBackgrounds()
5704 ImGuiWindow* modal_window = GetTopMostAndVisiblePopupModal();
5705 if (
g.DimBgRatio <= 0.0f &&
g.NavWindowingHighlightAlpha <= 0.0f)
5707 const bool dim_bg_for_modal = (modal_window != NULL);
5708 const bool dim_bg_for_window_list = (
g.NavWindowingTargetAnim != NULL &&
g.NavWindowingTargetAnim->Active);
5709 if (!dim_bg_for_modal && !dim_bg_for_window_list)
5712 ImGuiViewport* viewports_already_dimmed[2] = { NULL, NULL };
5713 if (dim_bg_for_modal)
5716 ImGuiWindow* dim_behind_window = FindBottomMostVisibleWindowWithinBeginStack(modal_window);
5717 RenderDimmedBackgroundBehindWindow(dim_behind_window, GetColorU32(modal_window->DC.ModalDimBgColor,
g.DimBgRatio));
5718 viewports_already_dimmed[0] = modal_window->Viewport;
5720 else if (dim_bg_for_window_list)
5723 RenderDimmedBackgroundBehindWindow(
g.NavWindowingTargetAnim, GetColorU32(ImGuiCol_NavWindowingDimBg,
g.DimBgRatio));
5724 if (
g.NavWindowingListWindow != NULL &&
g.NavWindowingListWindow->Viewport &&
g.NavWindowingListWindow->Viewport !=
g.NavWindowingTargetAnim->Viewport)
5725 RenderDimmedBackgroundBehindWindow(
g.NavWindowingListWindow, GetColorU32(ImGuiCol_NavWindowingDimBg,
g.DimBgRatio));
5726 viewports_already_dimmed[0] =
g.NavWindowingTargetAnim->Viewport;
5727 viewports_already_dimmed[1] =
g.NavWindowingListWindow ?
g.NavWindowingListWindow->Viewport : NULL;
5730 ImGuiWindow* window =
g.NavWindowingTargetAnim;
5731 ImGuiViewport* viewport = window->Viewport;
5733 ImRect bb = window->Rect();
5734 bb.Expand(distance);
5735 if (bb.GetWidth() >= viewport->Size.x && bb.GetHeight() >= viewport->Size.y)
5736 bb.Expand(-distance - 1.0f);
5737 window->DrawList->ChannelsMerge();
5738 if (window->DrawList->CmdBuffer.Size == 0)
5739 window->DrawList->AddDrawCmd();
5740 window->DrawList->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size);
5741 window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight,
g.NavWindowingHighlightAlpha), window->WindowRounding, 0, 3.0f);
5742 window->DrawList->PopClipRect();
5746 for (ImGuiViewportP* viewport :
g.Viewports)
5748 if (viewport == viewports_already_dimmed[0] || viewport == viewports_already_dimmed[1])
5750 if (modal_window && viewport->Window && IsWindowAbove(viewport->Window, modal_window))
5752 ImDrawList* draw_list = GetForegroundDrawList(viewport);
5753 const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg,
g.DimBgRatio);
5754 draw_list->AddRectFilled(viewport->Pos, viewport->Pos + viewport->Size, dim_bg_col);
5759void ImGui::EndFrame()
5762 IM_ASSERT(
g.Initialized);
5765 if (
g.FrameCountEnded ==
g.FrameCount)
5767 IM_ASSERT(
g.WithinFrameScope &&
"Forgot to call ImGui::NewFrame()?");
5769 CallContextHooks(&
g, ImGuiContextHookType_EndFramePre);
5772 if (
g.IO.ConfigErrorRecovery)
5773 ErrorRecoveryTryToRecoverState(&
g.StackSizesInNewFrame);
5774 ErrorCheckEndFrameSanityChecks();
5775 ErrorCheckEndFrameFinalizeErrorTooltip();
5778 ImGuiPlatformImeData* ime_data = &
g.PlatformImeData;
5779 if (
g.PlatformIO.Platform_SetImeDataFn != NULL && memcmp(ime_data, &
g.PlatformImeDataPrev,
sizeof(ImGuiPlatformImeData)) != 0)
5781 ImGuiViewport* viewport = FindViewportByID(
g.PlatformImeViewport);
5782 IMGUI_DEBUG_LOG_IO(
"[io] Calling Platform_SetImeDataFn(): WantVisible: %d, InputPos (%.2f,%.2f)\n", ime_data->WantVisible, ime_data->InputPos.x, ime_data->InputPos.y);
5783 if (viewport == NULL)
5784 viewport = GetMainViewport();
5785 g.PlatformIO.Platform_SetImeDataFn(&
g, viewport, ime_data);
5789 g.WithinFrameScopeWithImplicitWindow =
false;
5790 if (
g.CurrentWindow && !
g.CurrentWindow->WriteAccessed)
5791 g.CurrentWindow->Active =
false;
5798 DockContextEndFrame(&
g);
5800 SetCurrentViewport(NULL, NULL);
5803 if (
g.DragDropActive)
5805 bool is_delivered =
g.DragDropPayload.Delivery;
5806 bool is_elapsed = (
g.DragDropSourceFrameCount + 1 <
g.FrameCount) && ((
g.DragDropSourceFlags & ImGuiDragDropFlags_PayloadAutoExpire) ||
g.DragDropMouseButton == -1 || !IsMouseDown(
g.DragDropMouseButton));
5807 if (is_delivered || is_elapsed)
5816 if (
g.DragDropActive &&
g.DragDropSourceFrameCount + 1 <
g.FrameCount && !(
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
5818 g.DragDropWithinSource =
true;
5820 g.DragDropWithinSource =
false;
5824 g.WithinFrameScope =
false;
5825 g.FrameCountEnded =
g.FrameCount;
5828 UpdateMouseMovingWindowEndFrame();
5831 UpdateViewportsEndFrame();
5835 g.WindowsTempSortBuffer.resize(0);
5836 g.WindowsTempSortBuffer.reserve(
g.Windows.Size);
5837 for (ImGuiWindow* window :
g.Windows)
5839 if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow))
5841 AddWindowToSortBuffer(&
g.WindowsTempSortBuffer, window);
5845 IM_ASSERT(
g.Windows.Size ==
g.WindowsTempSortBuffer.Size);
5846 g.Windows.swap(
g.WindowsTempSortBuffer);
5847 g.IO.MetricsActiveWindows =
g.WindowsActiveCount;
5850 g.IO.Fonts->Locked =
false;
5853 g.IO.MousePosPrev =
g.IO.MousePos;
5854 g.IO.AppFocusLost =
false;
5855 g.IO.MouseWheel =
g.IO.MouseWheelH = 0.0f;
5856 g.IO.InputQueueCharacters.resize(0);
5858 CallContextHooks(&
g, ImGuiContextHookType_EndFramePost);
5867 IM_ASSERT(
g.Initialized);
5869 if (
g.FrameCountEnded !=
g.FrameCount)
5871 if (
g.FrameCountRendered ==
g.FrameCount)
5873 g.FrameCountRendered =
g.FrameCount;
5875 g.IO.MetricsRenderWindows = 0;
5876 CallContextHooks(&
g, ImGuiContextHookType_RenderPre);
5879 for (ImGuiViewportP* viewport :
g.Viewports)
5881 InitViewportDrawData(viewport);
5882 if (viewport->BgFgDrawLists[0] != NULL)
5883 AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport));
5887 RenderDimmedBackgrounds();
5890 ImGuiWindow* windows_to_render_top_most[2];
5891 windows_to_render_top_most[0] = (
g.NavWindowingTarget && !(
g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ?
g.NavWindowingTarget->RootWindowDockTree : NULL;
5892 windows_to_render_top_most[1] = (
g.NavWindowingTarget ?
g.NavWindowingListWindow : NULL);
5893 for (ImGuiWindow* window :
g.Windows)
5895 IM_MSVC_WARNING_SUPPRESS(6011);
5896 if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1])
5897 AddRootWindowToDrawData(window);
5899 for (
int n = 0; n < IM_ARRAYSIZE(windows_to_render_top_most); n++)
5900 if (windows_to_render_top_most[n] && IsWindowActiveAndVisible(windows_to_render_top_most[n]))
5901 AddRootWindowToDrawData(windows_to_render_top_most[n]);
5904 if (
g.IO.MouseDrawCursor &&
g.MouseCursor != ImGuiMouseCursor_None)
5905 RenderMouseCursor(
g.IO.MousePos,
g.Style.MouseCursorScale,
g.MouseCursor, IM_COL32_WHITE, IM_COL32_BLACK, IM_COL32(0, 0, 0, 48));
5908 g.IO.MetricsRenderVertices =
g.IO.MetricsRenderIndices = 0;
5909 for (ImGuiViewportP* viewport :
g.Viewports)
5911 FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder);
5914 if (viewport->BgFgDrawLists[1] != NULL)
5915 AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport));
5918 ImDrawData* draw_data = &viewport->DrawDataP;
5919 IM_ASSERT(draw_data->CmdLists.Size == draw_data->CmdListsCount);
5920 for (ImDrawList* draw_list : draw_data->CmdLists)
5921 draw_list->_PopUnusedDrawCmd();
5923 g.IO.MetricsRenderVertices += draw_data->TotalVtxCount;
5924 g.IO.MetricsRenderIndices += draw_data->TotalIdxCount;
5927 CallContextHooks(&
g, ImGuiContextHookType_RenderPost);
5932ImVec2
ImGui::CalcTextSize(
const char* text,
const char* text_end,
bool hide_text_after_double_hash,
float wrap_width)
5936 const char* text_display_end;
5937 if (hide_text_after_double_hash)
5938 text_display_end = FindRenderedTextEnd(text, text_end);
5940 text_display_end = text_end;
5942 ImFont* font =
g.Font;
5943 const float font_size =
g.FontSize;
5944 if (text == text_display_end)
5945 return ImVec2(0.0f, font_size);
5946 ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);
5953 text_size.x = IM_TRUNC(text_size.x + 0.99999f);
5964void ImGui::FindHoveredWindowEx(
const ImVec2& pos,
bool find_first_and_in_any_viewport, ImGuiWindow** out_hovered_window, ImGuiWindow** out_hovered_window_under_moving_window)
5967 ImGuiWindow* hovered_window = NULL;
5968 ImGuiWindow* hovered_window_under_moving_window = NULL;
5971 ImGuiViewportP* backup_moving_window_viewport = NULL;
5972 if (find_first_and_in_any_viewport ==
false &&
g.MovingWindow)
5974 backup_moving_window_viewport =
g.MovingWindow->Viewport;
5975 g.MovingWindow->Viewport =
g.MouseViewport;
5976 if (!(
g.MovingWindow->Flags & ImGuiWindowFlags_NoMouseInputs))
5977 hovered_window =
g.MovingWindow;
5980 ImVec2 padding_regular =
g.Style.TouchExtraPadding;
5981 ImVec2 padding_for_resize =
g.IO.ConfigWindowsResizeFromEdges ?
g.WindowsHoverPadding : padding_regular;
5982 for (
int i =
g.Windows.Size - 1; i >= 0; i--)
5984 ImGuiWindow* window =
g.Windows[i];
5985 IM_MSVC_WARNING_SUPPRESS(28182);
5986 if (!window->WasActive || window->Hidden)
5988 if (window->Flags & ImGuiWindowFlags_NoMouseInputs)
5990 IM_ASSERT(window->Viewport);
5991 if (window->Viewport !=
g.MouseViewport)
5995 ImVec2 hit_padding = (window->Flags & (ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) ? padding_regular : padding_for_resize;
5996 if (!window->OuterRectClipped.ContainsWithPad(pos, hit_padding))
6001 if (window->HitTestHoleSize.x != 0)
6003 ImVec2 hole_pos(window->Pos.x + (
float)window->HitTestHoleOffset.x, window->Pos.y + (
float)window->HitTestHoleOffset.y);
6004 ImVec2 hole_size((
float)window->HitTestHoleSize.x, (
float)window->HitTestHoleSize.y);
6005 if (ImRect(hole_pos, hole_pos + hole_size).Contains(pos))
6009 if (find_first_and_in_any_viewport)
6011 hovered_window = window;
6016 if (hovered_window == NULL)
6017 hovered_window = window;
6018 IM_MSVC_WARNING_SUPPRESS(28182);
6019 if (hovered_window_under_moving_window == NULL && (!
g.MovingWindow || window->RootWindowDockTree !=
g.MovingWindow->RootWindowDockTree))
6020 hovered_window_under_moving_window = window;
6021 if (hovered_window && hovered_window_under_moving_window)
6026 *out_hovered_window = hovered_window;
6027 if (out_hovered_window_under_moving_window != NULL)
6028 *out_hovered_window_under_moving_window = hovered_window_under_moving_window;
6029 if (find_first_and_in_any_viewport ==
false &&
g.MovingWindow)
6030 g.MovingWindow->Viewport = backup_moving_window_viewport;
6033bool ImGui::IsItemActive()
6037 return g.ActiveId ==
g.LastItemData.ID;
6041bool ImGui::IsItemActivated()
6045 if (
g.ActiveId ==
g.LastItemData.ID &&
g.ActiveIdPreviousFrame !=
g.LastItemData.ID)
6050bool ImGui::IsItemDeactivated()
6053 if (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDeactivated)
6054 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Deactivated) != 0;
6055 return (
g.ActiveIdPreviousFrame ==
g.LastItemData.ID &&
g.ActiveIdPreviousFrame != 0 &&
g.ActiveId !=
g.LastItemData.ID);
6058bool ImGui::IsItemDeactivatedAfterEdit()
6061 return IsItemDeactivated() && (
g.ActiveIdPreviousFrameHasBeenEditedBefore || (
g.ActiveId == 0 &&
g.ActiveIdHasBeenEditedBefore));
6065bool ImGui::IsItemFocused()
6068 if (
g.NavId !=
g.LastItemData.ID ||
g.NavId == 0)
6073 ImGuiWindow* window =
g.CurrentWindow;
6074 if (
g.LastItemData.ID == window->ID && window->WriteAccessed)
6082bool ImGui::IsItemClicked(ImGuiMouseButton mouse_button)
6084 return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None);
6087bool ImGui::IsItemToggledOpen()
6090 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true :
false;
6098bool ImGui::IsItemToggledSelection()
6101 IM_ASSERT(
g.CurrentMultiSelect != NULL);
6102 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true :
false;
6108bool ImGui::IsAnyItemHovered()
6111 return g.HoveredId != 0 ||
g.HoveredIdPreviousFrame != 0;
6114bool ImGui::IsAnyItemActive()
6117 return g.ActiveId != 0;
6120bool ImGui::IsAnyItemFocused()
6123 return g.NavId != 0 &&
g.NavCursorVisible;
6126bool ImGui::IsItemVisible()
6129 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) != 0;
6132bool ImGui::IsItemEdited()
6135 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Edited) != 0;
6141void ImGui::SetNextItemAllowOverlap()
6144 g.NextItemData.ItemFlags |= ImGuiItemFlags_AllowOverlap;
6147#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
6150void ImGui::SetItemAllowOverlap()
6153 ImGuiID
id =
g.LastItemData.ID;
6154 if (
g.HoveredId ==
id)
6155 g.HoveredIdAllowOverlap =
true;
6156 if (
g.ActiveId ==
id)
6157 g.ActiveIdAllowOverlap =
true;
6163void ImGui::SetActiveIdUsingAllKeyboardKeys()
6166 IM_ASSERT(
g.ActiveId != 0);
6167 g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_COUNT) - 1;
6168 g.ActiveIdUsingAllKeyboardKeys =
true;
6169 NavMoveRequestCancel();
6172ImGuiID ImGui::GetItemID()
6175 return g.LastItemData.ID;
6178ImVec2 ImGui::GetItemRectMin()
6181 return g.LastItemData.Rect.Min;
6184ImVec2 ImGui::GetItemRectMax()
6187 return g.LastItemData.Rect.Max;
6190ImVec2 ImGui::GetItemRectSize()
6193 return g.LastItemData.Rect.GetSize();
6198bool ImGui::BeginChild(
const char* str_id,
const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags)
6200 ImGuiID
id = GetCurrentWindow()->GetID(str_id);
6201 return BeginChildEx(str_id,
id, size_arg, child_flags, window_flags);
6204bool ImGui::BeginChild(ImGuiID
id,
const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags)
6206 return BeginChildEx(NULL,
id, size_arg, child_flags, window_flags);
6209bool ImGui::BeginChildEx(
const char* name, ImGuiID
id,
const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags)
6212 ImGuiWindow* parent_window =
g.CurrentWindow;
6216 const ImGuiChildFlags ImGuiChildFlags_SupportedMask_ = ImGuiChildFlags_Borders | ImGuiChildFlags_AlwaysUseWindowPadding | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_FrameStyle | ImGuiChildFlags_NavFlattened;
6217 IM_UNUSED(ImGuiChildFlags_SupportedMask_);
6218 IM_ASSERT((child_flags & ~ImGuiChildFlags_SupportedMask_) == 0 &&
"Illegal ImGuiChildFlags value. Did you pass ImGuiWindowFlags values instead of ImGuiChildFlags?");
6219 IM_ASSERT((window_flags & ImGuiWindowFlags_AlwaysAutoResize) == 0 &&
"Cannot specify ImGuiWindowFlags_AlwaysAutoResize for BeginChild(). Use ImGuiChildFlags_AlwaysAutoResize!");
6220 if (child_flags & ImGuiChildFlags_AlwaysAutoResize)
6222 IM_ASSERT((child_flags & (ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY)) == 0 &&
"Cannot use ImGuiChildFlags_ResizeX or ImGuiChildFlags_ResizeY with ImGuiChildFlags_AlwaysAutoResize!");
6223 IM_ASSERT((child_flags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY)) != 0 &&
"Must use ImGuiChildFlags_AutoResizeX or ImGuiChildFlags_AutoResizeY with ImGuiChildFlags_AlwaysAutoResize!");
6225#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
6226 if (window_flags & ImGuiWindowFlags_AlwaysUseWindowPadding)
6227 child_flags |= ImGuiChildFlags_AlwaysUseWindowPadding;
6228 if (window_flags & ImGuiWindowFlags_NavFlattened)
6229 child_flags |= ImGuiChildFlags_NavFlattened;
6231 if (child_flags & ImGuiChildFlags_AutoResizeX)
6232 child_flags &= ~ImGuiChildFlags_ResizeX;
6233 if (child_flags & ImGuiChildFlags_AutoResizeY)
6234 child_flags &= ~ImGuiChildFlags_ResizeY;
6237 window_flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDocking;
6238 window_flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove);
6239 if (child_flags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize))
6240 window_flags |= ImGuiWindowFlags_AlwaysAutoResize;
6241 if ((child_flags & (ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY)) == 0)
6242 window_flags |= ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings;
6245 if (child_flags & ImGuiChildFlags_FrameStyle)
6247 PushStyleColor(ImGuiCol_ChildBg,
g.Style.Colors[ImGuiCol_FrameBg]);
6248 PushStyleVar(ImGuiStyleVar_ChildRounding,
g.Style.FrameRounding);
6249 PushStyleVar(ImGuiStyleVar_ChildBorderSize,
g.Style.FrameBorderSize);
6250 PushStyleVar(ImGuiStyleVar_WindowPadding,
g.Style.FramePadding);
6251 child_flags |= ImGuiChildFlags_Borders | ImGuiChildFlags_AlwaysUseWindowPadding;
6252 window_flags |= ImGuiWindowFlags_NoMove;
6258 const ImVec2 size_avail = GetContentRegionAvail();
6259 const ImVec2 size_default((child_flags & ImGuiChildFlags_AutoResizeX) ? 0.0f : size_avail.x, (child_flags & ImGuiChildFlags_AutoResizeY) ? 0.0f : size_avail.y);
6260 ImVec2
size = CalcItemSize(size_arg, size_default.x, size_default.y);
6265 if ((
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) != 0 && (
g.NextWindowData.SizeCond & ImGuiCond_Always) != 0)
6267 if (
g.NextWindowData.SizeVal.x > 0.0f)
6269 size.x =
g.NextWindowData.SizeVal.x;
6270 child_flags &= ~ImGuiChildFlags_ResizeX;
6272 if (
g.NextWindowData.SizeVal.y > 0.0f)
6274 size.y =
g.NextWindowData.SizeVal.y;
6275 child_flags &= ~ImGuiChildFlags_ResizeY;
6278 SetNextWindowSize(size);
6281 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags;
6282 g.NextWindowData.ChildFlags = child_flags;
6287 const char* temp_window_name;
6297 const float backup_border_size =
g.Style.ChildBorderSize;
6298 if ((child_flags & ImGuiChildFlags_Borders) == 0)
6299 g.Style.ChildBorderSize = 0.0f;
6302 const bool ret = Begin(temp_window_name, NULL, window_flags);
6305 g.Style.ChildBorderSize = backup_border_size;
6306 if (child_flags & ImGuiChildFlags_FrameStyle)
6312 ImGuiWindow* child_window =
g.CurrentWindow;
6313 child_window->ChildId =
id;
6317 if (child_window->BeginCount == 1)
6318 parent_window->DC.CursorPos = child_window->Pos;
6322 const ImGuiID temp_id_for_activation =
ImHashStr(
"##Child", 0,
id);
6323 if (
g.ActiveId == temp_id_for_activation)
6325 if (
g.NavActivateId ==
id && !(child_flags & ImGuiChildFlags_NavFlattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY))
6327 FocusWindow(child_window);
6328 NavInitWindow(child_window,
false);
6329 SetActiveID(temp_id_for_activation, child_window);
6330 g.ActiveIdSource =
g.NavInputSource;
6335void ImGui::EndChild()
6338 ImGuiWindow* child_window =
g.CurrentWindow;
6340 IM_ASSERT(
g.WithinEndChild ==
false);
6341 IM_ASSERT(child_window->Flags & ImGuiWindowFlags_ChildWindow);
6343 g.WithinEndChild =
true;
6344 ImVec2 child_size = child_window->Size;
6346 if (child_window->BeginCount == 1)
6348 ImGuiWindow* parent_window =
g.CurrentWindow;
6349 ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + child_size);
6350 ItemSize(child_size);
6351 const bool nav_flattened = (child_window->ChildFlags & ImGuiChildFlags_NavFlattened) != 0;
6352 if ((child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY) && !nav_flattened)
6354 ItemAdd(bb, child_window->ChildId);
6355 RenderNavCursor(bb, child_window->ChildId);
6358 if (child_window->DC.NavLayersActiveMask == 0 && child_window ==
g.NavWindow)
6359 RenderNavCursor(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)),
g.NavId, ImGuiNavRenderCursorFlags_Compact);
6366 ItemAdd(bb, child_window->ChildId, NULL, ImGuiItemFlags_NoNav);
6370 parent_window->DC.NavLayersActiveMaskNext |= child_window->DC.NavLayersActiveMaskNext;
6372 if (
g.HoveredWindow == child_window)
6373 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
6375 g.WithinEndChild =
false;
6376 g.LogLinePosY = -FLT_MAX;
6379static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags,
bool enabled)
6381 window->SetWindowPosAllowFlags = enabled ? (window->SetWindowPosAllowFlags | flags) : (window->SetWindowPosAllowFlags & ~flags);
6382 window->SetWindowSizeAllowFlags = enabled ? (window->SetWindowSizeAllowFlags | flags) : (window->SetWindowSizeAllowFlags & ~flags);
6383 window->SetWindowCollapsedAllowFlags = enabled ? (window->SetWindowCollapsedAllowFlags | flags) : (window->SetWindowCollapsedAllowFlags & ~flags);
6384 window->SetWindowDockAllowFlags = enabled ? (window->SetWindowDockAllowFlags | flags) : (window->SetWindowDockAllowFlags & ~flags);
6387ImGuiWindow* ImGui::FindWindowByID(ImGuiID
id)
6390 return (ImGuiWindow*)
g.WindowsById.GetVoidPtr(
id);
6393ImGuiWindow* ImGui::FindWindowByName(
const char* name)
6396 return FindWindowByID(
id);
6399static void ApplyWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
6401 const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
6402 window->ViewportPos = main_viewport->Pos;
6403 if (settings->ViewportId)
6405 window->ViewportId = settings->ViewportId;
6406 window->ViewportPos = ImVec2(settings->ViewportPos.x, settings->ViewportPos.y);
6408 window->Pos = ImTrunc(ImVec2(settings->Pos.x + window->ViewportPos.x, settings->Pos.y + window->ViewportPos.y));
6409 if (settings->Size.x > 0 && settings->Size.y > 0)
6410 window->Size = window->SizeFull = ImTrunc(ImVec2(settings->Size.x, settings->Size.y));
6411 window->Collapsed = settings->Collapsed;
6412 window->DockId = settings->DockId;
6413 window->DockOrder = settings->DockOrder;
6416static void UpdateWindowInFocusOrderList(ImGuiWindow* window,
bool just_created, ImGuiWindowFlags new_flags)
6420 const bool new_is_explicit_child = (new_flags & ImGuiWindowFlags_ChildWindow) != 0 && ((new_flags & ImGuiWindowFlags_Popup) == 0 || (new_flags & ImGuiWindowFlags_ChildMenu) != 0);
6421 const bool child_flag_changed = new_is_explicit_child != window->IsExplicitChild;
6422 if ((just_created || child_flag_changed) && !new_is_explicit_child)
6424 IM_ASSERT(!
g.WindowsFocusOrder.contains(window));
6425 g.WindowsFocusOrder.push_back(window);
6426 window->FocusOrder = (short)(
g.WindowsFocusOrder.Size - 1);
6428 else if (!just_created && child_flag_changed && new_is_explicit_child)
6430 IM_ASSERT(
g.WindowsFocusOrder[window->FocusOrder] == window);
6431 for (
int n = window->FocusOrder + 1; n <
g.WindowsFocusOrder.Size; n++)
6432 g.WindowsFocusOrder[n]->FocusOrder--;
6433 g.WindowsFocusOrder.erase(
g.WindowsFocusOrder.Data + window->FocusOrder);
6434 window->FocusOrder = -1;
6436 window->IsExplicitChild = new_is_explicit_child;
6439static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
6443 const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
6444 window->Pos = main_viewport->Pos + ImVec2(60, 60);
6445 window->Size = window->SizeFull = ImVec2(0, 0);
6446 window->ViewportPos = main_viewport->Pos;
6447 window->SetWindowPosAllowFlags = window->SetWindowSizeAllowFlags = window->SetWindowCollapsedAllowFlags = window->SetWindowDockAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
6449 if (settings != NULL)
6451 SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver,
false);
6452 ApplyWindowSettings(window, settings);
6454 window->DC.CursorStartPos = window->DC.CursorMaxPos = window->DC.IdealMaxPos = window->Pos;
6456 if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
6458 window->AutoFitFramesX = window->AutoFitFramesY = 2;
6459 window->AutoFitOnlyGrows =
false;
6463 if (window->Size.x <= 0.0f)
6464 window->AutoFitFramesX = 2;
6465 if (window->Size.y <= 0.0f)
6466 window->AutoFitFramesY = 2;
6467 window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
6471static ImGuiWindow* CreateNewWindow(
const char* name, ImGuiWindowFlags flags)
6476 ImGuiWindow* window = IM_NEW(ImGuiWindow)(&
g, name);
6477 window->Flags = flags;
6478 g.WindowsById.SetVoidPtr(window->ID, window);
6480 ImGuiWindowSettings* settings = NULL;
6481 if (!(flags & ImGuiWindowFlags_NoSavedSettings))
6482 if ((settings = ImGui::FindWindowSettingsByWindow(window)) != 0)
6483 window->SettingsOffset =
g.SettingsWindows.offset_from_ptr(settings);
6485 InitOrLoadWindowSettings(window, settings);
6487 if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus)
6488 g.Windows.push_front(window);
6490 g.Windows.push_back(window);
6495static ImGuiWindow* GetWindowForTitleDisplay(ImGuiWindow* window)
6497 return window->DockNodeAsHost ? window->DockNodeAsHost->VisibleWindow : window;
6500static ImGuiWindow* GetWindowForTitleAndMenuHeight(ImGuiWindow* window)
6502 return (window->DockNodeAsHost && window->DockNodeAsHost->VisibleWindow) ? window->DockNodeAsHost->VisibleWindow : window;
6505static inline ImVec2 CalcWindowMinSize(ImGuiWindow* window)
6512 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_Popup))
6514 size_min.x = (window->ChildFlags & ImGuiChildFlags_ResizeX) ?
g.Style.WindowMinSize.x : 4.0f;
6515 size_min.y = (window->ChildFlags & ImGuiChildFlags_ResizeY) ?
g.Style.WindowMinSize.y : 4.0f;
6519 size_min.x = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ?
g.Style.WindowMinSize.x : 4.0f;
6520 size_min.y = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ?
g.Style.WindowMinSize.y : 4.0f;
6524 ImGuiWindow* window_for_height = GetWindowForTitleAndMenuHeight(window);
6525 size_min.y = ImMax(size_min.y, window_for_height->TitleBarHeight + window_for_height->MenuBarHeight + ImMax(0.0f,
g.Style.WindowRounding - 1.0f));
6529static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window,
const ImVec2& size_desired)
6532 ImVec2 new_size = size_desired;
6533 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)
6536 ImRect cr =
g.NextWindowData.SizeConstraintRect;
6537 new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x;
6538 new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y;
6539 if (
g.NextWindowData.SizeCallback)
6541 ImGuiSizeCallbackData data;
6542 data.UserData =
g.NextWindowData.SizeCallbackUserData;
6543 data.Pos = window->Pos;
6544 data.CurrentSize = window->SizeFull;
6545 data.DesiredSize = new_size;
6546 g.NextWindowData.SizeCallback(&data);
6547 new_size = data.DesiredSize;
6549 new_size.x = IM_TRUNC(new_size.x);
6550 new_size.y = IM_TRUNC(new_size.y);
6554 ImVec2 size_min = CalcWindowMinSize(window);
6555 return ImMax(new_size, size_min);
6558static void CalcWindowContentSizes(ImGuiWindow* window, ImVec2* content_size_current, ImVec2* content_size_ideal)
6560 bool preserve_old_content_sizes =
false;
6561 if (window->Collapsed && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
6562 preserve_old_content_sizes =
true;
6563 else if (window->Hidden && window->HiddenFramesCannotSkipItems == 0 && window->HiddenFramesCanSkipItems > 0)
6564 preserve_old_content_sizes =
true;
6565 if (preserve_old_content_sizes)
6567 *content_size_current = window->ContentSize;
6568 *content_size_ideal = window->ContentSizeIdeal;
6572 content_size_current->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : IM_TRUNC(window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x);
6573 content_size_current->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : IM_TRUNC(window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y);
6574 content_size_ideal->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : IM_TRUNC(ImMax(window->DC.CursorMaxPos.x, window->DC.IdealMaxPos.x) - window->DC.CursorStartPos.x);
6575 content_size_ideal->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : IM_TRUNC(ImMax(window->DC.CursorMaxPos.y, window->DC.IdealMaxPos.y) - window->DC.CursorStartPos.y);
6578static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window,
const ImVec2& size_contents)
6581 ImGuiStyle& style =
g.Style;
6582 const float decoration_w_without_scrollbars = window->DecoOuterSizeX1 + window->DecoOuterSizeX2 - window->ScrollbarSizes.x;
6583 const float decoration_h_without_scrollbars = window->DecoOuterSizeY1 + window->DecoOuterSizeY2 - window->ScrollbarSizes.y;
6584 ImVec2 size_pad = window->WindowPadding * 2.0f;
6585 ImVec2 size_desired = size_contents + size_pad + ImVec2(decoration_w_without_scrollbars, decoration_h_without_scrollbars);
6586 if (window->Flags & ImGuiWindowFlags_Tooltip)
6589 return size_desired;
6594 ImVec2 size_min = CalcWindowMinSize(window);
6595 ImVec2 size_max = ImVec2(FLT_MAX, FLT_MAX);
6598 if ((window->Flags & ImGuiWindowFlags_ChildWindow) == 0 || (window->Flags & ImGuiWindowFlags_Popup) != 0)
6600 if (!window->ViewportOwned)
6601 size_max = ImGui::GetMainViewport()->WorkSize - style.DisplaySafeAreaPadding * 2.0f;
6602 const int monitor_idx = window->ViewportAllowPlatformMonitorExtend;
6603 if (monitor_idx >= 0 && monitor_idx <
g.PlatformIO.Monitors.Size)
6604 size_max =
g.PlatformIO.Monitors[monitor_idx].WorkSize - style.DisplaySafeAreaPadding * 2.0f;
6607 ImVec2 size_auto_fit = ImClamp(size_desired, size_min, ImMax(size_min, size_max));
6612 if ((window->ChildFlags & ImGuiChildFlags_ResizeX) && !(window->ChildFlags & ImGuiChildFlags_ResizeY))
6613 size_auto_fit.y = window->SizeFull.y;
6614 else if (!(window->ChildFlags & ImGuiChildFlags_ResizeX) && (window->ChildFlags & ImGuiChildFlags_ResizeY))
6615 size_auto_fit.x = window->SizeFull.x;
6619 ImVec2 size_auto_fit_after_constraint = CalcWindowSizeAfterConstraint(window, size_auto_fit);
6620 bool will_have_scrollbar_x = (size_auto_fit_after_constraint.x - size_pad.x - decoration_w_without_scrollbars < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar);
6621 bool will_have_scrollbar_y = (size_auto_fit_after_constraint.y - size_pad.y - decoration_h_without_scrollbars < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysVerticalScrollbar);
6622 if (will_have_scrollbar_x)
6623 size_auto_fit.y += style.ScrollbarSize;
6624 if (will_have_scrollbar_y)
6625 size_auto_fit.x += style.ScrollbarSize;
6626 return size_auto_fit;
6630ImVec2 ImGui::CalcWindowNextAutoFitSize(ImGuiWindow* window)
6632 ImVec2 size_contents_current;
6633 ImVec2 size_contents_ideal;
6634 CalcWindowContentSizes(window, &size_contents_current, &size_contents_ideal);
6635 ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, size_contents_ideal);
6636 ImVec2 size_final = CalcWindowSizeAfterConstraint(window, size_auto_fit);
6640static ImGuiCol GetWindowBgColorIdx(ImGuiWindow* window)
6642 if (window->Flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
6643 return ImGuiCol_PopupBg;
6644 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !window->DockIsActive)
6645 return ImGuiCol_ChildBg;
6646 return ImGuiCol_WindowBg;
6649static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window,
const ImVec2& corner_target,
const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size)
6651 ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm);
6652 ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm);
6653 ImVec2 size_expected = pos_max - pos_min;
6654 ImVec2 size_constrained = CalcWindowSizeAfterConstraint(window, size_expected);
6656 if (corner_norm.x == 0.0f)
6657 out_pos->x -= (size_constrained.x - size_expected.x);
6658 if (corner_norm.y == 0.0f)
6659 out_pos->y -= (size_constrained.y - size_expected.y);
6660 *out_size = size_constrained;
6672 { ImVec2(1, 1), ImVec2(-1, -1), 0, 3 },
6673 { ImVec2(0, 1), ImVec2(+1, -1), 3, 6 },
6674 { ImVec2(0, 0), ImVec2(+1, +1), 6, 9 },
6675 { ImVec2(1, 0), ImVec2(-1, +1), 9, 12 }
6687 { ImVec2(+1, 0), ImVec2(0, 1), ImVec2(0, 0), IM_PI * 1.00f },
6688 { ImVec2(-1, 0), ImVec2(1, 0), ImVec2(1, 1), IM_PI * 0.00f },
6689 { ImVec2(0, +1), ImVec2(0, 0), ImVec2(1, 0), IM_PI * 1.50f },
6690 { ImVec2(0, -1), ImVec2(1, 1), ImVec2(0, 1), IM_PI * 0.50f }
6693static ImRect GetResizeBorderRect(ImGuiWindow* window,
int border_n,
float perp_padding,
float thickness)
6695 ImRect rect = window->Rect();
6696 if (thickness == 0.0f)
6697 rect.Max -= ImVec2(1, 1);
6698 if (border_n == ImGuiDir_Left) {
return ImRect(rect.Min.x - thickness, rect.Min.y + perp_padding, rect.Min.x + thickness, rect.Max.y - perp_padding); }
6699 if (border_n == ImGuiDir_Right) {
return ImRect(rect.Max.x - thickness, rect.Min.y + perp_padding, rect.Max.x + thickness, rect.Max.y - perp_padding); }
6700 if (border_n == ImGuiDir_Up) {
return ImRect(rect.Min.x + perp_padding, rect.Min.y - thickness, rect.Max.x - perp_padding, rect.Min.y + thickness); }
6701 if (border_n == ImGuiDir_Down) {
return ImRect(rect.Min.x + perp_padding, rect.Max.y - thickness, rect.Max.x - perp_padding, rect.Max.y + thickness); }
6707ImGuiID ImGui::GetWindowResizeCornerID(ImGuiWindow* window,
int n)
6709 IM_ASSERT(n >= 0 && n < 4);
6710 ImGuiID
id = window->DockIsActive ? window->DockNode->HostWindow->ID : window->ID;
6717ImGuiID ImGui::GetWindowResizeBorderID(ImGuiWindow* window, ImGuiDir dir)
6719 IM_ASSERT(dir >= 0 && dir < 4);
6720 int n = (int)dir + 4;
6721 ImGuiID
id = window->DockIsActive ? window->DockNode->HostWindow->ID : window->ID;
6729static int ImGui::UpdateWindowManualResize(ImGuiWindow* window,
const ImVec2& size_auto_fit,
int* border_hovered,
int* border_held,
int resize_grip_count, ImU32 resize_grip_col[4],
const ImRect& visibility_rect)
6732 ImGuiWindowFlags flags = window->Flags;
6734 if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
6736 if (window->WasActive ==
false)
6739 int ret_auto_fit_mask = 0x00;
6740 const float grip_draw_size = IM_TRUNC(ImMax(
g.FontSize * 1.35f, window->WindowRounding + 1.0f +
g.FontSize * 0.2f));
6741 const float grip_hover_inner_size = (resize_grip_count > 0) ? IM_TRUNC(grip_draw_size * 0.75f) : 0.0f;
6742 const float grip_hover_outer_size =
g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_HOVER_PADDING : 0.0f;
6744 ImRect clamp_rect = visibility_rect;
6745 const bool window_move_from_title_bar =
g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar);
6746 if (window_move_from_title_bar)
6747 clamp_rect.Min.y -= window->TitleBarHeight;
6749 ImVec2 pos_target(FLT_MAX, FLT_MAX);
6750 ImVec2 size_target(FLT_MAX, FLT_MAX);
6758 const bool clip_with_viewport_rect = !(
g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport) || (
g.IO.MouseHoveredViewport != window->ViewportId) || !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration);
6759 if (clip_with_viewport_rect)
6760 window->ClipRect = window->Viewport->GetMainRect();
6763 window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
6767 for (
int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
6770 const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, def.
CornerPosN);
6774 ImRect resize_rect(corner - def.
InnerDir * grip_hover_outer_size, corner + def.
InnerDir * grip_hover_inner_size);
6775 if (resize_rect.Min.x > resize_rect.Max.x) ImSwap(resize_rect.Min.x, resize_rect.Max.x);
6776 if (resize_rect.Min.y > resize_rect.Max.y) ImSwap(resize_rect.Min.y, resize_rect.Max.y);
6777 ImGuiID resize_grip_id = window->GetID(resize_grip_n);
6778 ItemAdd(resize_rect, resize_grip_id, NULL, ImGuiItemFlags_NoNav);
6779 ButtonBehavior(resize_rect, resize_grip_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
6781 if (hovered || held)
6782 SetMouseCursor((resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE);
6784 if (held &&
g.IO.MouseDoubleClicked[0])
6787 size_target = CalcWindowSizeAfterConstraint(window, size_auto_fit);
6788 ret_auto_fit_mask = 0x03;
6795 ImVec2 clamp_min = ImVec2(def.
CornerPosN.x == 1.0f ? clamp_rect.Min.x : -FLT_MAX, (def.CornerPosN.y == 1.0f || (def.CornerPosN.y == 0.0f && window_move_from_title_bar)) ? clamp_rect.Min.y : -FLT_MAX);
6796 ImVec2 clamp_max = ImVec2(def.
CornerPosN.x == 0.0f ? clamp_rect.Max.x : +FLT_MAX, def.CornerPosN.y == 0.0f ? clamp_rect.Max.y : +FLT_MAX);
6797 ImVec2 corner_target =
g.IO.MousePos -
g.ActiveIdClickOffset + ImLerp(def.
InnerDir * grip_hover_outer_size, def.
InnerDir * -grip_hover_inner_size, def.
CornerPosN);
6798 corner_target = ImClamp(corner_target, clamp_min, clamp_max);
6799 CalcResizePosSizeFromAnyCorner(window, corner_target, def.
CornerPosN, &pos_target, &size_target);
6803 if (resize_grip_n == 0 || held || hovered)
6804 resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
6807 int resize_border_mask = 0x00;
6808 if (window->Flags & ImGuiWindowFlags_ChildWindow)
6809 resize_border_mask |= ((window->ChildFlags & ImGuiChildFlags_ResizeX) ? 0x02 : 0) | ((window->ChildFlags & ImGuiChildFlags_ResizeY) ? 0x08 : 0);
6811 resize_border_mask =
g.IO.ConfigWindowsResizeFromEdges ? 0x0F : 0x00;
6812 for (
int border_n = 0; border_n < 4; border_n++)
6814 if ((resize_border_mask & (1 << border_n)) == 0)
6817 const ImGuiAxis axis = (border_n == ImGuiDir_Left || border_n == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
6820 ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_HOVER_PADDING);
6821 ImGuiID border_id = window->GetID(border_n + 4);
6822 ItemAdd(border_rect, border_id, NULL, ImGuiItemFlags_NoNav);
6823 ButtonBehavior(border_rect, border_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
6825 if (hovered &&
g.HoveredIdTimer <= WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER)
6827 if (hovered || held)
6828 SetMouseCursor((axis == ImGuiAxis_X) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS);
6829 if (held &&
g.IO.MouseDoubleClicked[0])
6834 if (border_n == 1 || border_n == 3)
6836 size_target[axis] = CalcWindowSizeAfterConstraint(window, size_auto_fit)[axis];
6837 ret_auto_fit_mask |= (1 << axis);
6838 hovered = held =
false;
6847 const bool just_scrolled_manually_while_resizing = (
g.WheelingWindow != NULL &&
g.WheelingWindowScrolledFrame ==
g.FrameCount && IsWindowChildOf(window,
g.WheelingWindow,
false,
true));
6848 if (
g.ActiveIdIsJustActivated || just_scrolled_manually_while_resizing)
6850 g.WindowResizeBorderExpectedRect = border_rect;
6851 g.WindowResizeRelativeMode =
false;
6853 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && memcmp(&
g.WindowResizeBorderExpectedRect, &border_rect,
sizeof(ImRect)) != 0)
6854 g.WindowResizeRelativeMode =
true;
6856 const ImVec2 border_curr = (window->Pos + ImMin(def.
SegmentN1, def.
SegmentN2) * window->Size);
6857 const float border_target_rel_mode_for_axis = border_curr[axis] +
g.IO.MouseDelta[axis];
6858 const float border_target_abs_mode_for_axis =
g.IO.MousePos[axis] -
g.ActiveIdClickOffset[axis] + WINDOWS_HOVER_PADDING;
6861 ImVec2 border_target = window->Pos;
6862 border_target[axis] = border_target_abs_mode_for_axis;
6865 bool ignore_resize =
false;
6866 if (
g.WindowResizeRelativeMode)
6869 border_target[axis] = border_target_rel_mode_for_axis;
6870 if (
g.IO.MouseDelta[axis] == 0.0f || (
g.IO.MouseDelta[axis] > 0.0f) == (border_target_rel_mode_for_axis > border_target_abs_mode_for_axis))
6871 ignore_resize =
true;
6875 ImVec2 clamp_min(border_n == ImGuiDir_Right ? clamp_rect.Min.x : -FLT_MAX, border_n == ImGuiDir_Down || (border_n == ImGuiDir_Up && window_move_from_title_bar) ? clamp_rect.Min.y : -FLT_MAX);
6876 ImVec2 clamp_max(border_n == ImGuiDir_Left ? clamp_rect.Max.x : +FLT_MAX, border_n == ImGuiDir_Up ? clamp_rect.Max.y : +FLT_MAX);
6877 border_target = ImClamp(border_target, clamp_min, clamp_max);
6878 if (flags & ImGuiWindowFlags_ChildWindow)
6880 ImGuiWindow* parent_window = window->ParentWindow;
6881 ImGuiWindowFlags parent_flags = parent_window->Flags;
6882 ImRect border_limit_rect = parent_window->InnerRect;
6883 border_limit_rect.Expand(ImVec2(-ImMax(parent_window->WindowPadding.x, parent_window->WindowBorderSize), -ImMax(parent_window->WindowPadding.y, parent_window->WindowBorderSize)));
6884 if ((axis == ImGuiAxis_X) && ((parent_flags & (ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar)) == 0 || (parent_flags & ImGuiWindowFlags_NoScrollbar)))
6885 border_target.x = ImClamp(border_target.x, border_limit_rect.Min.x, border_limit_rect.Max.x);
6886 if ((axis == ImGuiAxis_Y) && (parent_flags & ImGuiWindowFlags_NoScrollbar))
6887 border_target.y = ImClamp(border_target.y, border_limit_rect.Min.y, border_limit_rect.Max.y);
6890 CalcResizePosSizeFromAnyCorner(window, border_target, ImMin(def.
SegmentN1, def.
SegmentN2), &pos_target, &size_target);
6893 *border_hovered = border_n;
6895 *border_held = border_n;
6900 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
6905 if (
g.NavWindowingTarget &&
g.NavWindowingTarget->RootWindowDockTree == window)
6907 ImVec2 nav_resize_dir;
6908 if (
g.NavInputSource == ImGuiInputSource_Keyboard &&
g.IO.KeyShift)
6909 nav_resize_dir = GetKeyMagnitude2d(ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow);
6910 if (
g.NavInputSource == ImGuiInputSource_Gamepad)
6911 nav_resize_dir = GetKeyMagnitude2d(ImGuiKey_GamepadDpadLeft, ImGuiKey_GamepadDpadRight, ImGuiKey_GamepadDpadUp, ImGuiKey_GamepadDpadDown);
6912 if (nav_resize_dir.x != 0.0f || nav_resize_dir.y != 0.0f)
6914 const float NAV_RESIZE_SPEED = 600.0f;
6915 const float resize_step = NAV_RESIZE_SPEED *
g.IO.DeltaTime * ImMin(
g.IO.DisplayFramebufferScale.x,
g.IO.DisplayFramebufferScale.y);
6916 g.NavWindowingAccumDeltaSize += nav_resize_dir * resize_step;
6917 g.NavWindowingAccumDeltaSize = ImMax(
g.NavWindowingAccumDeltaSize, clamp_rect.Min - window->Pos - window->Size);
6918 g.NavWindowingToggleLayer =
false;
6919 g.NavHighlightItemUnderNav =
true;
6920 resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive);
6921 ImVec2 accum_floored = ImTrunc(
g.NavWindowingAccumDeltaSize);
6922 if (accum_floored.x != 0.0f || accum_floored.y != 0.0f)
6925 size_target = CalcWindowSizeAfterConstraint(window, window->SizeFull + accum_floored);
6926 g.NavWindowingAccumDeltaSize -= accum_floored;
6932 const ImVec2 curr_pos = window->Pos;
6933 const ImVec2 curr_size = window->SizeFull;
6934 if (size_target.x != FLT_MAX && (window->Size.x != size_target.x || window->SizeFull.x != size_target.x))
6935 window->Size.x = window->SizeFull.x = size_target.x;
6936 if (size_target.y != FLT_MAX && (window->Size.y != size_target.y || window->SizeFull.y != size_target.y))
6937 window->Size.y = window->SizeFull.y = size_target.y;
6938 if (pos_target.x != FLT_MAX && window->Pos.x != ImTrunc(pos_target.x))
6939 window->Pos.x = ImTrunc(pos_target.x);
6940 if (pos_target.y != FLT_MAX && window->Pos.y != ImTrunc(pos_target.y))
6941 window->Pos.y = ImTrunc(pos_target.y);
6942 if (curr_pos.x != window->Pos.x || curr_pos.y != window->Pos.y || curr_size.x != window->SizeFull.x || curr_size.y != window->SizeFull.y)
6943 MarkIniSettingsDirty(window);
6946 if (*border_held != -1)
6947 g.WindowResizeBorderExpectedRect = GetResizeBorderRect(window, *border_held, grip_hover_inner_size, WINDOWS_HOVER_PADDING);
6949 return ret_auto_fit_mask;
6952static inline void ClampWindowPos(ImGuiWindow* window,
const ImRect& visibility_rect)
6955 ImVec2 size_for_clamping = window->Size;
6956 if (
g.IO.ConfigWindowsMoveFromTitleBarOnly && window->DockNodeAsHost)
6957 size_for_clamping.y = ImGui::GetFrameHeight();
6958 else if (
g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
6959 size_for_clamping.y = window->TitleBarHeight;
6960 window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max);
6963static void RenderWindowOuterSingleBorder(ImGuiWindow* window,
int border_n, ImU32 border_col,
float border_size)
6966 const float rounding = window->WindowRounding;
6967 const ImRect border_r = GetResizeBorderRect(window, border_n, rounding, 0.0f);
6968 window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.
SegmentN1) + ImVec2(0.5f, 0.5f) + def.
InnerDir * rounding, rounding, def.
OuterAngle - IM_PI * 0.25f, def.
OuterAngle);
6969 window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.
SegmentN2) + ImVec2(0.5f, 0.5f) + def.
InnerDir * rounding, rounding, def.
OuterAngle, def.
OuterAngle + IM_PI * 0.25f);
6970 window->DrawList->PathStroke(border_col, ImDrawFlags_None, border_size);
6973static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
6976 const float border_size = window->WindowBorderSize;
6977 const ImU32 border_col = GetColorU32(ImGuiCol_Border);
6978 if (border_size > 0.0f && (window->Flags & ImGuiWindowFlags_NoBackground) == 0)
6979 window->DrawList->AddRect(window->Pos, window->Pos + window->Size, border_col, window->WindowRounding, 0, window->WindowBorderSize);
6980 else if (border_size > 0.0f)
6982 if (window->ChildFlags & ImGuiChildFlags_ResizeX)
6983 RenderWindowOuterSingleBorder(window, 1, border_col, border_size);
6984 if (window->ChildFlags & ImGuiChildFlags_ResizeY)
6985 RenderWindowOuterSingleBorder(window, 3, border_col, border_size);
6987 if (window->ResizeBorderHovered != -1 || window->ResizeBorderHeld != -1)
6989 const int border_n = (window->ResizeBorderHeld != -1) ? window->ResizeBorderHeld : window->ResizeBorderHovered;
6990 const ImU32 border_col_resizing = GetColorU32((window->ResizeBorderHeld != -1) ? ImGuiCol_SeparatorActive : ImGuiCol_SeparatorHovered);
6991 RenderWindowOuterSingleBorder(window, border_n, border_col_resizing, ImMax(2.0f, window->WindowBorderSize));
6993 if (
g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
6995 float y = window->Pos.y + window->TitleBarHeight - 1;
6996 window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), border_col,
g.Style.FrameBorderSize);
7002void ImGui::RenderWindowDecorations(ImGuiWindow* window,
const ImRect& title_bar_rect,
bool title_bar_is_highlight,
bool handle_borders_and_resize_grips,
int resize_grip_count,
const ImU32 resize_grip_col[4],
float resize_grip_draw_size)
7005 ImGuiStyle& style =
g.Style;
7006 ImGuiWindowFlags flags = window->Flags;
7009 IM_ASSERT(window->BeginCount == 0);
7010 window->SkipItems =
false;
7014 const float window_rounding = window->WindowRounding;
7015 const float window_border_size = window->WindowBorderSize;
7016 if (window->Collapsed)
7019 const float backup_border_size = style.FrameBorderSize;
7020 g.Style.FrameBorderSize = window->WindowBorderSize;
7021 ImU32 title_bar_col = GetColorU32((title_bar_is_highlight &&
g.NavCursorVisible) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed);
7022 if (window->ViewportOwned)
7023 title_bar_col |= IM_COL32_A_MASK;
7024 RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col,
true, window_rounding);
7025 g.Style.FrameBorderSize = backup_border_size;
7030 if (!(flags & ImGuiWindowFlags_NoBackground))
7032 bool is_docking_transparent_payload =
false;
7033 if (
g.DragDropActive && (
g.FrameCount -
g.DragDropAcceptFrameCount) <= 1 &&
g.IO.ConfigDockingTransparentPayload)
7034 if (
g.DragDropPayload.IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) && *(ImGuiWindow**)
g.DragDropPayload.Data == window)
7035 is_docking_transparent_payload =
true;
7037 ImU32 bg_col = GetColorU32(GetWindowBgColorIdx(window));
7038 if (window->ViewportOwned)
7040 bg_col |= IM_COL32_A_MASK;
7041 if (is_docking_transparent_payload)
7042 window->Viewport->Alpha *= DOCKING_TRANSPARENT_PAYLOAD_ALPHA;
7047 bool override_alpha =
false;
7049 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasBgAlpha)
7051 alpha =
g.NextWindowData.BgAlphaVal;
7052 override_alpha =
true;
7054 if (is_docking_transparent_payload)
7056 alpha *= DOCKING_TRANSPARENT_PAYLOAD_ALPHA;
7057 override_alpha =
true;
7060 bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT);
7064 if (window->DockIsActive)
7065 window->DockNode->LastBgColor = bg_col;
7066 ImDrawList* bg_draw_list = window->DockIsActive ? window->DockNode->HostWindow->DrawList : window->DrawList;
7067 if (window->DockIsActive || (flags & ImGuiWindowFlags_DockNodeHost))
7068 bg_draw_list->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
7069 bg_draw_list->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
7070 if (window->DockIsActive || (flags & ImGuiWindowFlags_DockNodeHost))
7071 bg_draw_list->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_FG);
7073 if (window->DockIsActive)
7074 window->DockNode->IsBgDrawnThisFrame =
true;
7079 if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
7081 ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
7082 if (window->ViewportOwned)
7083 title_bar_col |= IM_COL32_A_MASK;
7084 window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawFlags_RoundCornersTop);
7088 if (flags & ImGuiWindowFlags_MenuBar)
7090 ImRect menu_bar_rect = window->MenuBarRect();
7091 menu_bar_rect.ClipWith(window->Rect());
7092 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);
7093 if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
7094 window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
7098 ImGuiDockNode* node = window->DockNode;
7099 if (window->DockIsActive && node->IsHiddenTabBar() && !node->IsNoTabBar())
7101 float unhide_sz_draw = ImTrunc(
g.FontSize * 0.70f);
7102 float unhide_sz_hit = ImTrunc(
g.FontSize * 0.55f);
7103 ImVec2 p = node->Pos;
7104 ImRect r(p, p + ImVec2(unhide_sz_hit, unhide_sz_hit));
7105 ImGuiID unhide_id = window->GetID(
"#UNHIDE");
7106 KeepAliveID(unhide_id);
7108 if (ButtonBehavior(r, unhide_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren))
7109 node->WantHiddenTabBarToggle =
true;
7110 else if (held && IsMouseDragging(0))
7111 StartMouseMovingWindowOrNode(window, node,
true);
7114 ImU32 col = GetColorU32(((held && hovered) || (node->IsFocused && !hovered)) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
7115 window->DrawList->AddTriangleFilled(p, p + ImVec2(unhide_sz_draw, 0.0f), p + ImVec2(0.0f, unhide_sz_draw), col);
7119 if (window->ScrollbarX)
7120 Scrollbar(ImGuiAxis_X);
7121 if (window->ScrollbarY)
7122 Scrollbar(ImGuiAxis_Y);
7125 if (handle_borders_and_resize_grips && !(flags & ImGuiWindowFlags_NoResize))
7127 for (
int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
7129 const ImU32 col = resize_grip_col[resize_grip_n];
7130 if ((col & IM_COL32_A_MASK) == 0)
7133 const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.
CornerPosN);
7134 window->DrawList->PathLineTo(corner + grip.
InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, window_border_size)));
7135 window->DrawList->PathLineTo(corner + grip.
InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_grip_draw_size, window_border_size) : ImVec2(window_border_size, resize_grip_draw_size)));
7136 window->DrawList->PathArcToFast(ImVec2(corner.x + grip.
InnerDir.x * (window_rounding + window_border_size), corner.y + grip.
InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.
AngleMin12, grip.
AngleMax12);
7137 window->DrawList->PathFillConvex(col);
7142 if (handle_borders_and_resize_grips && !window->DockNodeAsHost)
7143 RenderWindowOuterBorders(window);
7149void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window,
const ImRect& title_bar_rect,
const char* name,
bool* p_open)
7152 ImGuiStyle& style =
g.Style;
7153 ImGuiWindowFlags flags = window->Flags;
7155 const bool has_close_button = (p_open != NULL);
7156 const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None);
7160 const ImGuiItemFlags item_flags_backup =
g.CurrentItemFlags;
7161 g.CurrentItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
7162 window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
7166 float pad_l = style.FramePadding.x;
7167 float pad_r = style.FramePadding.x;
7168 float button_sz =
g.FontSize;
7169 ImVec2 close_button_pos;
7170 ImVec2 collapse_button_pos;
7171 if (has_close_button)
7173 close_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - button_sz, title_bar_rect.Min.y + style.FramePadding.y);
7174 pad_r += button_sz + style.ItemInnerSpacing.x;
7176 if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Right)
7178 collapse_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - button_sz, title_bar_rect.Min.y + style.FramePadding.y);
7179 pad_r += button_sz + style.ItemInnerSpacing.x;
7181 if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Left)
7183 collapse_button_pos = ImVec2(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y + style.FramePadding.y);
7184 pad_l += button_sz + style.ItemInnerSpacing.x;
7188 if (has_collapse_button)
7189 if (CollapseButton(window->GetID(
"#COLLAPSE"), collapse_button_pos, NULL))
7190 window->WantCollapseToggle =
true;
7193 if (has_close_button)
7194 if (CloseButton(window->GetID(
"#CLOSE"), close_button_pos))
7197 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
7198 g.CurrentItemFlags = item_flags_backup;
7202 const float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? button_sz * 0.80f : 0.0f;
7203 const ImVec2 text_size =
CalcTextSize(name, NULL,
true) + ImVec2(marker_size_x, 0.0f);
7207 if (pad_l > style.FramePadding.x)
7208 pad_l +=
g.Style.ItemInnerSpacing.x;
7209 if (pad_r > style.FramePadding.x)
7210 pad_r +=
g.Style.ItemInnerSpacing.x;
7211 if (style.WindowTitleAlign.x > 0.0f && style.WindowTitleAlign.x < 1.0f)
7213 float centerness = ImSaturate(1.0f - ImFabs(style.WindowTitleAlign.x - 0.5f) * 2.0f);
7214 float pad_extend = ImMin(ImMax(pad_l, pad_r), title_bar_rect.GetWidth() - pad_l - pad_r - text_size.x);
7215 pad_l = ImMax(pad_l, pad_extend * centerness);
7216 pad_r = ImMax(pad_r, pad_extend * centerness);
7219 ImRect layout_r(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y, title_bar_rect.Max.x - pad_r, title_bar_rect.Max.y);
7220 ImRect clip_r(layout_r.Min.x, layout_r.Min.y, ImMin(layout_r.Max.x +
g.Style.ItemInnerSpacing.x, title_bar_rect.Max.x), layout_r.Max.y);
7221 if (flags & ImGuiWindowFlags_UnsavedDocument)
7224 marker_pos.x = ImClamp(layout_r.Min.x + (layout_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x + text_size.x, layout_r.Min.x, layout_r.Max.x);
7225 marker_pos.y = (layout_r.Min.y + layout_r.Max.y) * 0.5f;
7226 if (marker_pos.x > layout_r.Min.x)
7228 RenderBullet(window->DrawList, marker_pos, GetColorU32(ImGuiCol_Text));
7229 clip_r.Max.x = ImMin(clip_r.Max.x, marker_pos.x - (
int)(marker_size_x * 0.5f));
7234 RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r);
7237void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window)
7239 window->ParentWindow = parent_window;
7240 window->RootWindow = window->RootWindowPopupTree = window->RootWindowDockTree = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window;
7241 if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
7243 window->RootWindowDockTree = parent_window->RootWindowDockTree;
7244 if (!window->DockIsActive && !(parent_window->Flags & ImGuiWindowFlags_DockNodeHost))
7245 window->RootWindow = parent_window->RootWindow;
7247 if (parent_window && (flags & ImGuiWindowFlags_Popup))
7248 window->RootWindowPopupTree = parent_window->RootWindowPopupTree;
7249 if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)))
7250 window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight;
7251 while (window->RootWindowForNav->ChildFlags & ImGuiChildFlags_NavFlattened)
7253 IM_ASSERT(window->RootWindowForNav->ParentWindow != NULL);
7254 window->RootWindowForNav = window->RootWindowForNav->ParentWindow;
7260void ImGui::UpdateWindowSkipRefresh(ImGuiWindow* window)
7263 window->SkipRefresh =
false;
7264 if ((
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasRefreshPolicy) == 0)
7266 if (
g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_TryToAvoidRefresh)
7269 if (window->Appearing)
7273 if ((
g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_RefreshOnHover) &&
g.HoveredWindow)
7274 if (window->RootWindow ==
g.HoveredWindow->RootWindow || IsWindowWithinBeginStackOf(
g.HoveredWindow->RootWindow, window))
7276 if ((
g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_RefreshOnFocus) &&
g.NavWindow)
7277 if (window->RootWindow ==
g.NavWindow->RootWindow || IsWindowWithinBeginStackOf(
g.NavWindow->RootWindow, window))
7279 window->DrawList = NULL;
7280 window->SkipRefresh =
true;
7284static void SetWindowActiveForSkipRefresh(ImGuiWindow* window)
7286 window->Active =
true;
7287 for (ImGuiWindow* child : window->DC.ChildWindows)
7290 child->Active = child->SkipRefresh =
true;
7291 SetWindowActiveForSkipRefresh(child);
7308ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
7311 if (
g.OpenPopupStack.Size <= 0)
7315 for (ImGuiPopupData& popup_data :
g.OpenPopupStack)
7317 ImGuiWindow* popup_window = popup_data.Window;
7318 if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal))
7320 if (!popup_window->Active && !popup_window->WasActive)
7323 return popup_window;
7324 if (IsWindowWithinBeginStackOf(window, popup_window))
7326 return popup_window;
7338bool ImGui::Begin(
const char* name,
bool* p_open, ImGuiWindowFlags flags)
7341 const ImGuiStyle& style =
g.Style;
7342 IM_ASSERT(name != NULL && name[0] !=
'\0');
7343 IM_ASSERT(
g.WithinFrameScope);
7344 IM_ASSERT(
g.FrameCountEnded !=
g.FrameCount);
7347 ImGuiWindow* window = FindWindowByName(name);
7348 const bool window_just_created = (window == NULL);
7349 if (window_just_created)
7350 window = CreateNewWindow(name, flags);
7353 if (
g.DebugBreakInWindow == window->ID)
7357 if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs)
7358 flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
7360 const int current_frame =
g.FrameCount;
7361 const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame);
7362 window->IsFallbackWindow = (
g.CurrentWindowStack.Size == 0 &&
g.WithinFrameScopeWithImplicitWindow);
7365 bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1);
7366 if (flags & ImGuiWindowFlags_Popup)
7368 ImGuiPopupData& popup_ref =
g.OpenPopupStack[
g.BeginPopupStack.Size];
7369 window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId);
7370 window_just_activated_by_user |= (window != popup_ref.Window);
7374 const bool window_was_appearing = window->Appearing;
7375 if (first_begin_of_the_frame)
7377 UpdateWindowInFocusOrderList(window, window_just_created, flags);
7378 window->Appearing = window_just_activated_by_user;
7379 if (window->Appearing)
7380 SetWindowConditionAllowFlags(window, ImGuiCond_Appearing,
true);
7381 window->FlagsPreviousFrame = window->Flags;
7382 window->Flags = (ImGuiWindowFlags)flags;
7383 window->ChildFlags = (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasChildFlags) ?
g.NextWindowData.ChildFlags : 0;
7384 window->LastFrameActive = current_frame;
7385 window->LastTimeActive = (float)
g.Time;
7386 window->BeginOrderWithinParent = 0;
7387 window->BeginOrderWithinContext = (short)(
g.WindowsActiveCount++);
7391 flags = window->Flags;
7396 IM_ASSERT(window->DockNode == NULL || window->DockNodeAsHost == NULL);
7397 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasDock)
7398 SetWindowDock(window,
g.NextWindowData.DockId,
g.NextWindowData.DockCond);
7399 if (first_begin_of_the_frame)
7401 bool has_dock_node = (window->DockId != 0 || window->DockNode != NULL);
7402 bool new_auto_dock_node = !has_dock_node && GetWindowAlwaysWantOwnTabBar(window);
7403 bool dock_node_was_visible = window->DockNodeIsVisible;
7404 bool dock_tab_was_visible = window->DockTabIsVisible;
7405 if (has_dock_node || new_auto_dock_node)
7407 BeginDocked(window, p_open);
7408 flags = window->Flags;
7409 if (window->DockIsActive)
7411 IM_ASSERT(window->DockNode != NULL);
7412 g.NextWindowData.Flags &= ~ImGuiNextWindowDataFlags_HasSizeConstraint;
7416 if (window->DockTabIsVisible && !dock_tab_was_visible && dock_node_was_visible && !window->Appearing && !window_was_appearing)
7418 window->Appearing =
true;
7419 SetWindowConditionAllowFlags(window, ImGuiCond_Appearing,
true);
7424 window->DockIsActive = window->DockNodeIsVisible = window->DockTabIsVisible =
false;
7429 ImGuiWindow* parent_window_in_stack = (window->DockIsActive && window->DockNode->HostWindow) ? window->DockNode->HostWindow :
g.CurrentWindowStack.empty() ? NULL :
g.CurrentWindowStack.back().
Window;
7430 ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow;
7431 IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
7434 if (window->IDStack.Size == 0)
7435 window->IDStack.push_back(window->ID);
7438 g.CurrentWindow = window;
7439 g.CurrentWindowStack.resize(
g.CurrentWindowStack.Size + 1);
7440 ImGuiWindowStackData& window_stack_data =
g.CurrentWindowStack.back();
7441 window_stack_data.Window = window;
7442 window_stack_data.ParentLastItemDataBackup =
g.LastItemData;
7443 window_stack_data.DisabledOverrideReenable = (flags & ImGuiWindowFlags_Tooltip) && (
g.CurrentItemFlags & ImGuiItemFlags_Disabled);
7444 ErrorRecoveryStoreState(&window_stack_data.StackSizesInBegin);
7445 g.StackSizesInBeginForCurrentWindow = &window_stack_data.StackSizesInBegin;
7446 if (flags & ImGuiWindowFlags_ChildMenu)
7450 if (first_begin_of_the_frame)
7452 UpdateWindowParentAndRootLinks(window, flags, parent_window);
7453 window->ParentWindowInBeginStack = parent_window_in_stack;
7458 window->ParentWindowForFocusRoute = (window->RootWindow != window) ? parent_window_in_stack : NULL;
7459 if (window->ParentWindowForFocusRoute == NULL && window->DockNode != NULL)
7460 if (window->DockNode->MergedFlags & ImGuiDockNodeFlags_DockedWindowsInFocusRoute)
7461 window->ParentWindowForFocusRoute = window->DockNode->HostWindow;
7464 if (window->WindowClass.FocusRouteParentWindowId != 0)
7466 window->ParentWindowForFocusRoute = FindWindowByID(window->WindowClass.FocusRouteParentWindowId);
7467 IM_ASSERT(window->ParentWindowForFocusRoute != 0);
7472 PushFocusScope((window->ChildFlags & ImGuiChildFlags_NavFlattened) ?
g.CurrentFocusScopeId : window->
ID);
7473 window->NavRootFocusScopeId =
g.CurrentFocusScopeId;
7476 if (flags & ImGuiWindowFlags_Popup)
7478 ImGuiPopupData& popup_ref =
g.OpenPopupStack[
g.BeginPopupStack.Size];
7479 popup_ref.Window = window;
7480 popup_ref.ParentNavLayer = parent_window_in_stack->DC.NavLayerCurrent;
7481 g.BeginPopupStack.push_back(popup_ref);
7482 window->PopupId = popup_ref.PopupId;
7487 bool window_pos_set_by_api =
false;
7488 bool window_size_x_set_by_api =
false, window_size_y_set_by_api =
false;
7489 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos)
7491 window_pos_set_by_api = (window->SetWindowPosAllowFlags &
g.NextWindowData.PosCond) != 0;
7492 if (window_pos_set_by_api && ImLengthSqr(
g.NextWindowData.PosPivotVal) > 0.00001f)
7496 window->SetWindowPosVal =
g.NextWindowData.PosVal;
7497 window->SetWindowPosPivot =
g.NextWindowData.PosPivotVal;
7498 window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
7502 SetWindowPos(window,
g.NextWindowData.PosVal,
g.NextWindowData.PosCond);
7505 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize)
7507 window_size_x_set_by_api = (window->SetWindowSizeAllowFlags &
g.NextWindowData.SizeCond) != 0 && (
g.NextWindowData.SizeVal.x > 0.0f);
7508 window_size_y_set_by_api = (window->SetWindowSizeAllowFlags &
g.NextWindowData.SizeCond) != 0 && (
g.NextWindowData.SizeVal.y > 0.0f);
7509 if ((window->ChildFlags & ImGuiChildFlags_ResizeX) && (window->SetWindowSizeAllowFlags & ImGuiCond_FirstUseEver) == 0)
7510 g.NextWindowData.SizeVal.x = window->SizeFull.x;
7511 if ((window->ChildFlags & ImGuiChildFlags_ResizeY) && (window->SetWindowSizeAllowFlags & ImGuiCond_FirstUseEver) == 0)
7512 g.NextWindowData.SizeVal.y = window->SizeFull.y;
7513 SetWindowSize(window,
g.NextWindowData.SizeVal,
g.NextWindowData.SizeCond);
7515 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasScroll)
7517 if (
g.NextWindowData.ScrollVal.x >= 0.0f)
7519 window->ScrollTarget.x =
g.NextWindowData.ScrollVal.x;
7520 window->ScrollTargetCenterRatio.x = 0.0f;
7522 if (
g.NextWindowData.ScrollVal.y >= 0.0f)
7524 window->ScrollTarget.y =
g.NextWindowData.ScrollVal.y;
7525 window->ScrollTargetCenterRatio.y = 0.0f;
7528 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasContentSize)
7529 window->ContentSizeExplicit =
g.NextWindowData.ContentSizeVal;
7530 else if (first_begin_of_the_frame)
7531 window->ContentSizeExplicit = ImVec2(0.0f, 0.0f);
7532 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasWindowClass)
7533 window->WindowClass =
g.NextWindowData.WindowClass;
7534 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasCollapsed)
7535 SetWindowCollapsed(window,
g.NextWindowData.CollapsedVal,
g.NextWindowData.CollapsedCond);
7536 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasFocus)
7537 FocusWindow(window);
7538 if (window->Appearing)
7539 SetWindowConditionAllowFlags(window, ImGuiCond_Appearing,
false);
7542 UpdateWindowSkipRefresh(window);
7545 if (window_stack_data.DisabledOverrideReenable && window->RootWindow == window)
7546 BeginDisabledOverrideReenable();
7549 g.CurrentWindow = NULL;
7552 if (first_begin_of_the_frame && !window->SkipRefresh)
7555 const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip);
7556 const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesCannotSkipItems > 0);
7557 window->Active =
true;
7558 window->HasCloseButton = (p_open != NULL);
7559 window->ClipRect = ImVec4(-FLT_MAX, -FLT_MAX, +FLT_MAX, +FLT_MAX);
7560 window->IDStack.resize(1);
7561 window->DrawList->_ResetForNewFrame();
7562 window->DC.CurrentTableIdx = -1;
7563 if (flags & ImGuiWindowFlags_DockNodeHost)
7565 window->DrawList->ChannelsSplit(2);
7566 window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_FG);
7570 if (window->MemoryCompacted)
7571 GcAwakeTransientWindowBuffers(window);
7575 bool window_title_visible_elsewhere =
false;
7576 if ((window->Viewport && window->Viewport->Window == window) || (window->DockIsActive))
7577 window_title_visible_elsewhere =
true;
7578 else if (
g.NavWindowingListWindow != NULL && (window->Flags & ImGuiWindowFlags_NoNavFocus) == 0)
7579 window_title_visible_elsewhere =
true;
7580 if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0)
7582 size_t buf_len = (size_t)window->NameBufLen;
7583 window->Name =
ImStrdupcpy(window->Name, &buf_len, name);
7584 window->NameBufLen = (int)buf_len;
7590 CalcWindowContentSizes(window, &window->ContentSize, &window->ContentSizeIdeal);
7595 if (window->HiddenFramesCanSkipItems > 0)
7596 window->HiddenFramesCanSkipItems--;
7597 if (window->HiddenFramesCannotSkipItems > 0)
7598 window->HiddenFramesCannotSkipItems--;
7599 if (window->HiddenFramesForRenderOnly > 0)
7600 window->HiddenFramesForRenderOnly--;
7603 if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api))
7604 window->HiddenFramesCannotSkipItems = 1;
7608 if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0)
7610 window->HiddenFramesCannotSkipItems = 1;
7611 if (flags & ImGuiWindowFlags_AlwaysAutoResize)
7613 if (!window_size_x_set_by_api)
7614 window->Size.x = window->SizeFull.x = 0.f;
7615 if (!window_size_y_set_by_api)
7616 window->Size.y = window->SizeFull.y = 0.f;
7617 window->ContentSize = window->ContentSizeIdeal = ImVec2(0.f, 0.f);
7624 WindowSelectViewport(window);
7625 SetCurrentViewport(window, window->Viewport);
7626 window->FontDpiScale = (
g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleFonts) ? window->Viewport->DpiScale : 1.0f;
7627 SetCurrentWindow(window);
7628 flags = window->Flags;
7633 if (!window->DockIsActive && (flags & ImGuiWindowFlags_ChildWindow))
7634 window->WindowBorderSize = style.ChildBorderSize;
7636 window->WindowBorderSize = ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize;
7637 window->WindowPadding = style.WindowPadding;
7638 if (!window->DockIsActive && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !(window->ChildFlags & ImGuiChildFlags_AlwaysUseWindowPadding) && window->WindowBorderSize == 0.0f)
7639 window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
7642 window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x),
g.NextWindowData.MenuBarOffsetMinVal.x);
7643 window->DC.MenuBarOffset.y =
g.NextWindowData.MenuBarOffsetMinVal.y;
7644 window->TitleBarHeight = (flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f :
g.FontSize +
g.Style.FramePadding.y * 2.0f;
7645 window->MenuBarHeight = (flags & ImGuiWindowFlags_MenuBar) ? window->DC.MenuBarOffset.y +
g.FontSize +
g.Style.FramePadding.y * 2.0f : 0.0f;
7649 bool use_current_size_for_scrollbar_x = window_just_created;
7650 bool use_current_size_for_scrollbar_y = window_just_created;
7651 if (window_size_x_set_by_api && window->ContentSizeExplicit.x != 0.0f)
7652 use_current_size_for_scrollbar_x =
true;
7653 if (window_size_y_set_by_api && window->ContentSizeExplicit.y != 0.0f)
7654 use_current_size_for_scrollbar_y =
true;
7658 if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse) && !window->DockIsActive)
7662 ImRect title_bar_rect = window->TitleBarRect();
7663 if (
g.HoveredWindow == window &&
g.HoveredId == 0 &&
g.HoveredIdPreviousFrame == 0 &&
g.ActiveId == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max))
7664 if (
g.IO.MouseClickedCount[0] == 2 && GetKeyOwner(ImGuiKey_MouseLeft) == ImGuiKeyOwner_NoOwner)
7665 window->WantCollapseToggle =
true;
7666 if (window->WantCollapseToggle)
7668 window->Collapsed = !window->Collapsed;
7669 if (!window->Collapsed)
7670 use_current_size_for_scrollbar_y =
true;
7671 MarkIniSettingsDirty(window);
7676 window->Collapsed =
false;
7678 window->WantCollapseToggle =
false;
7684 const ImVec2 scrollbar_sizes_from_last_frame = window->ScrollbarSizes;
7685 window->DecoOuterSizeX1 = 0.0f;
7686 window->DecoOuterSizeX2 = 0.0f;
7687 window->DecoOuterSizeY1 = window->TitleBarHeight + window->MenuBarHeight;
7688 window->DecoOuterSizeY2 = 0.0f;
7689 window->ScrollbarSizes = ImVec2(0.0f, 0.0f);
7692 const ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, window->ContentSizeIdeal);
7693 if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed)
7696 if (!window_size_x_set_by_api)
7698 window->SizeFull.x = size_auto_fit.x;
7699 use_current_size_for_scrollbar_x =
true;
7701 if (!window_size_y_set_by_api)
7703 window->SizeFull.y = size_auto_fit.y;
7704 use_current_size_for_scrollbar_y =
true;
7707 else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
7711 if (!window_size_x_set_by_api && window->AutoFitFramesX > 0)
7713 window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
7714 use_current_size_for_scrollbar_x =
true;
7716 if (!window_size_y_set_by_api && window->AutoFitFramesY > 0)
7718 window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
7719 use_current_size_for_scrollbar_y =
true;
7721 if (!window->Collapsed)
7722 MarkIniSettingsDirty(window);
7726 window->SizeFull = CalcWindowSizeAfterConstraint(window, window->SizeFull);
7727 window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull;
7732 if (window_just_activated_by_user)
7734 window->AutoPosLastDirection = ImGuiDir_None;
7735 if ((flags & ImGuiWindowFlags_Popup) != 0 && !(flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api)
7736 window->Pos =
g.BeginPopupStack.back().OpenPopupPos;
7740 if (flags & ImGuiWindowFlags_ChildWindow)
7742 IM_ASSERT(parent_window && parent_window->Active);
7743 window->BeginOrderWithinParent = (short)parent_window->DC.ChildWindows.Size;
7744 parent_window->DC.ChildWindows.push_back(window);
7745 if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api && !window_is_child_tooltip)
7746 window->Pos = parent_window->DC.CursorPos;
7749 const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesCannotSkipItems == 0);
7750 if (window_pos_with_pivot)
7751 SetWindowPos(window, window->SetWindowPosVal - window->Size * window->SetWindowPosPivot, 0);
7752 else if ((flags & ImGuiWindowFlags_ChildMenu) != 0)
7753 window->Pos = FindBestWindowPosForPopup(window);
7754 else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize)
7755 window->Pos = FindBestWindowPosForPopup(window);
7756 else if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip)
7757 window->Pos = FindBestWindowPosForPopup(window);
7760 if (window->ViewportAllowPlatformMonitorExtend >= 0 && !window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_IsMinimized))
7761 if (!window->Viewport->GetMainRect().Contains(window->Rect()))
7765 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoFocusOnAppearing);
7769 SetCurrentViewport(window, window->Viewport);
7770 window->FontDpiScale = (
g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleFonts) ? window->Viewport->DpiScale : 1.0f;
7771 SetCurrentWindow(window);
7774 if (window->ViewportOwned)
7775 WindowSyncOwnedViewport(window, parent_window_in_stack);
7779 ImRect viewport_rect(window->Viewport->GetMainRect());
7780 ImRect viewport_work_rect(window->Viewport->GetWorkRect());
7781 ImVec2 visibility_padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
7782 ImRect visibility_rect(viewport_work_rect.Min + visibility_padding, viewport_work_rect.Max - visibility_padding);
7787 if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow))
7789 if (!window->ViewportOwned && viewport_rect.GetWidth() > 0 && viewport_rect.GetHeight() > 0.0f)
7791 ClampWindowPos(window, visibility_rect);
7793 else if (window->ViewportOwned &&
g.PlatformIO.Monitors.Size > 0)
7795 if (
g.MovingWindow != NULL && window->RootWindowDockTree ==
g.MovingWindow->RootWindowDockTree)
7798 visibility_rect =
g.PlatformMonitorsFullWorkRect;
7804 const ImGuiPlatformMonitor* monitor = GetViewportPlatformMonitor(window->Viewport);
7805 visibility_rect = ImRect(monitor->WorkPos, monitor->WorkPos + monitor->WorkSize);
7807 visibility_rect.Expand(-visibility_padding);
7808 ClampWindowPos(window, visibility_rect);
7811 window->Pos = ImTrunc(window->Pos);
7815 if (window->ViewportOwned || window->DockIsActive)
7816 window->WindowRounding = 0.0f;
7818 window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
7825 bool want_focus =
false;
7826 if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing))
7828 if (flags & ImGuiWindowFlags_Popup)
7830 else if ((window->DockIsActive || (flags & ImGuiWindowFlags_ChildWindow) == 0) && !(flags & ImGuiWindowFlags_Tooltip))
7835#ifdef IMGUI_ENABLE_TEST_ENGINE
7836 if (
g.TestEngineHookItems)
7838 IM_ASSERT(window->IDStack.Size == 1);
7839 window->IDStack.Size = 0;
7840 IMGUI_TEST_ENGINE_ITEM_ADD(window->ID, window->Rect(), NULL);
7841 IMGUI_TEST_ENGINE_ITEM_INFO(window->ID, window->Name, (
g.HoveredWindow == window) ? ImGuiItemStatusFlags_HoveredRect : 0);
7842 window->IDStack.Size = 1;
7847 const bool handle_borders_and_resize_grips = (window->DockNodeAsHost || !window->DockIsActive);
7850 int border_hovered = -1, border_held = -1;
7851 ImU32 resize_grip_col[4] = {};
7852 const int resize_grip_count = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) ? 0 :
g.IO.ConfigWindowsResizeFromEdges ? 2 : 1;
7853 const float resize_grip_draw_size = IM_TRUNC(ImMax(
g.FontSize * 1.10f, window->WindowRounding + 1.0f +
g.FontSize * 0.2f));
7854 if (handle_borders_and_resize_grips && !window->Collapsed)
7855 if (
int auto_fit_mask = UpdateWindowManualResize(window, size_auto_fit, &border_hovered, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect))
7857 if (auto_fit_mask & (1 << ImGuiAxis_X))
7858 use_current_size_for_scrollbar_x =
true;
7859 if (auto_fit_mask & (1 << ImGuiAxis_Y))
7860 use_current_size_for_scrollbar_y =
true;
7862 window->ResizeBorderHovered = (
signed char)border_hovered;
7863 window->ResizeBorderHeld = (
signed char)border_held;
7866 if (window->ViewportOwned)
7868 if (!window->Viewport->PlatformRequestMove)
7869 window->Viewport->Pos = window->Pos;
7870 if (!window->Viewport->PlatformRequestResize)
7871 window->Viewport->Size = window->Size;
7872 window->Viewport->UpdateWorkRect();
7873 viewport_rect = window->Viewport->GetMainRect();
7877 window->ViewportPos = window->Viewport->Pos;
7882 if (!window->Collapsed)
7887 ImVec2 avail_size_from_current_frame = ImVec2(window->SizeFull.x, window->SizeFull.y - (window->DecoOuterSizeY1 + window->DecoOuterSizeY2));
7888 ImVec2 avail_size_from_last_frame = window->InnerRect.GetSize() + scrollbar_sizes_from_last_frame;
7889 ImVec2 needed_size_from_last_frame = window_just_created ? ImVec2(0, 0) : window->ContentSize + window->WindowPadding * 2.0f;
7890 float size_x_for_scrollbars = use_current_size_for_scrollbar_x ? avail_size_from_current_frame.x : avail_size_from_last_frame.x;
7891 float size_y_for_scrollbars = use_current_size_for_scrollbar_y ? avail_size_from_current_frame.y : avail_size_from_last_frame.y;
7893 window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
7894 window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
7895 if (window->ScrollbarX && !window->ScrollbarY)
7896 window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
7897 window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
7900 window->DecoOuterSizeX2 += window->ScrollbarSizes.x;
7901 window->DecoOuterSizeY2 += window->ScrollbarSizes.y;
7913 const ImRect host_rect = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) ? parent_window->ClipRect : viewport_rect;
7914 const ImRect outer_rect = window->Rect();
7915 const ImRect title_bar_rect = window->TitleBarRect();
7916 window->OuterRectClipped = outer_rect;
7917 if (window->DockIsActive)
7918 window->OuterRectClipped.Min.y += window->TitleBarHeight;
7919 window->OuterRectClipped.ClipWith(host_rect);
7927 window->InnerRect.Min.x = window->Pos.x + window->DecoOuterSizeX1;
7928 window->InnerRect.Min.y = window->Pos.y + window->DecoOuterSizeY1;
7929 window->InnerRect.Max.x = window->Pos.x + window->Size.x - window->DecoOuterSizeX2;
7930 window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->DecoOuterSizeY2;
7941 float top_border_size = (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
7946 window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + window->WindowBorderSize * 0.5f);
7947 window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + top_border_size * 0.5f);
7948 window->InnerClipRect.Max.x = ImFloor(window->InnerRect.Max.x - window->WindowBorderSize * 0.5f);
7949 window->InnerClipRect.Max.y = ImFloor(window->InnerRect.Max.y - window->WindowBorderSize * 0.5f);
7950 window->InnerClipRect.ClipWithFull(host_rect);
7953 if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))
7954 window->ItemWidthDefault = ImTrunc(window->Size.x * 0.65f);
7956 window->ItemWidthDefault = ImTrunc(
g.FontSize * 16.0f);
7963 window->ScrollMax.x = ImMax(0.0f, window->ContentSize.x + window->WindowPadding.x * 2.0f - window->InnerRect.GetWidth());
7964 window->ScrollMax.y = ImMax(0.0f, window->ContentSize.y + window->WindowPadding.y * 2.0f - window->InnerRect.GetHeight());
7967 window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window);
7968 window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
7969 window->DecoInnerSizeX1 = window->DecoInnerSizeY1 = 0.0f;
7974 IM_ASSERT(window->DrawList->CmdBuffer.Size == 1 && window->DrawList->CmdBuffer[0].ElemCount == 0);
7975 window->DrawList->PushTextureID(
g.Font->ContainerAtlas->TexID);
7976 PushClipRect(host_rect.Min, host_rect.Max,
false);
7981 const bool is_undocked_or_docked_visible = !window->DockIsActive || window->DockTabIsVisible;
7982 if (is_undocked_or_docked_visible)
7984 bool render_decorations_in_parent =
false;
7985 if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip)
7989 ImGuiWindow* previous_child = parent_window->DC.ChildWindows.Size >= 2 ? parent_window->DC.ChildWindows[parent_window->DC.ChildWindows.Size - 2] : NULL;
7990 bool previous_child_overlapping = previous_child ? previous_child->Rect().Overlaps(window->Rect()) :
false;
7991 bool parent_is_empty = (parent_window->DrawList->VtxBuffer.Size == 0);
7992 if (window->DrawList->CmdBuffer.back().ElemCount == 0 && !parent_is_empty && !previous_child_overlapping)
7993 render_decorations_in_parent =
true;
7995 if (render_decorations_in_parent)
7996 window->DrawList = parent_window->DrawList;
7999 const ImGuiWindow* window_to_highlight =
g.NavWindowingTarget ?
g.NavWindowingTarget :
g.NavWindow;
8000 const bool title_bar_is_highlight = want_focus || (window_to_highlight && (window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight || (window->DockNode && window->DockNode == window_to_highlight->DockNode)));
8001 RenderWindowDecorations(window, title_bar_rect, title_bar_is_highlight, handle_borders_and_resize_grips, resize_grip_count, resize_grip_col, resize_grip_draw_size);
8003 if (render_decorations_in_parent)
8004 window->DrawList = &window->DrawListInst;
8014 const bool allow_scrollbar_x = !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar);
8015 const bool allow_scrollbar_y = !(flags & ImGuiWindowFlags_NoScrollbar);
8016 const float work_rect_size_x = (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : ImMax(allow_scrollbar_x ? window->ContentSize.x : 0.0f, window->Size.x - window->WindowPadding.x * 2.0f - (window->DecoOuterSizeX1 + window->DecoOuterSizeX2)));
8017 const float work_rect_size_y = (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : ImMax(allow_scrollbar_y ? window->ContentSize.y : 0.0f, window->Size.y - window->WindowPadding.y * 2.0f - (window->DecoOuterSizeY1 + window->DecoOuterSizeY2)));
8018 window->WorkRect.Min.x = ImTrunc(window->InnerRect.Min.x - window->Scroll.x + ImMax(window->WindowPadding.x, window->WindowBorderSize));
8019 window->WorkRect.Min.y = ImTrunc(window->InnerRect.Min.y - window->Scroll.y + ImMax(window->WindowPadding.y, window->WindowBorderSize));
8020 window->WorkRect.Max.x = window->WorkRect.Min.x + work_rect_size_x;
8021 window->WorkRect.Max.y = window->WorkRect.Min.y + work_rect_size_y;
8022 window->ParentWorkRect = window->WorkRect;
8029 window->ContentRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x + window->DecoOuterSizeX1;
8030 window->ContentRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->DecoOuterSizeY1;
8031 window->ContentRegionRect.Max.x = window->ContentRegionRect.Min.x + (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : (window->Size.x - window->WindowPadding.x * 2.0f - (window->DecoOuterSizeX1 + window->DecoOuterSizeX2)));
8032 window->ContentRegionRect.Max.y = window->ContentRegionRect.Min.y + (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : (window->Size.y - window->WindowPadding.y * 2.0f - (window->DecoOuterSizeY1 + window->DecoOuterSizeY2)));
8036 window->DC.Indent.x = window->DecoOuterSizeX1 + window->WindowPadding.x - window->Scroll.x;
8037 window->DC.GroupOffset.x = 0.0f;
8038 window->DC.ColumnsOffset.x = 0.0f;
8042 double start_pos_highp_x = (double)window->Pos.x + window->WindowPadding.x - (
double)window->Scroll.x + window->DecoOuterSizeX1 + window->DC.ColumnsOffset.x;
8043 double start_pos_highp_y = (double)window->Pos.y + window->WindowPadding.y - (
double)window->Scroll.y + window->DecoOuterSizeY1;
8044 window->DC.CursorStartPos = ImVec2((
float)start_pos_highp_x, (
float)start_pos_highp_y);
8045 window->DC.CursorStartPosLossyness = ImVec2((
float)(start_pos_highp_x - window->DC.CursorStartPos.x), (
float)(start_pos_highp_y - window->DC.CursorStartPos.y));
8046 window->DC.CursorPos = window->DC.CursorStartPos;
8047 window->DC.CursorPosPrevLine = window->DC.CursorPos;
8048 window->DC.CursorMaxPos = window->DC.CursorStartPos;
8049 window->DC.IdealMaxPos = window->DC.CursorStartPos;
8050 window->DC.CurrLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f);
8051 window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
8052 window->DC.IsSameLine = window->DC.IsSetPos =
false;
8054 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
8055 window->DC.NavLayersActiveMask = window->DC.NavLayersActiveMaskNext;
8056 window->DC.NavLayersActiveMaskNext = 0x00;
8057 window->DC.NavIsScrollPushableX =
true;
8058 window->DC.NavHideHighlightOneFrame =
false;
8059 window->DC.NavWindowHasScrollY = (window->ScrollMax.y > 0.0f);
8061 window->DC.MenuBarAppending =
false;
8062 window->DC.MenuColumns.Update(style.ItemSpacing.x, window_just_activated_by_user);
8063 window->DC.TreeDepth = 0;
8064 window->DC.TreeHasStackDataDepthMask = 0x00;
8065 window->DC.ChildWindows.resize(0);
8066 window->DC.StateStorage = &window->StateStorage;
8067 window->DC.CurrentColumns = NULL;
8068 window->DC.LayoutType = ImGuiLayoutType_Vertical;
8069 window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
8071 window->DC.ItemWidth = window->ItemWidthDefault;
8072 window->DC.TextWrapPos = -1.0f;
8073 window->DC.ItemWidthStack.resize(0);
8074 window->DC.TextWrapPosStack.resize(0);
8075 if (flags & ImGuiWindowFlags_Modal)
8076 window->DC.ModalDimBgColor = ColorConvertFloat4ToU32(GetStyleColorVec4(ImGuiCol_ModalWindowDimBg));
8078 if (window->AutoFitFramesX > 0)
8079 window->AutoFitFramesX--;
8080 if (window->AutoFitFramesY > 0)
8081 window->AutoFitFramesY--;
8084 g.NextWindowData.ClearFlags();
8091 FocusWindow(window, ImGuiFocusRequestFlags_UnlessBelowModal);
8092 if (want_focus && window ==
g.NavWindow)
8093 NavInitWindow(window,
false);
8096 if (p_open != NULL && window->Viewport->PlatformRequestClose && window->Viewport != GetMainViewport())
8098 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Window '%s' closed by PlatformRequestClose\n", window->Name);
8100 g.NavWindowingToggleLayer =
false;
8104 if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
8105 RenderWindowTitleBarContents(window, ImRect(title_bar_rect.Min.x + window->WindowBorderSize, title_bar_rect.Min.y, title_bar_rect.Max.x - window->WindowBorderSize, title_bar_rect.Max.y), name, p_open);
8108 window->HitTestHoleSize.x = window->HitTestHoleSize.y = 0;
8110 if (flags & ImGuiWindowFlags_Tooltip)
8111 g.TooltipPreviousWindow = window;
8123 if (
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable)
8127 if (
g.MovingWindow == window && (window->RootWindowDockTree->Flags & ImGuiWindowFlags_NoDocking) == 0)
8128 BeginDockableDragDropSource(window);
8131 if (
g.DragDropActive && !(flags & ImGuiWindowFlags_NoDocking))
8132 if (
g.MovingWindow == NULL ||
g.MovingWindow->RootWindowDockTree != window)
8133 if ((window == window->RootWindowDockTree) && !(window->Flags & ImGuiWindowFlags_DockNodeHost))
8134 BeginDockableDragDropTarget(window);
8139 SetLastItemDataForWindow(window, title_bar_rect);
8142#ifndef IMGUI_DISABLE_DEBUG_TOOLS
8143 if (
g.DebugLocateId != 0 && (window->ID ==
g.DebugLocateId || window->MoveId ==
g.DebugLocateId))
8144 DebugLocateItemResolveWithLastItem();
8148#ifdef IMGUI_ENABLE_TEST_ENGINE
8149 if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
8150 IMGUI_TEST_ENGINE_ITEM_ADD(
g.LastItemData.ID,
g.LastItemData.Rect, &
g.LastItemData);
8156 if (window->SkipRefresh)
8157 SetWindowActiveForSkipRefresh(window);
8160 SetCurrentViewport(window, window->Viewport);
8161 SetCurrentWindow(window);
8162 g.NextWindowData.ClearFlags();
8163 SetLastItemDataForWindow(window, window->TitleBarRect());
8166 if (!(flags & ImGuiWindowFlags_DockNodeHost) && !window->SkipRefresh)
8167 PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max,
true);
8170 window->WriteAccessed =
false;
8171 window->BeginCount++;
8174 if (first_begin_of_the_frame && !window->SkipRefresh)
8180 if (window->DockIsActive && !window->DockTabIsVisible)
8182 if (window->LastFrameJustFocused ==
g.FrameCount)
8183 window->HiddenFramesCannotSkipItems = 1;
8185 window->HiddenFramesCanSkipItems = 1;
8188 if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ChildMenu))
8192 IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0 || window->DockIsActive);
8193 const bool nav_request = (window->ChildFlags & ImGuiChildFlags_NavFlattened) && (
g.NavAnyRequest &&
g.NavWindow &&
g.NavWindow->RootWindowForNav == window->RootWindowForNav);
8194 if (!
g.LogEnabled && !nav_request)
8195 if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y)
8197 if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
8198 window->HiddenFramesCannotSkipItems = 1;
8200 window->HiddenFramesCanSkipItems = 1;
8204 if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCanSkipItems > 0))
8205 window->HiddenFramesCanSkipItems = 1;
8206 if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCannotSkipItems > 0))
8207 window->HiddenFramesCannotSkipItems = 1;
8211 if (style.Alpha <= 0.0f)
8212 window->HiddenFramesCanSkipItems = 1;
8215 bool hidden_regular = (window->HiddenFramesCanSkipItems > 0) || (window->HiddenFramesCannotSkipItems > 0);
8216 window->Hidden = hidden_regular || (window->HiddenFramesForRenderOnly > 0);
8219 if (window->DisableInputsFrames > 0)
8221 window->DisableInputsFrames--;
8222 window->Flags |= ImGuiWindowFlags_NoInputs;
8226 bool skip_items =
false;
8227 if (window->Collapsed || !window->Active || hidden_regular)
8228 if (window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesCannotSkipItems <= 0)
8230 window->SkipItems = skip_items;
8233 if (window->SkipItems)
8234 window->DC.NavLayersActiveMaskNext = window->DC.NavLayersActiveMask;
8239 if (window->SkipItems && !window->Appearing)
8240 IM_ASSERT(window->Appearing ==
false);
8242 else if (first_begin_of_the_frame)
8245 window->SkipItems =
true;
8250#ifndef IMGUI_DISABLE_DEBUG_TOOLS
8251 if (!window->IsFallbackWindow)
8252 if ((
g.IO.ConfigDebugBeginReturnValueOnce && window_just_created) || (
g.IO.ConfigDebugBeginReturnValueLoop &&
g.DebugBeginReturnValueCullDepth ==
g.CurrentWindowStack.Size))
8254 if (window->AutoFitFramesX > 0) { window->AutoFitFramesX++; }
8255 if (window->AutoFitFramesY > 0) { window->AutoFitFramesY++; }
8260 return !window->SkipItems;
8263static void ImGui::SetLastItemDataForWindow(ImGuiWindow* window,
const ImRect& rect)
8266 if (window->DockIsActive)
8267 SetLastItemData(window->MoveId,
g.CurrentItemFlags, window->DockTabItemStatusFlags, window->DockTabItemRect);
8269 SetLastItemData(window->MoveId,
g.CurrentItemFlags, IsMouseHoveringRect(rect.Min, rect.Max,
false) ? ImGuiItemStatusFlags_HoveredRect : 0, rect);
8275 ImGuiWindow* window =
g.CurrentWindow;
8278 if (
g.CurrentWindowStack.Size <= 1 &&
g.WithinFrameScopeWithImplicitWindow)
8280 IM_ASSERT_USER_ERROR(
g.CurrentWindowStack.Size > 1,
"Calling End() too many times!");
8283 ImGuiWindowStackData& window_stack_data =
g.CurrentWindowStack.back();
8286 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_DockNodeHost) && !window->DockIsActive)
8287 IM_ASSERT_USER_ERROR(
g.WithinEndChild,
"Must call EndChild() and not End()!");
8290 if (window->DC.CurrentColumns)
8292 if (!(window->Flags & ImGuiWindowFlags_DockNodeHost) && !window->SkipRefresh)
8295 if (window_stack_data.DisabledOverrideReenable && window->RootWindow == window)
8296 EndDisabledOverrideReenable();
8298 if (window->SkipRefresh)
8300 IM_ASSERT(window->DrawList == NULL);
8301 window->DrawList = &window->DrawListInst;
8305 if (!(window->Flags & ImGuiWindowFlags_ChildWindow))
8308 if (window->DC.IsSetPos)
8309 ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
8312 if (window->DockNode && window->DockTabIsVisible)
8313 if (ImGuiWindow* host_window = window->DockNode->HostWindow)
8314 host_window->DC.CursorMaxPos = window->DC.CursorMaxPos + window->WindowPadding - host_window->WindowPadding;
8317 g.LastItemData = window_stack_data.ParentLastItemDataBackup;
8318 if (window->Flags & ImGuiWindowFlags_ChildMenu)
8320 if (window->Flags & ImGuiWindowFlags_Popup)
8321 g.BeginPopupStack.pop_back();
8324 if (
g.IO.ConfigErrorRecovery)
8325 ErrorRecoveryTryToRecoverWindowState(&window_stack_data.StackSizesInBegin);
8327 g.CurrentWindowStack.pop_back();
8328 SetCurrentWindow(
g.CurrentWindowStack.Size == 0 ? NULL :
g.CurrentWindowStack.back().
Window);
8329 if (
g.CurrentWindow)
8330 SetCurrentViewport(
g.CurrentWindow,
g.CurrentWindow->Viewport);
8333void ImGui::BringWindowToFocusFront(ImGuiWindow* window)
8336 IM_ASSERT(window == window->RootWindow);
8338 const int cur_order = window->FocusOrder;
8339 IM_ASSERT(
g.WindowsFocusOrder[cur_order] == window);
8340 if (
g.WindowsFocusOrder.back() == window)
8343 const int new_order =
g.WindowsFocusOrder.Size - 1;
8344 for (
int n = cur_order; n < new_order; n++)
8346 g.WindowsFocusOrder[n] =
g.WindowsFocusOrder[n + 1];
8347 g.WindowsFocusOrder[n]->FocusOrder--;
8348 IM_ASSERT(
g.WindowsFocusOrder[n]->FocusOrder == n);
8350 g.WindowsFocusOrder[new_order] = window;
8351 window->FocusOrder = (short)new_order;
8354void ImGui::BringWindowToDisplayFront(ImGuiWindow* window)
8357 ImGuiWindow* current_front_window =
g.Windows.back();
8358 if (current_front_window == window || current_front_window->RootWindowDockTree == window)
8360 for (
int i =
g.Windows.Size - 2; i >= 0; i--)
8361 if (
g.Windows[i] == window)
8363 memmove(&
g.Windows[i], &
g.Windows[i + 1], (
size_t)(
g.Windows.Size - i - 1) *
sizeof(ImGuiWindow*));
8364 g.Windows[
g.Windows.Size - 1] = window;
8369void ImGui::BringWindowToDisplayBack(ImGuiWindow* window)
8372 if (
g.Windows[0] == window)
8374 for (
int i = 0; i <
g.Windows.Size; i++)
8375 if (
g.Windows[i] == window)
8377 memmove(&
g.Windows[1], &
g.Windows[0], (
size_t)i *
sizeof(ImGuiWindow*));
8378 g.Windows[0] = window;
8383void ImGui::BringWindowToDisplayBehind(ImGuiWindow* window, ImGuiWindow* behind_window)
8385 IM_ASSERT(window != NULL && behind_window != NULL);
8387 window = window->RootWindow;
8388 behind_window = behind_window->RootWindow;
8389 int pos_wnd = FindWindowDisplayIndex(window);
8390 int pos_beh = FindWindowDisplayIndex(behind_window);
8391 if (pos_wnd < pos_beh)
8393 size_t copy_bytes = (pos_beh - pos_wnd - 1) *
sizeof(ImGuiWindow*);
8394 memmove(&
g.Windows.Data[pos_wnd], &
g.Windows.Data[pos_wnd + 1], copy_bytes);
8395 g.Windows[pos_beh - 1] = window;
8399 size_t copy_bytes = (pos_wnd - pos_beh) *
sizeof(ImGuiWindow*);
8400 memmove(&
g.Windows.Data[pos_beh + 1], &
g.Windows.Data[pos_beh], copy_bytes);
8401 g.Windows[pos_beh] = window;
8405int ImGui::FindWindowDisplayIndex(ImGuiWindow* window)
8408 return g.Windows.index_from_ptr(
g.Windows.find(window));
8412void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags)
8417 if ((flags & ImGuiFocusRequestFlags_UnlessBelowModal) && (
g.NavWindow != window))
8418 if (ImGuiWindow* blocking_modal = FindBlockingModal(window))
8423 IMGUI_DEBUG_LOG_FOCUS(
"[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n", window ? window->Name :
"<NULL>", blocking_modal->Name);
8424 if (window && window == window->RootWindow && (window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
8425 BringWindowToDisplayBehind(window, blocking_modal);
8426 ClosePopupsOverWindow(GetTopMostPopupModal(),
false);
8431 if ((flags & ImGuiFocusRequestFlags_RestoreFocusedChild) && window != NULL)
8432 window = NavRestoreLastChildNavWindow(window);
8435 if (
g.NavWindow != window)
8437 SetNavWindow(window);
8438 if (window &&
g.NavHighlightItemUnderNav)
8439 g.NavMousePosDirty =
true;
8440 g.NavId = window ? window->NavLastIds[0] : 0;
8441 g.NavLayer = ImGuiNavLayer_Main;
8442 SetNavFocusScope(window ? window->NavRootFocusScopeId : 0);
8443 g.NavIdIsAlive =
false;
8444 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
8447 ClosePopupsOverWindow(window,
false);
8451 IM_ASSERT(window == NULL || window->RootWindowDockTree != NULL);
8452 ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL;
8453 ImGuiWindow* display_front_window = window ? window->RootWindowDockTree : NULL;
8454 ImGuiDockNode* dock_node = window ? window->DockNode : NULL;
8455 bool active_id_window_is_dock_node_host = (
g.ActiveIdWindow && dock_node && dock_node->HostWindow ==
g.ActiveIdWindow);
8461 if (
g.ActiveId != 0 &&
g.ActiveIdWindow &&
g.ActiveIdWindow->RootWindow != focus_front_window)
8462 if (!
g.ActiveIdNoClearOnFocusLoss && !active_id_window_is_dock_node_host)
8468 window->LastFrameJustFocused =
g.FrameCount;
8476 BringWindowToFocusFront(focus_front_window);
8477 if (((window->Flags | focus_front_window->Flags | display_front_window->Flags) & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
8478 BringWindowToDisplayFront(display_front_window);
8481void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport, ImGuiFocusRequestFlags flags)
8484 int start_idx =
g.WindowsFocusOrder.Size - 1;
8485 if (under_this_window != NULL)
8489 while (under_this_window->Flags & ImGuiWindowFlags_ChildWindow)
8491 under_this_window = under_this_window->ParentWindow;
8494 start_idx = FindWindowFocusIndex(under_this_window) + offset;
8496 for (
int i = start_idx; i >= 0; i--)
8499 ImGuiWindow* window =
g.WindowsFocusOrder[i];
8500 if (window == ignore_window || !window->WasActive)
8502 if (filter_viewport != NULL && window->Viewport != filter_viewport)
8504 if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
8511 FocusWindow(window, flags);
8515 FocusWindow(NULL, flags);
8519void ImGui::SetCurrentFont(ImFont* font)
8522 IM_ASSERT(font && font->IsLoaded());
8523 IM_ASSERT(font->Scale > 0.0f);
8525 g.FontBaseSize = ImMax(1.0f,
g.IO.FontGlobalScale *
g.Font->FontSize *
g.Font->Scale);
8526 g.FontSize =
g.CurrentWindow ?
g.CurrentWindow->CalcFontSize() : 0.0f;
8527 g.FontScale =
g.FontSize /
g.Font->FontSize;
8529 ImFontAtlas* atlas =
g.Font->ContainerAtlas;
8530 g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel;
8531 g.DrawListSharedData.TexUvLines = atlas->TexUvLines;
8532 g.DrawListSharedData.Font =
g.Font;
8533 g.DrawListSharedData.FontSize =
g.FontSize;
8534 g.DrawListSharedData.FontScale =
g.FontScale;
8544void ImGui::PushFont(ImFont* font)
8548 font = GetDefaultFont();
8549 g.FontStack.push_back(font);
8550 SetCurrentFont(font);
8551 g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID);
8554void ImGui::PopFont()
8557 if (
g.FontStack.Size <= 0)
8559 IM_ASSERT_USER_ERROR(0,
"Calling PopFont() too many times!");
8562 g.FontStack.pop_back();
8563 ImFont* font =
g.FontStack.Size == 0 ? GetDefaultFont() :
g.FontStack.back();
8564 SetCurrentFont(font);
8565 g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID);
8568void ImGui::PushItemFlag(ImGuiItemFlags option,
bool enabled)
8571 ImGuiItemFlags item_flags =
g.CurrentItemFlags;
8572 IM_ASSERT(item_flags ==
g.ItemFlagsStack.back());
8574 item_flags |= option;
8576 item_flags &= ~option;
8577 g.CurrentItemFlags = item_flags;
8578 g.ItemFlagsStack.push_back(item_flags);
8581void ImGui::PopItemFlag()
8584 if (
g.ItemFlagsStack.Size <= 1)
8586 IM_ASSERT_USER_ERROR(0,
"Calling PopItemFlag() too many times!");
8589 g.ItemFlagsStack.pop_back();
8590 g.CurrentItemFlags =
g.ItemFlagsStack.back();
8600void ImGui::BeginDisabled(
bool disabled)
8603 bool was_disabled = (
g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
8604 if (!was_disabled && disabled)
8606 g.DisabledAlphaBackup =
g.Style.Alpha;
8607 g.Style.Alpha *=
g.Style.DisabledAlpha;
8609 if (was_disabled || disabled)
8610 g.CurrentItemFlags |= ImGuiItemFlags_Disabled;
8611 g.ItemFlagsStack.push_back(
g.CurrentItemFlags);
8612 g.DisabledStackSize++;
8615void ImGui::EndDisabled()
8618 if (
g.DisabledStackSize <= 0)
8620 IM_ASSERT_USER_ERROR(0,
"Calling EndDisabled() too many times!");
8623 g.DisabledStackSize--;
8624 bool was_disabled = (
g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
8626 g.ItemFlagsStack.pop_back();
8627 g.CurrentItemFlags =
g.ItemFlagsStack.back();
8628 if (was_disabled && (
g.CurrentItemFlags & ImGuiItemFlags_Disabled) == 0)
8629 g.Style.Alpha =
g.DisabledAlphaBackup;
8635void ImGui::BeginDisabledOverrideReenable()
8638 IM_ASSERT(
g.CurrentItemFlags & ImGuiItemFlags_Disabled);
8639 g.Style.Alpha =
g.DisabledAlphaBackup;
8640 g.CurrentItemFlags &= ~ImGuiItemFlags_Disabled;
8641 g.ItemFlagsStack.push_back(
g.CurrentItemFlags);
8642 g.DisabledStackSize++;
8645void ImGui::EndDisabledOverrideReenable()
8648 g.DisabledStackSize--;
8649 IM_ASSERT(
g.DisabledStackSize > 0);
8650 g.ItemFlagsStack.pop_back();
8651 g.CurrentItemFlags =
g.ItemFlagsStack.back();
8652 g.Style.Alpha =
g.DisabledAlphaBackup *
g.Style.DisabledAlpha;
8655void ImGui::PushTextWrapPos(
float wrap_pos_x)
8658 ImGuiWindow* window =
g.CurrentWindow;
8659 window->DC.TextWrapPosStack.push_back(window->DC.TextWrapPos);
8660 window->DC.TextWrapPos = wrap_pos_x;
8663void ImGui::PopTextWrapPos()
8666 ImGuiWindow* window =
g.CurrentWindow;
8667 if (window->DC.TextWrapPosStack.Size <= 0)
8669 IM_ASSERT_USER_ERROR(0,
"Calling PopTextWrapPos() too many times!");
8672 window->DC.TextWrapPos = window->DC.TextWrapPosStack.back();
8673 window->DC.TextWrapPosStack.pop_back();
8676static ImGuiWindow* GetCombinedRootWindow(ImGuiWindow* window,
bool popup_hierarchy,
bool dock_hierarchy)
8678 ImGuiWindow* last_window = NULL;
8679 while (last_window != window)
8681 last_window = window;
8682 window = window->RootWindow;
8683 if (popup_hierarchy)
8684 window = window->RootWindowPopupTree;
8686 window = window->RootWindowDockTree;
8691bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent,
bool popup_hierarchy,
bool dock_hierarchy)
8693 ImGuiWindow* window_root = GetCombinedRootWindow(window, popup_hierarchy, dock_hierarchy);
8694 if (window_root == potential_parent)
8696 while (window != NULL)
8698 if (window == potential_parent)
8700 if (window == window_root)
8702 window = window->ParentWindow;
8707bool ImGui::IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent)
8709 if (window->RootWindow == potential_parent)
8711 while (window != NULL)
8713 if (window == potential_parent)
8715 window = window->ParentWindowInBeginStack;
8720bool ImGui::IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below)
8725 const int display_layer_delta = GetWindowDisplayLayer(potential_above) - GetWindowDisplayLayer(potential_below);
8726 if (display_layer_delta != 0)
8727 return display_layer_delta > 0;
8729 for (
int i =
g.Windows.Size - 1; i >= 0; i--)
8731 ImGuiWindow* candidate_window =
g.Windows[i];
8732 if (candidate_window == potential_above)
8734 if (candidate_window == potential_below)
8744bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
8747 IM_ASSERT_USER_ERROR((flags & ~ImGuiHoveredFlags_AllowedMaskForIsWindowHovered) == 0,
"Invalid flags for IsWindowHovered()!");
8749 ImGuiWindow* ref_window =
g.HoveredWindow;
8750 ImGuiWindow* cur_window =
g.CurrentWindow;
8751 if (ref_window == NULL)
8754 if ((flags & ImGuiHoveredFlags_AnyWindow) == 0)
8756 IM_ASSERT(cur_window);
8757 const bool popup_hierarchy = (flags & ImGuiHoveredFlags_NoPopupHierarchy) == 0;
8758 const bool dock_hierarchy = (flags & ImGuiHoveredFlags_DockHierarchy) != 0;
8759 if (flags & ImGuiHoveredFlags_RootWindow)
8760 cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy, dock_hierarchy);
8763 if (flags & ImGuiHoveredFlags_ChildWindows)
8764 result = IsWindowChildOf(ref_window, cur_window, popup_hierarchy, dock_hierarchy);
8766 result = (ref_window == cur_window);
8771 if (!IsWindowContentHoverable(ref_window, flags))
8773 if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
8774 if (
g.ActiveId != 0 && !
g.ActiveIdAllowOverlap &&
g.ActiveId != ref_window->MoveId)
8782 if (flags & ImGuiHoveredFlags_ForTooltip)
8783 flags = ApplyHoverFlagsForTooltip(flags,
g.Style.HoverFlagsForTooltipMouse);
8784 if ((flags & ImGuiHoveredFlags_Stationary) != 0 &&
g.HoverWindowUnlockedStationaryId != ref_window->ID)
8790bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags)
8793 ImGuiWindow* ref_window =
g.NavWindow;
8794 ImGuiWindow* cur_window =
g.CurrentWindow;
8796 if (ref_window == NULL)
8798 if (flags & ImGuiFocusedFlags_AnyWindow)
8801 IM_ASSERT(cur_window);
8802 const bool popup_hierarchy = (flags & ImGuiFocusedFlags_NoPopupHierarchy) == 0;
8803 const bool dock_hierarchy = (flags & ImGuiFocusedFlags_DockHierarchy) != 0;
8804 if (flags & ImGuiHoveredFlags_RootWindow)
8805 cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy, dock_hierarchy);
8807 if (flags & ImGuiHoveredFlags_ChildWindows)
8808 return IsWindowChildOf(ref_window, cur_window, popup_hierarchy, dock_hierarchy);
8810 return (ref_window == cur_window);
8813ImGuiID ImGui::GetWindowDockID()
8816 return g.CurrentWindow->DockId;
8819bool ImGui::IsWindowDocked()
8822 return g.CurrentWindow->DockIsActive;
8828bool ImGui::IsWindowNavFocusable(ImGuiWindow* window)
8830 return window->WasActive && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
8833float ImGui::GetWindowWidth()
8835 ImGuiWindow* window =
GImGui->CurrentWindow;
8836 return window->Size.x;
8839float ImGui::GetWindowHeight()
8841 ImGuiWindow* window =
GImGui->CurrentWindow;
8842 return window->Size.y;
8845ImVec2 ImGui::GetWindowPos()
8848 ImGuiWindow* window =
g.CurrentWindow;
8852void ImGui::SetWindowPos(ImGuiWindow* window,
const ImVec2& pos, ImGuiCond cond)
8855 if (cond && (window->SetWindowPosAllowFlags & cond) == 0)
8858 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
8859 window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
8860 window->SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX);
8863 const ImVec2 old_pos = window->Pos;
8864 window->Pos = ImTrunc(pos);
8865 ImVec2 offset = window->Pos - old_pos;
8866 if (offset.x == 0.0f && offset.y == 0.0f)
8868 MarkIniSettingsDirty(window);
8870 window->DC.CursorPos += offset;
8871 window->DC.CursorMaxPos += offset;
8872 window->DC.IdealMaxPos += offset;
8873 window->DC.CursorStartPos += offset;
8876void ImGui::SetWindowPos(
const ImVec2& pos, ImGuiCond cond)
8878 ImGuiWindow* window = GetCurrentWindowRead();
8879 SetWindowPos(window, pos, cond);
8882void ImGui::SetWindowPos(
const char* name,
const ImVec2& pos, ImGuiCond cond)
8884 if (ImGuiWindow* window = FindWindowByName(name))
8885 SetWindowPos(window, pos, cond);
8888ImVec2 ImGui::GetWindowSize()
8890 ImGuiWindow* window = GetCurrentWindowRead();
8891 return window->Size;
8894void ImGui::SetWindowSize(ImGuiWindow* window,
const ImVec2& size, ImGuiCond cond)
8897 if (cond && (window->SetWindowSizeAllowFlags & cond) == 0)
8900 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
8901 window->SetWindowSizeAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
8904 if ((window->Flags & ImGuiWindowFlags_ChildWindow) == 0 || window->Appearing || (window->ChildFlags & ImGuiChildFlags_AlwaysAutoResize) != 0)
8905 window->AutoFitFramesX = (
size.x <= 0.0f) ? 2 : 0;
8906 if ((window->Flags & ImGuiWindowFlags_ChildWindow) == 0 || window->Appearing || (window->ChildFlags & ImGuiChildFlags_AlwaysAutoResize) != 0)
8907 window->AutoFitFramesY = (
size.y <= 0.0f) ? 2 : 0;
8910 ImVec2 old_size = window->SizeFull;
8912 window->AutoFitOnlyGrows =
false;
8914 window->SizeFull.x = IM_TRUNC(
size.x);
8916 window->AutoFitOnlyGrows =
false;
8918 window->SizeFull.y = IM_TRUNC(
size.y);
8919 if (old_size.x != window->SizeFull.x || old_size.y != window->SizeFull.y)
8920 MarkIniSettingsDirty(window);
8923void ImGui::SetWindowSize(
const ImVec2& size, ImGuiCond cond)
8925 SetWindowSize(
GImGui->CurrentWindow, size, cond);
8928void ImGui::SetWindowSize(
const char* name,
const ImVec2& size, ImGuiCond cond)
8930 if (ImGuiWindow* window = FindWindowByName(name))
8931 SetWindowSize(window, size, cond);
8934void ImGui::SetWindowCollapsed(ImGuiWindow* window,
bool collapsed, ImGuiCond cond)
8937 if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0)
8939 window->SetWindowCollapsedAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
8942 window->Collapsed = collapsed;
8945void ImGui::SetWindowHitTestHole(ImGuiWindow* window,
const ImVec2& pos,
const ImVec2& size)
8947 IM_ASSERT(window->HitTestHoleSize.x == 0);
8948 window->HitTestHoleSize = ImVec2ih(size);
8949 window->HitTestHoleOffset = ImVec2ih(pos - window->Pos);
8952void ImGui::SetWindowHiddenAndSkipItemsForCurrentFrame(ImGuiWindow* window)
8954 window->Hidden = window->SkipItems =
true;
8955 window->HiddenFramesCanSkipItems = 1;
8958void ImGui::SetWindowCollapsed(
bool collapsed, ImGuiCond cond)
8960 SetWindowCollapsed(
GImGui->CurrentWindow, collapsed, cond);
8963bool ImGui::IsWindowCollapsed()
8965 ImGuiWindow* window = GetCurrentWindowRead();
8966 return window->Collapsed;
8969bool ImGui::IsWindowAppearing()
8971 ImGuiWindow* window = GetCurrentWindowRead();
8972 return window->Appearing;
8975void ImGui::SetWindowCollapsed(
const char* name,
bool collapsed, ImGuiCond cond)
8977 if (ImGuiWindow* window = FindWindowByName(name))
8978 SetWindowCollapsed(window, collapsed, cond);
8981void ImGui::SetWindowFocus()
8983 FocusWindow(
GImGui->CurrentWindow);
8986void ImGui::SetWindowFocus(
const char* name)
8990 if (ImGuiWindow* window = FindWindowByName(name))
8991 FocusWindow(window);
8999void ImGui::SetNextWindowPos(
const ImVec2& pos, ImGuiCond cond,
const ImVec2& pivot)
9002 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
9003 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasPos;
9004 g.NextWindowData.PosVal = pos;
9005 g.NextWindowData.PosPivotVal = pivot;
9006 g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always;
9007 g.NextWindowData.PosUndock =
true;
9010void ImGui::SetNextWindowSize(
const ImVec2& size, ImGuiCond cond)
9013 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
9014 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSize;
9015 g.NextWindowData.SizeVal =
size;
9016 g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always;
9023void ImGui::SetNextWindowSizeConstraints(
const ImVec2& size_min,
const ImVec2& size_max, ImGuiSizeCallback custom_callback,
void* custom_callback_user_data)
9026 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint;
9027 g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max);
9028 g.NextWindowData.SizeCallback = custom_callback;
9029 g.NextWindowData.SizeCallbackUserData = custom_callback_user_data;
9034void ImGui::SetNextWindowContentSize(
const ImVec2& size)
9037 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasContentSize;
9038 g.NextWindowData.ContentSizeVal = ImTrunc(size);
9041void ImGui::SetNextWindowScroll(
const ImVec2& scroll)
9044 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasScroll;
9045 g.NextWindowData.ScrollVal = scroll;
9048void ImGui::SetNextWindowCollapsed(
bool collapsed, ImGuiCond cond)
9051 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
9052 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasCollapsed;
9053 g.NextWindowData.CollapsedVal = collapsed;
9054 g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always;
9057void ImGui::SetNextWindowFocus()
9060 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus;
9063void ImGui::SetNextWindowBgAlpha(
float alpha)
9066 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasBgAlpha;
9067 g.NextWindowData.BgAlphaVal = alpha;
9070void ImGui::SetNextWindowViewport(ImGuiID
id)
9073 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasViewport;
9074 g.NextWindowData.ViewportId =
id;
9077void ImGui::SetNextWindowDockID(ImGuiID
id, ImGuiCond cond)
9080 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasDock;
9081 g.NextWindowData.DockCond = cond ? cond : ImGuiCond_Always;
9082 g.NextWindowData.DockId =
id;
9085void ImGui::SetNextWindowClass(
const ImGuiWindowClass* window_class)
9088 IM_ASSERT((window_class->ViewportFlagsOverrideSet & window_class->ViewportFlagsOverrideClear) == 0);
9089 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasWindowClass;
9090 g.NextWindowData.WindowClass = *window_class;
9094void ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags)
9097 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasRefreshPolicy;
9098 g.NextWindowData.RefreshFlagsVal = flags;
9101ImDrawList* ImGui::GetWindowDrawList()
9103 ImGuiWindow* window = GetCurrentWindow();
9104 return window->DrawList;
9107float ImGui::GetWindowDpiScale()
9110 return g.CurrentDpiScale;
9113ImGuiViewport* ImGui::GetWindowViewport()
9116 IM_ASSERT(
g.CurrentViewport != NULL &&
g.CurrentViewport ==
g.CurrentWindow->Viewport);
9117 return g.CurrentViewport;
9120ImFont* ImGui::GetFont()
9125float ImGui::GetFontSize()
9130ImVec2 ImGui::GetFontTexUvWhitePixel()
9132 return GImGui->DrawListSharedData.TexUvWhitePixel;
9135void ImGui::SetWindowFontScale(
float scale)
9137 IM_ASSERT(scale > 0.0f);
9139 ImGuiWindow* window = GetCurrentWindow();
9140 window->FontWindowScale =
scale;
9141 g.FontSize =
g.DrawListSharedData.FontSize = window->CalcFontSize();
9142 g.FontScale =
g.DrawListSharedData.FontScale =
g.FontSize /
g.Font->FontSize;
9145void ImGui::PushFocusScope(ImGuiID
id)
9148 ImGuiFocusScopeData data;
9150 data.WindowID =
g.CurrentWindow->ID;
9151 g.FocusScopeStack.push_back(data);
9152 g.CurrentFocusScopeId =
id;
9155void ImGui::PopFocusScope()
9158 if (
g.FocusScopeStack.Size <=
g.StackSizesInBeginForCurrentWindow->SizeOfFocusScopeStack)
9160 IM_ASSERT_USER_ERROR(0,
"Calling PopFocusScope() too many times!");
9163 g.FocusScopeStack.pop_back();
9164 g.CurrentFocusScopeId =
g.FocusScopeStack.Size ?
g.FocusScopeStack.back().ID : 0;
9167void ImGui::SetNavFocusScope(ImGuiID focus_scope_id)
9170 g.NavFocusScopeId = focus_scope_id;
9171 g.NavFocusRoute.resize(0);
9172 if (focus_scope_id == 0)
9174 IM_ASSERT(
g.NavWindow != NULL);
9177 if (focus_scope_id ==
g.CurrentFocusScopeId)
9180 for (
int n =
g.FocusScopeStack.Size - 1; n >= 0 &&
g.FocusScopeStack.Data[n].WindowID ==
g.CurrentWindow->ID; n--)
9181 g.NavFocusRoute.push_back(
g.FocusScopeStack.Data[n]);
9183 else if (focus_scope_id ==
g.NavWindow->NavRootFocusScopeId)
9184 g.NavFocusRoute.push_back({ focus_scope_id,
g.NavWindow->ID });
9189 for (ImGuiWindow* window =
g.NavWindow->ParentWindowForFocusRoute; window != NULL; window = window->ParentWindowForFocusRoute)
9190 g.NavFocusRoute.push_back({ window->NavRootFocusScopeId, window->ID });
9191 IM_ASSERT(
g.NavFocusRoute.Size < 100);
9195void ImGui::FocusItem()
9198 ImGuiWindow* window =
g.CurrentWindow;
9199 IMGUI_DEBUG_LOG_FOCUS(
"FocusItem(0x%08x) in window \"%s\"\n",
g.LastItemData.ID, window->Name);
9200 if (
g.DragDropActive ||
g.MovingWindow != NULL)
9202 IMGUI_DEBUG_LOG_FOCUS(
"FocusItem() ignored while DragDropActive!\n");
9206 ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavCursorVisible | ImGuiNavMoveFlags_NoSelect;
9207 ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
9208 SetNavWindow(window);
9209 NavMoveRequestSubmit(ImGuiDir_None, ImGuiDir_Up, move_flags, scroll_flags);
9210 NavMoveRequestResolveWithLastItem(&
g.NavMoveResultLocal);
9213void ImGui::ActivateItemByID(ImGuiID
id)
9216 g.NavNextActivateId =
id;
9217 g.NavNextActivateFlags = ImGuiActivateFlags_None;
9222void ImGui::SetKeyboardFocusHere(
int offset)
9225 ImGuiWindow* window =
g.CurrentWindow;
9226 IM_ASSERT(offset >= -1);
9227 IMGUI_DEBUG_LOG_FOCUS(
"SetKeyboardFocusHere(%d) in window \"%s\"\n", offset, window->Name);
9233 if (
g.DragDropActive ||
g.MovingWindow != NULL)
9235 IMGUI_DEBUG_LOG_FOCUS(
"SetKeyboardFocusHere() ignored while DragDropActive!\n");
9239 SetNavWindow(window);
9241 ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavCursorVisible;
9242 ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
9243 NavMoveRequestSubmit(ImGuiDir_None, offset < 0 ? ImGuiDir_Up : ImGuiDir_Down, move_flags, scroll_flags);
9246 NavMoveRequestResolveWithLastItem(&
g.NavMoveResultLocal);
9250 g.NavTabbingDir = 1;
9251 g.NavTabbingCounter = offset + 1;
9255void ImGui::SetItemDefaultFocus()
9258 ImGuiWindow* window =
g.CurrentWindow;
9259 if (!window->Appearing)
9261 if (
g.NavWindow != window->RootWindowForNav || (!
g.NavInitRequest &&
g.NavInitResult.ID == 0) ||
g.NavLayer != window->DC.NavLayerCurrent)
9264 g.NavInitRequest =
false;
9265 NavApplyItemToResult(&
g.NavInitResult);
9266 NavUpdateAnyRequestFlag();
9269 if (!window->ClipRect.Contains(
g.LastItemData.Rect))
9270 ScrollToRectEx(window,
g.LastItemData.Rect, ImGuiScrollFlags_None);
9273void ImGui::SetStateStorage(ImGuiStorage* tree)
9275 ImGuiWindow* window =
GImGui->CurrentWindow;
9276 window->DC.StateStorage = tree ? tree : &window->StateStorage;
9279ImGuiStorage* ImGui::GetStateStorage()
9281 ImGuiWindow* window =
GImGui->CurrentWindow;
9282 return window->DC.StateStorage;
9285bool ImGui::IsRectVisible(
const ImVec2& size)
9287 ImGuiWindow* window =
GImGui->CurrentWindow;
9288 return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size));
9291bool ImGui::IsRectVisible(
const ImVec2& rect_min,
const ImVec2& rect_max)
9293 ImGuiWindow* window =
GImGui->CurrentWindow;
9294 return window->ClipRect.Overlaps(ImRect(rect_min, rect_max));
9303IM_MSVC_RUNTIME_CHECKS_OFF
9304ImGuiID ImGuiWindow::GetID(
const char* str,
const char* str_end)
9306 ImGuiID seed = IDStack.back();
9307 ImGuiID
id =
ImHashStr(str, str_end ? (str_end - str) : 0, seed);
9308#ifndef IMGUI_DISABLE_DEBUG_TOOLS
9309 ImGuiContext&
g = *Ctx;
9310 if (
g.DebugHookIdInfo ==
id)
9311 ImGui::DebugHookIdInfo(
id, ImGuiDataType_String, str, str_end);
9316ImGuiID ImGuiWindow::GetID(
const void* ptr)
9318 ImGuiID seed = IDStack.back();
9319 ImGuiID
id =
ImHashData(&ptr,
sizeof(
void*), seed);
9320#ifndef IMGUI_DISABLE_DEBUG_TOOLS
9321 ImGuiContext&
g = *Ctx;
9322 if (
g.DebugHookIdInfo ==
id)
9323 ImGui::DebugHookIdInfo(
id, ImGuiDataType_Pointer, ptr, NULL);
9328ImGuiID ImGuiWindow::GetID(
int n)
9330 ImGuiID seed = IDStack.back();
9331 ImGuiID
id =
ImHashData(&n,
sizeof(n), seed);
9332#ifndef IMGUI_DISABLE_DEBUG_TOOLS
9333 ImGuiContext&
g = *Ctx;
9334 if (
g.DebugHookIdInfo ==
id)
9335 ImGui::DebugHookIdInfo(
id, ImGuiDataType_S32, (
void*)(intptr_t)n, NULL);
9342ImGuiID ImGuiWindow::GetIDFromPos(
const ImVec2& p_abs)
9344 ImGuiID seed = IDStack.back();
9345 ImVec2 p_rel = ImGui::WindowPosAbsToRel(
this, p_abs);
9346 ImGuiID
id =
ImHashData(&p_rel,
sizeof(p_rel), seed);
9351ImGuiID ImGuiWindow::GetIDFromRectangle(
const ImRect& r_abs)
9353 ImGuiID seed = IDStack.back();
9354 ImRect r_rel = ImGui::WindowRectAbsToRel(
this, r_abs);
9355 ImGuiID
id =
ImHashData(&r_rel,
sizeof(r_rel), seed);
9359void ImGui::PushID(
const char* str_id)
9362 ImGuiWindow* window =
g.CurrentWindow;
9363 ImGuiID
id = window->GetID(str_id);
9364 window->IDStack.push_back(
id);
9367void ImGui::PushID(
const char* str_id_begin,
const char* str_id_end)
9370 ImGuiWindow* window =
g.CurrentWindow;
9371 ImGuiID
id = window->GetID(str_id_begin, str_id_end);
9372 window->IDStack.push_back(
id);
9375void ImGui::PushID(
const void* ptr_id)
9378 ImGuiWindow* window =
g.CurrentWindow;
9379 ImGuiID
id = window->GetID(ptr_id);
9380 window->IDStack.push_back(
id);
9383void ImGui::PushID(
int int_id)
9386 ImGuiWindow* window =
g.CurrentWindow;
9387 ImGuiID
id = window->GetID(int_id);
9388 window->IDStack.push_back(
id);
9392void ImGui::PushOverrideID(ImGuiID
id)
9395 ImGuiWindow* window =
g.CurrentWindow;
9396#ifndef IMGUI_DISABLE_DEBUG_TOOLS
9397 if (
g.DebugHookIdInfo ==
id)
9398 DebugHookIdInfo(
id, ImGuiDataType_ID, NULL, NULL);
9400 window->IDStack.push_back(
id);
9406ImGuiID ImGui::GetIDWithSeed(
const char* str,
const char* str_end, ImGuiID seed)
9408 ImGuiID
id =
ImHashStr(str, str_end ? (str_end - str) : 0, seed);
9409#ifndef IMGUI_DISABLE_DEBUG_TOOLS
9411 if (
g.DebugHookIdInfo ==
id)
9412 DebugHookIdInfo(
id, ImGuiDataType_String, str, str_end);
9417ImGuiID ImGui::GetIDWithSeed(
int n, ImGuiID seed)
9419 ImGuiID
id =
ImHashData(&n,
sizeof(n), seed);
9420#ifndef IMGUI_DISABLE_DEBUG_TOOLS
9422 if (
g.DebugHookIdInfo ==
id)
9423 DebugHookIdInfo(
id, ImGuiDataType_S32, (
void*)(intptr_t)n, NULL);
9430 ImGuiWindow* window =
GImGui->CurrentWindow;
9431 if (window->IDStack.Size <= 1)
9433 IM_ASSERT_USER_ERROR(0,
"Calling PopID() too many times!");
9436 window->IDStack.pop_back();
9439ImGuiID ImGui::GetID(
const char* str_id)
9441 ImGuiWindow* window =
GImGui->CurrentWindow;
9442 return window->GetID(str_id);
9445ImGuiID ImGui::GetID(
const char* str_id_begin,
const char* str_id_end)
9447 ImGuiWindow* window =
GImGui->CurrentWindow;
9448 return window->GetID(str_id_begin, str_id_end);
9451ImGuiID ImGui::GetID(
const void* ptr_id)
9453 ImGuiWindow* window =
GImGui->CurrentWindow;
9454 return window->GetID(ptr_id);
9457ImGuiID ImGui::GetID(
int int_id)
9459 ImGuiWindow* window =
GImGui->CurrentWindow;
9460 return window->GetID(int_id);
9462IM_MSVC_RUNTIME_CHECKS_RESTORE
9530static ImGuiKeyChord GetModForLRModKey(ImGuiKey key)
9532 if (key == ImGuiKey_LeftCtrl || key == ImGuiKey_RightCtrl)
9533 return ImGuiMod_Ctrl;
9534 if (key == ImGuiKey_LeftShift || key == ImGuiKey_RightShift)
9535 return ImGuiMod_Shift;
9536 if (key == ImGuiKey_LeftAlt || key == ImGuiKey_RightAlt)
9537 return ImGuiMod_Alt;
9538 if (key == ImGuiKey_LeftSuper || key == ImGuiKey_RightSuper)
9539 return ImGuiMod_Super;
9540 return ImGuiMod_None;
9543ImGuiKeyChord ImGui::FixupKeyChord(ImGuiKeyChord key_chord)
9546 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
9547 if (IsLRModKey(key))
9548 key_chord |= GetModForLRModKey(key);
9552ImGuiKeyData* ImGui::GetKeyData(ImGuiContext* ctx, ImGuiKey key)
9554 ImGuiContext&
g = *ctx;
9557 if (key & ImGuiMod_Mask_)
9558 key = ConvertSingleModFlagToKey(key);
9560#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
9561 IM_ASSERT(key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_NamedKey_END);
9562 if (IsLegacyKey(key) &&
g.IO.KeyMap[key] != -1)
9563 key = (ImGuiKey)
g.IO.KeyMap[key];
9565 IM_ASSERT(IsNamedKey(key) &&
"Support for user key indices was dropped in favor of ImGuiKey. Please update backend & user code.");
9567 return &
g.IO.KeysData[key - ImGuiKey_KeysData_OFFSET];
9570#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
9572ImGuiKey ImGui::GetKeyIndex(ImGuiKey key)
9575 IM_ASSERT(IsNamedKey(key));
9576 const ImGuiKeyData* key_data = GetKeyData(key);
9577 return (ImGuiKey)(key_data -
g.IO.KeysData);
9582static const char*
const GKeyNames[] =
9584 "Tab",
"LeftArrow",
"RightArrow",
"UpArrow",
"DownArrow",
"PageUp",
"PageDown",
9585 "Home",
"End",
"Insert",
"Delete",
"Backspace",
"Space",
"Enter",
"Escape",
9586 "LeftCtrl",
"LeftShift",
"LeftAlt",
"LeftSuper",
"RightCtrl",
"RightShift",
"RightAlt",
"RightSuper",
"Menu",
9587 "0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
9588 "I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
9589 "F1",
"F2",
"F3",
"F4",
"F5",
"F6",
"F7",
"F8",
"F9",
"F10",
"F11",
"F12",
9590 "F13",
"F14",
"F15",
"F16",
"F17",
"F18",
"F19",
"F20",
"F21",
"F22",
"F23",
"F24",
9591 "Apostrophe",
"Comma",
"Minus",
"Period",
"Slash",
"Semicolon",
"Equal",
"LeftBracket",
9592 "Backslash",
"RightBracket",
"GraveAccent",
"CapsLock",
"ScrollLock",
"NumLock",
"PrintScreen",
9593 "Pause",
"Keypad0",
"Keypad1",
"Keypad2",
"Keypad3",
"Keypad4",
"Keypad5",
"Keypad6",
9594 "Keypad7",
"Keypad8",
"Keypad9",
"KeypadDecimal",
"KeypadDivide",
"KeypadMultiply",
9595 "KeypadSubtract",
"KeypadAdd",
"KeypadEnter",
"KeypadEqual",
9596 "AppBack",
"AppForward",
9597 "GamepadStart",
"GamepadBack",
9598 "GamepadFaceLeft",
"GamepadFaceRight",
"GamepadFaceUp",
"GamepadFaceDown",
9599 "GamepadDpadLeft",
"GamepadDpadRight",
"GamepadDpadUp",
"GamepadDpadDown",
9600 "GamepadL1",
"GamepadR1",
"GamepadL2",
"GamepadR2",
"GamepadL3",
"GamepadR3",
9601 "GamepadLStickLeft",
"GamepadLStickRight",
"GamepadLStickUp",
"GamepadLStickDown",
9602 "GamepadRStickLeft",
"GamepadRStickRight",
"GamepadRStickUp",
"GamepadRStickDown",
9603 "MouseLeft",
"MouseRight",
"MouseMiddle",
"MouseX1",
"MouseX2",
"MouseWheelX",
"MouseWheelY",
9604 "ModCtrl",
"ModShift",
"ModAlt",
"ModSuper",
9608const char* ImGui::GetKeyName(ImGuiKey key)
9610 if (key == ImGuiKey_None)
9612#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
9613 IM_ASSERT(IsNamedKeyOrMod(key) &&
"Support for user key indices was dropped in favor of ImGuiKey. Please update backend and user code.");
9616 if (IsLegacyKey(key))
9618 if (
g.IO.KeyMap[key] == -1)
9620 IM_ASSERT(IsNamedKey((ImGuiKey)
g.IO.KeyMap[key]));
9621 key = (ImGuiKey)
g.IO.KeyMap[key];
9624 if (key & ImGuiMod_Mask_)
9625 key = ConvertSingleModFlagToKey(key);
9626 if (!IsNamedKey(key))
9629 return GKeyNames[key - ImGuiKey_NamedKey_BEGIN];
9634const char* ImGui::GetKeyChordName(ImGuiKeyChord key_chord)
9638 const ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
9639 if (IsLRModKey(key))
9640 key_chord &= ~GetModForLRModKey(key);
9641 ImFormatString(
g.TempKeychordName, IM_ARRAYSIZE(
g.TempKeychordName),
"%s%s%s%s%s",
9642 (key_chord & ImGuiMod_Ctrl) ?
"Ctrl+" :
"",
9643 (key_chord & ImGuiMod_Shift) ?
"Shift+" :
"",
9644 (key_chord & ImGuiMod_Alt) ?
"Alt+" :
"",
9645 (key_chord & ImGuiMod_Super) ?
"Super+" :
"",
9646 (key != ImGuiKey_None || key_chord == ImGuiKey_None) ? GetKeyName(key) :
"");
9648 if (key == ImGuiKey_None && key_chord != 0)
9649 if ((len = strlen(
g.TempKeychordName)) != 0)
9650 g.TempKeychordName[len - 1] = 0;
9651 return g.TempKeychordName;
9658int ImGui::CalcTypematicRepeatAmount(
float t0,
float t1,
float repeat_delay,
float repeat_rate)
9664 if (repeat_rate <= 0.0f)
9665 return (t0 < repeat_delay) && (t1 >= repeat_delay);
9666 const int count_t0 = (t0 < repeat_delay) ? -1 : (int)((t0 - repeat_delay) / repeat_rate);
9667 const int count_t1 = (t1 < repeat_delay) ? -1 : (int)((t1 - repeat_delay) / repeat_rate);
9668 const int count = count_t1 - count_t0;
9672void ImGui::GetTypematicRepeatRate(ImGuiInputFlags flags,
float* repeat_delay,
float* repeat_rate)
9675 switch (flags & ImGuiInputFlags_RepeatRateMask_)
9677 case ImGuiInputFlags_RepeatRateNavMove: *repeat_delay =
g.IO.KeyRepeatDelay * 0.72f; *repeat_rate =
g.IO.KeyRepeatRate * 0.80f;
return;
9678 case ImGuiInputFlags_RepeatRateNavTweak: *repeat_delay =
g.IO.KeyRepeatDelay * 0.72f; *repeat_rate =
g.IO.KeyRepeatRate * 0.30f;
return;
9679 case ImGuiInputFlags_RepeatRateDefault:
default: *repeat_delay =
g.IO.KeyRepeatDelay * 1.00f; *repeat_rate =
g.IO.KeyRepeatRate * 1.00f;
return;
9685int ImGui::GetKeyPressedAmount(ImGuiKey key,
float repeat_delay,
float repeat_rate)
9688 const ImGuiKeyData* key_data = GetKeyData(key);
9689 if (!key_data->Down)
9691 const float t = key_data->DownDuration;
9692 return CalcTypematicRepeatAmount(
t -
g.IO.DeltaTime,
t, repeat_delay, repeat_rate);
9696ImVec2 ImGui::GetKeyMagnitude2d(ImGuiKey key_left, ImGuiKey key_right, ImGuiKey key_up, ImGuiKey key_down)
9699 GetKeyData(key_right)->AnalogValue - GetKeyData(key_left)->AnalogValue,
9700 GetKeyData(key_down)->AnalogValue - GetKeyData(key_up)->AnalogValue);
9707static void ImGui::UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt)
9710 rt->EntriesNext.resize(0);
9711 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
9713 const int new_routing_start_idx = rt->EntriesNext.Size;
9714 ImGuiKeyRoutingData* routing_entry;
9715 for (
int old_routing_idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; old_routing_idx != -1; old_routing_idx = routing_entry->NextEntryIndex)
9717 routing_entry = &rt->Entries[old_routing_idx];
9718 routing_entry->RoutingCurrScore = routing_entry->RoutingNextScore;
9719 routing_entry->RoutingCurr = routing_entry->RoutingNext;
9720 routing_entry->RoutingNext = ImGuiKeyOwner_NoOwner;
9721 routing_entry->RoutingNextScore = 255;
9722 if (routing_entry->RoutingCurr == ImGuiKeyOwner_NoOwner)
9724 rt->EntriesNext.push_back(*routing_entry);
9728 if (routing_entry->Mods ==
g.IO.KeyMods)
9730 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
9731 if (owner_data->OwnerCurr == ImGuiKeyOwner_NoOwner)
9733 owner_data->OwnerCurr = routing_entry->RoutingCurr;
9740 rt->Index[key - ImGuiKey_NamedKey_BEGIN] = (ImGuiKeyRoutingIndex)(new_routing_start_idx < rt->EntriesNext.Size ? new_routing_start_idx : -1);
9741 for (
int n = new_routing_start_idx; n < rt->EntriesNext.Size; n++)
9742 rt->EntriesNext[n].NextEntryIndex = (ImGuiKeyRoutingIndex)((n + 1 < rt->EntriesNext.Size) ? n + 1 : -1);
9744 rt->Entries.swap(rt->EntriesNext);
9748static inline ImGuiID GetRoutingIdFromOwnerId(ImGuiID owner_id)
9751 return (owner_id != ImGuiKeyOwner_NoOwner && owner_id != ImGuiKeyOwner_Any) ? owner_id :
g.CurrentFocusScopeId;
9754ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord)
9763 ImGuiKeyRoutingTable* rt = &
g.KeysRoutingTable;
9764 ImGuiKeyRoutingData* routing_data;
9765 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
9766 ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
9767 if (key == ImGuiKey_None)
9768 key = ConvertSingleModFlagToKey(mods);
9769 IM_ASSERT(IsNamedKey(key));
9773 for (ImGuiKeyRoutingIndex idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; idx != -1; idx = routing_data->NextEntryIndex)
9775 routing_data = &rt->Entries[idx];
9776 if (routing_data->Mods == mods)
9777 return routing_data;
9781 ImGuiKeyRoutingIndex routing_data_idx = (ImGuiKeyRoutingIndex)rt->Entries.Size;
9782 rt->Entries.push_back(ImGuiKeyRoutingData());
9783 routing_data = &rt->Entries[routing_data_idx];
9784 routing_data->Mods = (ImU16)mods;
9785 routing_data->NextEntryIndex = rt->Index[key - ImGuiKey_NamedKey_BEGIN];
9786 rt->Index[key - ImGuiKey_NamedKey_BEGIN] = routing_data_idx;
9787 return routing_data;
9798static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInputFlags flags)
9801 if (flags & ImGuiInputFlags_RouteFocused)
9805 if (owner_id != 0 &&
g.ActiveId == owner_id)
9815 if (focus_scope_id == 0)
9817 for (
int index_in_focus_path = 0; index_in_focus_path <
g.NavFocusRoute.Size; index_in_focus_path++)
9818 if (
g.NavFocusRoute.Data[index_in_focus_path].ID == focus_scope_id)
9819 return 3 + index_in_focus_path;
9822 else if (flags & ImGuiInputFlags_RouteActive)
9824 if (owner_id != 0 &&
g.ActiveId == owner_id)
9828 else if (flags & ImGuiInputFlags_RouteGlobal)
9830 if (flags & ImGuiInputFlags_RouteOverActive)
9832 if (flags & ImGuiInputFlags_RouteOverFocused)
9843static bool IsKeyChordPotentiallyCharInput(ImGuiKeyChord key_chord)
9849 ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
9850 const bool ignore_char_inputs = ((mods & ImGuiMod_Ctrl) && !(mods & ImGuiMod_Alt)) || (
g.IO.ConfigMacOSXBehaviors && (mods & ImGuiMod_Ctrl));
9851 if (ignore_char_inputs)
9855 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
9856 if (key == ImGuiKey_None)
9858 return g.KeysMayBeCharInput.TestBit(key);
9866bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id)
9869 if ((flags & ImGuiInputFlags_RouteTypeMask_) == 0)
9870 flags |= ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive;
9872 IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteTypeMask_));
9873 IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_NoOwner);
9874 if (flags & (ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused))
9875 IM_ASSERT(flags & ImGuiInputFlags_RouteGlobal);
9878 key_chord = FixupKeyChord(key_chord);
9881 if (
g.DebugBreakInShortcutRouting == key_chord)
9884 if (flags & ImGuiInputFlags_RouteUnlessBgFocused)
9885 if (
g.NavWindow == NULL)
9889 if (flags & ImGuiInputFlags_RouteAlways)
9891 IMGUI_DEBUG_LOG_INPUTROUTING(
"SetShortcutRouting(%s, flags=%04X, owner_id=0x%08X) -> always, no register\n", GetKeyChordName(key_chord), flags, owner_id);
9896 if (
g.ActiveId != 0 &&
g.ActiveId != owner_id)
9898 if (flags & ImGuiInputFlags_RouteActive)
9906 if (
g.IO.WantTextInput && IsKeyChordPotentiallyCharInput(key_chord))
9908 IMGUI_DEBUG_LOG_INPUTROUTING(
"SetShortcutRouting(%s, flags=%04X, owner_id=0x%08X) -> filtered as potential char input\n", GetKeyChordName(key_chord), flags, owner_id);
9913 if ((flags & ImGuiInputFlags_RouteOverActive) == 0 &&
g.ActiveIdUsingAllKeyboardKeys)
9915 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
9916 if (key == ImGuiKey_None)
9917 key = ConvertSingleModFlagToKey((ImGuiKey)(key_chord & ImGuiMod_Mask_));
9918 if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END)
9924 ImGuiID focus_scope_id =
g.CurrentFocusScopeId;
9925 if (flags & ImGuiInputFlags_RouteFromRootWindow)
9926 focus_scope_id =
g.CurrentWindow->RootWindow->ID;
9928 const int score = CalcRoutingScore(focus_scope_id, owner_id, flags);
9929 IMGUI_DEBUG_LOG_INPUTROUTING(
"SetShortcutRouting(%s, flags=%04X, owner_id=0x%08X) -> score %d\n", GetKeyChordName(key_chord), flags, owner_id, score);
9935 ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord);
9937 if (score < routing_data->RoutingNextScore)
9939 routing_data->RoutingNext = owner_id;
9940 routing_data->RoutingNextScore = (ImU8)score;
9944 if (routing_data->RoutingCurr == owner_id)
9945 IMGUI_DEBUG_LOG_INPUTROUTING(
"--> granting current route\n");
9946 return routing_data->RoutingCurr == owner_id;
9951bool ImGui::TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id)
9953 const ImGuiID routing_id = GetRoutingIdFromOwnerId(owner_id);
9954 key_chord = FixupKeyChord(key_chord);
9955 ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord);
9956 return routing_data->RoutingCurr == routing_id;
9961bool ImGui::IsKeyDown(ImGuiKey key)
9963 return IsKeyDown(key, ImGuiKeyOwner_Any);
9966bool ImGui::IsKeyDown(ImGuiKey key, ImGuiID owner_id)
9968 const ImGuiKeyData* key_data = GetKeyData(key);
9969 if (!key_data->Down)
9971 if (!TestKeyOwner(key, owner_id))
9976bool ImGui::IsKeyPressed(ImGuiKey key,
bool repeat)
9978 return IsKeyPressed(key,
repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None, ImGuiKeyOwner_Any);
9982bool ImGui::IsKeyPressed(ImGuiKey key, ImGuiInputFlags flags, ImGuiID owner_id)
9984 const ImGuiKeyData* key_data = GetKeyData(key);
9985 if (!key_data->Down)
9987 const float t = key_data->DownDuration;
9990 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsKeyPressed) == 0);
9991 if (flags & (ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_))
9992 flags |= ImGuiInputFlags_Repeat;
9994 bool pressed = (
t == 0.0f);
9995 if (!pressed && (flags & ImGuiInputFlags_Repeat) != 0)
9997 float repeat_delay, repeat_rate;
9998 GetTypematicRepeatRate(flags, &repeat_delay, &repeat_rate);
9999 pressed = (
t > repeat_delay) && GetKeyPressedAmount(key, repeat_delay, repeat_rate) > 0;
10000 if (pressed && (flags & ImGuiInputFlags_RepeatUntilMask_))
10005 double key_pressed_time =
g.Time -
t + 0.00001f;
10006 if ((flags & ImGuiInputFlags_RepeatUntilKeyModsChange) && (
g.LastKeyModsChangeTime > key_pressed_time))
10008 if ((flags & ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone) && (
g.LastKeyModsChangeFromNoneTime > key_pressed_time))
10010 if ((flags & ImGuiInputFlags_RepeatUntilOtherKeyPress) && (
g.LastKeyboardKeyPressTime > key_pressed_time))
10016 if (!TestKeyOwner(key, owner_id))
10021bool ImGui::IsKeyReleased(ImGuiKey key)
10023 return IsKeyReleased(key, ImGuiKeyOwner_Any);
10026bool ImGui::IsKeyReleased(ImGuiKey key, ImGuiID owner_id)
10028 const ImGuiKeyData* key_data = GetKeyData(key);
10029 if (key_data->DownDurationPrev < 0.0f || key_data->Down)
10031 if (!TestKeyOwner(key, owner_id))
10036bool ImGui::IsMouseDown(ImGuiMouseButton button)
10039 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
10040 return g.IO.MouseDown[button] && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any);
10043bool ImGui::IsMouseDown(ImGuiMouseButton button, ImGuiID owner_id)
10046 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
10047 return g.IO.MouseDown[button] && TestKeyOwner(MouseButtonToKey(button), owner_id);
10050bool ImGui::IsMouseClicked(ImGuiMouseButton button,
bool repeat)
10052 return IsMouseClicked(button,
repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None, ImGuiKeyOwner_Any);
10055bool ImGui::IsMouseClicked(ImGuiMouseButton button, ImGuiInputFlags flags, ImGuiID owner_id)
10058 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
10059 if (!
g.IO.MouseDown[button])
10061 const float t =
g.IO.MouseDownDuration[button];
10064 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsMouseClicked) == 0);
10066 const bool repeat = (flags & ImGuiInputFlags_Repeat) != 0;
10067 const bool pressed = (
t == 0.0f) || (
repeat &&
t >
g.IO.KeyRepeatDelay && CalcTypematicRepeatAmount(
t -
g.IO.DeltaTime,
t,
g.IO.KeyRepeatDelay,
g.IO.KeyRepeatRate) > 0);
10071 if (!TestKeyOwner(MouseButtonToKey(button), owner_id))
10077bool ImGui::IsMouseReleased(ImGuiMouseButton button)
10080 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
10081 return g.IO.MouseReleased[button] && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any);
10084bool ImGui::IsMouseReleased(ImGuiMouseButton button, ImGuiID owner_id)
10087 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
10088 return g.IO.MouseReleased[button] && TestKeyOwner(MouseButtonToKey(button), owner_id);
10091bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button)
10094 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
10095 return g.IO.MouseClickedCount[button] == 2 && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any);
10098bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button, ImGuiID owner_id)
10101 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
10102 return g.IO.MouseClickedCount[button] == 2 && TestKeyOwner(MouseButtonToKey(button), owner_id);
10105int ImGui::GetMouseClickedCount(ImGuiMouseButton button)
10108 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
10109 return g.IO.MouseClickedCount[button];
10115bool ImGui::IsMouseHoveringRect(
const ImVec2& r_min,
const ImVec2& r_max,
bool clip)
10120 ImRect rect_clipped(r_min, r_max);
10122 rect_clipped.ClipWith(
g.CurrentWindow->ClipRect);
10125 if (!rect_clipped.ContainsWithPad(
g.IO.MousePos,
g.Style.TouchExtraPadding))
10127 if (!
g.MouseViewport->GetMainRect().Overlaps(rect_clipped))
10134bool ImGui::IsMouseDragPastThreshold(ImGuiMouseButton button,
float lock_threshold)
10137 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
10138 if (lock_threshold < 0.0f)
10139 lock_threshold =
g.IO.MouseDragThreshold;
10140 return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;
10143bool ImGui::IsMouseDragging(ImGuiMouseButton button,
float lock_threshold)
10146 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
10147 if (!
g.IO.MouseDown[button])
10149 return IsMouseDragPastThreshold(button, lock_threshold);
10152ImVec2 ImGui::GetMousePos()
10155 return g.IO.MousePos;
10160void ImGui::TeleportMousePos(
const ImVec2& pos)
10163 g.IO.MousePos =
g.IO.MousePosPrev = pos;
10164 g.IO.MouseDelta = ImVec2(0.0f, 0.0f);
10165 g.IO.WantSetMousePos =
true;
10170ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
10173 if (
g.BeginPopupStack.Size > 0)
10174 return g.OpenPopupStack[
g.BeginPopupStack.Size - 1].OpenMousePos;
10175 return g.IO.MousePos;
10179bool ImGui::IsMousePosValid(
const ImVec2* mouse_pos)
10183 IM_ASSERT(
GImGui != NULL);
10184 const float MOUSE_INVALID = -256000.0f;
10185 ImVec2 p = mouse_pos ? *mouse_pos :
GImGui->IO.MousePos;
10186 return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID;
10190bool ImGui::IsAnyMouseDown()
10193 for (
int n = 0; n < IM_ARRAYSIZE(
g.IO.MouseDown); n++)
10194 if (
g.IO.MouseDown[n])
10202ImVec2 ImGui::GetMouseDragDelta(ImGuiMouseButton button,
float lock_threshold)
10205 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
10206 if (lock_threshold < 0.0f)
10207 lock_threshold =
g.IO.MouseDragThreshold;
10208 if (
g.IO.MouseDown[button] ||
g.IO.MouseReleased[button])
10209 if (
g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold)
10210 if (IsMousePosValid(&
g.IO.MousePos) && IsMousePosValid(&
g.IO.MouseClickedPos[button]))
10211 return g.IO.MousePos -
g.IO.MouseClickedPos[button];
10212 return ImVec2(0.0f, 0.0f);
10215void ImGui::ResetMouseDragDelta(ImGuiMouseButton button)
10218 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
10220 g.IO.MouseClickedPos[button] =
g.IO.MousePos;
10227ImGuiMouseCursor ImGui::GetMouseCursor()
10230 return g.MouseCursor;
10236void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)
10239 g.MouseCursor = cursor_type;
10242static void UpdateAliasKey(ImGuiKey key,
bool v,
float analog_value)
10244 IM_ASSERT(ImGui::IsAliasKey(key));
10245 ImGuiKeyData* key_data = ImGui::GetKeyData(key);
10246 key_data->Down = v;
10247 key_data->AnalogValue = analog_value;
10251static ImGuiKeyChord GetMergedModsFromKeys()
10253 ImGuiKeyChord mods = 0;
10254 if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) { mods |= ImGuiMod_Ctrl; }
10255 if (ImGui::IsKeyDown(ImGuiMod_Shift)) { mods |= ImGuiMod_Shift; }
10256 if (ImGui::IsKeyDown(ImGuiMod_Alt)) { mods |= ImGuiMod_Alt; }
10257 if (ImGui::IsKeyDown(ImGuiMod_Super)) { mods |= ImGuiMod_Super; }
10261static void ImGui::UpdateKeyboardInputs()
10264 ImGuiIO& io =
g.IO;
10266 if (io.ConfigFlags & ImGuiConfigFlags_NoKeyboard)
10267 io.ClearInputKeys();
10270#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
10271 if (io.BackendUsingLegacyKeyArrays == 0)
10274 for (
int n = 0; n < ImGuiKey_LegacyNativeKey_END; n++)
10275 IM_ASSERT((io.KeysDown[n] ==
false || IsKeyDown((ImGuiKey)n)) &&
"Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
10279 if (
g.FrameCount == 0)
10280 for (
int n = ImGuiKey_LegacyNativeKey_BEGIN; n < ImGuiKey_LegacyNativeKey_END; n++)
10281 IM_ASSERT(
g.IO.KeyMap[n] == -1 &&
"Backend is not allowed to write to io.KeyMap[0..511]!");
10284 for (
int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++)
10285 if (io.KeyMap[n] != -1)
10287 IM_ASSERT(IsLegacyKey((ImGuiKey)io.KeyMap[n]));
10288 io.KeyMap[io.KeyMap[n]] = n;
10292 for (
int n = ImGuiKey_LegacyNativeKey_BEGIN; n < ImGuiKey_LegacyNativeKey_END; n++)
10293 if (io.KeysDown[n] || io.BackendUsingLegacyKeyArrays == 1)
10295 const ImGuiKey key = (ImGuiKey)(io.KeyMap[n] != -1 ? io.KeyMap[n] : n);
10296 IM_ASSERT(io.KeyMap[n] == -1 || IsNamedKey(key));
10297 io.KeysData[key].Down = io.KeysDown[n];
10299 io.KeysDown[key] = io.KeysDown[n];
10300 io.BackendUsingLegacyKeyArrays = 1;
10302 if (io.BackendUsingLegacyKeyArrays == 1)
10304 GetKeyData(ImGuiMod_Ctrl)->Down = io.KeyCtrl;
10305 GetKeyData(ImGuiMod_Shift)->Down = io.KeyShift;
10306 GetKeyData(ImGuiMod_Alt)->Down = io.KeyAlt;
10307 GetKeyData(ImGuiMod_Super)->Down = io.KeySuper;
10313#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
10314 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
10315 if (io.BackendUsingLegacyNavInputArray && nav_gamepad_active)
10317 #define MAP_LEGACY_NAV_INPUT_TO_KEY1(_KEY, _NAV1) do { io.KeysData[_KEY].Down = (io.NavInputs[_NAV1] > 0.0f); io.KeysData[_KEY].AnalogValue = io.NavInputs[_NAV1]; } while (0)
10318 #define MAP_LEGACY_NAV_INPUT_TO_KEY2(_KEY, _NAV1, _NAV2) do { io.KeysData[_KEY].Down = (io.NavInputs[_NAV1] > 0.0f) || (io.NavInputs[_NAV2] > 0.0f); io.KeysData[_KEY].AnalogValue = ImMax(io.NavInputs[_NAV1], io.NavInputs[_NAV2]); } while (0)
10319 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceDown, ImGuiNavInput_Activate);
10320 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceRight, ImGuiNavInput_Cancel);
10321 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceLeft, ImGuiNavInput_Menu);
10322 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceUp, ImGuiNavInput_Input);
10323 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadLeft, ImGuiNavInput_DpadLeft);
10324 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadRight, ImGuiNavInput_DpadRight);
10325 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadUp, ImGuiNavInput_DpadUp);
10326 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadDown, ImGuiNavInput_DpadDown);
10327 MAP_LEGACY_NAV_INPUT_TO_KEY2(ImGuiKey_GamepadL1, ImGuiNavInput_FocusPrev, ImGuiNavInput_TweakSlow);
10328 MAP_LEGACY_NAV_INPUT_TO_KEY2(ImGuiKey_GamepadR1, ImGuiNavInput_FocusNext, ImGuiNavInput_TweakFast);
10329 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickLeft, ImGuiNavInput_LStickLeft);
10330 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickRight, ImGuiNavInput_LStickRight);
10331 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickUp, ImGuiNavInput_LStickUp);
10332 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickDown, ImGuiNavInput_LStickDown);
10338 for (
int n = 0; n < ImGuiMouseButton_COUNT; n++)
10339 UpdateAliasKey(MouseButtonToKey(n), io.MouseDown[n], io.MouseDown[n] ? 1.0f : 0.0f);
10340 UpdateAliasKey(ImGuiKey_MouseWheelX, io.MouseWheelH != 0.0f, io.MouseWheelH);
10341 UpdateAliasKey(ImGuiKey_MouseWheelY, io.MouseWheel != 0.0f, io.MouseWheel);
10347 const ImGuiKeyChord prev_key_mods = io.KeyMods;
10348 io.KeyMods = GetMergedModsFromKeys();
10349 io.KeyCtrl = (io.KeyMods & ImGuiMod_Ctrl) != 0;
10350 io.KeyShift = (io.KeyMods & ImGuiMod_Shift) != 0;
10351 io.KeyAlt = (io.KeyMods & ImGuiMod_Alt) != 0;
10352 io.KeySuper = (io.KeyMods & ImGuiMod_Super) != 0;
10353 if (prev_key_mods != io.KeyMods)
10354 g.LastKeyModsChangeTime =
g.Time;
10355 if (prev_key_mods != io.KeyMods && prev_key_mods == 0)
10356 g.LastKeyModsChangeFromNoneTime =
g.Time;
10359 if ((io.BackendFlags & ImGuiBackendFlags_HasGamepad) == 0)
10360 for (
int i = ImGuiKey_Gamepad_BEGIN; i < ImGuiKey_Gamepad_END; i++)
10362 io.KeysData[i - ImGuiKey_KeysData_OFFSET].Down =
false;
10363 io.KeysData[i - ImGuiKey_KeysData_OFFSET].AnalogValue = 0.0f;
10367 for (
int i = 0; i < ImGuiKey_KeysData_SIZE; i++)
10369 ImGuiKeyData* key_data = &io.KeysData[i];
10370 key_data->DownDurationPrev = key_data->DownDuration;
10371 key_data->DownDuration = key_data->Down ? (key_data->DownDuration < 0.0f ? 0.0f : key_data->DownDuration + io.DeltaTime) : -1.0f;
10372 if (key_data->DownDuration == 0.0f)
10374 ImGuiKey key = (ImGuiKey)(ImGuiKey_KeysData_OFFSET + i);
10375 if (IsKeyboardKey(key))
10376 g.LastKeyboardKeyPressTime =
g.Time;
10377 else if (key == ImGuiKey_ReservedForModCtrl || key == ImGuiKey_ReservedForModShift || key == ImGuiKey_ReservedForModAlt || key == ImGuiKey_ReservedForModSuper)
10378 g.LastKeyboardKeyPressTime =
g.Time;
10383 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
10385 ImGuiKeyData* key_data = &io.KeysData[key - ImGuiKey_KeysData_OFFSET];
10386 ImGuiKeyOwnerData* owner_data = &
g.KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN];
10387 owner_data->OwnerCurr = owner_data->OwnerNext;
10388 if (!key_data->Down)
10389 owner_data->OwnerNext = ImGuiKeyOwner_NoOwner;
10390 owner_data->LockThisFrame = owner_data->LockUntilRelease = owner_data->LockUntilRelease && key_data->Down;
10394 UpdateKeyRoutingTable(&
g.KeysRoutingTable);
10397static void ImGui::UpdateMouseInputs()
10400 ImGuiIO& io =
g.IO;
10407 io.MouseWheelRequestAxisSwap = io.KeyShift && !io.ConfigMacOSXBehaviors;
10410 if (IsMousePosValid(&io.MousePos))
10411 io.MousePos =
g.MouseLastValidPos = ImFloor(io.MousePos);
10414 if (IsMousePosValid(&io.MousePos) && IsMousePosValid(&io.MousePosPrev))
10415 io.MouseDelta = io.MousePos - io.MousePosPrev;
10417 io.MouseDelta = ImVec2(0.0f, 0.0f);
10421 const float mouse_stationary_threshold = (io.MouseSource == ImGuiMouseSource_Mouse) ? 2.0f : 3.0f;
10422 const bool mouse_stationary = (ImLengthSqr(io.MouseDelta) <= mouse_stationary_threshold * mouse_stationary_threshold);
10423 g.MouseStationaryTimer = mouse_stationary ? (
g.MouseStationaryTimer + io.DeltaTime) : 0.0f;
10427 if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)
10428 g.NavHighlightItemUnderNav =
false;
10430 for (
int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
10432 io.MouseClicked[i] = io.MouseDown[i] && io.MouseDownDuration[i] < 0.0f;
10433 io.MouseClickedCount[i] = 0;
10434 io.MouseReleased[i] = !io.MouseDown[i] && io.MouseDownDuration[i] >= 0.0f;
10435 io.MouseDownDurationPrev[i] = io.MouseDownDuration[i];
10436 io.MouseDownDuration[i] = io.MouseDown[i] ? (io.MouseDownDuration[i] < 0.0f ? 0.0f : io.MouseDownDuration[i] + io.DeltaTime) : -1.0f;
10437 if (io.MouseClicked[i])
10439 bool is_repeated_click =
false;
10440 if ((
float)(
g.Time - io.MouseClickedTime[i]) < io.MouseDoubleClickTime)
10442 ImVec2 delta_from_click_pos = IsMousePosValid(&io.MousePos) ? (io.MousePos - io.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
10443 if (ImLengthSqr(delta_from_click_pos) < io.MouseDoubleClickMaxDist * io.MouseDoubleClickMaxDist)
10444 is_repeated_click =
true;
10446 if (is_repeated_click)
10447 io.MouseClickedLastCount[i]++;
10449 io.MouseClickedLastCount[i] = 1;
10450 io.MouseClickedTime[i] =
g.Time;
10451 io.MouseClickedPos[i] = io.MousePos;
10452 io.MouseClickedCount[i] = io.MouseClickedLastCount[i];
10453 io.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f);
10454 io.MouseDragMaxDistanceSqr[i] = 0.0f;
10456 else if (io.MouseDown[i])
10459 ImVec2 delta_from_click_pos = IsMousePosValid(&io.MousePos) ? (io.MousePos - io.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
10460 io.MouseDragMaxDistanceSqr[i] = ImMax(io.MouseDragMaxDistanceSqr[i], ImLengthSqr(delta_from_click_pos));
10461 io.MouseDragMaxDistanceAbs[i].x = ImMax(io.MouseDragMaxDistanceAbs[i].x, delta_from_click_pos.x < 0.0f ? -delta_from_click_pos.x : delta_from_click_pos.x);
10462 io.MouseDragMaxDistanceAbs[i].y = ImMax(io.MouseDragMaxDistanceAbs[i].y, delta_from_click_pos.y < 0.0f ? -delta_from_click_pos.y : delta_from_click_pos.y);
10466 io.MouseDoubleClicked[i] = (io.MouseClickedCount[i] == 2);
10469 if (io.MouseClicked[i])
10470 g.NavHighlightItemUnderNav =
false;
10474static void LockWheelingWindow(ImGuiWindow* window,
float wheel_amount)
10478 g.WheelingWindowReleaseTimer = ImMin(
g.WheelingWindowReleaseTimer + ImAbs(wheel_amount) * WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER, WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER);
10480 g.WheelingWindowReleaseTimer = 0.0f;
10481 if (
g.WheelingWindow == window)
10483 IMGUI_DEBUG_LOG_IO(
"[io] LockWheelingWindow() \"%s\"\n", window ? window->Name :
"NULL");
10484 g.WheelingWindow = window;
10485 g.WheelingWindowRefMousePos =
g.IO.MousePos;
10486 if (window == NULL)
10488 g.WheelingWindowStartFrame = -1;
10489 g.WheelingAxisAvg = ImVec2(0.0f, 0.0f);
10493static ImGuiWindow* FindBestWheelingWindow(
const ImVec2& wheel)
10497 ImGuiWindow* windows[2] = { NULL, NULL };
10498 for (
int axis = 0; axis < 2; axis++)
10499 if (wheel[axis] != 0.0f)
10500 for (ImGuiWindow* window = windows[axis] =
g.HoveredWindow; window->Flags & ImGuiWindowFlags_ChildWindow; window = windows[axis] = window->ParentWindow)
10506 const bool has_scrolling = (window->ScrollMax[axis] != 0.0f);
10507 const bool inputs_disabled = (window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs);
10509 if (has_scrolling && !inputs_disabled)
10512 if (windows[0] == NULL && windows[1] == NULL)
10516 if (windows[0] == windows[1] || windows[0] == NULL || windows[1] == NULL)
10517 return windows[1] ? windows[1] : windows[0];
10522 if (
g.WheelingWindowStartFrame == -1)
10523 g.WheelingWindowStartFrame =
g.FrameCount;
10524 if ((
g.WheelingWindowStartFrame ==
g.FrameCount && wheel.x != 0.0f && wheel.y != 0.0f) || (
g.WheelingAxisAvg.x ==
g.WheelingAxisAvg.y))
10526 g.WheelingWindowWheelRemainder = wheel;
10529 return (
g.WheelingAxisAvg.x >
g.WheelingAxisAvg.y) ? windows[0] : windows[1];
10533void ImGui::UpdateMouseWheel()
10538 if (
g.WheelingWindow != NULL)
10540 g.WheelingWindowReleaseTimer -=
g.IO.DeltaTime;
10541 if (IsMousePosValid() && ImLengthSqr(
g.IO.MousePos -
g.WheelingWindowRefMousePos) >
g.IO.MouseDragThreshold *
g.IO.MouseDragThreshold)
10542 g.WheelingWindowReleaseTimer = 0.0f;
10543 if (
g.WheelingWindowReleaseTimer <= 0.0f)
10544 LockWheelingWindow(NULL, 0.0f);
10548 wheel.x = TestKeyOwner(ImGuiKey_MouseWheelX, ImGuiKeyOwner_NoOwner) ?
g.IO.MouseWheelH : 0.0f;
10549 wheel.y = TestKeyOwner(ImGuiKey_MouseWheelY, ImGuiKeyOwner_NoOwner) ?
g.IO.MouseWheel : 0.0f;
10552 ImGuiWindow* mouse_window =
g.WheelingWindow ?
g.WheelingWindow :
g.HoveredWindow;
10553 if (!mouse_window || mouse_window->Collapsed)
10558 if (wheel.y != 0.0f &&
g.IO.KeyCtrl &&
g.IO.FontAllowUserScaling)
10560 LockWheelingWindow(mouse_window, wheel.y);
10561 ImGuiWindow* window = mouse_window;
10562 const float new_font_scale = ImClamp(window->FontWindowScale +
g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
10563 const float scale = new_font_scale / window->FontWindowScale;
10564 window->FontWindowScale = new_font_scale;
10565 if (window == window->RootWindow)
10567 const ImVec2 offset = window->Size * (1.0f -
scale) * (
g.IO.MousePos - window->Pos) / window->Size;
10568 SetWindowPos(window, window->Pos + offset, 0);
10569 window->Size = ImTrunc(window->Size * scale);
10570 window->SizeFull = ImTrunc(window->SizeFull * scale);
10579 if (
g.IO.MouseWheelRequestAxisSwap)
10580 wheel = ImVec2(wheel.y, 0.0f);
10584 g.WheelingAxisAvg.x = ImExponentialMovingAverage(
g.WheelingAxisAvg.x, ImAbs(wheel.x), 30);
10585 g.WheelingAxisAvg.y = ImExponentialMovingAverage(
g.WheelingAxisAvg.y, ImAbs(wheel.y), 30);
10588 wheel +=
g.WheelingWindowWheelRemainder;
10589 g.WheelingWindowWheelRemainder = ImVec2(0.0f, 0.0f);
10590 if (wheel.x == 0.0f && wheel.y == 0.0f)
10596 if (ImGuiWindow* window = (
g.WheelingWindow ?
g.WheelingWindow : FindBestWheelingWindow(wheel)))
10597 if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))
10599 bool do_scroll[2] = { wheel.x != 0.0f && window->ScrollMax.x != 0.0f, wheel.y != 0.0f && window->ScrollMax.y != 0.0f };
10600 if (do_scroll[ImGuiAxis_X] && do_scroll[ImGuiAxis_Y])
10601 do_scroll[(
g.WheelingAxisAvg.x >
g.WheelingAxisAvg.y) ? ImGuiAxis_Y : ImGuiAxis_X] = false;
10602 if (do_scroll[ImGuiAxis_X])
10604 LockWheelingWindow(window, wheel.x);
10605 float max_step = window->InnerRect.GetWidth() * 0.67f;
10606 float scroll_step = ImTrunc(ImMin(2 * window->CalcFontSize(), max_step));
10607 SetScrollX(window, window->Scroll.x - wheel.x * scroll_step);
10608 g.WheelingWindowScrolledFrame =
g.FrameCount;
10610 if (do_scroll[ImGuiAxis_Y])
10612 LockWheelingWindow(window, wheel.y);
10613 float max_step = window->InnerRect.GetHeight() * 0.67f;
10614 float scroll_step = ImTrunc(ImMin(5 * window->CalcFontSize(), max_step));
10615 SetScrollY(window, window->Scroll.y - wheel.y * scroll_step);
10616 g.WheelingWindowScrolledFrame =
g.FrameCount;
10621void ImGui::SetNextFrameWantCaptureKeyboard(
bool want_capture_keyboard)
10624 g.WantCaptureKeyboardNextFrame = want_capture_keyboard ? 1 : 0;
10627void ImGui::SetNextFrameWantCaptureMouse(
bool want_capture_mouse)
10630 g.WantCaptureMouseNextFrame = want_capture_mouse ? 1 : 0;
10633#ifndef IMGUI_DISABLE_DEBUG_TOOLS
10634static const char* GetInputSourceName(ImGuiInputSource source)
10636 const char* input_source_names[] = {
"None",
"Mouse",
"Keyboard",
"Gamepad" };
10637 IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT && source >= 0 && source < ImGuiInputSource_COUNT);
10638 return input_source_names[source];
10640static const char* GetMouseSourceName(ImGuiMouseSource source)
10642 const char* mouse_source_names[] = {
"Mouse",
"TouchScreen",
"Pen" };
10643 IM_ASSERT(IM_ARRAYSIZE(mouse_source_names) == ImGuiMouseSource_COUNT && source >= 0 && source < ImGuiMouseSource_COUNT);
10644 return mouse_source_names[source];
10646static void DebugPrintInputEvent(
const char* prefix,
const ImGuiInputEvent* e)
10649 if (
e->Type == ImGuiInputEventType_MousePos) {
if (
e->MousePos.PosX == -FLT_MAX &&
e->MousePos.PosY == -FLT_MAX) IMGUI_DEBUG_LOG_IO(
"[io] %s: MousePos (-FLT_MAX, -FLT_MAX)\n", prefix);
else IMGUI_DEBUG_LOG_IO(
"[io] %s: MousePos (%.1f, %.1f) (%s)\n", prefix,
e->MousePos.PosX,
e->MousePos.PosY, GetMouseSourceName(
e->MousePos.MouseSource));
return; }
10650 if (
e->Type == ImGuiInputEventType_MouseButton) { IMGUI_DEBUG_LOG_IO(
"[io] %s: MouseButton %d %s (%s)\n", prefix,
e->MouseButton.Button,
e->MouseButton.Down ?
"Down" :
"Up", GetMouseSourceName(
e->MouseButton.MouseSource));
return; }
10651 if (
e->Type == ImGuiInputEventType_MouseWheel) { IMGUI_DEBUG_LOG_IO(
"[io] %s: MouseWheel (%.3f, %.3f) (%s)\n", prefix,
e->MouseWheel.WheelX,
e->MouseWheel.WheelY, GetMouseSourceName(
e->MouseWheel.MouseSource));
return; }
10652 if (
e->Type == ImGuiInputEventType_MouseViewport){IMGUI_DEBUG_LOG_IO(
"[io] %s: MouseViewport (0x%08X)\n", prefix,
e->MouseViewport.HoveredViewportID);
return; }
10653 if (
e->Type == ImGuiInputEventType_Key) { IMGUI_DEBUG_LOG_IO(
"[io] %s: Key \"%s\" %s\n", prefix, ImGui::GetKeyName(
e->Key.Key),
e->Key.Down ?
"Down" :
"Up");
return; }
10654 if (
e->Type == ImGuiInputEventType_Text) { IMGUI_DEBUG_LOG_IO(
"[io] %s: Text: %c (U+%08X)\n", prefix,
e->Text.Char,
e->Text.Char);
return; }
10655 if (
e->Type == ImGuiInputEventType_Focus) { IMGUI_DEBUG_LOG_IO(
"[io] %s: AppFocused %d\n", prefix,
e->AppFocused.Focused);
return; }
10663void ImGui::UpdateInputEvents(
bool trickle_fast_inputs)
10666 ImGuiIO& io =
g.IO;
10671 const bool trickle_interleaved_nonchar_keys_and_text = (trickle_fast_inputs &&
g.WantTextInputNextFrame == 1);
10673 bool mouse_moved =
false, mouse_wheeled =
false, key_changed =
false, key_changed_nonchar =
false, text_inputted =
false;
10674 int mouse_button_changed = 0x00;
10675 ImBitArray<ImGuiKey_KeysData_SIZE> key_changed_mask;
10678 for (; event_n <
g.InputEventsQueue.Size; event_n++)
10680 ImGuiInputEvent*
e = &
g.InputEventsQueue[event_n];
10681 if (
e->Type == ImGuiInputEventType_MousePos)
10683 if (
g.IO.WantSetMousePos)
10686 ImVec2 event_pos(
e->MousePos.PosX,
e->MousePos.PosY);
10687 if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || text_inputted))
10689 io.MousePos = event_pos;
10690 io.MouseSource =
e->MousePos.MouseSource;
10691 mouse_moved =
true;
10693 else if (
e->Type == ImGuiInputEventType_MouseButton)
10696 const ImGuiMouseButton button =
e->MouseButton.Button;
10697 IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT);
10698 if (trickle_fast_inputs && ((mouse_button_changed & (1 << button)) || mouse_wheeled))
10700 if (trickle_fast_inputs &&
e->MouseButton.MouseSource == ImGuiMouseSource_TouchScreen && mouse_moved)
10702 io.MouseDown[button] =
e->MouseButton.Down;
10703 io.MouseSource =
e->MouseButton.MouseSource;
10704 mouse_button_changed |= (1 << button);
10706 else if (
e->Type == ImGuiInputEventType_MouseWheel)
10709 if (trickle_fast_inputs && (mouse_moved || mouse_button_changed != 0))
10711 io.MouseWheelH +=
e->MouseWheel.WheelX;
10712 io.MouseWheel +=
e->MouseWheel.WheelY;
10713 io.MouseSource =
e->MouseWheel.MouseSource;
10714 mouse_wheeled =
true;
10716 else if (
e->Type == ImGuiInputEventType_MouseViewport)
10718 io.MouseHoveredViewport =
e->MouseViewport.HoveredViewportID;
10720 else if (
e->Type == ImGuiInputEventType_Key)
10723 if (io.ConfigFlags & ImGuiConfigFlags_NoKeyboard)
10725 ImGuiKey key =
e->Key.Key;
10726 IM_ASSERT(key != ImGuiKey_None);
10727 ImGuiKeyData* key_data = GetKeyData(key);
10728 const int key_data_index = (int)(key_data -
g.IO.KeysData);
10729 if (trickle_fast_inputs && key_data->Down !=
e->Key.Down && (key_changed_mask.TestBit(key_data_index) || mouse_button_changed != 0))
10732 const bool key_is_potentially_for_char_input = IsKeyChordPotentiallyCharInput(GetMergedModsFromKeys() | key);
10733 if (trickle_interleaved_nonchar_keys_and_text && (text_inputted && !key_is_potentially_for_char_input))
10736 key_data->Down =
e->Key.Down;
10737 key_data->AnalogValue =
e->Key.AnalogValue;
10738 key_changed =
true;
10739 key_changed_mask.SetBit(key_data_index);
10740 if (trickle_interleaved_nonchar_keys_and_text && !key_is_potentially_for_char_input)
10741 key_changed_nonchar =
true;
10744#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
10745 io.KeysDown[key_data_index] = key_data->Down;
10746 if (io.KeyMap[key_data_index] != -1)
10747 io.KeysDown[io.KeyMap[key_data_index]] = key_data->Down;
10750 else if (
e->Type == ImGuiInputEventType_Text)
10752 if (io.ConfigFlags & ImGuiConfigFlags_NoKeyboard)
10755 if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_moved || mouse_wheeled))
10757 if (trickle_interleaved_nonchar_keys_and_text && key_changed_nonchar)
10759 unsigned int c =
e->Text.Char;
10760 io.InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID);
10761 if (trickle_interleaved_nonchar_keys_and_text)
10762 text_inputted =
true;
10764 else if (
e->Type == ImGuiInputEventType_Focus)
10768 const bool focus_lost = !
e->AppFocused.Focused;
10769 io.AppFocusLost = focus_lost;
10773 IM_ASSERT(0 &&
"Unknown event!");
10779 for (
int n = 0; n < event_n; n++)
10780 g.InputEventsTrail.push_back(
g.InputEventsQueue[n]);
10783#ifndef IMGUI_DISABLE_DEBUG_TOOLS
10784 if (event_n != 0 && (
g.DebugLogFlags & ImGuiDebugLogFlags_EventIO))
10785 for (
int n = 0; n <
g.InputEventsQueue.Size; n++)
10786 DebugPrintInputEvent(n < event_n ?
"Processed" :
"Remaining", &
g.InputEventsQueue[n]);
10790 if (event_n ==
g.InputEventsQueue.Size)
10791 g.InputEventsQueue.resize(0);
10793 g.InputEventsQueue.erase(
g.InputEventsQueue.Data,
g.InputEventsQueue.Data + event_n);
10799 if (
g.IO.AppFocusLost)
10801 g.IO.ClearInputKeys();
10802 g.IO.ClearInputMouse();
10806ImGuiID ImGui::GetKeyOwner(ImGuiKey key)
10808 if (!IsNamedKeyOrMod(key))
10809 return ImGuiKeyOwner_NoOwner;
10812 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
10813 ImGuiID owner_id = owner_data->OwnerCurr;
10815 if (
g.ActiveIdUsingAllKeyboardKeys && owner_id !=
g.ActiveId && owner_id != ImGuiKeyOwner_Any)
10816 if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END)
10817 return ImGuiKeyOwner_NoOwner;
10826bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id)
10828 if (!IsNamedKeyOrMod(key))
10832 if (
g.ActiveIdUsingAllKeyboardKeys && owner_id !=
g.ActiveId && owner_id != ImGuiKeyOwner_Any)
10833 if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END)
10836 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
10837 if (owner_id == ImGuiKeyOwner_Any)
10838 return (owner_data->LockThisFrame ==
false);
10843 if (owner_data->OwnerCurr != owner_id)
10845 if (owner_data->LockThisFrame)
10847 if (owner_data->OwnerCurr != ImGuiKeyOwner_NoOwner)
10859void ImGui::SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags)
10862 IM_ASSERT(IsNamedKeyOrMod(key) && (owner_id != ImGuiKeyOwner_Any || (flags & (ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease))));
10863 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetKeyOwner) == 0);
10866 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
10867 owner_data->OwnerCurr = owner_data->OwnerNext = owner_id;
10871 owner_data->LockUntilRelease = (flags & ImGuiInputFlags_LockUntilRelease) != 0;
10872 owner_data->LockThisFrame = (flags & ImGuiInputFlags_LockThisFrame) != 0 || (owner_data->LockUntilRelease);
10876void ImGui::SetKeyOwnersForKeyChord(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
10878 if (key_chord & ImGuiMod_Ctrl) { SetKeyOwner(ImGuiMod_Ctrl, owner_id, flags); }
10879 if (key_chord & ImGuiMod_Shift) { SetKeyOwner(ImGuiMod_Shift, owner_id, flags); }
10880 if (key_chord & ImGuiMod_Alt) { SetKeyOwner(ImGuiMod_Alt, owner_id, flags); }
10881 if (key_chord & ImGuiMod_Super) { SetKeyOwner(ImGuiMod_Super, owner_id, flags); }
10882 if (key_chord & ~ImGuiMod_Mask_) { SetKeyOwner((ImGuiKey)(key_chord & ~ImGuiMod_Mask_), owner_id, flags); }
10891void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
10894 ImGuiID
id =
g.LastItemData.ID;
10895 if (
id == 0 || (
g.HoveredId !=
id &&
g.ActiveId !=
id))
10897 if ((flags & ImGuiInputFlags_CondMask_) == 0)
10898 flags |= ImGuiInputFlags_CondDefault_;
10899 if ((
g.HoveredId ==
id && (flags & ImGuiInputFlags_CondHovered)) || (
g.ActiveId ==
id && (flags & ImGuiInputFlags_CondActive)))
10901 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetItemKeyOwner) == 0);
10902 SetKeyOwner(key,
id, flags & ~ImGuiInputFlags_CondMask_);
10906void ImGui::SetItemKeyOwner(ImGuiKey key)
10908 SetItemKeyOwner(key, ImGuiInputFlags_None);
10912bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord)
10914 return IsKeyChordPressed(key_chord, ImGuiInputFlags_None, ImGuiKeyOwner_Any);
10918bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id)
10921 key_chord = FixupKeyChord(key_chord);
10922 ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
10923 if (
g.IO.KeyMods != mods)
10927 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
10928 if (key == ImGuiKey_None)
10929 key = ConvertSingleModFlagToKey(mods);
10930 if (!IsKeyPressed(key, (flags & ImGuiInputFlags_RepeatMask_), owner_id))
10935void ImGui::SetNextItemShortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags)
10938 g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasShortcut;
10939 g.NextItemData.Shortcut = key_chord;
10940 g.NextItemData.ShortcutFlags = flags;
10944void ImGui::ItemHandleShortcut(ImGuiID
id)
10947 ImGuiInputFlags flags =
g.NextItemData.ShortcutFlags;
10948 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetNextItemShortcut) == 0);
10950 if (
g.LastItemData.ItemFlags & ImGuiItemFlags_Disabled)
10952 if (flags & ImGuiInputFlags_Tooltip)
10954 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasShortcut;
10955 g.LastItemData.Shortcut =
g.NextItemData.Shortcut;
10957 if (!Shortcut(
g.NextItemData.Shortcut, flags & ImGuiInputFlags_SupportedByShortcut,
id) ||
g.NavActivateId != 0)
10961 g.NavActivateId =
id;
10962 g.NavActivateFlags = ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_FromShortcut;
10964 g.NavActivateDownId =
g.NavActivatePressedId =
id;
10965 NavHighlightActivated(
id);
10968bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags)
10970 return Shortcut(key_chord, flags, ImGuiKeyOwner_Any);
10973bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id)
10979 if ((flags & ImGuiInputFlags_RouteTypeMask_) == 0)
10980 flags |= ImGuiInputFlags_RouteFocused;
10984 if (owner_id == ImGuiKeyOwner_Any || owner_id == ImGuiKeyOwner_NoOwner)
10985 owner_id = GetRoutingIdFromOwnerId(owner_id);
10987 if (
g.CurrentItemFlags & ImGuiItemFlags_Disabled)
10991 if (!SetShortcutRouting(key_chord, flags, owner_id))
10996 if ((flags & ImGuiInputFlags_Repeat) != 0 && (flags & ImGuiInputFlags_RepeatUntilMask_) == 0)
10997 flags |= ImGuiInputFlags_RepeatUntilKeyModsChange;
10999 if (!IsKeyChordPressed(key_chord, flags, owner_id))
11003 SetKeyOwnersForKeyChord(key_chord & ImGuiMod_Mask_, owner_id);
11005 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByShortcut) == 0);
11033bool ImGui::DebugCheckVersionAndDataLayout(
const char* version,
size_t sz_io,
size_t sz_style,
size_t sz_vec2,
size_t sz_vec4,
size_t sz_vert,
size_t sz_idx)
11035 bool error =
false;
11036 if (strcmp(version, IMGUI_VERSION) != 0) { error =
true; IM_ASSERT(strcmp(version, IMGUI_VERSION) == 0 &&
"Mismatched version string!"); }
11037 if (sz_io !=
sizeof(ImGuiIO)) { error =
true; IM_ASSERT(sz_io ==
sizeof(ImGuiIO) &&
"Mismatched struct layout!"); }
11038 if (sz_style !=
sizeof(ImGuiStyle)) { error =
true; IM_ASSERT(sz_style ==
sizeof(ImGuiStyle) &&
"Mismatched struct layout!"); }
11039 if (sz_vec2 !=
sizeof(ImVec2)) { error =
true; IM_ASSERT(sz_vec2 ==
sizeof(ImVec2) &&
"Mismatched struct layout!"); }
11040 if (sz_vec4 !=
sizeof(ImVec4)) { error =
true; IM_ASSERT(sz_vec4 ==
sizeof(ImVec4) &&
"Mismatched struct layout!"); }
11041 if (sz_vert !=
sizeof(ImDrawVert)) { error =
true; IM_ASSERT(sz_vert ==
sizeof(ImDrawVert) &&
"Mismatched struct layout!"); }
11042 if (sz_idx !=
sizeof(ImDrawIdx)) { error =
true; IM_ASSERT(sz_idx ==
sizeof(ImDrawIdx) &&
"Mismatched struct layout!"); }
11061void ImGui::ErrorCheckUsingSetCursorPosToExtendParentBoundaries()
11064 ImGuiWindow* window =
g.CurrentWindow;
11065 IM_ASSERT(window->DC.IsSetPos);
11066 window->DC.IsSetPos =
false;
11067#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
11068 if (window->DC.CursorPos.x <= window->DC.CursorMaxPos.x && window->DC.CursorPos.y <= window->DC.CursorMaxPos.y)
11070 if (window->SkipItems)
11072 IM_ASSERT(0 &&
"Code uses SetCursorPos()/SetCursorScreenPos() to extend window/parent boundaries. Please submit an item e.g. Dummy() to validate extent.");
11074 window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
11078static void ImGui::ErrorCheckNewFrameSanityChecks()
11088 if (
true) IM_ASSERT(1);
else IM_ASSERT(0);
11092#ifdef __EMSCRIPTEN__
11093 if (
g.IO.DeltaTime <= 0.0f &&
g.FrameCount > 0)
11094 g.IO.DeltaTime = 0.00001f;
11099 IM_ASSERT(
g.Initialized);
11100 IM_ASSERT((
g.IO.DeltaTime > 0.0f ||
g.FrameCount == 0) &&
"Need a positive DeltaTime!");
11101 IM_ASSERT((
g.FrameCount == 0 ||
g.FrameCountEnded ==
g.FrameCount) &&
"Forgot to call Render() or EndFrame() at the end of the previous frame?");
11102 IM_ASSERT(
g.IO.DisplaySize.x >= 0.0f &&
g.IO.DisplaySize.y >= 0.0f &&
"Invalid DisplaySize value!");
11103 IM_ASSERT(
g.IO.Fonts->IsBuilt() &&
"Font Atlas not built! Make sure you called ImGui_ImplXXXX_NewFrame() function for renderer backend, which should call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()");
11104 IM_ASSERT(
g.Style.CurveTessellationTol > 0.0f &&
"Invalid style setting!");
11105 IM_ASSERT(
g.Style.CircleTessellationMaxError > 0.0f &&
"Invalid style setting!");
11106 IM_ASSERT(
g.Style.Alpha >= 0.0f &&
g.Style.Alpha <= 1.0f &&
"Invalid style setting!");
11107 IM_ASSERT(
g.Style.WindowMinSize.x >= 1.0f &&
g.Style.WindowMinSize.y >= 1.0f &&
"Invalid style setting.");
11108 IM_ASSERT(
g.Style.WindowMenuButtonPosition == ImGuiDir_None ||
g.Style.WindowMenuButtonPosition == ImGuiDir_Left ||
g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
11109 IM_ASSERT(
g.Style.ColorButtonPosition == ImGuiDir_Left ||
g.Style.ColorButtonPosition == ImGuiDir_Right);
11110#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
11111 for (
int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_COUNT; n++)
11112 IM_ASSERT(
g.IO.KeyMap[n] >= -1 &&
g.IO.KeyMap[n] < ImGuiKey_LegacyNativeKey_END &&
"io.KeyMap[] contains an out of bound value (need to be 0..511, or -1 for unmapped key)");
11115 if ((
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) &&
g.IO.BackendUsingLegacyKeyArrays == 1)
11116 IM_ASSERT(
g.IO.KeyMap[ImGuiKey_Space] != -1 &&
"ImGuiKey_Space is not mapped, required for keyboard navigation.");
11120 if (
g.IO.ConfigErrorRecovery)
11121 IM_ASSERT(
g.IO.ConfigErrorRecoveryEnableAssert ||
g.IO.ConfigErrorRecoveryEnableDebugLog ||
g.IO.ConfigErrorRecoveryEnableTooltip ||
g.ErrorCallback != NULL);
11123#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
11125 if (
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)
11127 g.IO.ConfigNavMoveSetMousePos =
true;
11128 g.IO.ConfigFlags &= ~ImGuiConfigFlags_NavEnableSetMousePos;
11130 if (
g.IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)
11132 g.IO.ConfigNavCaptureKeyboard =
false;
11133 g.IO.ConfigFlags &= ~ImGuiConfigFlags_NavNoCaptureKeyboard;
11137 if (
g.IO.GetClipboardTextFn != NULL && (
g.PlatformIO.Platform_GetClipboardTextFn == NULL ||
g.PlatformIO.Platform_GetClipboardTextFn == Platform_GetClipboardTextFn_DefaultImpl))
11138 g.PlatformIO.Platform_GetClipboardTextFn = [](ImGuiContext* ctx) {
return ctx->IO.GetClipboardTextFn(ctx->IO.ClipboardUserData); };
11139 if (
g.IO.SetClipboardTextFn != NULL && (
g.PlatformIO.Platform_SetClipboardTextFn == NULL ||
g.PlatformIO.Platform_SetClipboardTextFn == Platform_SetClipboardTextFn_DefaultImpl))
11140 g.PlatformIO.Platform_SetClipboardTextFn = [](ImGuiContext* ctx,
const char* text) {
return ctx->IO.SetClipboardTextFn(ctx->IO.ClipboardUserData, text); };
11144 if (
g.FrameCount == 1 && (
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable) && (
g.ConfigFlagsLastFrame & ImGuiConfigFlags_DockingEnable) == 0)
11145 IM_ASSERT(0 &&
"Please set DockingEnable before the first call to NewFrame()! Otherwise you will lose your .ini settings!");
11146 if (
g.FrameCount == 1 && (
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) && (
g.ConfigFlagsLastFrame & ImGuiConfigFlags_ViewportsEnable) == 0)
11147 IM_ASSERT(0 &&
"Please set ViewportsEnable before the first call to NewFrame()! Otherwise you will lose your .ini settings!");
11150 if (
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
11152 if ((
g.IO.BackendFlags & ImGuiBackendFlags_PlatformHasViewports) && (
g.IO.BackendFlags & ImGuiBackendFlags_RendererHasViewports))
11154 IM_ASSERT((
g.FrameCount == 0 ||
g.FrameCount ==
g.FrameCountPlatformEnded) &&
"Forgot to call UpdatePlatformWindows() in main loop after EndFrame()? Check examples/ applications for reference.");
11155 IM_ASSERT(
g.PlatformIO.Platform_CreateWindow != NULL &&
"Platform init didn't install handlers?");
11156 IM_ASSERT(
g.PlatformIO.Platform_DestroyWindow != NULL &&
"Platform init didn't install handlers?");
11157 IM_ASSERT(
g.PlatformIO.Platform_GetWindowPos != NULL &&
"Platform init didn't install handlers?");
11158 IM_ASSERT(
g.PlatformIO.Platform_SetWindowPos != NULL &&
"Platform init didn't install handlers?");
11159 IM_ASSERT(
g.PlatformIO.Platform_GetWindowSize != NULL &&
"Platform init didn't install handlers?");
11160 IM_ASSERT(
g.PlatformIO.Platform_SetWindowSize != NULL &&
"Platform init didn't install handlers?");
11161 IM_ASSERT(
g.PlatformIO.Monitors.Size > 0 &&
"Platform init didn't setup Monitors list?");
11162 IM_ASSERT((
g.Viewports[0]->PlatformUserData != NULL ||
g.Viewports[0]->PlatformHandle != NULL) &&
"Platform init didn't setup main viewport.");
11163 if (
g.IO.ConfigDockingTransparentPayload && (
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
11164 IM_ASSERT(
g.PlatformIO.Platform_SetWindowAlpha != NULL &&
"Platform_SetWindowAlpha handler is required to use io.ConfigDockingTransparent!");
11169 g.IO.ConfigFlags &= ~ImGuiConfigFlags_ViewportsEnable;
11173 for (ImGuiPlatformMonitor& mon :
g.PlatformIO.Monitors)
11176 IM_ASSERT(mon.MainSize.x > 0.0f && mon.MainSize.y > 0.0f &&
"Monitor main bounds not setup properly.");
11177 IM_ASSERT(ImRect(mon.MainPos, mon.MainPos + mon.MainSize).Contains(ImRect(mon.WorkPos, mon.WorkPos + mon.WorkSize)) &&
"Monitor work bounds not setup properly. If you don't have work area information, just copy MainPos/MainSize into them.");
11178 IM_ASSERT(mon.DpiScale != 0.0f);
11183static void ImGui::ErrorCheckEndFrameSanityChecks()
11192 const ImGuiKeyChord key_mods = GetMergedModsFromKeys();
11194 IM_UNUSED(key_mods);
11195 IM_ASSERT((key_mods == 0 ||
g.IO.KeyMods == key_mods) &&
"Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
11196 IM_UNUSED(key_mods);
11198 IM_ASSERT(
g.CurrentWindowStack.Size == 1);
11199 IM_ASSERT(
g.CurrentWindowStack[0].Window->IsFallbackWindow);
11203void ImGui::ErrorRecoveryStoreState(ImGuiErrorRecoveryState* state_out)
11206 state_out->SizeOfWindowStack = (short)
g.CurrentWindowStack.Size;
11207 state_out->SizeOfIDStack = (short)
g.CurrentWindow->IDStack.Size;
11208 state_out->SizeOfTreeStack = (short)
g.CurrentWindow->DC.TreeDepth;
11209 state_out->SizeOfColorStack = (short)
g.ColorStack.Size;
11210 state_out->SizeOfStyleVarStack = (short)
g.StyleVarStack.Size;
11211 state_out->SizeOfFontStack = (short)
g.FontStack.Size;
11212 state_out->SizeOfFocusScopeStack = (short)
g.FocusScopeStack.Size;
11213 state_out->SizeOfGroupStack = (short)
g.GroupStack.Size;
11214 state_out->SizeOfItemFlagsStack = (short)
g.ItemFlagsStack.Size;
11215 state_out->SizeOfBeginPopupStack = (short)
g.BeginPopupStack.Size;
11216 state_out->SizeOfDisabledStack = (short)
g.DisabledStackSize;
11222void ImGui::ErrorRecoveryTryToRecoverState(
const ImGuiErrorRecoveryState* state_in)
11226 while (
g.CurrentWindowStack.Size > state_in->SizeOfWindowStack)
11233 ImGuiWindow* window =
g.CurrentWindow;
11234 if (window->Flags & ImGuiWindowFlags_ChildWindow)
11236 IM_ASSERT_USER_ERROR(0,
"Missing EndChild()");
11241 IM_ASSERT_USER_ERROR(0,
"Missing End()");
11245 if (
g.CurrentWindowStack.Size == state_in->SizeOfWindowStack)
11246 ErrorRecoveryTryToRecoverWindowState(state_in);
11252void ImGui::ErrorRecoveryTryToRecoverWindowState(
const ImGuiErrorRecoveryState* state_in)
11256 while (
g.CurrentTable != NULL &&
g.CurrentTable->InnerWindow ==
g.CurrentWindow)
11258 IM_ASSERT_USER_ERROR(0,
"Missing EndTable()");
11262 ImGuiWindow* window =
g.CurrentWindow;
11265 while (
g.CurrentTabBar != NULL &&
g.CurrentTabBar->Window == window)
11267 IM_ASSERT_USER_ERROR(0,
"Missing EndTabBar()");
11270 while (
g.CurrentMultiSelect != NULL &&
g.CurrentMultiSelect->Storage->Window == window)
11272 IM_ASSERT_USER_ERROR(0,
"Missing EndMultiSelect()");
11275 while (window->DC.TreeDepth > state_in->SizeOfTreeStack)
11277 IM_ASSERT_USER_ERROR(0,
"Missing TreePop()");
11280 while (
g.GroupStack.Size > state_in->SizeOfGroupStack)
11282 IM_ASSERT_USER_ERROR(0,
"Missing EndGroup()");
11285 IM_ASSERT(
g.GroupStack.Size == state_in->SizeOfGroupStack);
11286 while (window->IDStack.Size > state_in->SizeOfIDStack)
11288 IM_ASSERT_USER_ERROR(0,
"Missing PopID()");
11291 while (
g.DisabledStackSize > state_in->SizeOfDisabledStack)
11293 IM_ASSERT_USER_ERROR(0,
"Missing EndDisabled()");
11294 if (
g.CurrentItemFlags & ImGuiItemFlags_Disabled)
11298 EndDisabledOverrideReenable();
11299 g.CurrentWindowStack.back().DisabledOverrideReenable =
false;
11302 IM_ASSERT(
g.DisabledStackSize == state_in->SizeOfDisabledStack);
11303 while (
g.ColorStack.Size > state_in->SizeOfColorStack)
11305 IM_ASSERT_USER_ERROR(0,
"Missing PopStyleColor()");
11308 while (
g.ItemFlagsStack.Size > state_in->SizeOfItemFlagsStack)
11310 IM_ASSERT_USER_ERROR(0,
"Missing PopItemFlag()");
11313 while (
g.StyleVarStack.Size > state_in->SizeOfStyleVarStack)
11315 IM_ASSERT_USER_ERROR(0,
"Missing PopStyleVar()");
11318 while (
g.FontStack.Size > state_in->SizeOfFontStack)
11320 IM_ASSERT_USER_ERROR(0,
"Missing PopFont()");
11323 while (
g.FocusScopeStack.Size > state_in->SizeOfFocusScopeStack)
11325 IM_ASSERT_USER_ERROR(0,
"Missing PopFocusScope()");
11331bool ImGui::ErrorLog(
const char* msg)
11336#ifndef IMGUI_DISABLE_DEBUG_TOOLS
11337 ImGuiWindow* window =
g.CurrentWindow;
11339 if (
g.IO.ConfigErrorRecoveryEnableDebugLog)
11342 IMGUI_DEBUG_LOG_ERROR(
"[imgui-error] (current settings: Assert=%d, Log=%d, Tooltip=%d)\n",
11343 g.IO.ConfigErrorRecoveryEnableAssert,
g.IO.ConfigErrorRecoveryEnableDebugLog,
g.IO.ConfigErrorRecoveryEnableTooltip);
11344 IMGUI_DEBUG_LOG_ERROR(
"[imgui-error] In window '%s': %s\n", window ? window->Name :
"NULL", msg);
11346 g.ErrorFirst =
false;
11349 if (
g.IO.ConfigErrorRecoveryEnableTooltip)
11351 if (BeginErrorTooltip())
11353 if (
g.ErrorCountCurrentFrame < 20)
11355 Text(
"In window '%s': %s", window ? window->Name :
"NULL", msg);
11356 if (window && (!window->IsFallbackWindow || window->WasActive))
11357 GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 0, 0, 255));
11359 if (
g.ErrorCountCurrentFrame == 20)
11360 Text(
"(and more errors)");
11364 g.ErrorCountCurrentFrame++;
11369 if (
g.ErrorCallback != NULL)
11370 g.ErrorCallback(&
g,
g.ErrorCallbackUserData, msg);
11373 return g.IO.ConfigErrorRecoveryEnableAssert;
11376void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
11378#ifndef IMGUI_DISABLE_DEBUG_TOOLS
11380 if (
g.DebugDrawIdConflicts != 0 &&
g.IO.KeyCtrl ==
false)
11381 g.DebugDrawIdConflictsCount =
g.HoveredIdPreviousFrameItemCount;
11382 if (
g.DebugDrawIdConflicts != 0 &&
g.DebugItemPickerActive ==
false && BeginErrorTooltip())
11384 Text(
"Programmer error: %d visible items with conflicting ID!",
g.DebugDrawIdConflictsCount);
11385 BulletText(
"Code should use PushID()/PopID() in loops, or append \"##xx\" to same-label identifiers!");
11386 BulletText(
"Empty label e.g. Button(\"\") == same ID as parent widget/node. Use Button(\"##xx\") instead!");
11388 BulletText(
"Set io.ConfigDebugDetectIdConflicts=false to disable this warning in non-programmers builds.");
11390 Text(
"(Hold CTRL to: use");
11392 if (SmallButton(
"Item Picker"))
11393 DebugStartItemPicker();
11395 Text(
"to break in item call-stack, or");
11397 if (SmallButton(
"Open FAQ->About ID Stack System") &&
g.PlatformIO.Platform_OpenInShellFn != NULL)
11398 g.PlatformIO.Platform_OpenInShellFn(&
g,
"https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage");
11402 if (
g.ErrorCountCurrentFrame > 0 && BeginErrorTooltip())
11405 Text(
"(Hold CTRL to:");
11407 if (SmallButton(
"Enable Asserts"))
11408 g.IO.ConfigErrorRecoveryEnableAssert =
true;
11420bool ImGui::BeginErrorTooltip()
11423 ImGuiWindow* window = FindWindowByName(
"##Tooltip_Error");
11424 const bool use_locked_pos = (
g.IO.KeyCtrl && window && window->WasActive);
11425 PushStyleColor(ImGuiCol_PopupBg, ImLerp(
g.Style.Colors[ImGuiCol_PopupBg], ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.15f));
11426 if (use_locked_pos)
11427 SetNextWindowPos(
g.ErrorTooltipLockedPos);
11428 bool is_visible = Begin(
"##Tooltip_Error", NULL, ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize);
11430 if (is_visible &&
g.CurrentWindow->BeginCount == 1)
11432 SeparatorText(
"MESSAGE FROM DEAR IMGUI");
11433 BringWindowToDisplayFront(
g.CurrentWindow);
11434 BringWindowToFocusFront(
g.CurrentWindow);
11435 g.ErrorTooltipLockedPos = GetWindowPos();
11437 else if (!is_visible)
11444void ImGui::EndErrorTooltip()
11457void ImGui::KeepAliveID(ImGuiID
id)
11460 if (
g.ActiveId ==
id)
11461 g.ActiveIdIsAlive =
id;
11462 if (
g.ActiveIdPreviousFrame ==
id)
11463 g.ActiveIdPreviousFrameIsAlive =
true;
11470IM_MSVC_RUNTIME_CHECKS_OFF
11471bool ImGui::ItemAdd(
const ImRect& bb, ImGuiID
id,
const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags)
11474 ImGuiWindow* window =
g.CurrentWindow;
11478 g.LastItemData.ID =
id;
11479 g.LastItemData.Rect = bb;
11480 g.LastItemData.NavRect = nav_bb_arg ? *nav_bb_arg : bb;
11481 g.LastItemData.ItemFlags =
g.CurrentItemFlags |
g.NextItemData.ItemFlags | extra_flags;
11482 g.LastItemData.StatusFlags = ImGuiItemStatusFlags_None;
11499 if (!(
g.LastItemData.ItemFlags & ImGuiItemFlags_NoNav))
11502 window->DC.NavLayersActiveMaskNext |= (1 << window->DC.NavLayerCurrent);
11503 if (
g.NavId ==
id ||
g.NavAnyRequest)
11504 if (
g.NavWindow->RootWindowForNav == window->RootWindowForNav)
11505 if (window ==
g.NavWindow || ((window->ChildFlags |
g.NavWindow->ChildFlags) & ImGuiChildFlags_NavFlattened))
11509 if (
g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasShortcut)
11510 ItemHandleShortcut(
id);
11514 g.NextItemData.HasFlags = ImGuiNextItemDataFlags_None;
11515 g.NextItemData.ItemFlags = ImGuiItemFlags_None;
11517#ifdef IMGUI_ENABLE_TEST_ENGINE
11519 IMGUI_TEST_ENGINE_ITEM_ADD(
id,
g.LastItemData.NavRect, &
g.LastItemData);
11525 const bool is_rect_visible = bb.Overlaps(window->ClipRect);
11526 if (!is_rect_visible)
11527 if (
id == 0 || (
id !=
g.ActiveId &&
id !=
g.ActiveIdPreviousFrame &&
id !=
g.NavId &&
id !=
g.NavActivateId))
11528 if (!
g.ItemUnclipByLog)
11532#ifndef IMGUI_DISABLE_DEBUG_TOOLS
11535 if (
id ==
g.DebugLocateId)
11536 DebugLocateItemResolveWithLastItem();
11541 IM_ASSERT(
id != window->ID &&
"Cannot have an empty ID at the root of a window. If you need an empty label, use ## and read the FAQ about how the ID Stack works!");
11549 if (is_rect_visible)
11550 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Visible;
11551 if (IsMouseHoveringRect(bb.Min, bb.Max))
11552 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect;
11555IM_MSVC_RUNTIME_CHECKS_RESTORE
11590IM_MSVC_RUNTIME_CHECKS_OFF
11591void ImGui::ItemSize(
const ImVec2& size,
float text_baseline_y)
11594 ImGuiWindow* window =
g.CurrentWindow;
11595 if (window->SkipItems)
11601 const float offset_to_match_baseline_y = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f;
11603 const float line_y1 = window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y;
11604 const float line_height = ImMax(window->DC.CurrLineSize.y, window->DC.CursorPos.y - line_y1 +
size.y + offset_to_match_baseline_y);
11608 window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x +
size.x;
11609 window->DC.CursorPosPrevLine.y = line_y1;
11610 window->DC.CursorPos.x = IM_TRUNC(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
11611 window->DC.CursorPos.y = IM_TRUNC(line_y1 + line_height +
g.Style.ItemSpacing.y);
11612 window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
11613 window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y -
g.Style.ItemSpacing.y);
11616 window->DC.PrevLineSize.y = line_height;
11617 window->DC.CurrLineSize.y = 0.0f;
11618 window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y);
11619 window->DC.CurrLineTextBaseOffset = 0.0f;
11620 window->DC.IsSameLine = window->DC.IsSetPos =
false;
11623 if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
11626IM_MSVC_RUNTIME_CHECKS_RESTORE
11633void ImGui::SameLine(
float offset_from_start_x,
float spacing_w)
11636 ImGuiWindow* window =
g.CurrentWindow;
11637 if (window->SkipItems)
11640 if (offset_from_start_x != 0.0f)
11642 if (spacing_w < 0.0f)
11644 window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + offset_from_start_x + spacing_w + window->DC.GroupOffset.x + window->DC.ColumnsOffset.x;
11645 window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
11649 if (spacing_w < 0.0f)
11650 spacing_w =
g.Style.ItemSpacing.x;
11651 window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w;
11652 window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
11654 window->DC.CurrLineSize = window->DC.PrevLineSize;
11655 window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
11656 window->DC.IsSameLine =
true;
11659ImVec2 ImGui::GetCursorScreenPos()
11661 ImGuiWindow* window = GetCurrentWindowRead();
11662 return window->DC.CursorPos;
11665void ImGui::SetCursorScreenPos(
const ImVec2& pos)
11667 ImGuiWindow* window = GetCurrentWindow();
11668 window->DC.CursorPos = pos;
11670 window->DC.IsSetPos =
true;
11675ImVec2 ImGui::GetCursorPos()
11677 ImGuiWindow* window = GetCurrentWindowRead();
11678 return window->DC.CursorPos - window->Pos + window->Scroll;
11681float ImGui::GetCursorPosX()
11683 ImGuiWindow* window = GetCurrentWindowRead();
11684 return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x;
11687float ImGui::GetCursorPosY()
11689 ImGuiWindow* window = GetCurrentWindowRead();
11690 return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y;
11693void ImGui::SetCursorPos(
const ImVec2& local_pos)
11695 ImGuiWindow* window = GetCurrentWindow();
11696 window->DC.CursorPos = window->Pos - window->Scroll + local_pos;
11698 window->DC.IsSetPos =
true;
11701void ImGui::SetCursorPosX(
float x)
11703 ImGuiWindow* window = GetCurrentWindow();
11704 window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x;
11706 window->DC.IsSetPos =
true;
11709void ImGui::SetCursorPosY(
float y)
11711 ImGuiWindow* window = GetCurrentWindow();
11712 window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y;
11714 window->DC.IsSetPos =
true;
11717ImVec2 ImGui::GetCursorStartPos()
11719 ImGuiWindow* window = GetCurrentWindowRead();
11720 return window->DC.CursorStartPos - window->Pos;
11723void ImGui::Indent(
float indent_w)
11726 ImGuiWindow* window = GetCurrentWindow();
11727 window->DC.Indent.x += (indent_w != 0.0f) ? indent_w :
g.Style.IndentSpacing;
11728 window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
11731void ImGui::Unindent(
float indent_w)
11734 ImGuiWindow* window = GetCurrentWindow();
11735 window->DC.Indent.x -= (indent_w != 0.0f) ? indent_w :
g.Style.IndentSpacing;
11736 window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
11740void ImGui::SetNextItemWidth(
float item_width)
11743 g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasWidth;
11744 g.NextItemData.Width = item_width;
11748void ImGui::PushItemWidth(
float item_width)
11751 ImGuiWindow* window =
g.CurrentWindow;
11752 window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);
11753 window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);
11754 g.NextItemData.HasFlags &= ~ImGuiNextItemDataFlags_HasWidth;
11757void ImGui::PushMultiItemsWidths(
int components,
float w_full)
11760 ImGuiWindow* window =
g.CurrentWindow;
11761 IM_ASSERT(components > 0);
11762 const ImGuiStyle& style =
g.Style;
11763 window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);
11764 float w_items = w_full - style.ItemInnerSpacing.x * (components - 1);
11765 float prev_split = w_items;
11766 for (
int i = components - 1; i > 0; i--)
11768 float next_split = IM_TRUNC(w_items * i / components);
11769 window->DC.ItemWidthStack.push_back(ImMax(prev_split - next_split, 1.0f));
11770 prev_split = next_split;
11772 window->DC.ItemWidth = ImMax(prev_split, 1.0f);
11773 g.NextItemData.HasFlags &= ~ImGuiNextItemDataFlags_HasWidth;
11776void ImGui::PopItemWidth()
11779 ImGuiWindow* window =
g.CurrentWindow;
11780 if (window->DC.ItemWidthStack.Size <= 0)
11782 IM_ASSERT_USER_ERROR(0,
"Calling PopItemWidth() too many times!");
11785 window->DC.ItemWidth = window->DC.ItemWidthStack.back();
11786 window->DC.ItemWidthStack.pop_back();
11791float ImGui::CalcItemWidth()
11794 ImGuiWindow* window =
g.CurrentWindow;
11796 if (
g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasWidth)
11797 w =
g.NextItemData.Width;
11799 w = window->DC.ItemWidth;
11802 float region_avail_x = GetContentRegionAvail().x;
11803 w = ImMax(1.0f, region_avail_x + w);
11813ImVec2 ImGui::CalcItemSize(ImVec2 size,
float default_w,
float default_h)
11816 if (
size.x < 0.0f ||
size.y < 0.0f)
11817 avail = GetContentRegionAvail();
11819 if (
size.x == 0.0f)
11820 size.x = default_w;
11821 else if (
size.x < 0.0f)
11822 size.x = ImMax(4.0f, avail.x +
size.x);
11824 if (
size.y == 0.0f)
11825 size.y = default_h;
11826 else if (
size.y < 0.0f)
11827 size.y = ImMax(4.0f, avail.y +
size.y);
11832float ImGui::GetTextLineHeight()
11838float ImGui::GetTextLineHeightWithSpacing()
11841 return g.FontSize +
g.Style.ItemSpacing.y;
11844float ImGui::GetFrameHeight()
11847 return g.FontSize +
g.Style.FramePadding.y * 2.0f;
11850float ImGui::GetFrameHeightWithSpacing()
11853 return g.FontSize +
g.Style.FramePadding.y * 2.0f +
g.Style.ItemSpacing.y;
11856ImVec2 ImGui::GetContentRegionAvail()
11859 ImGuiWindow* window =
g.CurrentWindow;
11860 ImVec2 mx = (window->DC.CurrentColumns ||
g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max;
11861 return mx - window->DC.CursorPos;
11864#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
11868ImVec2 ImGui::GetContentRegionMax()
11870 return GetContentRegionAvail() + GetCursorScreenPos() - GetWindowPos();
11873ImVec2 ImGui::GetWindowContentRegionMin()
11875 ImGuiWindow* window =
GImGui->CurrentWindow;
11876 return window->ContentRegionRect.Min - window->Pos;
11879ImVec2 ImGui::GetWindowContentRegionMax()
11881 ImGuiWindow* window =
GImGui->CurrentWindow;
11882 return window->ContentRegionRect.Max - window->Pos;
11889void ImGui::BeginGroup()
11892 ImGuiWindow* window =
g.CurrentWindow;
11894 g.GroupStack.resize(
g.GroupStack.Size + 1);
11895 ImGuiGroupData& group_data =
g.GroupStack.back();
11896 group_data.WindowID = window->ID;
11897 group_data.BackupCursorPos = window->DC.CursorPos;
11898 group_data.BackupCursorPosPrevLine = window->DC.CursorPosPrevLine;
11899 group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
11900 group_data.BackupIndent = window->DC.Indent;
11901 group_data.BackupGroupOffset = window->DC.GroupOffset;
11902 group_data.BackupCurrLineSize = window->DC.CurrLineSize;
11903 group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset;
11904 group_data.BackupActiveIdIsAlive =
g.ActiveIdIsAlive;
11905 group_data.BackupHoveredIdIsAlive =
g.HoveredId != 0;
11906 group_data.BackupIsSameLine = window->DC.IsSameLine;
11907 group_data.BackupActiveIdPreviousFrameIsAlive =
g.ActiveIdPreviousFrameIsAlive;
11908 group_data.EmitItem =
true;
11910 window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
11911 window->DC.Indent = window->DC.GroupOffset;
11912 window->DC.CursorMaxPos = window->DC.CursorPos;
11913 window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
11915 g.LogLinePosY = -FLT_MAX;
11918void ImGui::EndGroup()
11921 ImGuiWindow* window =
g.CurrentWindow;
11922 IM_ASSERT(
g.GroupStack.Size > 0);
11924 ImGuiGroupData& group_data =
g.GroupStack.back();
11925 IM_ASSERT(group_data.WindowID == window->ID);
11927 if (window->DC.IsSetPos)
11928 ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
11931 ImRect group_bb(group_data.BackupCursorPos, ImMax(ImMax(window->DC.CursorMaxPos,
g.LastItemData.Rect.Max), group_data.BackupCursorPos));
11932 window->DC.CursorPos = group_data.BackupCursorPos;
11933 window->DC.CursorPosPrevLine = group_data.BackupCursorPosPrevLine;
11934 window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, group_bb.Max);
11935 window->DC.Indent = group_data.BackupIndent;
11936 window->DC.GroupOffset = group_data.BackupGroupOffset;
11937 window->DC.CurrLineSize = group_data.BackupCurrLineSize;
11938 window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset;
11939 window->DC.IsSameLine = group_data.BackupIsSameLine;
11941 g.LogLinePosY = -FLT_MAX;
11943 if (!group_data.EmitItem)
11945 g.GroupStack.pop_back();
11949 window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset);
11950 ItemSize(group_bb.GetSize());
11951 ItemAdd(group_bb, 0, NULL, ImGuiItemFlags_NoTabStop);
11957 const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive !=
g.ActiveId) && (
g.ActiveIdIsAlive ==
g.ActiveId) &&
g.ActiveId;
11958 const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive ==
false) && (
g.ActiveIdPreviousFrameIsAlive ==
true);
11959 if (group_contains_curr_active_id)
11960 g.LastItemData.ID =
g.ActiveId;
11961 else if (group_contains_prev_active_id)
11962 g.LastItemData.ID =
g.ActiveIdPreviousFrame;
11963 g.LastItemData.Rect = group_bb;
11966 const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive ==
false) &&
g.HoveredId != 0;
11967 if (group_contains_curr_hovered_id)
11968 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
11971 if (group_contains_curr_active_id &&
g.ActiveIdHasBeenEditedThisFrame)
11972 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
11975 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated;
11976 if (group_contains_prev_active_id &&
g.ActiveId !=
g.ActiveIdPreviousFrame)
11977 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated;
11979 g.GroupStack.pop_back();
11980 if (
g.DebugShowGroupRects)
11981 window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255));
11993static float CalcScrollEdgeSnap(
float target,
float snap_min,
float snap_max,
float snap_threshold,
float center_ratio)
11995 if (target <= snap_min + snap_threshold)
11996 return ImLerp(snap_min, target, center_ratio);
11997 if (target >= snap_max - snap_threshold)
11998 return ImLerp(target, snap_max, center_ratio);
12002static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window)
12004 ImVec2 scroll = window->Scroll;
12005 ImVec2 decoration_size(window->DecoOuterSizeX1 + window->DecoInnerSizeX1 + window->DecoOuterSizeX2, window->DecoOuterSizeY1 + window->DecoInnerSizeY1 + window->DecoOuterSizeY2);
12006 for (
int axis = 0; axis < 2; axis++)
12008 if (window->ScrollTarget[axis] < FLT_MAX)
12010 float center_ratio = window->ScrollTargetCenterRatio[axis];
12011 float scroll_target = window->ScrollTarget[axis];
12012 if (window->ScrollTargetEdgeSnapDist[axis] > 0.0f)
12014 float snap_min = 0.0f;
12015 float snap_max = window->ScrollMax[axis] + window->SizeFull[axis] - decoration_size[axis];
12016 scroll_target = CalcScrollEdgeSnap(scroll_target, snap_min, snap_max, window->ScrollTargetEdgeSnapDist[axis], center_ratio);
12018 scroll[axis] = scroll_target - center_ratio * (window->SizeFull[axis] - decoration_size[axis]);
12020 scroll[axis] = IM_ROUND(ImMax(scroll[axis], 0.0f));
12021 if (!window->Collapsed && !window->SkipItems)
12022 scroll[axis] = ImMin(scroll[axis], window->ScrollMax[axis]);
12027void ImGui::ScrollToItem(ImGuiScrollFlags flags)
12030 ImGuiWindow* window =
g.CurrentWindow;
12031 ScrollToRectEx(window,
g.LastItemData.NavRect, flags);
12034void ImGui::ScrollToRect(ImGuiWindow* window,
const ImRect& item_rect, ImGuiScrollFlags flags)
12036 ScrollToRectEx(window, item_rect, flags);
12040ImVec2 ImGui::ScrollToRectEx(ImGuiWindow* window,
const ImRect& item_rect, ImGuiScrollFlags flags)
12043 ImRect scroll_rect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1));
12044 scroll_rect.Min.x = ImMin(scroll_rect.Min.x + window->DecoInnerSizeX1, scroll_rect.Max.x);
12045 scroll_rect.Min.y = ImMin(scroll_rect.Min.y + window->DecoInnerSizeY1, scroll_rect.Max.y);
12050 IM_ASSERT((flags & ImGuiScrollFlags_MaskX_) == 0 || ImIsPowerOfTwo(flags & ImGuiScrollFlags_MaskX_));
12051 IM_ASSERT((flags & ImGuiScrollFlags_MaskY_) == 0 || ImIsPowerOfTwo(flags & ImGuiScrollFlags_MaskY_));
12054 ImGuiScrollFlags in_flags = flags;
12055 if ((flags & ImGuiScrollFlags_MaskX_) == 0 && window->ScrollbarX)
12056 flags |= ImGuiScrollFlags_KeepVisibleEdgeX;
12057 if ((flags & ImGuiScrollFlags_MaskY_) == 0)
12058 flags |= window->Appearing ? ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeY;
12060 const bool fully_visible_x = item_rect.Min.x >= scroll_rect.Min.x && item_rect.Max.x <= scroll_rect.Max.x;
12061 const bool fully_visible_y = item_rect.Min.y >= scroll_rect.Min.y && item_rect.Max.y <= scroll_rect.Max.y;
12062 const bool can_be_fully_visible_x = (item_rect.GetWidth() +
g.Style.ItemSpacing.x * 2.0f) <= scroll_rect.GetWidth() || (window->AutoFitFramesX > 0) || (window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0;
12063 const bool can_be_fully_visible_y = (item_rect.GetHeight() +
g.Style.ItemSpacing.y * 2.0f) <= scroll_rect.GetHeight() || (window->AutoFitFramesY > 0) || (window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0;
12065 if ((flags & ImGuiScrollFlags_KeepVisibleEdgeX) && !fully_visible_x)
12067 if (item_rect.Min.x < scroll_rect.Min.x || !can_be_fully_visible_x)
12068 SetScrollFromPosX(window, item_rect.Min.x -
g.Style.ItemSpacing.x - window->Pos.x, 0.0f);
12069 else if (item_rect.Max.x >= scroll_rect.Max.x)
12070 SetScrollFromPosX(window, item_rect.Max.x +
g.Style.ItemSpacing.x - window->Pos.x, 1.0f);
12072 else if (((flags & ImGuiScrollFlags_KeepVisibleCenterX) && !fully_visible_x) || (flags & ImGuiScrollFlags_AlwaysCenterX))
12074 if (can_be_fully_visible_x)
12075 SetScrollFromPosX(window, ImTrunc((item_rect.Min.x + item_rect.Max.x) * 0.5f) - window->Pos.x, 0.5f);
12077 SetScrollFromPosX(window, item_rect.Min.x - window->Pos.x, 0.0f);
12080 if ((flags & ImGuiScrollFlags_KeepVisibleEdgeY) && !fully_visible_y)
12082 if (item_rect.Min.y < scroll_rect.Min.y || !can_be_fully_visible_y)
12083 SetScrollFromPosY(window, item_rect.Min.y -
g.Style.ItemSpacing.y - window->Pos.y, 0.0f);
12084 else if (item_rect.Max.y >= scroll_rect.Max.y)
12085 SetScrollFromPosY(window, item_rect.Max.y +
g.Style.ItemSpacing.y - window->Pos.y, 1.0f);
12087 else if (((flags & ImGuiScrollFlags_KeepVisibleCenterY) && !fully_visible_y) || (flags & ImGuiScrollFlags_AlwaysCenterY))
12089 if (can_be_fully_visible_y)
12090 SetScrollFromPosY(window, ImTrunc((item_rect.Min.y + item_rect.Max.y) * 0.5f) - window->Pos.y, 0.5f);
12092 SetScrollFromPosY(window, item_rect.Min.y - window->Pos.y, 0.0f);
12095 ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
12096 ImVec2 delta_scroll = next_scroll - window->Scroll;
12099 if (!(flags & ImGuiScrollFlags_NoScrollParent) && (window->Flags & ImGuiWindowFlags_ChildWindow))
12102 if ((in_flags & (ImGuiScrollFlags_AlwaysCenterX | ImGuiScrollFlags_KeepVisibleCenterX)) != 0)
12103 in_flags = (in_flags & ~ImGuiScrollFlags_MaskX_) | ImGuiScrollFlags_KeepVisibleEdgeX;
12104 if ((in_flags & (ImGuiScrollFlags_AlwaysCenterY | ImGuiScrollFlags_KeepVisibleCenterY)) != 0)
12105 in_flags = (in_flags & ~ImGuiScrollFlags_MaskY_) | ImGuiScrollFlags_KeepVisibleEdgeY;
12106 delta_scroll += ScrollToRectEx(window->ParentWindow, ImRect(item_rect.Min - delta_scroll, item_rect.Max - delta_scroll), in_flags);
12109 return delta_scroll;
12112float ImGui::GetScrollX()
12114 ImGuiWindow* window =
GImGui->CurrentWindow;
12115 return window->Scroll.x;
12118float ImGui::GetScrollY()
12120 ImGuiWindow* window =
GImGui->CurrentWindow;
12121 return window->Scroll.y;
12124float ImGui::GetScrollMaxX()
12126 ImGuiWindow* window =
GImGui->CurrentWindow;
12127 return window->ScrollMax.x;
12130float ImGui::GetScrollMaxY()
12132 ImGuiWindow* window =
GImGui->CurrentWindow;
12133 return window->ScrollMax.y;
12136void ImGui::SetScrollX(ImGuiWindow* window,
float scroll_x)
12138 window->ScrollTarget.x = scroll_x;
12139 window->ScrollTargetCenterRatio.x = 0.0f;
12140 window->ScrollTargetEdgeSnapDist.x = 0.0f;
12143void ImGui::SetScrollY(ImGuiWindow* window,
float scroll_y)
12145 window->ScrollTarget.y = scroll_y;
12146 window->ScrollTargetCenterRatio.y = 0.0f;
12147 window->ScrollTargetEdgeSnapDist.y = 0.0f;
12150void ImGui::SetScrollX(
float scroll_x)
12153 SetScrollX(
g.CurrentWindow, scroll_x);
12156void ImGui::SetScrollY(
float scroll_y)
12159 SetScrollY(
g.CurrentWindow, scroll_y);
12172void ImGui::SetScrollFromPosX(ImGuiWindow* window,
float local_x,
float center_x_ratio)
12174 IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f);
12175 window->ScrollTarget.x = IM_TRUNC(local_x - window->DecoOuterSizeX1 - window->DecoInnerSizeX1 + window->Scroll.x);
12176 window->ScrollTargetCenterRatio.x = center_x_ratio;
12177 window->ScrollTargetEdgeSnapDist.x = 0.0f;
12180void ImGui::SetScrollFromPosY(ImGuiWindow* window,
float local_y,
float center_y_ratio)
12182 IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f);
12183 window->ScrollTarget.y = IM_TRUNC(local_y - window->DecoOuterSizeY1 - window->DecoInnerSizeY1 + window->Scroll.y);
12184 window->ScrollTargetCenterRatio.y = center_y_ratio;
12185 window->ScrollTargetEdgeSnapDist.y = 0.0f;
12188void ImGui::SetScrollFromPosX(
float local_x,
float center_x_ratio)
12191 SetScrollFromPosX(
g.CurrentWindow, local_x, center_x_ratio);
12194void ImGui::SetScrollFromPosY(
float local_y,
float center_y_ratio)
12197 SetScrollFromPosY(
g.CurrentWindow, local_y, center_y_ratio);
12201void ImGui::SetScrollHereX(
float center_x_ratio)
12204 ImGuiWindow* window =
g.CurrentWindow;
12205 float spacing_x = ImMax(window->WindowPadding.x,
g.Style.ItemSpacing.x);
12206 float target_pos_x = ImLerp(
g.LastItemData.Rect.Min.x - spacing_x,
g.LastItemData.Rect.Max.x + spacing_x, center_x_ratio);
12207 SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio);
12210 window->ScrollTargetEdgeSnapDist.x = ImMax(0.0f, window->WindowPadding.x - spacing_x);
12214void ImGui::SetScrollHereY(
float center_y_ratio)
12217 ImGuiWindow* window =
g.CurrentWindow;
12218 float spacing_y = ImMax(window->WindowPadding.y,
g.Style.ItemSpacing.y);
12219 float target_pos_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y, window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y, center_y_ratio);
12220 SetScrollFromPosY(window, target_pos_y - window->Pos.y, center_y_ratio);
12223 window->ScrollTargetEdgeSnapDist.y = ImMax(0.0f, window->WindowPadding.y - spacing_y);
12230bool ImGui::BeginTooltip()
12232 return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None);
12235bool ImGui::BeginItemTooltip()
12237 if (!IsItemHovered(ImGuiHoveredFlags_ForTooltip))
12239 return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None);
12242bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags)
12246 const bool is_dragdrop_tooltip =
g.DragDropWithinSource ||
g.DragDropWithinTarget;
12247 if (is_dragdrop_tooltip)
12255 const bool is_touchscreen = (
g.IO.MouseSource == ImGuiMouseSource_TouchScreen);
12256 if ((
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0)
12258 ImVec2 tooltip_pos = is_touchscreen ? (
g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_TOUCH *
g.Style.MouseCursorScale) : (
g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_MOUSE *
g.Style.MouseCursorScale);
12259 ImVec2 tooltip_pivot = is_touchscreen ? TOOLTIP_DEFAULT_PIVOT_TOUCH : ImVec2(0.0f, 0.0f);
12260 SetNextWindowPos(tooltip_pos, ImGuiCond_None, tooltip_pivot);
12263 SetNextWindowBgAlpha(
g.Style.Colors[ImGuiCol_PopupBg].w * 0.60f);
12265 tooltip_flags |= ImGuiTooltipFlags_OverridePrevious;
12268 const char* window_name_template = is_dragdrop_tooltip ?
"##Tooltip_DragDrop_%02d" :
"##Tooltip_%02d";
12269 char window_name[32];
12270 ImFormatString(window_name, IM_ARRAYSIZE(window_name), window_name_template,
g.TooltipOverrideCount);
12271 if ((tooltip_flags & ImGuiTooltipFlags_OverridePrevious) &&
g.TooltipPreviousWindow != NULL &&
g.TooltipPreviousWindow->Active)
12275 SetWindowHiddenAndSkipItemsForCurrentFrame(
g.TooltipPreviousWindow);
12276 ImFormatString(window_name, IM_ARRAYSIZE(window_name), window_name_template, ++
g.TooltipOverrideCount);
12279 ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDocking;
12280 Begin(window_name, NULL, flags | extra_window_flags);
12289void ImGui::EndTooltip()
12291 IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip);
12295void ImGui::SetTooltip(
const char* fmt, ...)
12298 va_start(args, fmt);
12299 SetTooltipV(fmt, args);
12303void ImGui::SetTooltipV(
const char* fmt, va_list args)
12305 if (!BeginTooltipEx(ImGuiTooltipFlags_OverridePrevious, ImGuiWindowFlags_None))
12313void ImGui::SetItemTooltip(
const char* fmt, ...)
12316 va_start(args, fmt);
12317 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip))
12318 SetTooltipV(fmt, args);
12322void ImGui::SetItemTooltipV(
const char* fmt, va_list args)
12324 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip))
12325 SetTooltipV(fmt, args);
12334bool ImGui::IsPopupOpen(ImGuiID
id, ImGuiPopupFlags popup_flags)
12337 if (popup_flags & ImGuiPopupFlags_AnyPopupId)
12341 IM_ASSERT(
id == 0);
12342 if (popup_flags & ImGuiPopupFlags_AnyPopupLevel)
12343 return g.OpenPopupStack.Size > 0;
12345 return g.OpenPopupStack.Size >
g.BeginPopupStack.Size;
12349 if (popup_flags & ImGuiPopupFlags_AnyPopupLevel)
12352 for (ImGuiPopupData& popup_data :
g.OpenPopupStack)
12353 if (popup_data.PopupId ==
id)
12360 return g.OpenPopupStack.Size >
g.BeginPopupStack.Size &&
g.OpenPopupStack[
g.BeginPopupStack.Size].PopupId ==
id;
12365bool ImGui::IsPopupOpen(
const char* str_id, ImGuiPopupFlags popup_flags)
12368 ImGuiID
id = (popup_flags & ImGuiPopupFlags_AnyPopupId) ? 0 :
g.CurrentWindow->GetID(str_id);
12369 if ((popup_flags & ImGuiPopupFlags_AnyPopupLevel) &&
id != 0)
12370 IM_ASSERT(0 &&
"Cannot use IsPopupOpen() with a string id and ImGuiPopupFlags_AnyPopupLevel.");
12371 return IsPopupOpen(
id, popup_flags);
12375ImGuiWindow* ImGui::GetTopMostPopupModal()
12378 for (
int n =
g.OpenPopupStack.Size - 1; n >= 0; n--)
12379 if (ImGuiWindow* popup =
g.OpenPopupStack.Data[n].Window)
12380 if (popup->Flags & ImGuiWindowFlags_Modal)
12386ImGuiWindow* ImGui::GetTopMostAndVisiblePopupModal()
12389 for (
int n =
g.OpenPopupStack.Size - 1; n >= 0; n--)
12390 if (ImGuiWindow* popup =
g.OpenPopupStack.Data[n].Window)
12391 if ((popup->Flags & ImGuiWindowFlags_Modal) && IsWindowActiveAndVisible(popup))
12396void ImGui::OpenPopup(
const char* str_id, ImGuiPopupFlags popup_flags)
12399 ImGuiID
id =
g.CurrentWindow->GetID(str_id);
12400 IMGUI_DEBUG_LOG_POPUP(
"[popup] OpenPopup(\"%s\" -> 0x%08X)\n", str_id,
id);
12401 OpenPopupEx(
id, popup_flags);
12404void ImGui::OpenPopup(ImGuiID
id, ImGuiPopupFlags popup_flags)
12406 OpenPopupEx(
id, popup_flags);
12413void ImGui::OpenPopupEx(ImGuiID
id, ImGuiPopupFlags popup_flags)
12416 ImGuiWindow* parent_window =
g.CurrentWindow;
12417 const int current_stack_size =
g.BeginPopupStack.Size;
12419 if (popup_flags & ImGuiPopupFlags_NoOpenOverExistingPopup)
12420 if (IsPopupOpen((ImGuiID)0, ImGuiPopupFlags_AnyPopupId))
12423 ImGuiPopupData popup_ref;
12424 popup_ref.PopupId =
id;
12425 popup_ref.Window = NULL;
12426 popup_ref.RestoreNavWindow =
g.NavWindow;
12427 popup_ref.OpenFrameCount =
g.FrameCount;
12428 popup_ref.OpenParentId = parent_window->IDStack.back();
12429 popup_ref.OpenPopupPos = NavCalcPreferredRefPos();
12430 popup_ref.OpenMousePos = IsMousePosValid(&
g.IO.MousePos) ?
g.IO.MousePos : popup_ref.OpenPopupPos;
12432 IMGUI_DEBUG_LOG_POPUP(
"[popup] OpenPopupEx(0x%08X)\n",
id);
12433 if (
g.OpenPopupStack.Size < current_stack_size + 1)
12435 g.OpenPopupStack.push_back(popup_ref);
12443 bool keep_existing =
false;
12444 if (
g.OpenPopupStack[current_stack_size].PopupId ==
id)
12445 if ((
g.OpenPopupStack[current_stack_size].OpenFrameCount ==
g.FrameCount - 1) || (popup_flags & ImGuiPopupFlags_NoReopen))
12446 keep_existing =
true;
12450 g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount;
12455 ClosePopupToLevel(current_stack_size,
true);
12456 g.OpenPopupStack.push_back(popup_ref);
12468void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window,
bool restore_focus_to_window_under_popup)
12471 if (
g.OpenPopupStack.Size == 0)
12476 int popup_count_to_keep = 0;
12480 for (; popup_count_to_keep <
g.OpenPopupStack.Size; popup_count_to_keep++)
12482 ImGuiPopupData& popup =
g.OpenPopupStack[popup_count_to_keep];
12485 IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0);
12495 bool ref_window_is_descendent_of_popup =
false;
12496 for (
int n = popup_count_to_keep; n <
g.OpenPopupStack.Size; n++)
12497 if (ImGuiWindow* popup_window =
g.OpenPopupStack[n].Window)
12499 if (IsWindowWithinBeginStackOf(ref_window, popup_window))
12501 ref_window_is_descendent_of_popup =
true;
12504 if (!ref_window_is_descendent_of_popup)
12508 if (popup_count_to_keep <
g.OpenPopupStack.Size)
12510 IMGUI_DEBUG_LOG_POPUP(
"[popup] ClosePopupsOverWindow(\"%s\")\n", ref_window ? ref_window->Name :
"<NULL>");
12511 ClosePopupToLevel(popup_count_to_keep, restore_focus_to_window_under_popup);
12515void ImGui::ClosePopupsExceptModals()
12519 int popup_count_to_keep;
12520 for (popup_count_to_keep =
g.OpenPopupStack.Size; popup_count_to_keep > 0; popup_count_to_keep--)
12522 ImGuiWindow* window =
g.OpenPopupStack[popup_count_to_keep - 1].Window;
12523 if (!window || (window->Flags & ImGuiWindowFlags_Modal))
12526 if (popup_count_to_keep <
g.OpenPopupStack.Size)
12527 ClosePopupToLevel(popup_count_to_keep,
true);
12530void ImGui::ClosePopupToLevel(
int remaining,
bool restore_focus_to_window_under_popup)
12533 IMGUI_DEBUG_LOG_POPUP(
"[popup] ClosePopupToLevel(%d), restore_under=%d\n", remaining, restore_focus_to_window_under_popup);
12534 IM_ASSERT(remaining >= 0 && remaining <
g.OpenPopupStack.Size);
12535 if (
g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup)
12536 for (
int n = remaining; n <
g.OpenPopupStack.Size; n++)
12537 IMGUI_DEBUG_LOG_POPUP(
"[popup] - Closing PopupID 0x%08X Window \"%s\"\n",
g.OpenPopupStack[n].PopupId,
g.OpenPopupStack[n].Window ?
g.OpenPopupStack[n].Window->Name : NULL);
12540 ImGuiPopupData prev_popup =
g.OpenPopupStack[remaining];
12541 g.OpenPopupStack.resize(remaining);
12544 if (restore_focus_to_window_under_popup && prev_popup.Window)
12546 ImGuiWindow* popup_window = prev_popup.Window;
12547 ImGuiWindow* focus_window = (popup_window->Flags & ImGuiWindowFlags_ChildMenu) ? popup_window->ParentWindow : prev_popup.RestoreNavWindow;
12548 if (focus_window && !focus_window->WasActive)
12549 FocusTopMostWindowUnderOne(popup_window, NULL, NULL, ImGuiFocusRequestFlags_RestoreFocusedChild);
12551 FocusWindow(focus_window, (
g.NavLayer == ImGuiNavLayer_Main) ? ImGuiFocusRequestFlags_RestoreFocusedChild : ImGuiFocusRequestFlags_None);
12556void ImGui::CloseCurrentPopup()
12559 int popup_idx =
g.BeginPopupStack.Size - 1;
12560 if (popup_idx < 0 || popup_idx >=
g.OpenPopupStack.Size ||
g.BeginPopupStack[popup_idx].PopupId !=
g.OpenPopupStack[popup_idx].PopupId)
12564 while (popup_idx > 0)
12566 ImGuiWindow* popup_window =
g.OpenPopupStack[popup_idx].Window;
12567 ImGuiWindow* parent_popup_window =
g.OpenPopupStack[popup_idx - 1].Window;
12568 bool close_parent =
false;
12569 if (popup_window && (popup_window->Flags & ImGuiWindowFlags_ChildMenu))
12570 if (parent_popup_window && !(parent_popup_window->Flags & ImGuiWindowFlags_MenuBar))
12571 close_parent =
true;
12576 IMGUI_DEBUG_LOG_POPUP(
"[popup] CloseCurrentPopup %d -> %d\n",
g.BeginPopupStack.Size - 1, popup_idx);
12577 ClosePopupToLevel(popup_idx,
true);
12582 if (ImGuiWindow* window =
g.NavWindow)
12583 window->DC.NavHideHighlightOneFrame =
true;
12587bool ImGui::BeginPopupEx(ImGuiID
id, ImGuiWindowFlags extra_window_flags)
12590 if (!IsPopupOpen(
id, ImGuiPopupFlags_None))
12592 g.NextWindowData.ClearFlags();
12597 if (extra_window_flags & ImGuiWindowFlags_ChildMenu)
12598 ImFormatString(name, IM_ARRAYSIZE(name),
"##Menu_%02d",
g.BeginMenuDepth);
12602 bool is_open = Begin(name, NULL, extra_window_flags | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoDocking);
12611bool ImGui::BeginPopup(
const char* str_id, ImGuiWindowFlags flags)
12614 if (
g.OpenPopupStack.Size <=
g.BeginPopupStack.Size)
12616 g.NextWindowData.ClearFlags();
12619 flags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings;
12620 ImGuiID
id =
g.CurrentWindow->GetID(str_id);
12621 return BeginPopupEx(
id, flags);
12628bool ImGui::BeginPopupModal(
const char* name,
bool* p_open, ImGuiWindowFlags flags)
12631 ImGuiWindow* window =
g.CurrentWindow;
12632 const ImGuiID
id = window->GetID(name);
12633 if (!IsPopupOpen(
id, ImGuiPopupFlags_None))
12635 g.NextWindowData.ClearFlags();
12636 if (p_open && *p_open)
12644 if ((
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0)
12646 const ImGuiViewport* viewport = window->WasActive ? window->Viewport : GetMainViewport();
12647 SetNextWindowPos(viewport->GetCenter(), ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f));
12650 flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDocking;
12651 const bool is_open = Begin(name, p_open, flags);
12652 if (!is_open || (p_open && !*p_open))
12656 ClosePopupToLevel(
g.BeginPopupStack.Size,
true);
12662void ImGui::EndPopup()
12665 ImGuiWindow* window =
g.CurrentWindow;
12666 IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup);
12667 IM_ASSERT(
g.BeginPopupStack.Size > 0);
12670 if (
g.NavWindow == window)
12671 NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY);
12674 IM_ASSERT(
g.WithinEndChild ==
false);
12675 if (window->Flags & ImGuiWindowFlags_ChildWindow)
12676 g.WithinEndChild =
true;
12678 g.WithinEndChild =
false;
12683void ImGui::OpenPopupOnItemClick(
const char* str_id, ImGuiPopupFlags popup_flags)
12686 ImGuiWindow* window =
g.CurrentWindow;
12687 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
12688 if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
12690 ImGuiID
id = str_id ? window->GetID(str_id) :
g.LastItemData.ID;
12691 IM_ASSERT(
id != 0);
12692 OpenPopupEx(
id, popup_flags);
12712bool ImGui::BeginPopupContextItem(
const char* str_id, ImGuiPopupFlags popup_flags)
12715 ImGuiWindow* window =
g.CurrentWindow;
12716 if (window->SkipItems)
12718 ImGuiID
id = str_id ? window->GetID(str_id) :
g.LastItemData.ID;
12719 IM_ASSERT(
id != 0);
12720 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
12721 if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
12722 OpenPopupEx(
id, popup_flags);
12723 return BeginPopupEx(
id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
12726bool ImGui::BeginPopupContextWindow(
const char* str_id, ImGuiPopupFlags popup_flags)
12729 ImGuiWindow* window =
g.CurrentWindow;
12731 str_id =
"window_context";
12732 ImGuiID
id = window->GetID(str_id);
12733 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
12734 if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
12735 if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
12736 OpenPopupEx(
id, popup_flags);
12737 return BeginPopupEx(
id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
12740bool ImGui::BeginPopupContextVoid(
const char* str_id, ImGuiPopupFlags popup_flags)
12743 ImGuiWindow* window =
g.CurrentWindow;
12745 str_id =
"void_context";
12746 ImGuiID
id = window->GetID(str_id);
12747 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
12748 if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
12749 if (GetTopMostPopupModal() == NULL)
12750 OpenPopupEx(
id, popup_flags);
12751 return BeginPopupEx(
id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
12759ImVec2 ImGui::FindBestWindowPosForPopupEx(
const ImVec2& ref_pos,
const ImVec2& size, ImGuiDir* last_dir,
const ImRect& r_outer,
const ImRect& r_avoid, ImGuiPopupPositionPolicy policy)
12761 ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size);
12766 if (policy == ImGuiPopupPositionPolicy_ComboBox)
12768 const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Down, ImGuiDir_Right, ImGuiDir_Left, ImGuiDir_Up };
12769 for (
int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
12771 const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
12772 if (n != -1 && dir == *last_dir)
12775 if (dir == ImGuiDir_Down) pos = ImVec2(r_avoid.Min.x, r_avoid.Max.y);
12776 if (dir == ImGuiDir_Right) pos = ImVec2(r_avoid.Min.x, r_avoid.Min.y -
size.y);
12777 if (dir == ImGuiDir_Left) pos = ImVec2(r_avoid.Max.x -
size.x, r_avoid.Max.y);
12778 if (dir == ImGuiDir_Up) pos = ImVec2(r_avoid.Max.x -
size.x, r_avoid.Min.y -
size.y);
12779 if (!r_outer.Contains(ImRect(pos, pos + size)))
12788 if (policy == ImGuiPopupPositionPolicy_Tooltip || policy == ImGuiPopupPositionPolicy_Default)
12790 const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left };
12791 for (
int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
12793 const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
12794 if (n != -1 && dir == *last_dir)
12797 const float avail_w = (dir == ImGuiDir_Left ? r_avoid.Min.x : r_outer.Max.x) - (dir == ImGuiDir_Right ? r_avoid.Max.x : r_outer.Min.x);
12798 const float avail_h = (dir == ImGuiDir_Up ? r_avoid.Min.y : r_outer.Max.y) - (dir == ImGuiDir_Down ? r_avoid.Max.y : r_outer.Min.y);
12801 if (avail_w <
size.x && (dir == ImGuiDir_Left || dir == ImGuiDir_Right))
12803 if (avail_h <
size.y && (dir == ImGuiDir_Up || dir == ImGuiDir_Down))
12807 pos.x = (dir == ImGuiDir_Left) ? r_avoid.Min.x -
size.x : (dir == ImGuiDir_Right) ? r_avoid.Max.x : base_pos_clamped.x;
12808 pos.y = (dir == ImGuiDir_Up) ? r_avoid.Min.y -
size.y : (dir == ImGuiDir_Down) ? r_avoid.Max.y : base_pos_clamped.y;
12811 pos.x = ImMax(pos.x, r_outer.Min.x);
12812 pos.y = ImMax(pos.y, r_outer.Min.y);
12820 *last_dir = ImGuiDir_None;
12823 if (policy == ImGuiPopupPositionPolicy_Tooltip)
12824 return ref_pos + ImVec2(2, 2);
12827 ImVec2 pos = ref_pos;
12828 pos.x = ImMax(ImMin(pos.x +
size.x, r_outer.Max.x) -
size.x, r_outer.Min.x);
12829 pos.y = ImMax(ImMin(pos.y +
size.y, r_outer.Max.y) -
size.y, r_outer.Min.y);
12834ImRect ImGui::GetPopupAllowedExtentRect(ImGuiWindow* window)
12838 if (window->ViewportAllowPlatformMonitorExtend >= 0)
12841 const ImGuiPlatformMonitor& monitor =
g.PlatformIO.Monitors[window->ViewportAllowPlatformMonitorExtend];
12842 r_screen.Min = monitor.WorkPos;
12843 r_screen.Max = monitor.WorkPos + monitor.WorkSize;
12848 r_screen = window->Viewport->GetMainRect();
12850 ImVec2 padding =
g.Style.DisplaySafeAreaPadding;
12851 r_screen.Expand(ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f, (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f));
12855ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
12859 ImRect r_outer = GetPopupAllowedExtentRect(window);
12860 if (window->Flags & ImGuiWindowFlags_ChildMenu)
12864 ImGuiWindow* parent_window = window->ParentWindow;
12865 float horizontal_overlap =
g.Style.ItemInnerSpacing.x;
12867 if (parent_window->DC.MenuBarAppending)
12868 r_avoid = ImRect(-FLT_MAX, parent_window->ClipRect.Min.y, FLT_MAX, parent_window->ClipRect.Max.y);
12870 r_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX);
12871 return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Default);
12873 if (window->Flags & ImGuiWindowFlags_Popup)
12875 return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, ImRect(window->Pos, window->Pos), ImGuiPopupPositionPolicy_Default);
12877 if (window->Flags & ImGuiWindowFlags_Tooltip)
12885 IM_ASSERT(
g.CurrentWindow == window);
12886 const float scale =
g.Style.MouseCursorScale;
12887 const ImVec2 ref_pos = NavCalcPreferredRefPos();
12889 if (
g.IO.MouseSource == ImGuiMouseSource_TouchScreen && NavCalcPreferredRefPosSource() == ImGuiInputSource_Mouse)
12891 ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET_TOUCH *
scale - (TOOLTIP_DEFAULT_PIVOT_TOUCH * window->Size);
12892 if (r_outer.Contains(ImRect(tooltip_pos, tooltip_pos + window->Size)))
12893 return tooltip_pos;
12896 ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET_MOUSE *
scale;
12898 if (
g.NavCursorVisible &&
g.NavHighlightItemUnderNav && !
g.IO.ConfigNavMoveSetMousePos)
12899 r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
12901 r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * scale, ref_pos.y + 24 * scale);
12904 return FindBestWindowPosForPopupEx(tooltip_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Tooltip);
12907 return window->Pos;
12918void ImGui::SetNavCursorVisible(
bool visible)
12921 if (
g.IO.ConfigNavCursorVisibleAlways)
12923 g.NavCursorVisible = visible;
12927void ImGui::SetNavCursorVisibleAfterMove()
12930 if (
g.IO.ConfigNavCursorVisibleAuto)
12931 g.NavCursorVisible =
true;
12932 g.NavHighlightItemUnderNav =
g.NavMousePosDirty =
true;
12935void ImGui::SetNavWindow(ImGuiWindow* window)
12938 if (
g.NavWindow != window)
12940 IMGUI_DEBUG_LOG_FOCUS(
"[focus] SetNavWindow(\"%s\")\n", window ? window->Name :
"<NULL>");
12941 g.NavWindow = window;
12942 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
12944 g.NavInitRequest =
g.NavMoveSubmitted =
g.NavMoveScoringItems =
false;
12945 NavUpdateAnyRequestFlag();
12948void ImGui::NavHighlightActivated(ImGuiID
id)
12951 g.NavHighlightActivatedId =
id;
12952 g.NavHighlightActivatedTimer = NAV_ACTIVATE_HIGHLIGHT_TIMER;
12955void ImGui::NavClearPreferredPosForAxis(ImGuiAxis axis)
12958 g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[
g.NavLayer][axis] = FLT_MAX;
12961void ImGui::SetNavID(ImGuiID
id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id,
const ImRect& rect_rel)
12964 IM_ASSERT(
g.NavWindow != NULL);
12965 IM_ASSERT(nav_layer == ImGuiNavLayer_Main || nav_layer == ImGuiNavLayer_Menu);
12967 g.NavLayer = nav_layer;
12968 SetNavFocusScope(focus_scope_id);
12969 g.NavWindow->NavLastIds[nav_layer] =
id;
12970 g.NavWindow->NavRectRel[nav_layer] = rect_rel;
12973 NavClearPreferredPosForAxis(ImGuiAxis_X);
12974 NavClearPreferredPosForAxis(ImGuiAxis_Y);
12977void ImGui::SetFocusID(ImGuiID
id, ImGuiWindow* window)
12980 IM_ASSERT(
id != 0);
12982 if (
g.NavWindow != window)
12983 SetNavWindow(window);
12987 const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent;
12989 g.NavLayer = nav_layer;
12990 SetNavFocusScope(
g.CurrentFocusScopeId);
12991 window->NavLastIds[nav_layer] =
id;
12992 if (
g.LastItemData.ID ==
id)
12993 window->NavRectRel[nav_layer] = WindowRectAbsToRel(window,
g.LastItemData.NavRect);
12995 if (
g.ActiveIdSource == ImGuiInputSource_Keyboard ||
g.ActiveIdSource == ImGuiInputSource_Gamepad)
12996 g.NavHighlightItemUnderNav =
true;
12997 else if (
g.IO.ConfigNavCursorVisibleAuto)
12998 g.NavCursorVisible =
false;
13001 NavClearPreferredPosForAxis(ImGuiAxis_X);
13002 NavClearPreferredPosForAxis(ImGuiAxis_Y);
13005static ImGuiDir ImGetDirQuadrantFromDelta(
float dx,
float dy)
13007 if (ImFabs(dx) > ImFabs(dy))
13008 return (dx > 0.0f) ? ImGuiDir_Right : ImGuiDir_Left;
13009 return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up;
13012static float inline NavScoreItemDistInterval(
float cand_min,
float cand_max,
float curr_min,
float curr_max)
13014 if (cand_max < curr_min)
13015 return cand_max - curr_min;
13016 if (curr_max < cand_min)
13017 return cand_min - curr_max;
13022static bool ImGui::NavScoreItem(ImGuiNavItemData* result)
13025 ImGuiWindow* window =
g.CurrentWindow;
13026 if (
g.NavLayer != window->DC.NavLayerCurrent)
13030 ImRect cand =
g.LastItemData.NavRect;
13031 const ImRect curr =
g.NavScoringRect;
13032 g.NavScoringDebugCount++;
13035 if (window->ParentWindow ==
g.NavWindow)
13037 IM_ASSERT((window->ChildFlags |
g.NavWindow->ChildFlags) & ImGuiChildFlags_NavFlattened);
13038 if (!window->ClipRect.Overlaps(cand))
13040 cand.ClipWithFull(window->ClipRect);
13045 float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x);
13046 float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f));
13047 if (dby != 0.0f && dbx != 0.0f)
13048 dbx = (dbx / 1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f);
13049 float dist_box = ImFabs(dbx) + ImFabs(dby);
13052 float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x);
13053 float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y);
13054 float dist_center = ImFabs(dcx) + ImFabs(dcy);
13058 float dax = 0.0f, day = 0.0f, dist_axial = 0.0f;
13059 if (dbx != 0.0f || dby != 0.0f)
13067 dist_axial = dist_box;
13068 quadrant = ImGetDirQuadrantFromDelta(dbx, dby);
13070 else if (dcx != 0.0f || dcy != 0.0f)
13075 dist_axial = dist_center;
13076 quadrant = ImGetDirQuadrantFromDelta(dcx, dcy);
13081 quadrant = (
g.LastItemData.ID <
g.NavId) ? ImGuiDir_Left : ImGuiDir_Right;
13084 const ImGuiDir move_dir =
g.NavMoveDir;
13085#if IMGUI_DEBUG_NAV_SCORING
13089 if (quadrant == move_dir)
13091 ImFormatString(buf, IM_ARRAYSIZE(buf),
"%.0f/%.0f", dist_box, dist_center);
13092 ImDrawList* draw_list = GetForegroundDrawList(window);
13093 draw_list->AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 80));
13094 draw_list->AddRectFilled(cand.Min, cand.Min +
CalcTextSize(buf), IM_COL32(255, 0, 0, 200));
13095 draw_list->AddText(cand.Min, IM_COL32(255, 255, 255, 255), buf);
13098 const bool debug_hovering = IsMouseHoveringRect(cand.Min, cand.Max);
13099 const bool debug_tty = (
g.IO.KeyCtrl && IsKeyPressed(ImGuiKey_Space));
13100 if (debug_hovering || debug_tty)
13103 "d-box (%7.3f,%7.3f) -> %7.3f\nd-center (%7.3f,%7.3f) -> %7.3f\nd-axial (%7.3f,%7.3f) -> %7.3f\nnav %c, quadrant %c",
13104 dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial,
"-WENS"[move_dir+1],
"-WENS"[quadrant+1]);
13105 if (debug_hovering)
13107 ImDrawList* draw_list = GetForegroundDrawList(window);
13108 draw_list->AddRect(curr.Min, curr.Max, IM_COL32(255, 200, 0, 100));
13109 draw_list->AddRect(cand.Min, cand.Max, IM_COL32(255, 255, 0, 200));
13110 draw_list->AddRectFilled(cand.Max - ImVec2(4, 4), cand.Max +
CalcTextSize(buf) + ImVec2(4, 4), IM_COL32(40, 0, 0, 200));
13111 draw_list->AddText(cand.Max, ~0U, buf);
13113 if (debug_tty) { IMGUI_DEBUG_LOG_NAV(
"id 0x%08X\n%s\n",
g.LastItemData.ID, buf); }
13118 bool new_best =
false;
13119 if (quadrant == move_dir)
13122 if (dist_box < result->DistBox)
13124 result->DistBox = dist_box;
13125 result->DistCenter = dist_center;
13128 if (dist_box == result->DistBox)
13131 if (dist_center < result->DistCenter)
13133 result->DistCenter = dist_center;
13136 else if (dist_center == result->DistCenter)
13141 if (((move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) ? dby : dbx) < 0.0f)
13152 if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial)
13153 if (
g.NavLayer == ImGuiNavLayer_Menu && !(
g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
13154 if ((move_dir == ImGuiDir_Left && dax < 0.0f) || (move_dir == ImGuiDir_Right && dax > 0.0f) || (move_dir == ImGuiDir_Up && day < 0.0f) || (move_dir == ImGuiDir_Down && day > 0.0f))
13156 result->DistAxial = dist_axial;
13163static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result)
13166 ImGuiWindow* window =
g.CurrentWindow;
13167 result->Window = window;
13168 result->ID =
g.LastItemData.ID;
13169 result->FocusScopeId =
g.CurrentFocusScopeId;
13170 result->ItemFlags =
g.LastItemData.ItemFlags;
13171 result->RectRel = WindowRectAbsToRel(window,
g.LastItemData.NavRect);
13172 if (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData)
13174 IM_ASSERT(
g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
13175 result->SelectionUserData =
g.NextItemData.SelectionUserData;
13181void ImGui::NavUpdateCurrentWindowIsScrollPushableX()
13184 ImGuiWindow* window =
g.CurrentWindow;
13185 window->DC.NavIsScrollPushableX = (
g.CurrentTable == NULL && window->DC.CurrentColumns == NULL);
13190static void ImGui::NavProcessItem()
13193 ImGuiWindow* window =
g.CurrentWindow;
13194 const ImGuiID
id =
g.LastItemData.ID;
13195 const ImGuiItemFlags item_flags =
g.LastItemData.ItemFlags;
13198 if (window->DC.NavIsScrollPushableX ==
false)
13200 g.LastItemData.NavRect.Min.x = ImClamp(
g.LastItemData.NavRect.Min.x, window->ClipRect.Min.x, window->ClipRect.Max.x);
13201 g.LastItemData.NavRect.Max.x = ImClamp(
g.LastItemData.NavRect.Max.x, window->ClipRect.Min.x, window->ClipRect.Max.x);
13203 const ImRect nav_bb =
g.LastItemData.NavRect;
13206 if (
g.NavInitRequest &&
g.NavLayer == window->DC.NavLayerCurrent && (item_flags & ImGuiItemFlags_Disabled) == 0)
13209 const bool candidate_for_nav_default_focus = (item_flags & ImGuiItemFlags_NoNavDefaultFocus) == 0;
13210 if (candidate_for_nav_default_focus ||
g.NavInitResult.ID == 0)
13212 NavApplyItemToResult(&
g.NavInitResult);
13214 if (candidate_for_nav_default_focus)
13216 g.NavInitRequest =
false;
13217 NavUpdateAnyRequestFlag();
13223 if (
g.NavMoveScoringItems && (item_flags & ImGuiItemFlags_Disabled) == 0)
13225 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_FocusApi) || (window->Flags & ImGuiWindowFlags_NoNavInputs) == 0)
13227 const bool is_tabbing = (
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0;
13230 NavProcessItemForTabbingRequest(
id, item_flags,
g.NavMoveFlags);
13232 else if (
g.NavId !=
id || (
g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId))
13234 ImGuiNavItemData* result = (window ==
g.NavWindow) ? &
g.NavMoveResultLocal : &
g.NavMoveResultOther;
13235 if (NavScoreItem(result))
13236 NavApplyItemToResult(result);
13239 const float VISIBLE_RATIO = 0.70f;
13240 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb))
13241 if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO)
13242 if (NavScoreItem(&
g.NavMoveResultLocalVisible))
13243 NavApplyItemToResult(&
g.NavMoveResultLocalVisible);
13251 if (
g.NavWindow != window)
13252 SetNavWindow(window);
13253 g.NavLayer = window->DC.NavLayerCurrent;
13254 SetNavFocusScope(
g.CurrentFocusScopeId);
13255 g.NavFocusScopeId =
g.CurrentFocusScopeId;
13256 g.NavIdIsAlive =
true;
13257 if (
g.LastItemData.ItemFlags & ImGuiItemFlags_HasSelectionUserData)
13259 IM_ASSERT(
g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
13260 g.NavLastValidSelectionUserData =
g.NextItemData.SelectionUserData;
13262 window->NavRectRel[window->DC.NavLayerCurrent] = WindowRectAbsToRel(window, nav_bb);
13273void ImGui::NavProcessItemForTabbingRequest(ImGuiID
id, ImGuiItemFlags item_flags, ImGuiNavMoveFlags move_flags)
13277 if ((move_flags & ImGuiNavMoveFlags_FocusApi) == 0)
13279 if (
g.NavLayer !=
g.CurrentWindow->DC.NavLayerCurrent)
13281 if (
g.NavFocusScopeId !=
g.CurrentFocusScopeId)
13289 if (move_flags & ImGuiNavMoveFlags_FocusApi)
13292 can_stop = (item_flags & ImGuiItemFlags_NoTabStop) == 0 && ((
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) || (item_flags & ImGuiItemFlags_Inputable));
13295 ImGuiNavItemData* result = &
g.NavMoveResultLocal;
13296 if (
g.NavTabbingDir == +1)
13299 if (can_stop &&
g.NavTabbingResultFirst.ID == 0)
13300 NavApplyItemToResult(&
g.NavTabbingResultFirst);
13301 if (can_stop &&
g.NavTabbingCounter > 0 && --
g.NavTabbingCounter == 0)
13302 NavMoveRequestResolveWithLastItem(result);
13303 else if (
g.NavId ==
id)
13304 g.NavTabbingCounter = 1;
13306 else if (
g.NavTabbingDir == -1)
13313 g.NavMoveScoringItems =
false;
13314 NavUpdateAnyRequestFlag();
13320 NavApplyItemToResult(result);
13323 else if (
g.NavTabbingDir == 0)
13325 if (can_stop &&
g.NavId ==
id)
13326 NavMoveRequestResolveWithLastItem(result);
13327 if (can_stop &&
g.NavTabbingResultFirst.ID == 0)
13328 NavApplyItemToResult(&
g.NavTabbingResultFirst);
13332bool ImGui::NavMoveRequestButNoResultYet()
13335 return g.NavMoveScoringItems &&
g.NavMoveResultLocal.ID == 0 &&
g.NavMoveResultOther.ID == 0;
13339void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags)
13342 IM_ASSERT(
g.NavWindow != NULL);
13345 if (move_flags & ImGuiNavMoveFlags_IsTabbing)
13346 move_flags |= ImGuiNavMoveFlags_AllowCurrentNavId;
13348 g.NavMoveSubmitted =
g.NavMoveScoringItems =
true;
13349 g.NavMoveDir = move_dir;
13350 g.NavMoveDirForDebug = move_dir;
13351 g.NavMoveClipDir = clip_dir;
13352 g.NavMoveFlags = move_flags;
13353 g.NavMoveScrollFlags = scroll_flags;
13354 g.NavMoveForwardToNextFrame =
false;
13355 g.NavMoveKeyMods = (move_flags & ImGuiNavMoveFlags_FocusApi) ? 0 :
g.IO.KeyMods;
13356 g.NavMoveResultLocal.Clear();
13357 g.NavMoveResultLocalVisible.Clear();
13358 g.NavMoveResultOther.Clear();
13359 g.NavTabbingCounter = 0;
13360 g.NavTabbingResultFirst.Clear();
13361 NavUpdateAnyRequestFlag();
13364void ImGui::NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result)
13367 g.NavMoveScoringItems =
false;
13368 NavApplyItemToResult(result);
13369 NavUpdateAnyRequestFlag();
13373void ImGui::NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiTreeNodeStackData* tree_node_data)
13376 g.NavMoveScoringItems =
false;
13377 g.LastItemData.ID = tree_node_data->ID;
13378 g.LastItemData.ItemFlags = tree_node_data->ItemFlags & ~ImGuiItemFlags_HasSelectionUserData;
13379 g.LastItemData.NavRect = tree_node_data->NavRect;
13380 NavApplyItemToResult(result);
13381 NavClearPreferredPosForAxis(ImGuiAxis_Y);
13382 NavUpdateAnyRequestFlag();
13385void ImGui::NavMoveRequestCancel()
13388 g.NavMoveSubmitted =
g.NavMoveScoringItems =
false;
13389 NavUpdateAnyRequestFlag();
13393void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags)
13396 IM_ASSERT(
g.NavMoveForwardToNextFrame ==
false);
13397 NavMoveRequestCancel();
13398 g.NavMoveForwardToNextFrame =
true;
13399 g.NavMoveDir = move_dir;
13400 g.NavMoveClipDir = clip_dir;
13401 g.NavMoveFlags = move_flags | ImGuiNavMoveFlags_Forwarded;
13402 g.NavMoveScrollFlags = scroll_flags;
13407void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags wrap_flags)
13410 IM_ASSERT((wrap_flags & ImGuiNavMoveFlags_WrapMask_ ) != 0 && (wrap_flags & ~ImGuiNavMoveFlags_WrapMask_) == 0);
13414 if (
g.NavWindow == window &&
g.NavMoveScoringItems &&
g.NavLayer == ImGuiNavLayer_Main)
13415 g.NavMoveFlags = (
g.NavMoveFlags & ~ImGuiNavMoveFlags_WrapMask_) | wrap_flags;
13420static void ImGui::NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window)
13422 ImGuiWindow* parent = nav_window;
13423 while (parent && parent->RootWindow != parent && (parent->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
13424 parent = parent->ParentWindow;
13425 if (parent && parent != nav_window)
13426 parent->NavLastChildNavWindow = nav_window;
13431static ImGuiWindow* ImGui::NavRestoreLastChildNavWindow(ImGuiWindow* window)
13433 if (window->NavLastChildNavWindow && window->NavLastChildNavWindow->WasActive)
13434 return window->NavLastChildNavWindow;
13435 if (window->DockNodeAsHost && window->DockNodeAsHost->TabBar)
13436 if (ImGuiTabItem* tab = TabBarFindMostRecentlySelectedTabForActiveWindow(window->DockNodeAsHost->TabBar))
13437 return tab->Window;
13441void ImGui::NavRestoreLayer(ImGuiNavLayer layer)
13444 if (layer == ImGuiNavLayer_Main)
13446 ImGuiWindow* prev_nav_window =
g.NavWindow;
13447 g.NavWindow = NavRestoreLastChildNavWindow(
g.NavWindow);
13448 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
13449 if (prev_nav_window)
13450 IMGUI_DEBUG_LOG_FOCUS(
"[focus] NavRestoreLayer: from \"%s\" to SetNavWindow(\"%s\")\n", prev_nav_window->Name,
g.NavWindow->Name);
13452 ImGuiWindow* window =
g.NavWindow;
13453 if (window->NavLastIds[layer] != 0)
13455 SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
13459 g.NavLayer = layer;
13460 NavInitWindow(window,
true);
13464static inline void ImGui::NavUpdateAnyRequestFlag()
13468 if (
g.NavAnyRequest)
13469 IM_ASSERT(
g.NavWindow != NULL);
13473void ImGui::NavInitWindow(ImGuiWindow* window,
bool force_reinit)
13477 IM_ASSERT(window ==
g.NavWindow);
13479 if (window->Flags & ImGuiWindowFlags_NoNavInputs)
13482 SetNavFocusScope(window->NavRootFocusScopeId);
13486 bool init_for_nav =
false;
13487 if (window == window->RootWindow || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
13488 init_for_nav =
true;
13489 IMGUI_DEBUG_LOG_NAV(
"[nav] NavInitRequest: from NavInitWindow(), init_for_nav=%d, window=\"%s\", layer=%d\n", init_for_nav, window->Name,
g.NavLayer);
13492 SetNavID(0,
g.NavLayer, window->NavRootFocusScopeId, ImRect());
13493 g.NavInitRequest =
true;
13494 g.NavInitRequestFromMove =
false;
13495 g.NavInitResult.ID = 0;
13496 NavUpdateAnyRequestFlag();
13500 g.NavId = window->NavLastIds[0];
13501 SetNavFocusScope(window->NavRootFocusScopeId);
13505static ImGuiInputSource ImGui::NavCalcPreferredRefPosSource()
13508 ImGuiWindow* window =
g.NavWindow;
13509 const bool activated_shortcut =
g.ActiveId != 0 &&
g.ActiveIdFromShortcut &&
g.ActiveId ==
g.LastItemData.ID;
13512 if ((!
g.NavCursorVisible || !
g.NavHighlightItemUnderNav || !window) && !activated_shortcut)
13513 return ImGuiInputSource_Mouse;
13515 return ImGuiInputSource_Keyboard;
13518static ImVec2 ImGui::NavCalcPreferredRefPos()
13521 ImGuiWindow* window =
g.NavWindow;
13522 ImGuiInputSource source = NavCalcPreferredRefPosSource();
13524 const bool activated_shortcut =
g.ActiveId != 0 &&
g.ActiveIdFromShortcut &&
g.ActiveId ==
g.LastItemData.ID;
13527 if (source == ImGuiInputSource_Mouse)
13532 ImVec2 p = IsMousePosValid(&
g.IO.MousePos) ?
g.IO.MousePos :
g.MouseLastValidPos;
13533 return ImVec2(p.x + 1.0f, p.y);
13539 if (activated_shortcut)
13540 ref_rect =
g.LastItemData.NavRect;
13542 ref_rect = WindowRectRelToAbs(window, window->NavRectRel[
g.NavLayer]);
13545 if (window->LastFrameActive !=
g.FrameCount && (window->ScrollTarget.x != FLT_MAX || window->ScrollTarget.y != FLT_MAX))
13547 ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
13548 ref_rect.Translate(window->Scroll - next_scroll);
13550 ImVec2 pos = ImVec2(ref_rect.Min.x + ImMin(
g.Style.FramePadding.x * 4, ref_rect.GetWidth()), ref_rect.Max.y - ImMin(
g.Style.FramePadding.y, ref_rect.GetHeight()));
13551 ImGuiViewport* viewport = window->Viewport;
13552 return ImTrunc(ImClamp(pos, viewport->Pos, viewport->Pos + viewport->Size));
13556float ImGui::GetNavTweakPressedAmount(ImGuiAxis axis)
13559 float repeat_delay, repeat_rate;
13560 GetTypematicRepeatRate(ImGuiInputFlags_RepeatRateNavTweak, &repeat_delay, &repeat_rate);
13562 ImGuiKey key_less, key_more;
13563 if (
g.NavInputSource == ImGuiInputSource_Gamepad)
13565 key_less = (axis == ImGuiAxis_X) ? ImGuiKey_GamepadDpadLeft : ImGuiKey_GamepadDpadUp;
13566 key_more = (axis == ImGuiAxis_X) ? ImGuiKey_GamepadDpadRight : ImGuiKey_GamepadDpadDown;
13570 key_less = (axis == ImGuiAxis_X) ? ImGuiKey_LeftArrow : ImGuiKey_UpArrow;
13571 key_more = (axis == ImGuiAxis_X) ? ImGuiKey_RightArrow : ImGuiKey_DownArrow;
13573 float amount = (float)GetKeyPressedAmount(key_more, repeat_delay, repeat_rate) - (float)GetKeyPressedAmount(key_less, repeat_delay, repeat_rate);
13574 if (amount != 0.0f && IsKeyDown(key_less) && IsKeyDown(key_more))
13579static void ImGui::NavUpdate()
13582 ImGuiIO& io =
g.IO;
13584 io.WantSetMousePos =
false;
13589 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
13590 const ImGuiKey nav_gamepad_keys_to_change_source[] = { ImGuiKey_GamepadFaceRight, ImGuiKey_GamepadFaceLeft, ImGuiKey_GamepadFaceUp, ImGuiKey_GamepadFaceDown, ImGuiKey_GamepadDpadRight, ImGuiKey_GamepadDpadLeft, ImGuiKey_GamepadDpadUp, ImGuiKey_GamepadDpadDown };
13591 if (nav_gamepad_active)
13592 for (ImGuiKey key : nav_gamepad_keys_to_change_source)
13593 if (IsKeyDown(key))
13594 g.NavInputSource = ImGuiInputSource_Gamepad;
13595 const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
13596 const ImGuiKey nav_keyboard_keys_to_change_source[] = { ImGuiKey_Space, ImGuiKey_Enter, ImGuiKey_Escape, ImGuiKey_RightArrow, ImGuiKey_LeftArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow };
13597 if (nav_keyboard_active)
13598 for (ImGuiKey key : nav_keyboard_keys_to_change_source)
13599 if (IsKeyDown(key))
13600 g.NavInputSource = ImGuiInputSource_Keyboard;
13603 g.NavJustMovedToId = 0;
13604 g.NavJustMovedToFocusScopeId =
g.NavJustMovedFromFocusScopeId = 0;
13605 if (
g.NavInitResult.ID != 0)
13606 NavInitRequestApplyResult();
13607 g.NavInitRequest =
false;
13608 g.NavInitRequestFromMove =
false;
13609 g.NavInitResult.ID = 0;
13612 if (
g.NavMoveSubmitted)
13613 NavMoveRequestApplyResult();
13614 g.NavTabbingCounter = 0;
13615 g.NavMoveSubmitted =
g.NavMoveScoringItems =
false;
13616 if (
g.NavCursorHideFrames > 0)
13617 if (--
g.NavCursorHideFrames == 0)
13618 g.NavCursorVisible =
true;
13621 bool set_mouse_pos =
false;
13622 if (
g.NavMousePosDirty &&
g.NavIdIsAlive)
13623 if (
g.NavCursorVisible &&
g.NavHighlightItemUnderNav &&
g.NavWindow)
13624 set_mouse_pos =
true;
13625 g.NavMousePosDirty =
false;
13626 IM_ASSERT(
g.NavLayer == ImGuiNavLayer_Main ||
g.NavLayer == ImGuiNavLayer_Menu);
13630 NavSaveLastChildNavWindowIntoParent(
g.NavWindow);
13631 if (
g.NavWindow &&
g.NavWindow->NavLastChildNavWindow != NULL &&
g.NavLayer == ImGuiNavLayer_Main)
13632 g.NavWindow->NavLastChildNavWindow = NULL;
13635 NavUpdateWindowing();
13638 io.NavActive = (nav_keyboard_active || nav_gamepad_active) &&
g.NavWindow && !(
g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs);
13639 io.NavVisible = (io.NavActive &&
g.NavId != 0 &&
g.NavCursorVisible) || (
g.NavWindowingTarget != NULL);
13642 NavUpdateCancelRequest();
13645 g.NavActivateId =
g.NavActivateDownId =
g.NavActivatePressedId = 0;
13646 g.NavActivateFlags = ImGuiActivateFlags_None;
13647 if (
g.NavId != 0 &&
g.NavCursorVisible && !
g.NavWindowingTarget &&
g.NavWindow && !(
g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
13649 const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space, ImGuiKeyOwner_NoOwner)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_NoOwner));
13650 const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, 0, ImGuiKeyOwner_NoOwner)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, 0, ImGuiKeyOwner_NoOwner)));
13651 const bool input_down = (nav_keyboard_active && (IsKeyDown(ImGuiKey_Enter, ImGuiKeyOwner_NoOwner) || IsKeyDown(ImGuiKey_KeypadEnter, ImGuiKeyOwner_NoOwner))) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput, ImGuiKeyOwner_NoOwner));
13652 const bool input_pressed = input_down && ((nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, 0, ImGuiKeyOwner_NoOwner) || IsKeyPressed(ImGuiKey_KeypadEnter, 0, ImGuiKeyOwner_NoOwner))) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, 0, ImGuiKeyOwner_NoOwner)));
13653 if (
g.ActiveId == 0 && activate_pressed)
13655 g.NavActivateId =
g.NavId;
13656 g.NavActivateFlags = ImGuiActivateFlags_PreferTweak;
13658 if ((
g.ActiveId == 0 ||
g.ActiveId ==
g.NavId) && input_pressed)
13660 g.NavActivateId =
g.NavId;
13661 g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
13663 if ((
g.ActiveId == 0 ||
g.ActiveId ==
g.NavId) && (activate_down || input_down))
13664 g.NavActivateDownId =
g.NavId;
13665 if ((
g.ActiveId == 0 ||
g.ActiveId ==
g.NavId) && (activate_pressed || input_pressed))
13667 g.NavActivatePressedId =
g.NavId;
13668 NavHighlightActivated(
g.NavId);
13671 if (
g.NavWindow && (
g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
13672 g.NavCursorVisible =
false;
13673 else if (
g.IO.ConfigNavCursorVisibleAlways &&
g.NavCursorHideFrames == 0)
13674 g.NavCursorVisible =
true;
13675 if (
g.NavActivateId != 0)
13676 IM_ASSERT(
g.NavActivateDownId ==
g.NavActivateId);
13679 if (
g.NavHighlightActivatedTimer > 0.0f)
13680 g.NavHighlightActivatedTimer = ImMax(0.0f,
g.NavHighlightActivatedTimer - io.DeltaTime);
13681 if (
g.NavHighlightActivatedTimer == 0.0f)
13682 g.NavHighlightActivatedId = 0;
13686 if (
g.NavNextActivateId != 0)
13688 g.NavActivateId =
g.NavActivateDownId =
g.NavActivatePressedId =
g.NavNextActivateId;
13689 g.NavActivateFlags =
g.NavNextActivateFlags;
13691 g.NavNextActivateId = 0;
13694 NavUpdateCreateMoveRequest();
13695 if (
g.NavMoveDir == ImGuiDir_None)
13696 NavUpdateCreateTabbingRequest();
13697 NavUpdateAnyRequestFlag();
13698 g.NavIdIsAlive =
false;
13701 if (
g.NavWindow && !(
g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !
g.NavWindowingTarget)
13704 ImGuiWindow* window =
g.NavWindow;
13705 const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * io.DeltaTime);
13706 const ImGuiDir move_dir =
g.NavMoveDir;
13707 if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavWindowHasScrollY && move_dir != ImGuiDir_None)
13709 if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right)
13710 SetScrollX(window, ImTrunc(window->Scroll.x + ((move_dir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
13711 if (move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down)
13712 SetScrollY(window, ImTrunc(window->Scroll.y + ((move_dir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed));
13717 if (nav_gamepad_active)
13719 const ImVec2 scroll_dir = GetKeyMagnitude2d(ImGuiKey_GamepadLStickLeft, ImGuiKey_GamepadLStickRight, ImGuiKey_GamepadLStickUp, ImGuiKey_GamepadLStickDown);
13720 const float tweak_factor = IsKeyDown(ImGuiKey_NavGamepadTweakSlow) ? 1.0f / 10.0f : IsKeyDown(ImGuiKey_NavGamepadTweakFast) ? 10.0f : 1.0f;
13721 if (scroll_dir.x != 0.0f && window->ScrollbarX)
13722 SetScrollX(window, ImTrunc(window->Scroll.x + scroll_dir.x * scroll_speed * tweak_factor));
13723 if (scroll_dir.y != 0.0f)
13724 SetScrollY(window, ImTrunc(window->Scroll.y + scroll_dir.y * scroll_speed * tweak_factor));
13729 if (!nav_keyboard_active && !nav_gamepad_active)
13731 g.NavCursorVisible =
false;
13732 g.NavHighlightItemUnderNav = set_mouse_pos =
false;
13737 if (set_mouse_pos && io.ConfigNavMoveSetMousePos && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
13738 TeleportMousePos(NavCalcPreferredRefPos());
13741 g.NavScoringDebugCount = 0;
13742#if IMGUI_DEBUG_NAV_RECTS
13743 if (ImGuiWindow* debug_window =
g.NavWindow)
13745 ImDrawList* draw_list = GetForegroundDrawList(debug_window);
13746 int layer =
g.NavLayer; { ImRect r = WindowRectRelToAbs(debug_window, debug_window->NavRectRel[layer]); draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 200, 0, 255)); }
13752void ImGui::NavInitRequestApplyResult()
13759 ImGuiNavItemData* result = &
g.NavInitResult;
13760 if (
g.NavId != result->ID)
13762 g.NavJustMovedFromFocusScopeId =
g.NavFocusScopeId;
13763 g.NavJustMovedToId = result->ID;
13764 g.NavJustMovedToFocusScopeId = result->FocusScopeId;
13765 g.NavJustMovedToKeyMods = 0;
13766 g.NavJustMovedToIsTabbing =
false;
13767 g.NavJustMovedToHasSelectionData = (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
13772 IMGUI_DEBUG_LOG_NAV(
"[nav] NavInitRequest: ApplyResult: NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID,
g.NavLayer,
g.NavWindow->Name);
13773 SetNavID(result->ID,
g.NavLayer, result->FocusScopeId, result->RectRel);
13774 g.NavIdIsAlive =
true;
13775 if (result->SelectionUserData != ImGuiSelectionUserData_Invalid)
13776 g.NavLastValidSelectionUserData = result->SelectionUserData;
13777 if (
g.NavInitRequestFromMove)
13778 SetNavCursorVisibleAfterMove();
13782static void NavBiasScoringRect(ImRect& r, ImVec2& preferred_pos_rel, ImGuiDir move_dir, ImGuiNavMoveFlags move_flags)
13786 const ImVec2 rel_to_abs_offset =
g.NavWindow->DC.CursorStartPos;
13791 if ((move_flags & ImGuiNavMoveFlags_Forwarded) == 0)
13793 if (preferred_pos_rel.x == FLT_MAX)
13794 preferred_pos_rel.x = ImMin(r.Min.x + 1.0f, r.Max.x) - rel_to_abs_offset.x;
13795 if (preferred_pos_rel.y == FLT_MAX)
13796 preferred_pos_rel.y = r.GetCenter().y - rel_to_abs_offset.y;
13800 if ((move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) && preferred_pos_rel.x != FLT_MAX)
13801 r.Min.x = r.Max.x = preferred_pos_rel.x + rel_to_abs_offset.x;
13802 else if ((move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right) && preferred_pos_rel.y != FLT_MAX)
13803 r.Min.y = r.Max.y = preferred_pos_rel.y + rel_to_abs_offset.y;
13806void ImGui::NavUpdateCreateMoveRequest()
13809 ImGuiIO& io =
g.IO;
13810 ImGuiWindow* window =
g.NavWindow;
13811 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
13812 const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
13814 if (
g.NavMoveForwardToNextFrame && window != NULL)
13818 IM_ASSERT(
g.NavMoveDir != ImGuiDir_None &&
g.NavMoveClipDir != ImGuiDir_None);
13819 IM_ASSERT(
g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded);
13820 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveRequestForward %d\n",
g.NavMoveDir);
13825 g.NavMoveDir = ImGuiDir_None;
13826 g.NavMoveFlags = ImGuiNavMoveFlags_None;
13827 g.NavMoveScrollFlags = ImGuiScrollFlags_None;
13828 if (window && !
g.NavWindowingTarget && !(window->Flags & ImGuiWindowFlags_NoNavInputs))
13830 const ImGuiInputFlags repeat_mode = ImGuiInputFlags_Repeat | (ImGuiInputFlags)ImGuiInputFlags_RepeatRateNavMove;
13831 if (!IsActiveIdUsingNavDir(ImGuiDir_Left) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadLeft, repeat_mode, ImGuiKeyOwner_NoOwner)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_LeftArrow, repeat_mode, ImGuiKeyOwner_NoOwner)))) {
g.NavMoveDir = ImGuiDir_Left; }
13832 if (!IsActiveIdUsingNavDir(ImGuiDir_Right) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadRight, repeat_mode, ImGuiKeyOwner_NoOwner)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_RightArrow, repeat_mode, ImGuiKeyOwner_NoOwner)))) {
g.NavMoveDir = ImGuiDir_Right; }
13833 if (!IsActiveIdUsingNavDir(ImGuiDir_Up) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadUp, repeat_mode, ImGuiKeyOwner_NoOwner)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_UpArrow, repeat_mode, ImGuiKeyOwner_NoOwner)))) {
g.NavMoveDir = ImGuiDir_Up; }
13834 if (!IsActiveIdUsingNavDir(ImGuiDir_Down) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadDown, repeat_mode, ImGuiKeyOwner_NoOwner)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_DownArrow, repeat_mode, ImGuiKeyOwner_NoOwner)))) {
g.NavMoveDir = ImGuiDir_Down; }
13836 g.NavMoveClipDir =
g.NavMoveDir;
13837 g.NavScoringNoClipRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
13842 float scoring_rect_offset_y = 0.0f;
13843 if (window &&
g.NavMoveDir == ImGuiDir_None && nav_keyboard_active)
13844 scoring_rect_offset_y = NavUpdatePageUpPageDown();
13845 if (scoring_rect_offset_y != 0.0f)
13847 g.NavScoringNoClipRect = window->InnerRect;
13848 g.NavScoringNoClipRect.TranslateY(scoring_rect_offset_y);
13852#if IMGUI_DEBUG_NAV_SCORING
13857 if (
g.NavMoveDir == ImGuiDir_None)
13858 g.NavMoveDir =
g.NavMoveDirForDebug;
13859 g.NavMoveClipDir =
g.NavMoveDir;
13860 g.NavMoveFlags |= ImGuiNavMoveFlags_DebugNoResult;
13865 g.NavMoveForwardToNextFrame =
false;
13866 if (
g.NavMoveDir != ImGuiDir_None)
13867 NavMoveRequestSubmit(
g.NavMoveDir,
g.NavMoveClipDir,
g.NavMoveFlags,
g.NavMoveScrollFlags);
13870 if (
g.NavMoveSubmitted &&
g.NavId == 0)
13872 IMGUI_DEBUG_LOG_NAV(
"[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", window ? window->Name :
"<NULL>",
g.NavLayer);
13873 g.NavInitRequest =
g.NavInitRequestFromMove =
true;
13874 g.NavInitResult.ID = 0;
13875 if (
g.IO.ConfigNavCursorVisibleAuto)
13876 g.NavCursorVisible =
true;
13882 if (
g.NavMoveSubmitted &&
g.NavInputSource == ImGuiInputSource_Gamepad &&
g.NavLayer == ImGuiNavLayer_Main && window != NULL)
13884 bool clamp_x = (
g.NavMoveFlags & (ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_WrapX)) == 0;
13885 bool clamp_y = (
g.NavMoveFlags & (ImGuiNavMoveFlags_LoopY | ImGuiNavMoveFlags_WrapY)) == 0;
13886 ImRect inner_rect_rel = WindowRectAbsToRel(window, ImRect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1)));
13890 inner_rect_rel.Translate(CalcNextScrollFromScrollTargetAndClamp(window) - window->Scroll);
13892 if ((clamp_x || clamp_y) && !inner_rect_rel.Contains(window->NavRectRel[
g.NavLayer]))
13894 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveRequest: clamp NavRectRel for gamepad move\n");
13895 float pad_x = ImMin(inner_rect_rel.GetWidth(), window->CalcFontSize() * 0.5f);
13896 float pad_y = ImMin(inner_rect_rel.GetHeight(), window->CalcFontSize() * 0.5f);
13897 inner_rect_rel.Min.x = clamp_x ? (inner_rect_rel.Min.x + pad_x) : -FLT_MAX;
13898 inner_rect_rel.Max.x = clamp_x ? (inner_rect_rel.Max.x - pad_x) : +FLT_MAX;
13899 inner_rect_rel.Min.y = clamp_y ? (inner_rect_rel.Min.y + pad_y) : -FLT_MAX;
13900 inner_rect_rel.Max.y = clamp_y ? (inner_rect_rel.Max.y - pad_y) : +FLT_MAX;
13901 window->NavRectRel[
g.NavLayer].ClipWithFull(inner_rect_rel);
13907 ImRect scoring_rect;
13908 if (window != NULL)
13910 ImRect nav_rect_rel = !window->NavRectRel[
g.NavLayer].IsInverted() ? window->NavRectRel[
g.NavLayer] : ImRect(0, 0, 0, 0);
13911 scoring_rect = WindowRectRelToAbs(window, nav_rect_rel);
13912 scoring_rect.TranslateY(scoring_rect_offset_y);
13913 if (
g.NavMoveSubmitted)
13914 NavBiasScoringRect(scoring_rect, window->RootWindowForNav->NavPreferredScoringPosRel[
g.NavLayer],
g.NavMoveDir,
g.NavMoveFlags);
13915 IM_ASSERT(!scoring_rect.IsInverted());
13919 g.NavScoringRect = scoring_rect;
13920 g.NavScoringNoClipRect.Add(scoring_rect);
13923void ImGui::NavUpdateCreateTabbingRequest()
13926 ImGuiWindow* window =
g.NavWindow;
13927 IM_ASSERT(
g.NavMoveDir == ImGuiDir_None);
13928 if (window == NULL ||
g.NavWindowingTarget != NULL || (window->Flags & ImGuiWindowFlags_NoNavInputs))
13931 const bool tab_pressed = IsKeyPressed(ImGuiKey_Tab, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner) && !
g.IO.KeyCtrl && !
g.IO.KeyAlt;
13938 const bool nav_keyboard_active = (
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
13939 if (nav_keyboard_active)
13940 g.NavTabbingDir =
g.IO.KeyShift ? -1 : (
g.NavCursorVisible ==
false &&
g.ActiveId == 0) ? 0 : +1;
13942 g.NavTabbingDir =
g.IO.KeyShift ? -1 : (
g.ActiveId == 0) ? 0 : +1;
13943 ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate;
13944 ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
13945 ImGuiDir clip_dir = (
g.NavTabbingDir < 0) ? ImGuiDir_Up : ImGuiDir_Down;
13946 NavMoveRequestSubmit(ImGuiDir_None, clip_dir, move_flags, scroll_flags);
13947 g.NavTabbingCounter = -1;
13951void ImGui::NavMoveRequestApplyResult()
13954#if IMGUI_DEBUG_NAV_SCORING
13955 if (
g.NavMoveFlags & ImGuiNavMoveFlags_DebugNoResult)
13960 ImGuiNavItemData* result = (
g.NavMoveResultLocal.ID != 0) ? &
g.NavMoveResultLocal : (
g.NavMoveResultOther.
ID != 0) ? &
g.NavMoveResultOther : NULL;
13963 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && result == NULL)
13964 if ((
g.NavTabbingCounter == 1 ||
g.NavTabbingDir == 0) &&
g.NavTabbingResultFirst.ID)
13965 result = &
g.NavTabbingResultFirst;
13968 const ImGuiAxis axis = (
g.NavMoveDir == ImGuiDir_Up ||
g.NavMoveDir == ImGuiDir_Down) ? ImGuiAxis_Y : ImGuiAxis_X;
13969 if (result == NULL)
13971 if (
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing)
13972 g.NavMoveFlags |= ImGuiNavMoveFlags_NoSetNavCursorVisible;
13973 if (
g.NavId != 0 && (
g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavCursorVisible) == 0)
13974 SetNavCursorVisibleAfterMove();
13975 NavClearPreferredPosForAxis(axis);
13976 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveSubmitted but not led to a result!\n");
13981 if (
g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet)
13982 if (
g.NavMoveResultLocalVisible.ID != 0 &&
g.NavMoveResultLocalVisible.ID !=
g.NavId)
13983 result = &
g.NavMoveResultLocalVisible;
13986 if (result != &
g.NavMoveResultOther &&
g.NavMoveResultOther.ID != 0 &&
g.NavMoveResultOther.Window->ParentWindow ==
g.NavWindow)
13987 if ((
g.NavMoveResultOther.DistBox < result->DistBox) || (
g.NavMoveResultOther.DistBox == result->DistBox &&
g.NavMoveResultOther.DistCenter < result->DistCenter))
13988 result = &
g.NavMoveResultOther;
13989 IM_ASSERT(
g.NavWindow && result->Window);
13992 if (
g.NavLayer == ImGuiNavLayer_Main)
13994 ImRect rect_abs = WindowRectRelToAbs(result->Window, result->RectRel);
13995 ScrollToRectEx(result->Window, rect_abs,
g.NavMoveScrollFlags);
13997 if (
g.NavMoveFlags & ImGuiNavMoveFlags_ScrollToEdgeY)
14000 float scroll_target = (
g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f;
14001 SetScrollY(result->Window, scroll_target);
14005 if (
g.NavWindow != result->Window)
14007 IMGUI_DEBUG_LOG_FOCUS(
"[focus] NavMoveRequest: SetNavWindow(\"%s\")\n", result->Window->Name);
14008 g.NavWindow = result->Window;
14009 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
14015 if (
g.ActiveId != result->ID && (
g.NavMoveFlags & ImGuiNavMoveFlags_NoClearActiveId) == 0)
14020 if ((
g.NavId != result->ID || (
g.NavMoveFlags & ImGuiNavMoveFlags_IsPageMove)) && (
g.NavMoveFlags & ImGuiNavMoveFlags_NoSelect) == 0)
14022 g.NavJustMovedFromFocusScopeId =
g.NavFocusScopeId;
14023 g.NavJustMovedToId = result->ID;
14024 g.NavJustMovedToFocusScopeId = result->FocusScopeId;
14025 g.NavJustMovedToKeyMods =
g.NavMoveKeyMods;
14026 g.NavJustMovedToIsTabbing = (
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0;
14027 g.NavJustMovedToHasSelectionData = (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
14032 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID,
g.NavLayer,
g.NavWindow->Name);
14033 ImVec2 preferred_scoring_pos_rel =
g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[
g.NavLayer];
14034 SetNavID(result->ID,
g.NavLayer, result->FocusScopeId, result->RectRel);
14035 if (result->SelectionUserData != ImGuiSelectionUserData_Invalid)
14036 g.NavLastValidSelectionUserData = result->SelectionUserData;
14040 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) == 0)
14042 preferred_scoring_pos_rel[axis] = result->RectRel.GetCenter()[axis];
14043 g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[
g.NavLayer] = preferred_scoring_pos_rel;
14047 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && (result->ItemFlags & ImGuiItemFlags_Inputable) == 0)
14048 g.NavMoveFlags &= ~ImGuiNavMoveFlags_Activate;
14051 if (
g.NavMoveFlags & ImGuiNavMoveFlags_Activate)
14053 g.NavNextActivateId = result->ID;
14054 g.NavNextActivateFlags = ImGuiActivateFlags_None;
14055 if (
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing)
14056 g.NavNextActivateFlags |= ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState | ImGuiActivateFlags_FromTabbing;
14060 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavCursorVisible) == 0)
14061 SetNavCursorVisibleAfterMove();
14068static void ImGui::NavUpdateCancelRequest()
14071 const bool nav_gamepad_active = (
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (
g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
14072 const bool nav_keyboard_active = (
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
14073 if (!(nav_keyboard_active && IsKeyPressed(ImGuiKey_Escape, 0, ImGuiKeyOwner_NoOwner)) && !(nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadCancel, 0, ImGuiKeyOwner_NoOwner)))
14076 IMGUI_DEBUG_LOG_NAV(
"[nav] NavUpdateCancelRequest()\n");
14077 if (
g.ActiveId != 0)
14081 else if (
g.NavLayer != ImGuiNavLayer_Main)
14084 NavRestoreLayer(ImGuiNavLayer_Main);
14085 SetNavCursorVisibleAfterMove();
14087 else if (
g.NavWindow &&
g.NavWindow !=
g.NavWindow->RootWindow && !(
g.NavWindow->RootWindowForNav->Flags & ImGuiWindowFlags_Popup) &&
g.NavWindow->RootWindowForNav->ParentWindow)
14090 ImGuiWindow* child_window =
g.NavWindow->RootWindowForNav;
14091 ImGuiWindow* parent_window = child_window->ParentWindow;
14092 IM_ASSERT(child_window->ChildId != 0);
14093 FocusWindow(parent_window);
14094 SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, WindowRectAbsToRel(parent_window, child_window->Rect()));
14095 SetNavCursorVisibleAfterMove();
14097 else if (
g.OpenPopupStack.Size > 0 &&
g.OpenPopupStack.back().Window != NULL && !(
g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal))
14100 ClosePopupToLevel(
g.OpenPopupStack.Size - 1,
true);
14106 if (
g.IO.ConfigNavEscapeClearFocusItem ||
g.IO.ConfigNavEscapeClearFocusWindow)
14107 if (
g.NavWindow && ((
g.NavWindow->Flags & ImGuiWindowFlags_Popup)))
14108 g.NavWindow->NavLastIds[0] = 0;
14111 if (
g.IO.ConfigNavEscapeClearFocusItem ||
g.IO.ConfigNavEscapeClearFocusWindow)
14113 if (
g.IO.ConfigNavEscapeClearFocusWindow)
14122static float ImGui::NavUpdatePageUpPageDown()
14125 ImGuiWindow* window =
g.NavWindow;
14126 if ((window->Flags & ImGuiWindowFlags_NoNavInputs) ||
g.NavWindowingTarget != NULL)
14129 const bool page_up_held = IsKeyDown(ImGuiKey_PageUp, ImGuiKeyOwner_NoOwner);
14130 const bool page_down_held = IsKeyDown(ImGuiKey_PageDown, ImGuiKeyOwner_NoOwner);
14131 const bool home_pressed = IsKeyPressed(ImGuiKey_Home, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner);
14132 const bool end_pressed = IsKeyPressed(ImGuiKey_End, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner);
14133 if (page_up_held == page_down_held && home_pressed == end_pressed)
14136 if (
g.NavLayer != ImGuiNavLayer_Main)
14137 NavRestoreLayer(ImGuiNavLayer_Main);
14139 if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavWindowHasScrollY)
14142 if (IsKeyPressed(ImGuiKey_PageUp, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner))
14143 SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight());
14144 else if (IsKeyPressed(ImGuiKey_PageDown, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner))
14145 SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight());
14146 else if (home_pressed)
14147 SetScrollY(window, 0.0f);
14148 else if (end_pressed)
14149 SetScrollY(window, window->ScrollMax.y);
14153 ImRect& nav_rect_rel = window->NavRectRel[
g.NavLayer];
14154 const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
14155 float nav_scoring_rect_offset_y = 0.0f;
14156 if (IsKeyPressed(ImGuiKey_PageUp,
true))
14158 nav_scoring_rect_offset_y = -page_offset_y;
14159 g.NavMoveDir = ImGuiDir_Down;
14160 g.NavMoveClipDir = ImGuiDir_Up;
14161 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet | ImGuiNavMoveFlags_IsPageMove;
14163 else if (IsKeyPressed(ImGuiKey_PageDown,
true))
14165 nav_scoring_rect_offset_y = +page_offset_y;
14166 g.NavMoveDir = ImGuiDir_Up;
14167 g.NavMoveClipDir = ImGuiDir_Down;
14168 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet | ImGuiNavMoveFlags_IsPageMove;
14170 else if (home_pressed)
14175 nav_rect_rel.Min.y = nav_rect_rel.Max.y = 0.0f;
14176 if (nav_rect_rel.IsInverted())
14177 nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
14178 g.NavMoveDir = ImGuiDir_Down;
14179 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdgeY;
14182 else if (end_pressed)
14184 nav_rect_rel.Min.y = nav_rect_rel.Max.y = window->ContentSize.y;
14185 if (nav_rect_rel.IsInverted())
14186 nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
14187 g.NavMoveDir = ImGuiDir_Up;
14188 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdgeY;
14191 return nav_scoring_rect_offset_y;
14196static void ImGui::NavEndFrame()
14201 if (
g.NavWindowingTarget != NULL)
14202 NavUpdateWindowingOverlay();
14207 if (
g.NavWindow && NavMoveRequestButNoResultYet() && (
g.NavMoveFlags & ImGuiNavMoveFlags_WrapMask_) && (
g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0)
14208 NavUpdateCreateWrappingRequest();
14211static void ImGui::NavUpdateCreateWrappingRequest()
14214 ImGuiWindow* window =
g.NavWindow;
14216 bool do_forward =
false;
14217 ImRect bb_rel = window->NavRectRel[
g.NavLayer];
14218 ImGuiDir clip_dir =
g.NavMoveDir;
14220 const ImGuiNavMoveFlags move_flags =
g.NavMoveFlags;
14222 if (
g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
14224 bb_rel.Min.x = bb_rel.Max.x = window->ContentSize.x + window->WindowPadding.x;
14225 if (move_flags & ImGuiNavMoveFlags_WrapX)
14227 bb_rel.TranslateY(-bb_rel.GetHeight());
14228 clip_dir = ImGuiDir_Up;
14232 if (
g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
14234 bb_rel.Min.x = bb_rel.Max.x = -window->WindowPadding.x;
14235 if (move_flags & ImGuiNavMoveFlags_WrapX)
14237 bb_rel.TranslateY(+bb_rel.GetHeight());
14238 clip_dir = ImGuiDir_Down;
14242 if (
g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
14244 bb_rel.Min.y = bb_rel.Max.y = window->ContentSize.y + window->WindowPadding.y;
14245 if (move_flags & ImGuiNavMoveFlags_WrapY)
14247 bb_rel.TranslateX(-bb_rel.GetWidth());
14248 clip_dir = ImGuiDir_Left;
14252 if (
g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
14254 bb_rel.Min.y = bb_rel.Max.y = -window->WindowPadding.y;
14255 if (move_flags & ImGuiNavMoveFlags_WrapY)
14257 bb_rel.TranslateX(+bb_rel.GetWidth());
14258 clip_dir = ImGuiDir_Right;
14264 window->NavRectRel[
g.NavLayer] = bb_rel;
14265 NavClearPreferredPosForAxis(ImGuiAxis_X);
14266 NavClearPreferredPosForAxis(ImGuiAxis_Y);
14267 NavMoveRequestForward(
g.NavMoveDir, clip_dir, move_flags,
g.NavMoveScrollFlags);
14270static int ImGui::FindWindowFocusIndex(ImGuiWindow* window)
14274 int order = window->FocusOrder;
14275 IM_ASSERT(window->RootWindow == window);
14276 IM_ASSERT(
g.WindowsFocusOrder[order] == window);
14280static ImGuiWindow* FindWindowNavFocusable(
int i_start,
int i_stop,
int dir)
14283 for (
int i = i_start; i >= 0 && i <
g.WindowsFocusOrder.Size && i != i_stop; i += dir)
14284 if (ImGui::IsWindowNavFocusable(
g.WindowsFocusOrder[i]))
14285 return g.WindowsFocusOrder[i];
14289static void NavUpdateWindowingTarget(
int focus_change_dir)
14292 IM_ASSERT(
g.NavWindowingTarget);
14293 if (
g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)
14296 const int i_current = ImGui::FindWindowFocusIndex(
g.NavWindowingTarget);
14297 ImGuiWindow* window_target = FindWindowNavFocusable(i_current + focus_change_dir, -INT_MAX, focus_change_dir);
14298 if (!window_target)
14299 window_target = FindWindowNavFocusable((focus_change_dir < 0) ? (
g.WindowsFocusOrder.Size - 1) : 0, i_current, focus_change_dir);
14302 g.NavWindowingTarget =
g.NavWindowingTargetAnim = window_target;
14303 g.NavWindowingAccumDeltaPos =
g.NavWindowingAccumDeltaSize = ImVec2(0.0f, 0.0f);
14305 g.NavWindowingToggleLayer =
false;
14311static void ImGui::NavUpdateWindowing()
14314 ImGuiIO& io =
g.IO;
14316 ImGuiWindow* apply_focus_window = NULL;
14317 bool apply_toggle_layer =
false;
14319 ImGuiWindow* modal_window = GetTopMostPopupModal();
14320 bool allow_windowing = (modal_window == NULL);
14321 if (!allow_windowing)
14322 g.NavWindowingTarget = NULL;
14325 if (
g.NavWindowingTargetAnim &&
g.NavWindowingTarget == NULL)
14327 g.NavWindowingHighlightAlpha = ImMax(
g.NavWindowingHighlightAlpha - io.DeltaTime * 10.0f, 0.0f);
14328 if (
g.DimBgRatio <= 0.0f &&
g.NavWindowingHighlightAlpha <= 0.0f)
14329 g.NavWindowingTargetAnim = NULL;
14334 const ImGuiID owner_id =
ImHashStr(
"###NavUpdateWindowing");
14335 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
14336 const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
14337 const bool keyboard_next_window = allow_windowing &&
g.ConfigNavWindowingKeyNext && Shortcut(
g.ConfigNavWindowingKeyNext, ImGuiInputFlags_Repeat | ImGuiInputFlags_RouteAlways, owner_id);
14338 const bool keyboard_prev_window = allow_windowing &&
g.ConfigNavWindowingKeyPrev && Shortcut(
g.ConfigNavWindowingKeyPrev, ImGuiInputFlags_Repeat | ImGuiInputFlags_RouteAlways, owner_id);
14339 const bool start_windowing_with_gamepad = allow_windowing && nav_gamepad_active && !
g.NavWindowingTarget && IsKeyPressed(ImGuiKey_NavGamepadMenu, ImGuiInputFlags_None);
14340 const bool start_windowing_with_keyboard = allow_windowing && !
g.NavWindowingTarget && (keyboard_next_window || keyboard_prev_window);
14341 bool just_started_windowing_from_null_focus =
false;
14342 if (start_windowing_with_gamepad || start_windowing_with_keyboard)
14343 if (ImGuiWindow* window =
g.NavWindow ?
g.NavWindow : FindWindowNavFocusable(
g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
14345 g.NavWindowingTarget =
g.NavWindowingTargetAnim = window->RootWindow;
14346 g.NavWindowingTimer =
g.NavWindowingHighlightAlpha = 0.0f;
14347 g.NavWindowingAccumDeltaPos =
g.NavWindowingAccumDeltaSize = ImVec2(0.0f, 0.0f);
14348 g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true :
false;
14349 g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad;
14350 if (
g.NavWindow == NULL)
14351 just_started_windowing_from_null_focus =
true;
14354 if (keyboard_next_window || keyboard_prev_window)
14355 SetKeyOwnersForKeyChord((
g.ConfigNavWindowingKeyNext |
g.ConfigNavWindowingKeyPrev) & ImGuiMod_Mask_, owner_id);
14359 g.NavWindowingTimer += io.DeltaTime;
14360 if (
g.NavWindowingTarget &&
g.NavInputSource == ImGuiInputSource_Gamepad)
14363 g.NavWindowingHighlightAlpha = ImMax(
g.NavWindowingHighlightAlpha, ImSaturate((
g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
14366 const int focus_change_dir = (int)IsKeyPressed(ImGuiKey_GamepadL1) - (int)IsKeyPressed(ImGuiKey_GamepadR1);
14367 if (focus_change_dir != 0 && !just_started_windowing_from_null_focus)
14369 NavUpdateWindowingTarget(focus_change_dir);
14370 g.NavWindowingHighlightAlpha = 1.0f;
14374 if (!IsKeyDown(ImGuiKey_NavGamepadMenu))
14376 g.NavWindowingToggleLayer &= (
g.NavWindowingHighlightAlpha < 1.0f);
14377 if (
g.NavWindowingToggleLayer &&
g.NavWindow)
14378 apply_toggle_layer =
true;
14379 else if (!
g.NavWindowingToggleLayer)
14380 apply_focus_window =
g.NavWindowingTarget;
14381 g.NavWindowingTarget = NULL;
14386 if (
g.NavWindowingTarget &&
g.NavInputSource == ImGuiInputSource_Keyboard)
14389 ImGuiKeyChord shared_mods = ((
g.ConfigNavWindowingKeyNext ?
g.ConfigNavWindowingKeyNext : ImGuiMod_Mask_) & (
g.ConfigNavWindowingKeyPrev ?
g.ConfigNavWindowingKeyPrev : ImGuiMod_Mask_)) & ImGuiMod_Mask_;
14390 IM_ASSERT(shared_mods != 0);
14391 g.NavWindowingHighlightAlpha = ImMax(
g.NavWindowingHighlightAlpha, ImSaturate((
g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
14392 if ((keyboard_next_window || keyboard_prev_window) && !just_started_windowing_from_null_focus)
14393 NavUpdateWindowingTarget(keyboard_next_window ? -1 : +1);
14394 else if ((io.KeyMods & shared_mods) != shared_mods)
14395 apply_focus_window =
g.NavWindowingTarget;
14399 const ImGuiKey windowing_toggle_keys[] = { ImGuiKey_LeftAlt, ImGuiKey_RightAlt };
14400 bool windowing_toggle_layer_start =
false;
14401 for (ImGuiKey windowing_toggle_key : windowing_toggle_keys)
14402 if (nav_keyboard_active && IsKeyPressed(windowing_toggle_key, 0, ImGuiKeyOwner_NoOwner))
14404 windowing_toggle_layer_start =
true;
14405 g.NavWindowingToggleLayer =
true;
14406 g.NavWindowingToggleKey = windowing_toggle_key;
14407 g.NavInputSource = ImGuiInputSource_Keyboard;
14410 if (
g.NavWindowingToggleLayer &&
g.NavInputSource == ImGuiInputSource_Keyboard)
14416 if (io.InputQueueCharacters.Size > 0 || io.KeyCtrl || io.KeyShift || io.KeySuper)
14417 g.NavWindowingToggleLayer =
false;
14418 else if (windowing_toggle_layer_start ==
false &&
g.LastKeyboardKeyPressTime ==
g.Time)
14419 g.NavWindowingToggleLayer =
false;
14420 else if (TestKeyOwner(
g.NavWindowingToggleKey, ImGuiKeyOwner_NoOwner) ==
false || TestKeyOwner(ImGuiMod_Alt, ImGuiKeyOwner_NoOwner) ==
false)
14421 g.NavWindowingToggleLayer =
false;
14425 if (IsKeyReleased(
g.NavWindowingToggleKey) &&
g.NavWindowingToggleLayer)
14426 if (
g.ActiveId == 0 ||
g.ActiveIdAllowOverlap)
14427 if (IsMousePosValid(&io.MousePos) == IsMousePosValid(&io.MousePosPrev))
14428 apply_toggle_layer =
true;
14429 if (!IsKeyDown(
g.NavWindowingToggleKey))
14430 g.NavWindowingToggleLayer =
false;
14434 if (
g.NavWindowingTarget && !(
g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove))
14436 ImVec2 nav_move_dir;
14437 if (
g.NavInputSource == ImGuiInputSource_Keyboard && !io.KeyShift)
14438 nav_move_dir = GetKeyMagnitude2d(ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow);
14439 if (
g.NavInputSource == ImGuiInputSource_Gamepad)
14440 nav_move_dir = GetKeyMagnitude2d(ImGuiKey_GamepadLStickLeft, ImGuiKey_GamepadLStickRight, ImGuiKey_GamepadLStickUp, ImGuiKey_GamepadLStickDown);
14441 if (nav_move_dir.x != 0.0f || nav_move_dir.y != 0.0f)
14443 const float NAV_MOVE_SPEED = 800.0f;
14444 const float move_step = NAV_MOVE_SPEED * io.DeltaTime * ImMin(io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
14445 g.NavWindowingAccumDeltaPos += nav_move_dir * move_step;
14446 g.NavHighlightItemUnderNav =
true;
14447 ImVec2 accum_floored = ImTrunc(
g.NavWindowingAccumDeltaPos);
14448 if (accum_floored.x != 0.0f || accum_floored.y != 0.0f)
14450 ImGuiWindow* moving_window =
g.NavWindowingTarget->RootWindowDockTree;
14451 SetWindowPos(moving_window, moving_window->Pos + accum_floored, ImGuiCond_Always);
14452 g.NavWindowingAccumDeltaPos -= accum_floored;
14458 if (apply_focus_window && (
g.NavWindow == NULL || apply_focus_window !=
g.NavWindow->RootWindow))
14462 ImGuiViewport* previous_viewport =
g.NavWindow ?
g.NavWindow->Viewport : NULL;
14464 SetNavCursorVisibleAfterMove();
14465 ClosePopupsOverWindow(apply_focus_window,
false);
14466 FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild);
14467 apply_focus_window =
g.NavWindow;
14468 if (apply_focus_window->NavLastIds[0] == 0)
14469 NavInitWindow(apply_focus_window,
false);
14478 if (apply_focus_window->DC.NavLayersActiveMaskNext == (1 << ImGuiNavLayer_Menu))
14479 g.NavLayer = ImGuiNavLayer_Menu;
14482 if (apply_focus_window->Viewport != previous_viewport &&
g.PlatformIO.Platform_SetWindowFocus)
14483 g.PlatformIO.Platform_SetWindowFocus(apply_focus_window->Viewport);
14485 if (apply_focus_window)
14486 g.NavWindowingTarget = NULL;
14489 if (apply_toggle_layer &&
g.NavWindow)
14494 ImGuiWindow* new_nav_window =
g.NavWindow;
14495 while (new_nav_window->ParentWindow
14496 && (new_nav_window->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) == 0
14497 && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0
14498 && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
14499 new_nav_window = new_nav_window->ParentWindow;
14500 if (new_nav_window !=
g.NavWindow)
14502 ImGuiWindow* old_nav_window =
g.NavWindow;
14503 FocusWindow(new_nav_window);
14504 new_nav_window->NavLastChildNavWindow = old_nav_window;
14508 const ImGuiNavLayer new_nav_layer = (
g.NavWindow->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((
int)
g.NavLayer ^ 1) : ImGuiNavLayer_Main;
14509 if (new_nav_layer !=
g.NavLayer)
14512 const bool preserve_layer_1_nav_id = (new_nav_window->DockNodeAsHost != NULL);
14513 if (new_nav_layer == ImGuiNavLayer_Menu && !preserve_layer_1_nav_id)
14514 g.NavWindow->NavLastIds[new_nav_layer] = 0;
14515 NavRestoreLayer(new_nav_layer);
14516 SetNavCursorVisibleAfterMove();
14522static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window)
14524 if (window->Flags & ImGuiWindowFlags_Popup)
14525 return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingPopup);
14526 if ((window->Flags & ImGuiWindowFlags_MenuBar) && strcmp(window->Name,
"##MainMenuBar") == 0)
14527 return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingMainMenuBar);
14528 if (window->DockNodeAsHost)
14529 return "(Dock node)";
14530 return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingUntitled);
14534void ImGui::NavUpdateWindowingOverlay()
14537 IM_ASSERT(
g.NavWindowingTarget != NULL);
14539 if (
g.NavWindowingTimer < NAV_WINDOWING_LIST_APPEAR_DELAY)
14542 if (
g.NavWindowingListWindow == NULL)
14543 g.NavWindowingListWindow = FindWindowByName(
"###NavWindowingList");
14544 const ImGuiViewport* viewport = GetMainViewport();
14545 SetNextWindowSizeConstraints(ImVec2(viewport->Size.x * 0.20f, viewport->Size.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX));
14546 SetNextWindowPos(viewport->GetCenter(), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
14547 PushStyleVar(ImGuiStyleVar_WindowPadding,
g.Style.WindowPadding * 2.0f);
14548 Begin(
"###NavWindowingList", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings);
14549 if (
g.ContextName[0] != 0)
14550 SeparatorText(
g.ContextName);
14551 for (
int n =
g.WindowsFocusOrder.Size - 1; n >= 0; n--)
14553 ImGuiWindow* window =
g.WindowsFocusOrder[n];
14554 IM_ASSERT(window != NULL);
14555 if (!IsWindowNavFocusable(window))
14557 const char* label = window->Name;
14558 if (label == FindRenderedTextEnd(label))
14559 label = GetFallbackWindowNameForWindowingList(window);
14560 Selectable(label,
g.NavWindowingTarget == window);
14571bool ImGui::IsDragDropActive()
14574 return g.DragDropActive;
14577void ImGui::ClearDragDrop()
14580 if (
g.DragDropActive)
14581 IMGUI_DEBUG_LOG_ACTIVEID(
"[dragdrop] ClearDragDrop()\n");
14582 g.DragDropActive =
false;
14583 g.DragDropPayload.Clear();
14584 g.DragDropAcceptFlags = ImGuiDragDropFlags_None;
14585 g.DragDropAcceptIdCurr =
g.DragDropAcceptIdPrev = 0;
14586 g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
14587 g.DragDropAcceptFrameCount = -1;
14589 g.DragDropPayloadBufHeap.clear();
14590 memset(&
g.DragDropPayloadBufLocal, 0,
sizeof(
g.DragDropPayloadBufLocal));
14593bool ImGui::BeginTooltipHidden()
14596 bool ret = Begin(
"##Tooltip_Hidden", NULL, ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize);
14597 SetWindowHiddenAndSkipItemsForCurrentFrame(
g.CurrentWindow);
14608bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
14611 ImGuiWindow* window =
g.CurrentWindow;
14615 ImGuiMouseButton mouse_button = ImGuiMouseButton_Left;
14617 bool source_drag_active =
false;
14618 ImGuiID source_id = 0;
14619 ImGuiID source_parent_id = 0;
14620 if ((flags & ImGuiDragDropFlags_SourceExtern) == 0)
14622 source_id =
g.LastItemData.ID;
14623 if (source_id != 0)
14626 if (
g.ActiveId != source_id)
14628 if (
g.ActiveIdMouseButton != -1)
14629 mouse_button =
g.ActiveIdMouseButton;
14630 if (
g.IO.MouseDown[mouse_button] ==
false || window->SkipItems)
14632 g.ActiveIdAllowOverlap =
false;
14637 if (
g.IO.MouseDown[mouse_button] ==
false || window->SkipItems)
14639 if ((
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) == 0 && (
g.ActiveId == 0 ||
g.ActiveIdWindow != window))
14644 if (!(flags & ImGuiDragDropFlags_SourceAllowNullID))
14655 source_id =
g.LastItemData.ID = window->GetIDFromRectangle(
g.LastItemData.Rect);
14656 KeepAliveID(source_id);
14657 bool is_hovered = ItemHoverable(
g.LastItemData.Rect, source_id,
g.LastItemData.ItemFlags);
14658 if (is_hovered &&
g.IO.MouseClicked[mouse_button])
14660 SetActiveID(source_id, window);
14661 FocusWindow(window);
14663 if (
g.ActiveId == source_id)
14664 g.ActiveIdAllowOverlap = is_hovered;
14666 if (
g.ActiveId != source_id)
14668 source_parent_id = window->IDStack.back();
14669 source_drag_active = IsMouseDragging(mouse_button);
14672 SetActiveIdUsingAllKeyboardKeys();
14678 source_id =
ImHashStr(
"#SourceExtern");
14679 source_drag_active =
true;
14680 mouse_button =
g.IO.MouseDown[0] ? 0 : -1;
14681 KeepAliveID(source_id);
14682 SetActiveID(source_id, NULL);
14685 IM_ASSERT(
g.DragDropWithinTarget ==
false);
14686 if (!source_drag_active)
14690 if (!
g.DragDropActive)
14692 IM_ASSERT(source_id != 0);
14694 IMGUI_DEBUG_LOG_ACTIVEID(
"[dragdrop] BeginDragDropSource() DragDropActive = true, source_id = 0x%08X%s\n",
14695 source_id, (flags & ImGuiDragDropFlags_SourceExtern) ?
" (EXTERN)" :
"");
14696 ImGuiPayload& payload =
g.DragDropPayload;
14697 payload.SourceId = source_id;
14698 payload.SourceParentId = source_parent_id;
14699 g.DragDropActive =
true;
14700 g.DragDropSourceFlags = flags;
14701 g.DragDropMouseButton = mouse_button;
14702 if (payload.SourceId ==
g.ActiveId)
14703 g.ActiveIdNoClearOnFocusLoss =
true;
14705 g.DragDropSourceFrameCount =
g.FrameCount;
14706 g.DragDropWithinSource =
true;
14708 if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
14713 if (
g.DragDropAcceptIdPrev && (
g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
14714 ret = BeginTooltipHidden();
14716 ret = BeginTooltip();
14721 if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
14722 g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
14727void ImGui::EndDragDropSource()
14730 IM_ASSERT(
g.DragDropActive);
14731 IM_ASSERT(
g.DragDropWithinSource &&
"Not after a BeginDragDropSource()?");
14733 if (!(
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
14737 if (
g.DragDropPayload.DataFrameCount == -1)
14739 g.DragDropWithinSource =
false;
14743bool ImGui::SetDragDropPayload(
const char* type,
const void* data,
size_t data_size, ImGuiCond cond)
14746 ImGuiPayload& payload =
g.DragDropPayload;
14748 cond = ImGuiCond_Always;
14750 IM_ASSERT(type != NULL);
14751 IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType) &&
"Payload type can be at most 32 characters long");
14752 IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0));
14753 IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once);
14754 IM_ASSERT(payload.SourceId != 0);
14756 if (cond == ImGuiCond_Always || payload.DataFrameCount == -1)
14759 ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType));
14760 g.DragDropPayloadBufHeap.resize(0);
14761 if (data_size >
sizeof(
g.DragDropPayloadBufLocal))
14764 g.DragDropPayloadBufHeap.resize((
int)data_size);
14765 payload.Data =
g.DragDropPayloadBufHeap.Data;
14766 memcpy(payload.Data, data, data_size);
14768 else if (data_size > 0)
14771 memset(&
g.DragDropPayloadBufLocal, 0,
sizeof(
g.DragDropPayloadBufLocal));
14772 payload.Data =
g.DragDropPayloadBufLocal;
14773 memcpy(payload.Data, data, data_size);
14777 payload.Data = NULL;
14779 payload.DataSize = (int)data_size;
14781 payload.DataFrameCount =
g.FrameCount;
14784 return (
g.DragDropAcceptFrameCount ==
g.FrameCount) || (
g.DragDropAcceptFrameCount ==
g.FrameCount - 1);
14787bool ImGui::BeginDragDropTargetCustom(
const ImRect& bb, ImGuiID
id)
14790 if (!
g.DragDropActive)
14793 ImGuiWindow* window =
g.CurrentWindow;
14794 ImGuiWindow* hovered_window =
g.HoveredWindowUnderMovingWindow;
14795 if (hovered_window == NULL || window->RootWindowDockTree != hovered_window->RootWindowDockTree)
14797 IM_ASSERT(
id != 0);
14798 if (!IsMouseHoveringRect(bb.Min, bb.Max) || (
id ==
g.DragDropPayload.SourceId))
14800 if (window->SkipItems)
14803 IM_ASSERT(
g.DragDropWithinTarget ==
false &&
g.DragDropWithinSource ==
false);
14804 g.DragDropTargetRect = bb;
14805 g.DragDropTargetClipRect = window->ClipRect;
14806 g.DragDropTargetId =
id;
14807 g.DragDropWithinTarget =
true;
14815bool ImGui::BeginDragDropTarget()
14818 if (!
g.DragDropActive)
14821 ImGuiWindow* window =
g.CurrentWindow;
14822 if (!(
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect))
14824 ImGuiWindow* hovered_window =
g.HoveredWindowUnderMovingWindow;
14825 if (hovered_window == NULL || window->RootWindowDockTree != hovered_window->RootWindowDockTree || window->SkipItems)
14828 const ImRect& display_rect = (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ?
g.LastItemData.DisplayRect :
g.LastItemData.Rect;
14829 ImGuiID
id =
g.LastItemData.ID;
14832 id = window->GetIDFromRectangle(display_rect);
14835 if (
g.DragDropPayload.SourceId ==
id)
14838 IM_ASSERT(
g.DragDropWithinTarget ==
false &&
g.DragDropWithinSource ==
false);
14839 g.DragDropTargetRect = display_rect;
14840 g.DragDropTargetClipRect = (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasClipRect) ?
g.LastItemData.ClipRect : window->ClipRect;
14841 g.DragDropTargetId =
id;
14842 g.DragDropWithinTarget =
true;
14846bool ImGui::IsDragDropPayloadBeingAccepted()
14849 return g.DragDropActive &&
g.DragDropAcceptIdPrev != 0;
14852const ImGuiPayload* ImGui::AcceptDragDropPayload(
const char* type, ImGuiDragDropFlags flags)
14855 ImGuiPayload& payload =
g.DragDropPayload;
14856 IM_ASSERT(
g.DragDropActive);
14857 IM_ASSERT(payload.DataFrameCount != -1);
14858 if (type != NULL && !payload.IsDataType(type))
14863 const bool was_accepted_previously = (
g.DragDropAcceptIdPrev ==
g.DragDropTargetId);
14864 ImRect r =
g.DragDropTargetRect;
14865 float r_surface = r.GetWidth() * r.GetHeight();
14866 if (r_surface >
g.DragDropAcceptIdCurrRectSurface)
14869 g.DragDropAcceptFlags = flags;
14870 g.DragDropAcceptIdCurr =
g.DragDropTargetId;
14871 g.DragDropAcceptIdCurrRectSurface = r_surface;
14875 payload.Preview = was_accepted_previously;
14876 flags |= (
g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect);
14877 if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview)
14878 RenderDragDropTargetRect(r,
g.DragDropTargetClipRect);
14880 g.DragDropAcceptFrameCount =
g.FrameCount;
14881 if ((
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) &&
g.DragDropMouseButton == -1)
14882 payload.Delivery = was_accepted_previously && (
g.DragDropSourceFrameCount <
g.FrameCount);
14884 payload.Delivery = was_accepted_previously && !IsMouseDown(
g.DragDropMouseButton);
14885 if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery))
14888 if (payload.Delivery)
14889 IMGUI_DEBUG_LOG_ACTIVEID(
"[dragdrop] AcceptDragDropPayload(): 0x%08X: payload delivery\n",
g.DragDropTargetId);
14894void ImGui::RenderDragDropTargetRect(
const ImRect& bb,
const ImRect& item_clip_rect)
14897 ImGuiWindow* window =
g.CurrentWindow;
14898 ImRect bb_display = bb;
14899 bb_display.ClipWith(item_clip_rect);
14900 bb_display.Expand(3.5f);
14901 bool push_clip_rect = !window->ClipRect.Contains(bb_display);
14902 if (push_clip_rect)
14903 window->DrawList->PushClipRectFullScreen();
14904 window->DrawList->AddRect(bb_display.Min, bb_display.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f);
14905 if (push_clip_rect)
14906 window->DrawList->PopClipRect();
14909const ImGuiPayload* ImGui::GetDragDropPayload()
14912 return (
g.DragDropActive &&
g.DragDropPayload.DataFrameCount != -1) ? &
g.DragDropPayload : NULL;
14915void ImGui::EndDragDropTarget()
14918 IM_ASSERT(
g.DragDropActive);
14919 IM_ASSERT(
g.DragDropWithinTarget);
14920 g.DragDropWithinTarget =
false;
14923 if (
g.DragDropPayload.Delivery)
14935static inline void LogTextV(ImGuiContext&
g,
const char* fmt, va_list args)
14939 g.LogBuffer.Buf.resize(0);
14940 g.LogBuffer.appendfv(fmt, args);
14941 ImFileWrite(
g.LogBuffer.c_str(),
sizeof(
char), (ImU64)
g.LogBuffer.size(),
g.LogFile);
14945 g.LogBuffer.appendfv(fmt, args);
14949void ImGui::LogText(
const char* fmt, ...)
14956 va_start(args, fmt);
14957 LogTextV(
g, fmt, args);
14961void ImGui::LogTextV(
const char* fmt, va_list args)
14967 LogTextV(
g, fmt, args);
14973void ImGui::LogRenderedText(
const ImVec2* ref_pos,
const char* text,
const char* text_end)
14976 ImGuiWindow* window =
g.CurrentWindow;
14978 const char* prefix =
g.LogNextPrefix;
14979 const char* suffix =
g.LogNextSuffix;
14980 g.LogNextPrefix =
g.LogNextSuffix = NULL;
14983 text_end = FindRenderedTextEnd(text, text_end);
14985 const bool log_new_line = ref_pos && (ref_pos->y >
g.LogLinePosY +
g.Style.FramePadding.y + 1);
14987 g.LogLinePosY = ref_pos->y;
14991 g.LogLineFirstItem =
true;
14995 LogRenderedText(ref_pos, prefix, prefix + strlen(prefix));
14998 if (
g.LogDepthRef > window->DC.TreeDepth)
14999 g.LogDepthRef = window->DC.TreeDepth;
15000 const int tree_depth = (window->DC.TreeDepth -
g.LogDepthRef);
15002 const char* text_remaining = text;
15007 const char* line_start = text_remaining;
15008 const char* line_end =
ImStreolRange(line_start, text_end);
15009 const bool is_last_line = (line_end == text_end);
15010 if (line_start != line_end || !is_last_line)
15012 const int line_length = (int)(line_end - line_start);
15013 const int indentation =
g.LogLineFirstItem ? tree_depth * 4 : 1;
15014 LogText(
"%*s%.*s", indentation,
"", line_length, line_start);
15015 g.LogLineFirstItem =
false;
15016 if (*line_end ==
'\n')
15019 g.LogLineFirstItem =
true;
15024 text_remaining = line_end + 1;
15028 LogRenderedText(ref_pos, suffix, suffix + strlen(suffix));
15032void ImGui::LogBegin(ImGuiLogType type,
int auto_open_depth)
15035 ImGuiWindow* window =
g.CurrentWindow;
15036 IM_ASSERT(
g.LogEnabled ==
false);
15037 IM_ASSERT(
g.LogFile == NULL);
15038 IM_ASSERT(
g.LogBuffer.empty());
15039 g.LogEnabled =
g.ItemUnclipByLog =
true;
15041 g.LogNextPrefix =
g.LogNextSuffix = NULL;
15042 g.LogDepthRef = window->DC.TreeDepth;
15043 g.LogDepthToExpand = ((auto_open_depth >= 0) ? auto_open_depth :
g.LogDepthToExpandDefault);
15044 g.LogLinePosY = FLT_MAX;
15045 g.LogLineFirstItem =
true;
15049void ImGui::LogSetNextTextDecoration(
const char* prefix,
const char* suffix)
15052 g.LogNextPrefix = prefix;
15053 g.LogNextSuffix = suffix;
15056void ImGui::LogToTTY(
int auto_open_depth)
15061 IM_UNUSED(auto_open_depth);
15062#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
15063 LogBegin(ImGuiLogType_TTY, auto_open_depth);
15064 g.LogFile = stdout;
15069void ImGui::LogToFile(
int auto_open_depth,
const char* filename)
15079 filename =
g.IO.LogFilename;
15080 if (!filename || !filename[0])
15082 ImFileHandle f =
ImFileOpen(filename,
"ab");
15089 LogBegin(ImGuiLogType_File, auto_open_depth);
15094void ImGui::LogToClipboard(
int auto_open_depth)
15099 LogBegin(ImGuiLogType_Clipboard, auto_open_depth);
15102void ImGui::LogToBuffer(
int auto_open_depth)
15107 LogBegin(ImGuiLogType_Buffer, auto_open_depth);
15110void ImGui::LogFinish()
15119 case ImGuiLogType_TTY:
15120#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
15124 case ImGuiLogType_File:
15127 case ImGuiLogType_Buffer:
15129 case ImGuiLogType_Clipboard:
15130 if (!
g.LogBuffer.empty())
15131 SetClipboardText(
g.LogBuffer.begin());
15133 case ImGuiLogType_None:
15138 g.LogEnabled =
g.ItemUnclipByLog =
false;
15139 g.LogType = ImGuiLogType_None;
15141 g.LogBuffer.clear();
15146void ImGui::LogButtons()
15150 PushID(
"LogButtons");
15151#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
15152 const bool log_to_tty = Button(
"Log To TTY"); SameLine();
15154 const bool log_to_tty =
false;
15156 const bool log_to_file = Button(
"Log To File"); SameLine();
15157 const bool log_to_clipboard = Button(
"Log To Clipboard"); SameLine();
15158 PushItemFlag(ImGuiItemFlags_NoTabStop,
true);
15159 SetNextItemWidth(80.0f);
15160 SliderInt(
"Default Depth", &
g.LogDepthToExpandDefault, 0, 9, NULL);
15169 if (log_to_clipboard)
15194void ImGui::UpdateSettings()
15198 if (!
g.SettingsLoaded)
15200 IM_ASSERT(
g.SettingsWindows.empty());
15201 if (
g.IO.IniFilename)
15202 LoadIniSettingsFromDisk(
g.IO.IniFilename);
15203 g.SettingsLoaded =
true;
15207 if (
g.SettingsDirtyTimer > 0.0f)
15209 g.SettingsDirtyTimer -=
g.IO.DeltaTime;
15210 if (
g.SettingsDirtyTimer <= 0.0f)
15212 if (
g.IO.IniFilename != NULL)
15213 SaveIniSettingsToDisk(
g.IO.IniFilename);
15215 g.IO.WantSaveIniSettings =
true;
15216 g.SettingsDirtyTimer = 0.0f;
15221void ImGui::MarkIniSettingsDirty()
15224 if (
g.SettingsDirtyTimer <= 0.0f)
15225 g.SettingsDirtyTimer =
g.IO.IniSavingRate;
15228void ImGui::MarkIniSettingsDirty(ImGuiWindow* window)
15231 if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
15232 if (
g.SettingsDirtyTimer <= 0.0f)
15233 g.SettingsDirtyTimer =
g.IO.IniSavingRate;
15236void ImGui::AddSettingsHandler(
const ImGuiSettingsHandler* handler)
15239 IM_ASSERT(FindSettingsHandler(handler->TypeName) == NULL);
15240 g.SettingsHandlers.push_back(*handler);
15243void ImGui::RemoveSettingsHandler(
const char* type_name)
15246 if (ImGuiSettingsHandler* handler = FindSettingsHandler(type_name))
15247 g.SettingsHandlers.erase(handler);
15250ImGuiSettingsHandler* ImGui::FindSettingsHandler(
const char* type_name)
15253 const ImGuiID type_hash =
ImHashStr(type_name);
15254 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
15255 if (handler.TypeHash == type_hash)
15261void ImGui::ClearIniSettings()
15264 g.SettingsIniData.clear();
15265 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
15266 if (handler.ClearAllFn != NULL)
15267 handler.ClearAllFn(&
g, &handler);
15270void ImGui::LoadIniSettingsFromDisk(
const char* ini_filename)
15272 size_t file_data_size = 0;
15276 if (file_data_size > 0)
15277 LoadIniSettingsFromMemory(file_data, (
size_t)file_data_size);
15278 IM_FREE(file_data);
15283void ImGui::LoadIniSettingsFromMemory(
const char* ini_data,
size_t ini_size)
15286 IM_ASSERT(
g.Initialized);
15293 ini_size = strlen(ini_data);
15294 g.SettingsIniData.Buf.resize((
int)ini_size + 1);
15295 char*
const buf =
g.SettingsIniData.Buf.Data;
15296 char*
const buf_end = buf + ini_size;
15297 memcpy(buf, ini_data, ini_size);
15302 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
15303 if (handler.ReadInitFn != NULL)
15304 handler.ReadInitFn(&
g, &handler);
15306 void* entry_data = NULL;
15307 ImGuiSettingsHandler* entry_handler = NULL;
15309 char* line_end = NULL;
15310 for (
char* line = buf; line < buf_end; line = line_end + 1)
15313 while (*line ==
'\n' || *line ==
'\r')
15316 while (line_end < buf_end && *line_end !=
'\n' && *line_end !=
'\r')
15319 if (line[0] ==
';')
15321 if (line[0] ==
'[' && line_end > line && line_end[-1] ==
']')
15325 const char* name_end = line_end - 1;
15326 const char* type_start = line + 1;
15327 char* type_end = (
char*)(
void*)
ImStrchrRange(type_start, name_end,
']');
15328 const char* name_start = type_end ?
ImStrchrRange(type_end + 1, name_end,
'[') : NULL;
15329 if (!type_end || !name_start)
15333 entry_handler = FindSettingsHandler(type_start);
15334 entry_data = entry_handler ? entry_handler->ReadOpenFn(&
g, entry_handler, name_start) : NULL;
15336 else if (entry_handler != NULL && entry_data != NULL)
15339 entry_handler->ReadLineFn(&
g, entry_handler, entry_data, line);
15342 g.SettingsLoaded =
true;
15345 memcpy(buf, ini_data, ini_size);
15348 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
15349 if (handler.ApplyAllFn != NULL)
15350 handler.ApplyAllFn(&
g, &handler);
15353void ImGui::SaveIniSettingsToDisk(
const char* ini_filename)
15356 g.SettingsDirtyTimer = 0.0f;
15360 size_t ini_data_size = 0;
15361 const char* ini_data = SaveIniSettingsToMemory(&ini_data_size);
15362 ImFileHandle f =
ImFileOpen(ini_filename,
"wt");
15365 ImFileWrite(ini_data,
sizeof(
char), ini_data_size, f);
15370const char* ImGui::SaveIniSettingsToMemory(
size_t* out_size)
15373 g.SettingsDirtyTimer = 0.0f;
15374 g.SettingsIniData.Buf.resize(0);
15375 g.SettingsIniData.Buf.push_back(0);
15376 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
15377 handler.WriteAllFn(&
g, &handler, &
g.SettingsIniData);
15379 *out_size = (size_t)
g.SettingsIniData.size();
15380 return g.SettingsIniData.c_str();
15383ImGuiWindowSettings* ImGui::CreateNewWindowSettings(
const char* name)
15387 if (
g.IO.ConfigDebugIniSettings ==
false)
15391 if (
const char* p = strstr(name,
"###"))
15394 const size_t name_len = strlen(name);
15397 const size_t chunk_size =
sizeof(ImGuiWindowSettings) + name_len + 1;
15398 ImGuiWindowSettings* settings =
g.SettingsWindows.alloc_chunk(chunk_size);
15399 IM_PLACEMENT_NEW(settings) ImGuiWindowSettings();
15400 settings->ID =
ImHashStr(name, name_len);
15401 memcpy(settings->GetName(), name, name_len + 1);
15408ImGuiWindowSettings* ImGui::FindWindowSettingsByID(ImGuiID
id)
15411 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
15412 if (settings->ID ==
id && !settings->WantDelete)
15418ImGuiWindowSettings* ImGui::FindWindowSettingsByWindow(ImGuiWindow* window)
15421 if (window->SettingsOffset != -1)
15422 return g.SettingsWindows.ptr_from_offset(window->SettingsOffset);
15423 return FindWindowSettingsByID(window->ID);
15427void ImGui::ClearWindowSettings(
const char* name)
15431 ImGuiWindow* window = FindWindowByName(name);
15432 if (window != NULL)
15434 window->Flags |= ImGuiWindowFlags_NoSavedSettings;
15435 InitOrLoadWindowSettings(window, NULL);
15436 if (window->DockId != 0)
15437 DockContextProcessUndockWindow(&
g, window,
true);
15439 if (ImGuiWindowSettings* settings = window ? FindWindowSettingsByWindow(window) : FindWindowSettingsByID(
ImHashStr(name)))
15440 settings->WantDelete = true;
15443static void WindowSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
15445 ImGuiContext&
g = *ctx;
15446 for (ImGuiWindow* window :
g.Windows)
15447 window->SettingsOffset = -1;
15448 g.SettingsWindows.clear();
15451static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*,
const char* name)
15454 ImGuiWindowSettings* settings = ImGui::FindWindowSettingsByID(
id);
15456 *settings = ImGuiWindowSettings();
15458 settings = ImGui::CreateNewWindowSettings(name);
15460 settings->WantApply =
true;
15461 return (
void*)settings;
15464static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
void* entry,
const char* line)
15466 ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry;
15470 if (sscanf(line,
"Pos=%i,%i", &x, &y) == 2) { settings->Pos = ImVec2ih((
short)x, (
short)y); }
15471 else if (sscanf(line,
"Size=%i,%i", &x, &y) == 2) { settings->Size = ImVec2ih((
short)x, (
short)y); }
15472 else if (sscanf(line,
"ViewportId=0x%08X", &u1) == 1) { settings->ViewportId = u1; }
15473 else if (sscanf(line,
"ViewportPos=%i,%i", &x, &y) == 2){ settings->ViewportPos = ImVec2ih((
short)x, (
short)y); }
15474 else if (sscanf(line,
"Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); }
15475 else if (sscanf(line,
"IsChild=%d", &i) == 1) { settings->IsChild = (i != 0); }
15476 else if (sscanf(line,
"DockId=0x%X,%d", &u1, &i) == 2) { settings->DockId = u1; settings->DockOrder = (short)i; }
15477 else if (sscanf(line,
"DockId=0x%X", &u1) == 1) { settings->DockId = u1; settings->DockOrder = -1; }
15478 else if (sscanf(line,
"ClassId=0x%X", &u1) == 1) { settings->ClassId = u1; }
15482static void WindowSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
15484 ImGuiContext&
g = *ctx;
15485 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
15486 if (settings->WantApply)
15488 if (ImGuiWindow* window = ImGui::FindWindowByID(settings->ID))
15489 ApplyWindowSettings(window, settings);
15490 settings->WantApply =
false;
15494static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
15498 ImGuiContext&
g = *ctx;
15499 for (ImGuiWindow* window :
g.Windows)
15501 if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
15504 ImGuiWindowSettings* settings = ImGui::FindWindowSettingsByWindow(window);
15507 settings = ImGui::CreateNewWindowSettings(window->Name);
15508 window->SettingsOffset =
g.SettingsWindows.offset_from_ptr(settings);
15510 IM_ASSERT(settings->ID == window->ID);
15511 settings->Pos = ImVec2ih(window->Pos - window->ViewportPos);
15512 settings->Size = ImVec2ih(window->SizeFull);
15513 settings->ViewportId = window->ViewportId;
15514 settings->ViewportPos = ImVec2ih(window->ViewportPos);
15515 IM_ASSERT(window->DockNode == NULL || window->DockNode->ID == window->DockId);
15516 settings->DockId = window->DockId;
15517 settings->ClassId = window->WindowClass.ClassId;
15518 settings->DockOrder = window->DockOrder;
15519 settings->Collapsed = window->Collapsed;
15520 settings->IsChild = (window->RootWindow != window);
15521 settings->WantDelete =
false;
15525 buf->reserve(buf->size() +
g.SettingsWindows.size() * 6);
15526 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
15528 if (settings->WantDelete)
15530 const char* settings_name = settings->GetName();
15531 buf->appendf(
"[%s][%s]\n", handler->TypeName, settings_name);
15532 if (settings->IsChild)
15534 buf->appendf(
"IsChild=1\n");
15535 buf->appendf(
"Size=%d,%d\n", settings->Size.x, settings->Size.y);
15541 buf->appendf(
"ViewportPos=%d,%d\n", settings->ViewportPos.x, settings->ViewportPos.y);
15542 buf->appendf(
"ViewportId=0x%08X\n", settings->ViewportId);
15545 buf->appendf(
"Pos=%d,%d\n", settings->Pos.x, settings->Pos.y);
15546 if (settings->Size.x != 0 || settings->Size.y != 0)
15547 buf->appendf(
"Size=%d,%d\n", settings->Size.x, settings->Size.y);
15548 buf->appendf(
"Collapsed=%d\n", settings->Collapsed);
15549 if (settings->DockId != 0)
15552 if (settings->DockOrder == -1)
15553 buf->appendf(
"DockId=0x%08X\n", settings->DockId);
15555 buf->appendf(
"DockId=0x%08X,%d\n", settings->DockId, settings->DockOrder);
15556 if (settings->ClassId != 0)
15557 buf->appendf(
"ClassId=0x%08X\n", settings->ClassId);
15569void ImGui::LocalizeRegisterEntries(
const ImGuiLocEntry* entries,
int count)
15572 for (
int n = 0; n <
count; n++)
15573 g.LocalizationTable[entries[n].Key] = entries[n].Text;
15605ImGuiViewport* ImGui::GetMainViewport()
15608 return g.Viewports[0];
15612ImGuiViewport* ImGui::FindViewportByID(ImGuiID
id)
15615 for (ImGuiViewportP* viewport :
g.Viewports)
15616 if (viewport->
ID ==
id)
15621ImGuiViewport* ImGui::FindViewportByPlatformHandle(
void* platform_handle)
15624 for (ImGuiViewportP* viewport :
g.Viewports)
15625 if (viewport->PlatformHandle == platform_handle)
15630void ImGui::SetCurrentViewport(ImGuiWindow* current_window, ImGuiViewportP* viewport)
15633 (void)current_window;
15636 viewport->LastFrameActive =
g.FrameCount;
15637 if (
g.CurrentViewport == viewport)
15639 g.CurrentDpiScale = viewport ? viewport->DpiScale : 1.0f;
15640 g.CurrentViewport = viewport;
15645 if (
g.CurrentViewport &&
g.PlatformIO.Platform_OnChangedViewport)
15646 g.PlatformIO.Platform_OnChangedViewport(
g.CurrentViewport);
15649void ImGui::SetWindowViewport(ImGuiWindow* window, ImGuiViewportP* viewport)
15652 if (window->ViewportOwned && window->Viewport->Window == window)
15653 window->Viewport->Size = ImVec2(0.0f, 0.0f);
15655 window->Viewport = viewport;
15656 window->ViewportId = viewport->ID;
15657 window->ViewportOwned = (viewport->Window == window);
15660static bool ImGui::GetWindowAlwaysWantOwnViewport(ImGuiWindow* window)
15664 if (
g.IO.ConfigViewportsNoAutoMerge || (window->WindowClass.ViewportFlagsOverrideSet & ImGuiViewportFlags_NoAutoMerge))
15665 if (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
15666 if (!window->DockIsActive)
15667 if ((window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip)) == 0)
15668 if ((window->Flags & ImGuiWindowFlags_Popup) == 0 || (window->Flags & ImGuiWindowFlags_Modal) != 0)
15673static bool ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* viewport)
15676 if (window->Viewport == viewport)
15678 if ((viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) == 0)
15680 if ((viewport->Flags & ImGuiViewportFlags_IsMinimized) != 0)
15682 if (!viewport->GetMainRect().Contains(window->Rect()))
15684 if (GetWindowAlwaysWantOwnViewport(window))
15688 for (ImGuiWindow* window_behind :
g.Windows)
15690 if (window_behind == window)
15692 if (window_behind->WasActive && window_behind->ViewportOwned && !(window_behind->Flags & ImGuiWindowFlags_ChildWindow))
15693 if (window_behind->Viewport->GetMainRect().Overlaps(window->Rect()))
15698 ImGuiViewportP* old_viewport = window->Viewport;
15699 if (window->ViewportOwned)
15700 for (
int n = 0; n <
g.Windows.Size; n++)
15701 if (
g.Windows[n]->Viewport == old_viewport)
15702 SetWindowViewport(
g.Windows[n], viewport);
15703 SetWindowViewport(window, viewport);
15704 BringWindowToDisplayFront(window);
15710static bool ImGui::UpdateTryMergeWindowIntoHostViewports(ImGuiWindow* window)
15713 return UpdateTryMergeWindowIntoHostViewport(window,
g.Viewports[0]);
15718void ImGui::TranslateWindowsInViewport(ImGuiViewportP* viewport,
const ImVec2& old_pos,
const ImVec2& new_pos,
const ImVec2& old_size,
const ImVec2& new_size)
15721 IM_ASSERT(viewport->Window == NULL && (viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows));
15728 const bool translate_all_windows = (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable) != (
g.ConfigFlagsLastFrame & ImGuiConfigFlags_ViewportsEnable);
15729 ImRect test_still_fit_rect(old_pos, old_pos + viewport->Size);
15730 ImVec2 delta_pos = new_pos - old_pos;
15731 for (ImGuiWindow* window :
g.Windows)
15732 if (translate_all_windows || (window->Viewport == viewport && (old_size == new_size || test_still_fit_rect.Contains(window->Rect()))))
15733 TranslateWindow(window, delta_pos);
15737void ImGui::ScaleWindowsInViewport(ImGuiViewportP* viewport,
float scale)
15740 if (viewport->Window)
15742 ScaleWindow(viewport->Window, scale);
15746 for (ImGuiWindow* window :
g.Windows)
15747 if (window->Viewport == viewport)
15748 ScaleWindow(window,
scale);
15755ImGuiViewportP* ImGui::FindHoveredViewportFromPlatformWindowStack(
const ImVec2& mouse_platform_pos)
15758 ImGuiViewportP* best_candidate = NULL;
15759 for (ImGuiViewportP* viewport :
g.Viewports)
15760 if (!(viewport->Flags & (ImGuiViewportFlags_NoInputs | ImGuiViewportFlags_IsMinimized)) && viewport->GetMainRect().Contains(mouse_platform_pos))
15761 if (best_candidate == NULL || best_candidate->LastFocusedStampCount < viewport->LastFocusedStampCount)
15762 best_candidate = viewport;
15763 return best_candidate;
15768static void ImGui::UpdateViewportsNewFrame()
15771 IM_ASSERT(
g.PlatformIO.Viewports.Size <=
g.Viewports.Size);
15775 const bool viewports_enabled = (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable) != 0;
15776 if (viewports_enabled)
15778 ImGuiViewportP* focused_viewport = NULL;
15779 for (ImGuiViewportP* viewport :
g.Viewports)
15781 const bool platform_funcs_available = viewport->PlatformWindowCreated;
15782 if (
g.PlatformIO.Platform_GetWindowMinimized && platform_funcs_available)
15784 bool is_minimized =
g.PlatformIO.Platform_GetWindowMinimized(viewport);
15786 viewport->Flags |= ImGuiViewportFlags_IsMinimized;
15788 viewport->Flags &= ~ImGuiViewportFlags_IsMinimized;
15793 if (
g.PlatformIO.Platform_GetWindowFocus && platform_funcs_available)
15795 bool is_focused =
g.PlatformIO.Platform_GetWindowFocus(viewport);
15797 viewport->Flags |= ImGuiViewportFlags_IsFocused;
15799 viewport->Flags &= ~ImGuiViewportFlags_IsFocused;
15801 focused_viewport = viewport;
15806 if (focused_viewport &&
g.PlatformLastFocusedViewportId != focused_viewport->ID)
15808 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Focused viewport changed %08X -> %08X, attempting to apply our focus.\n",
g.PlatformLastFocusedViewportId, focused_viewport->ID);
15809 const ImGuiViewport* prev_focused_viewport = FindViewportByID(
g.PlatformLastFocusedViewportId);
15810 const bool prev_focused_has_been_destroyed = (prev_focused_viewport == NULL) || (prev_focused_viewport->PlatformWindowCreated ==
false);
15815 if (focused_viewport->LastFocusedStampCount !=
g.ViewportFocusedStampCount)
15816 focused_viewport->LastFocusedStampCount = ++
g.ViewportFocusedStampCount;
15817 g.PlatformLastFocusedViewportId = focused_viewport->ID;
15823 const bool apply_imgui_focus_on_focused_viewport = !IsAnyMouseDown() && !prev_focused_has_been_destroyed;
15824 if (apply_imgui_focus_on_focused_viewport)
15826 focused_viewport->LastFocusedHadNavWindow |= (
g.NavWindow != NULL) && (
g.NavWindow->Viewport == focused_viewport);
15827 ImGuiFocusRequestFlags focus_request_flags = ImGuiFocusRequestFlags_UnlessBelowModal | ImGuiFocusRequestFlags_RestoreFocusedChild;
15828 if (focused_viewport->Window != NULL)
15829 FocusWindow(focused_viewport->Window, focus_request_flags);
15830 else if (focused_viewport->LastFocusedHadNavWindow)
15831 FocusTopMostWindowUnderOne(NULL, NULL, focused_viewport, focus_request_flags);
15833 FocusWindow(NULL, focus_request_flags);
15836 if (focused_viewport)
15837 focused_viewport->LastFocusedHadNavWindow = (
g.NavWindow != NULL) && (
g.NavWindow->Viewport == focused_viewport);
15842 ImGuiViewportP* main_viewport =
g.Viewports[0];
15843 IM_ASSERT(main_viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID);
15844 IM_ASSERT(main_viewport->Window == NULL);
15845 ImVec2 main_viewport_pos = viewports_enabled ?
g.PlatformIO.Platform_GetWindowPos(main_viewport) : ImVec2(0.0f, 0.0f);
15846 ImVec2 main_viewport_size =
g.IO.DisplaySize;
15847 if (viewports_enabled && (main_viewport->Flags & ImGuiViewportFlags_IsMinimized))
15849 main_viewport_pos = main_viewport->Pos;
15850 main_viewport_size = main_viewport->Size;
15852 AddUpdateViewport(NULL, IMGUI_VIEWPORT_DEFAULT_ID, main_viewport_pos, main_viewport_size, ImGuiViewportFlags_OwnedByApp | ImGuiViewportFlags_CanHostOtherWindows);
15854 g.CurrentDpiScale = 0.0f;
15855 g.CurrentViewport = NULL;
15856 g.MouseViewport = NULL;
15857 for (
int n = 0; n <
g.Viewports.Size; n++)
15859 ImGuiViewportP* viewport =
g.Viewports[n];
15863 if (n > 0 && viewport->LastFrameActive <
g.FrameCount - 2)
15865 DestroyViewport(viewport);
15870 const bool platform_funcs_available = viewport->PlatformWindowCreated;
15871 if (viewports_enabled)
15875 if (!(viewport->Flags & ImGuiViewportFlags_IsMinimized) && platform_funcs_available)
15878 if (viewport->PlatformRequestMove)
15879 viewport->Pos = viewport->LastPlatformPos =
g.PlatformIO.Platform_GetWindowPos(viewport);
15880 if (viewport->PlatformRequestResize)
15881 viewport->Size = viewport->LastPlatformSize =
g.PlatformIO.Platform_GetWindowSize(viewport);
15886 UpdateViewportPlatformMonitor(viewport);
15890 viewport->WorkInsetMin = viewport->BuildWorkInsetMin;
15891 viewport->WorkInsetMax = viewport->BuildWorkInsetMax;
15892 viewport->BuildWorkInsetMin = viewport->BuildWorkInsetMax = ImVec2(0.0f, 0.0f);
15893 if (
g.PlatformIO.Platform_GetWindowWorkAreaInsets != NULL && platform_funcs_available)
15895 ImVec4 insets =
g.PlatformIO.Platform_GetWindowWorkAreaInsets(viewport);
15896 IM_ASSERT(insets.x >= 0.0f && insets.y >= 0.0f && insets.z >= 0.0f && insets.w >= 0.0f);
15897 viewport->BuildWorkInsetMin = ImVec2(insets.x, insets.y);
15898 viewport->BuildWorkInsetMax = ImVec2(insets.z, insets.w);
15900 viewport->UpdateWorkRect();
15903 viewport->Alpha = 1.0f;
15907 const ImVec2 viewport_delta_pos = viewport->Pos - viewport->LastPos;
15908 if ((viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) && (viewport_delta_pos.x != 0.0f || viewport_delta_pos.y != 0.0f))
15909 TranslateWindowsInViewport(viewport, viewport->LastPos, viewport->Pos, viewport->LastSize, viewport->Size);
15912 float new_dpi_scale;
15913 if (
g.PlatformIO.Platform_GetWindowDpiScale && platform_funcs_available)
15914 new_dpi_scale =
g.PlatformIO.Platform_GetWindowDpiScale(viewport);
15915 else if (viewport->PlatformMonitor != -1)
15916 new_dpi_scale =
g.PlatformIO.Monitors[viewport->PlatformMonitor].DpiScale;
15918 new_dpi_scale = (viewport->DpiScale != 0.0f) ? viewport->DpiScale : 1.0f;
15919 if (viewport->DpiScale != 0.0f && new_dpi_scale != viewport->DpiScale)
15921 float scale_factor = new_dpi_scale / viewport->DpiScale;
15922 if (
g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports)
15923 ScaleWindowsInViewport(viewport, scale_factor);
15933 viewport->DpiScale = new_dpi_scale;
15937 g.PlatformMonitorsFullWorkRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
15938 if (
g.PlatformIO.Monitors.Size == 0)
15940 ImGuiPlatformMonitor* monitor = &
g.FallbackMonitor;
15941 monitor->MainPos = main_viewport->Pos;
15942 monitor->MainSize = main_viewport->Size;
15943 monitor->WorkPos = main_viewport->WorkPos;
15944 monitor->WorkSize = main_viewport->WorkSize;
15945 monitor->DpiScale = main_viewport->DpiScale;
15946 g.PlatformMonitorsFullWorkRect.Add(monitor->WorkPos);
15947 g.PlatformMonitorsFullWorkRect.Add(monitor->WorkPos + monitor->WorkSize);
15951 g.FallbackMonitor =
g.PlatformIO.Monitors[0];
15953 for (ImGuiPlatformMonitor& monitor :
g.PlatformIO.Monitors)
15955 g.PlatformMonitorsFullWorkRect.Add(monitor.WorkPos);
15956 g.PlatformMonitorsFullWorkRect.Add(monitor.WorkPos + monitor.WorkSize);
15959 if (!viewports_enabled)
15961 g.MouseViewport = main_viewport;
15967 ImGuiViewportP* viewport_hovered = NULL;
15968 if (
g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport)
15970 viewport_hovered =
g.IO.MouseHoveredViewport ? (ImGuiViewportP*)FindViewportByID(
g.IO.MouseHoveredViewport) : NULL;
15971 if (viewport_hovered && (viewport_hovered->Flags & ImGuiViewportFlags_NoInputs))
15972 viewport_hovered = FindHoveredViewportFromPlatformWindowStack(
g.IO.MousePos);
15980 viewport_hovered = FindHoveredViewportFromPlatformWindowStack(
g.IO.MousePos);
15982 if (viewport_hovered != NULL)
15983 g.MouseLastHoveredViewport = viewport_hovered;
15984 else if (
g.MouseLastHoveredViewport == NULL)
15985 g.MouseLastHoveredViewport =
g.Viewports[0];
15990 if (
g.MovingWindow &&
g.MovingWindow->Viewport)
15991 g.MouseViewport =
g.MovingWindow->Viewport;
15993 g.MouseViewport =
g.MouseLastHoveredViewport;
16000 const bool is_mouse_dragging_with_an_expected_destination =
g.DragDropActive;
16001 if (is_mouse_dragging_with_an_expected_destination && viewport_hovered == NULL)
16002 viewport_hovered =
g.MouseLastHoveredViewport;
16003 if (is_mouse_dragging_with_an_expected_destination ||
g.ActiveId == 0 || !IsAnyMouseDown())
16004 if (viewport_hovered != NULL && viewport_hovered !=
g.MouseViewport && !(viewport_hovered->Flags & ImGuiViewportFlags_NoInputs))
16005 g.MouseViewport = viewport_hovered;
16007 IM_ASSERT(
g.MouseViewport != NULL);
16011static void ImGui::UpdateViewportsEndFrame()
16014 g.PlatformIO.Viewports.resize(0);
16015 for (
int i = 0; i <
g.Viewports.Size; i++)
16017 ImGuiViewportP* viewport =
g.Viewports[i];
16018 viewport->LastPos = viewport->Pos;
16019 viewport->LastSize = viewport->Size;
16020 if (viewport->LastFrameActive <
g.FrameCount || viewport->Size.x <= 0.0f || viewport->Size.y <= 0.0f)
16023 if (viewport->Window && !IsWindowActiveAndVisible(viewport->Window))
16026 IM_ASSERT(viewport->Window != NULL);
16027 g.PlatformIO.Viewports.push_back(viewport);
16029 g.Viewports[0]->ClearRequestFlags();
16033ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID
id,
const ImVec2& pos,
const ImVec2& size, ImGuiViewportFlags flags)
16036 IM_ASSERT(
id != 0);
16038 flags |= ImGuiViewportFlags_IsPlatformWindow;
16039 if (window != NULL)
16041 if (
g.MovingWindow &&
g.MovingWindow->RootWindowDockTree == window)
16042 flags |= ImGuiViewportFlags_NoInputs | ImGuiViewportFlags_NoFocusOnAppearing;
16043 if ((window->Flags & ImGuiWindowFlags_NoMouseInputs) && (window->Flags & ImGuiWindowFlags_NoNavInputs))
16044 flags |= ImGuiViewportFlags_NoInputs;
16045 if (window->Flags & ImGuiWindowFlags_NoFocusOnAppearing)
16046 flags |= ImGuiViewportFlags_NoFocusOnAppearing;
16049 ImGuiViewportP* viewport = (ImGuiViewportP*)FindViewportByID(
id);
16053 if (!viewport->PlatformRequestMove || viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID)
16054 viewport->Pos = pos;
16055 if (!viewport->PlatformRequestResize || viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID)
16056 viewport->Size =
size;
16057 viewport->Flags = flags | (viewport->Flags & (ImGuiViewportFlags_IsMinimized | ImGuiViewportFlags_IsFocused));
16062 viewport = IM_NEW(ImGuiViewportP)();
16064 viewport->Idx =
g.Viewports.Size;
16065 viewport->Pos = viewport->LastPos = pos;
16066 viewport->Size = viewport->LastSize =
size;
16067 viewport->Flags = flags;
16068 UpdateViewportPlatformMonitor(viewport);
16069 g.Viewports.push_back(viewport);
16070 g.ViewportCreatedCount++;
16071 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Add Viewport %08X '%s'\n",
id, window ? window->Name :
"<NULL>");
16075 g.DrawListSharedData.ClipRectFullscreen.x = ImMin(
g.DrawListSharedData.ClipRectFullscreen.x, viewport->Pos.x);
16076 g.DrawListSharedData.ClipRectFullscreen.y = ImMin(
g.DrawListSharedData.ClipRectFullscreen.y, viewport->Pos.y);
16077 g.DrawListSharedData.ClipRectFullscreen.z = ImMax(
g.DrawListSharedData.ClipRectFullscreen.z, viewport->Pos.x + viewport->Size.x);
16078 g.DrawListSharedData.ClipRectFullscreen.w = ImMax(
g.DrawListSharedData.ClipRectFullscreen.w, viewport->Pos.y + viewport->Size.y);
16082 if (viewport->PlatformMonitor != -1)
16083 viewport->DpiScale =
g.PlatformIO.Monitors[viewport->PlatformMonitor].DpiScale;
16086 viewport->Window = window;
16087 viewport->LastFrameActive =
g.FrameCount;
16088 viewport->UpdateWorkRect();
16089 IM_ASSERT(window == NULL || viewport->ID == window->ID);
16091 if (window != NULL)
16092 window->ViewportOwned =
true;
16097static void ImGui::DestroyViewport(ImGuiViewportP* viewport)
16101 for (ImGuiWindow* window :
g.Windows)
16103 if (window->Viewport != viewport)
16105 window->Viewport = NULL;
16106 window->ViewportOwned =
false;
16108 if (viewport ==
g.MouseLastHoveredViewport)
16109 g.MouseLastHoveredViewport = NULL;
16112 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Delete Viewport %08X '%s'\n", viewport->ID, viewport->Window ? viewport->Window->Name :
"n/a");
16113 DestroyPlatformWindow(viewport);
16114 IM_ASSERT(
g.PlatformIO.Viewports.contains(viewport) ==
false);
16115 IM_ASSERT(
g.Viewports[viewport->Idx] == viewport);
16116 g.Viewports.erase(
g.Viewports.Data + viewport->Idx);
16117 IM_DELETE(viewport);
16121static void ImGui::WindowSelectViewport(ImGuiWindow* window)
16124 ImGuiWindowFlags flags = window->Flags;
16125 window->ViewportAllowPlatformMonitorExtend = -1;
16128 ImGuiViewportP* main_viewport = (ImGuiViewportP*)(
void*)GetMainViewport();
16129 if (!(
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable))
16131 SetWindowViewport(window, main_viewport);
16134 window->ViewportOwned =
false;
16137 if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && window->Appearing)
16139 window->Viewport = NULL;
16140 window->ViewportId = 0;
16143 if ((
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasViewport) == 0)
16146 if (window->Viewport == NULL && window->ParentWindow && (!window->ParentWindow->IsFallbackWindow || window->ParentWindow->WasActive))
16147 window->Viewport = window->ParentWindow->Viewport;
16150 if (window->Viewport == NULL && window->ViewportId != 0)
16152 window->Viewport = (ImGuiViewportP*)FindViewportByID(window->ViewportId);
16153 if (window->Viewport == NULL && window->ViewportPos.x != FLT_MAX && window->ViewportPos.y != FLT_MAX)
16154 window->Viewport = AddUpdateViewport(window, window->ID, window->ViewportPos, window->Size, ImGuiViewportFlags_None);
16158 bool lock_viewport =
false;
16159 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasViewport)
16162 window->Viewport = (ImGuiViewportP*)FindViewportByID(
g.NextWindowData.ViewportId);
16163 window->ViewportId =
g.NextWindowData.ViewportId;
16164 if (window->Viewport && (window->Flags & ImGuiWindowFlags_DockNodeHost) != 0 && window->Viewport->Window != NULL)
16166 window->Viewport->Window = window;
16167 window->Viewport->ID = window->ViewportId = window->ID;
16169 lock_viewport =
true;
16171 else if ((flags & ImGuiWindowFlags_ChildWindow) || (flags & ImGuiWindowFlags_ChildMenu))
16174 if (window->DockNode && window->DockNode->HostWindow)
16175 IM_ASSERT(window->DockNode->HostWindow->Viewport == window->ParentWindow->Viewport);
16176 window->Viewport = window->ParentWindow->Viewport;
16178 else if (window->DockNode && window->DockNode->HostWindow)
16181 window->Viewport = window->DockNode->HostWindow->Viewport;
16183 else if (flags & ImGuiWindowFlags_Tooltip)
16185 window->Viewport =
g.MouseViewport;
16187 else if (GetWindowAlwaysWantOwnViewport(window))
16189 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
16191 else if (
g.MovingWindow &&
g.MovingWindow->RootWindowDockTree == window && IsMousePosValid())
16193 if (window->Viewport != NULL && window->Viewport->Window == window)
16194 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
16201 bool try_to_merge_into_host_viewport = (window->Viewport && window == window->Viewport->Window && (
g.ActiveId == 0 ||
g.ActiveIdAllowOverlap));
16202 if (try_to_merge_into_host_viewport)
16203 UpdateTryMergeWindowIntoHostViewports(window);
16207 if (window->Viewport == NULL)
16208 if (!UpdateTryMergeWindowIntoHostViewport(window, main_viewport))
16209 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
16212 if (!lock_viewport)
16214 if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
16218 ImVec2 mouse_ref = (flags & ImGuiWindowFlags_Tooltip) ?
g.IO.MousePos :
g.BeginPopupStack.back().OpenMousePos;
16219 bool use_mouse_ref = (!
g.NavCursorVisible || !
g.NavHighlightItemUnderNav || !
g.NavWindow);
16220 bool mouse_valid = IsMousePosValid(&mouse_ref);
16221 if ((window->Appearing || (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_ChildMenu))) && (!use_mouse_ref || mouse_valid))
16222 window->ViewportAllowPlatformMonitorExtend = FindPlatformMonitorForPos((use_mouse_ref && mouse_valid) ? mouse_ref : NavCalcPreferredRefPos());
16224 window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor;
16226 else if (window->Viewport && window != window->Viewport->Window && window->Viewport->Window && !(flags & ImGuiWindowFlags_ChildWindow) && window->DockNode == NULL)
16229 const bool will_be_visible = (window->DockIsActive && !window->DockTabIsVisible) ?
false : true;
16230 if ((window->Flags & ImGuiWindowFlags_DockNodeHost) && window->Viewport->LastFrameActive <
g.FrameCount && will_be_visible)
16233 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Window '%s' steal Viewport %08X from Window '%s'\n", window->Name, window->Viewport->ID, window->Viewport->Window->Name);
16234 window->Viewport->Window = window;
16235 window->Viewport->ID = window->ID;
16236 window->Viewport->LastNameHash = 0;
16238 else if (!UpdateTryMergeWindowIntoHostViewports(window))
16241 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoFocusOnAppearing);
16244 else if (window->ViewportAllowPlatformMonitorExtend < 0 && (flags & ImGuiWindowFlags_ChildWindow) == 0)
16248 window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor;
16253 window->ViewportOwned = (window == window->Viewport->Window);
16254 window->ViewportId = window->Viewport->ID;
16261void ImGui::WindowSyncOwnedViewport(ImGuiWindow* window, ImGuiWindow* parent_window_in_stack)
16265 bool viewport_rect_changed =
false;
16269 if (window->Viewport->PlatformRequestMove)
16271 window->Pos = window->Viewport->Pos;
16272 MarkIniSettingsDirty(window);
16274 else if (memcmp(&window->Viewport->Pos, &window->Pos,
sizeof(window->Pos)) != 0)
16276 viewport_rect_changed =
true;
16277 window->Viewport->Pos = window->Pos;
16280 if (window->Viewport->PlatformRequestResize)
16282 window->Size = window->SizeFull = window->Viewport->Size;
16283 MarkIniSettingsDirty(window);
16285 else if (memcmp(&window->Viewport->Size, &window->Size,
sizeof(window->Size)) != 0)
16287 viewport_rect_changed =
true;
16288 window->Viewport->Size = window->Size;
16290 window->Viewport->UpdateWorkRect();
16294 if (viewport_rect_changed)
16295 UpdateViewportPlatformMonitor(window->Viewport);
16298 const ImGuiViewportFlags viewport_flags_to_clear = ImGuiViewportFlags_TopMost | ImGuiViewportFlags_NoTaskBarIcon | ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoRendererClear;
16299 ImGuiViewportFlags viewport_flags = window->Viewport->Flags & ~viewport_flags_to_clear;
16300 ImGuiWindowFlags window_flags = window->Flags;
16301 const bool is_modal = (window_flags & ImGuiWindowFlags_Modal) != 0;
16302 const bool is_short_lived_floating_window = (window_flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0;
16303 if (window_flags & ImGuiWindowFlags_Tooltip)
16304 viewport_flags |= ImGuiViewportFlags_TopMost;
16305 if ((
g.IO.ConfigViewportsNoTaskBarIcon || is_short_lived_floating_window) && !is_modal)
16306 viewport_flags |= ImGuiViewportFlags_NoTaskBarIcon;
16307 if (
g.IO.ConfigViewportsNoDecoration || is_short_lived_floating_window)
16308 viewport_flags |= ImGuiViewportFlags_NoDecoration;
16320 if (is_short_lived_floating_window && !is_modal)
16321 viewport_flags |= ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoFocusOnClick;
16324 if (window->WindowClass.ViewportFlagsOverrideSet)
16325 viewport_flags |= window->WindowClass.ViewportFlagsOverrideSet;
16326 if (window->WindowClass.ViewportFlagsOverrideClear)
16327 viewport_flags &= ~window->WindowClass.ViewportFlagsOverrideClear;
16332 if (!(window_flags & ImGuiWindowFlags_NoBackground))
16333 viewport_flags |= ImGuiViewportFlags_NoRendererClear;
16335 window->Viewport->Flags = viewport_flags;
16339 if (window->WindowClass.ParentViewportId != (ImGuiID)-1)
16340 window->Viewport->ParentViewportId = window->WindowClass.ParentViewportId;
16341 else if ((window_flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && parent_window_in_stack && (!parent_window_in_stack->IsFallbackWindow || parent_window_in_stack->WasActive))
16342 window->Viewport->ParentViewportId = parent_window_in_stack->Viewport->ID;
16349void ImGui::UpdatePlatformWindows()
16352 IM_ASSERT(
g.FrameCountEnded ==
g.FrameCount &&
"Forgot to call Render() or EndFrame() before UpdatePlatformWindows()?");
16353 IM_ASSERT(
g.FrameCountPlatformEnded <
g.FrameCount);
16354 g.FrameCountPlatformEnded =
g.FrameCount;
16355 if (!(
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable))
16360 for (
int i = 1; i <
g.Viewports.Size; i++)
16362 ImGuiViewportP* viewport =
g.Viewports[i];
16366 bool destroy_platform_window =
false;
16367 destroy_platform_window |= (viewport->LastFrameActive <
g.FrameCount - 1);
16368 destroy_platform_window |= (viewport->Window && !IsWindowActiveAndVisible(viewport->Window));
16369 if (destroy_platform_window)
16371 DestroyPlatformWindow(viewport);
16376 if (viewport->LastFrameActive <
g.FrameCount || viewport->Size.x <= 0 || viewport->Size.y <= 0)
16380 const bool is_new_platform_window = (viewport->PlatformWindowCreated ==
false);
16381 if (is_new_platform_window)
16383 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Create Platform Window %08X '%s'\n", viewport->ID, viewport->Window ? viewport->Window->Name :
"n/a");
16384 g.PlatformIO.Platform_CreateWindow(viewport);
16385 if (
g.PlatformIO.Renderer_CreateWindow != NULL)
16386 g.PlatformIO.Renderer_CreateWindow(viewport);
16387 g.PlatformWindowsCreatedCount++;
16388 viewport->LastNameHash = 0;
16389 viewport->LastPlatformPos = viewport->LastPlatformSize = ImVec2(FLT_MAX, FLT_MAX);
16390 viewport->LastRendererSize = viewport->Size;
16391 viewport->PlatformWindowCreated =
true;
16395 if ((viewport->LastPlatformPos.x != viewport->Pos.x || viewport->LastPlatformPos.y != viewport->Pos.y) && !viewport->PlatformRequestMove)
16396 g.PlatformIO.Platform_SetWindowPos(viewport, viewport->Pos);
16397 if ((viewport->LastPlatformSize.x != viewport->Size.x || viewport->LastPlatformSize.y != viewport->Size.y) && !viewport->PlatformRequestResize)
16398 g.PlatformIO.Platform_SetWindowSize(viewport, viewport->Size);
16399 if ((viewport->LastRendererSize.x != viewport->Size.x || viewport->LastRendererSize.y != viewport->Size.y) &&
g.PlatformIO.Renderer_SetWindowSize)
16400 g.PlatformIO.Renderer_SetWindowSize(viewport, viewport->Size);
16401 viewport->LastPlatformPos = viewport->Pos;
16402 viewport->LastPlatformSize = viewport->LastRendererSize = viewport->Size;
16405 if (ImGuiWindow* window_for_title = GetWindowForTitleDisplay(viewport->Window))
16407 const char* title_begin = window_for_title->Name;
16408 char* title_end = (
char*)(intptr_t)FindRenderedTextEnd(title_begin);
16409 const ImGuiID title_hash =
ImHashStr(title_begin, title_end - title_begin);
16410 if (viewport->LastNameHash != title_hash)
16412 char title_end_backup_c = *title_end;
16414 g.PlatformIO.Platform_SetWindowTitle(viewport, title_begin);
16415 *title_end = title_end_backup_c;
16416 viewport->LastNameHash = title_hash;
16421 if (viewport->LastAlpha != viewport->Alpha &&
g.PlatformIO.Platform_SetWindowAlpha)
16422 g.PlatformIO.Platform_SetWindowAlpha(viewport, viewport->Alpha);
16423 viewport->LastAlpha = viewport->Alpha;
16426 if (
g.PlatformIO.Platform_UpdateWindow)
16427 g.PlatformIO.Platform_UpdateWindow(viewport);
16429 if (is_new_platform_window)
16432 if (
g.FrameCount < 3)
16433 viewport->Flags |= ImGuiViewportFlags_NoFocusOnAppearing;
16436 g.PlatformIO.Platform_ShowWindow(viewport);
16440 if (viewport->LastFocusedStampCount !=
g.ViewportFocusedStampCount)
16441 viewport->LastFocusedStampCount = ++
g.ViewportFocusedStampCount;
16445 viewport->ClearRequestFlags();
16461void ImGui::RenderPlatformWindowsDefault(
void* platform_render_arg,
void* renderer_render_arg)
16464 ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
16465 for (
int i = 1; i < platform_io.Viewports.Size; i++)
16467 ImGuiViewport* viewport = platform_io.Viewports[i];
16468 if (viewport->Flags & ImGuiViewportFlags_IsMinimized)
16470 if (platform_io.Platform_RenderWindow) platform_io.Platform_RenderWindow(viewport, platform_render_arg);
16471 if (platform_io.Renderer_RenderWindow) platform_io.Renderer_RenderWindow(viewport, renderer_render_arg);
16473 for (
int i = 1; i < platform_io.Viewports.Size; i++)
16475 ImGuiViewport* viewport = platform_io.Viewports[i];
16476 if (viewport->Flags & ImGuiViewportFlags_IsMinimized)
16478 if (platform_io.Platform_SwapBuffers) platform_io.Platform_SwapBuffers(viewport, platform_render_arg);
16479 if (platform_io.Renderer_SwapBuffers) platform_io.Renderer_SwapBuffers(viewport, renderer_render_arg);
16483static int ImGui::FindPlatformMonitorForPos(
const ImVec2& pos)
16486 for (
int monitor_n = 0; monitor_n <
g.PlatformIO.Monitors.Size; monitor_n++)
16488 const ImGuiPlatformMonitor& monitor =
g.PlatformIO.Monitors[monitor_n];
16489 if (ImRect(monitor.MainPos, monitor.MainPos + monitor.MainSize).Contains(pos))
16498static int ImGui::FindPlatformMonitorForRect(
const ImRect& rect)
16502 const int monitor_count =
g.PlatformIO.Monitors.Size;
16503 if (monitor_count <= 1)
16504 return monitor_count - 1;
16508 const float surface_threshold = ImMax(rect.GetWidth() * rect.GetHeight() * 0.5f, 1.0f);
16509 int best_monitor_n = -1;
16510 float best_monitor_surface = 0.001f;
16512 for (
int monitor_n = 0; monitor_n <
g.PlatformIO.Monitors.Size && best_monitor_surface < surface_threshold; monitor_n++)
16514 const ImGuiPlatformMonitor& monitor =
g.PlatformIO.Monitors[monitor_n];
16515 const ImRect monitor_rect = ImRect(monitor.MainPos, monitor.MainPos + monitor.MainSize);
16516 if (monitor_rect.Contains(rect))
16518 ImRect overlapping_rect = rect;
16519 overlapping_rect.ClipWithFull(monitor_rect);
16520 float overlapping_surface = overlapping_rect.GetWidth() * overlapping_rect.GetHeight();
16521 if (overlapping_surface < best_monitor_surface)
16523 best_monitor_surface = overlapping_surface;
16524 best_monitor_n = monitor_n;
16526 return best_monitor_n;
16530static void ImGui::UpdateViewportPlatformMonitor(ImGuiViewportP* viewport)
16532 viewport->PlatformMonitor = (short)FindPlatformMonitorForRect(viewport->GetMainRect());
16536const ImGuiPlatformMonitor* ImGui::GetViewportPlatformMonitor(ImGuiViewport* viewport_p)
16539 ImGuiViewportP* viewport = (ImGuiViewportP*)(
void*)viewport_p;
16540 int monitor_idx = viewport->PlatformMonitor;
16541 if (monitor_idx >= 0 && monitor_idx <
g.PlatformIO.Monitors.Size)
16542 return &
g.PlatformIO.Monitors[monitor_idx];
16543 return &
g.FallbackMonitor;
16546void ImGui::DestroyPlatformWindow(ImGuiViewportP* viewport)
16549 if (viewport->PlatformWindowCreated)
16551 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Destroy Platform Window %08X '%s'\n", viewport->ID, viewport->Window ? viewport->Window->Name :
"n/a");
16552 if (
g.PlatformIO.Renderer_DestroyWindow)
16553 g.PlatformIO.Renderer_DestroyWindow(viewport);
16554 if (
g.PlatformIO.Platform_DestroyWindow)
16555 g.PlatformIO.Platform_DestroyWindow(viewport);
16556 IM_ASSERT(viewport->RendererUserData == NULL && viewport->PlatformUserData == NULL);
16560 if (viewport->ID != IMGUI_VIEWPORT_DEFAULT_ID)
16561 viewport->PlatformWindowCreated =
false;
16565 IM_ASSERT(viewport->RendererUserData == NULL && viewport->PlatformUserData == NULL && viewport->PlatformHandle == NULL);
16567 viewport->RendererUserData = viewport->PlatformUserData = viewport->PlatformHandle = NULL;
16568 viewport->ClearRequestFlags();
16571void ImGui::DestroyPlatformWindows()
16580 for (ImGuiViewportP* viewport :
g.Viewports)
16581 DestroyPlatformWindow(viewport);
16726 static ImGuiDockNode* DockContextAddNode(ImGuiContext* ctx, ImGuiID
id);
16727 static void DockContextRemoveNode(ImGuiContext* ctx, ImGuiDockNode* node,
bool merge_sibling_into_parent_node);
16728 static void DockContextQueueNotifyRemovedNode(ImGuiContext* ctx, ImGuiDockNode* node);
16729 static void DockContextProcessDock(ImGuiContext* ctx,
ImGuiDockRequest* req);
16730 static void DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx);
16731 static ImGuiDockNode* DockContextBindNodeToWindow(ImGuiContext* ctx, ImGuiWindow* window);
16732 static void DockContextBuildNodesFromSettings(ImGuiContext* ctx,
ImGuiDockNodeSettings* node_settings_array,
int node_settings_count);
16733 static void DockContextBuildAddWindowsToNodes(ImGuiContext* ctx, ImGuiID root_id);
16736 static void DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window,
bool add_to_tab_bar);
16737 static void DockNodeMoveWindows(ImGuiDockNode* dst_node, ImGuiDockNode* src_node);
16738 static void DockNodeMoveChildNodes(ImGuiDockNode* dst_node, ImGuiDockNode* src_node);
16739 static ImGuiWindow* DockNodeFindWindowByID(ImGuiDockNode* node, ImGuiID
id);
16740 static void DockNodeApplyPosSizeToWindows(ImGuiDockNode* node);
16741 static void DockNodeRemoveWindow(ImGuiDockNode* node, ImGuiWindow* window, ImGuiID save_dock_id);
16742 static void DockNodeHideHostWindow(ImGuiDockNode* node);
16743 static void DockNodeUpdate(ImGuiDockNode* node);
16744 static void DockNodeUpdateForRootNode(ImGuiDockNode* node);
16745 static void DockNodeUpdateFlagsAndCollapse(ImGuiDockNode* node);
16746 static void DockNodeUpdateHasCentralNodeChild(ImGuiDockNode* node);
16747 static void DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_window);
16748 static void DockNodeAddTabBar(ImGuiDockNode* node);
16749 static void DockNodeRemoveTabBar(ImGuiDockNode* node);
16750 static void DockNodeWindowMenuUpdate(ImGuiDockNode* node, ImGuiTabBar* tab_bar);
16751 static void DockNodeUpdateVisibleFlag(ImGuiDockNode* node);
16752 static void DockNodeStartMouseMovingWindow(ImGuiDockNode* node, ImGuiWindow* window);
16753 static bool DockNodeIsDropAllowed(ImGuiWindow* host_window, ImGuiWindow* payload_window);
16754 static void DockNodePreviewDockSetup(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window, ImGuiDockNode* payload_node,
ImGuiDockPreviewData* preview_data,
bool is_explicit_target,
bool is_outer_docking);
16755 static void DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window,
const ImGuiDockPreviewData* preview_data);
16756 static void DockNodeCalcTabBarLayout(
const ImGuiDockNode* node, ImRect* out_title_rect, ImRect* out_tab_bar_rect, ImVec2* out_window_menu_button_pos, ImVec2* out_close_button_pos);
16757 static void DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& pos_new, ImVec2& size_new, ImGuiDir dir, ImVec2 size_new_desired);
16758 static bool DockNodeCalcDropRectsAndTestMousePos(
const ImRect& parent, ImGuiDir dir, ImRect& out_draw,
bool outer_docking, ImVec2* test_mouse_pos);
16759 static const char* DockNodeGetHostWindowTitle(ImGuiDockNode* node,
char* buf,
int buf_size) {
ImFormatString(buf, buf_size,
"##DockNode_%02X", node->ID);
return buf; }
16760 static int DockNodeGetTabOrder(ImGuiWindow* window);
16763 static void DockNodeTreeSplit(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiAxis split_axis,
int split_first_child,
float split_ratio, ImGuiDockNode* new_node);
16764 static void DockNodeTreeMerge(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiDockNode* merge_lead_child);
16765 static void DockNodeTreeUpdatePosSize(ImGuiDockNode* node, ImVec2 pos, ImVec2 size, ImGuiDockNode* only_write_to_single_node = NULL);
16766 static void DockNodeTreeUpdateSplitter(ImGuiDockNode* node);
16767 static ImGuiDockNode* DockNodeTreeFindVisibleNodeByPos(ImGuiDockNode* node, ImVec2 pos);
16768 static ImGuiDockNode* DockNodeTreeFindFallbackLeafNode(ImGuiDockNode* node);
16771 static void DockSettingsRenameNodeReferences(ImGuiID old_node_id, ImGuiID new_node_id);
16772 static void DockSettingsRemoveNodeReferences(ImGuiID* node_ids,
int node_ids_count);
16774 static void DockSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*);
16775 static void DockSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*);
16776 static void* DockSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*,
const char* name);
16777 static void DockSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
void* entry,
const char* line);
16778 static void DockSettingsHandler_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf);
16809void ImGui::DockContextInitialize(ImGuiContext* ctx)
16811 ImGuiContext&
g = *ctx;
16814 ImGuiSettingsHandler ini_handler;
16815 ini_handler.TypeName =
"Docking";
16816 ini_handler.TypeHash =
ImHashStr(
"Docking");
16817 ini_handler.ClearAllFn = DockSettingsHandler_ClearAll;
16818 ini_handler.ReadInitFn = DockSettingsHandler_ClearAll;
16819 ini_handler.ReadOpenFn = DockSettingsHandler_ReadOpen;
16820 ini_handler.ReadLineFn = DockSettingsHandler_ReadLine;
16821 ini_handler.ApplyAllFn = DockSettingsHandler_ApplyAll;
16822 ini_handler.WriteAllFn = DockSettingsHandler_WriteAll;
16823 g.SettingsHandlers.push_back(ini_handler);
16825 g.DockNodeWindowMenuHandler = &DockNodeWindowMenuHandler_Default;
16828void ImGui::DockContextShutdown(ImGuiContext* ctx)
16830 ImGuiDockContext* dc = &ctx->DockContext;
16831 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
16832 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
16836void ImGui::DockContextClearNodes(ImGuiContext* ctx, ImGuiID root_id,
bool clear_settings_refs)
16839 IM_ASSERT(ctx ==
GImGui);
16840 DockBuilderRemoveNodeDockedWindows(root_id, clear_settings_refs);
16841 DockBuilderRemoveNodeChildNodes(root_id);
16846void ImGui::DockContextRebuildNodes(ImGuiContext* ctx)
16848 ImGuiContext&
g = *ctx;
16849 ImGuiDockContext* dc = &ctx->DockContext;
16850 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextRebuildNodes\n");
16851 SaveIniSettingsToMemory();
16852 ImGuiID root_id = 0;
16853 DockContextClearNodes(ctx, root_id,
false);
16854 DockContextBuildNodesFromSettings(ctx, dc->NodesSettings.Data, dc->NodesSettings.Size);
16855 DockContextBuildAddWindowsToNodes(ctx, root_id);
16859void ImGui::DockContextNewFrameUpdateUndocking(ImGuiContext* ctx)
16861 ImGuiContext&
g = *ctx;
16862 ImGuiDockContext* dc = &ctx->DockContext;
16863 if (!(
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
16865 if (dc->Nodes.Data.Size > 0 || dc->Requests.Size > 0)
16866 DockContextClearNodes(ctx, 0,
true);
16871 if (
g.IO.ConfigDockingNoSplit)
16872 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
16873 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
16874 if (node->IsRootNode() && node->IsSplitNode())
16876 DockBuilderRemoveNodeChildNodes(node->ID);
16882 if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_C)))
16883 dc->WantFullRebuild =
true;
16885 if (dc->WantFullRebuild)
16887 DockContextRebuildNodes(ctx);
16888 dc->WantFullRebuild =
false;
16895 DockContextProcessUndockWindow(ctx, req.UndockTargetWindow);
16897 DockContextProcessUndockNode(ctx, req.UndockTargetNode);
16902void ImGui::DockContextNewFrameUpdateDocking(ImGuiContext* ctx)
16904 ImGuiContext&
g = *ctx;
16905 ImGuiDockContext* dc = &ctx->DockContext;
16906 if (!(
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
16912 g.DebugHoveredDockNode = NULL;
16913 if (ImGuiWindow* hovered_window =
g.HoveredWindowUnderMovingWindow)
16915 if (hovered_window->DockNodeAsHost)
16916 g.DebugHoveredDockNode = DockNodeTreeFindVisibleNodeByPos(hovered_window->DockNodeAsHost,
g.IO.MousePos);
16917 else if (hovered_window->RootWindow->DockNode)
16918 g.DebugHoveredDockNode = hovered_window->RootWindow->DockNode;
16924 DockContextProcessDock(ctx, &req);
16925 dc->Requests.resize(0);
16929 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
16930 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
16931 if (node->IsFloatingNode())
16932 DockNodeUpdate(node);
16935void ImGui::DockContextEndFrame(ImGuiContext* ctx)
16938 ImGuiContext&
g = *ctx;
16939 ImGuiDockContext* dc = &
g.DockContext;
16940 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
16941 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
16942 if (node->LastFrameActive ==
g.FrameCount && node->IsVisible && node->HostWindow && node->IsLeafNode() && !node->IsBgDrawnThisFrame)
16944 ImRect bg_rect(node->Pos + ImVec2(0.0f, GetFrameHeight()), node->Pos + node->Size);
16945 ImDrawFlags bg_rounding_flags = CalcRoundingFlagsForRectInRect(bg_rect, node->HostWindow->Rect(),
g.Style.DockingSeparatorSize);
16946 node->HostWindow->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
16947 node->HostWindow->DrawList->AddRectFilled(bg_rect.Min, bg_rect.Max, node->LastBgColor, node->HostWindow->WindowRounding, bg_rounding_flags);
16951ImGuiDockNode* ImGui::DockContextFindNodeByID(ImGuiContext* ctx, ImGuiID
id)
16953 return (ImGuiDockNode*)ctx->DockContext.Nodes.GetVoidPtr(
id);
16956ImGuiID ImGui::DockContextGenNodeID(ImGuiContext* ctx)
16961 ImGuiID
id = 0x0001;
16962 while (DockContextFindNodeByID(ctx,
id) != NULL)
16967static ImGuiDockNode* ImGui::DockContextAddNode(ImGuiContext* ctx, ImGuiID
id)
16970 ImGuiContext&
g = *ctx;
16972 id = DockContextGenNodeID(ctx);
16974 IM_ASSERT(DockContextFindNodeByID(ctx,
id) == NULL);
16977 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextAddNode 0x%08X\n",
id);
16978 ImGuiDockNode* node = IM_NEW(ImGuiDockNode)(
id);
16979 ctx->DockContext.Nodes.SetVoidPtr(node->ID, node);
16983static void ImGui::DockContextRemoveNode(ImGuiContext* ctx, ImGuiDockNode* node,
bool merge_sibling_into_parent_node)
16985 ImGuiContext&
g = *ctx;
16986 ImGuiDockContext* dc = &ctx->DockContext;
16988 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextRemoveNode 0x%08X\n", node->ID);
16989 IM_ASSERT(DockContextFindNodeByID(ctx, node->ID) == node);
16990 IM_ASSERT(node->ChildNodes[0] == NULL && node->ChildNodes[1] == NULL);
16991 IM_ASSERT(node->Windows.Size == 0);
16993 if (node->HostWindow)
16994 node->HostWindow->DockNodeAsHost = NULL;
16996 ImGuiDockNode* parent_node = node->ParentNode;
16997 const bool merge = (merge_sibling_into_parent_node && parent_node != NULL);
17000 IM_ASSERT(parent_node->ChildNodes[0] == node || parent_node->ChildNodes[1] == node);
17001 ImGuiDockNode* sibling_node = (parent_node->ChildNodes[0] == node ? parent_node->ChildNodes[1] : parent_node->ChildNodes[0]);
17002 DockNodeTreeMerge(&
g, parent_node, sibling_node);
17006 for (
int n = 0; parent_node && n < IM_ARRAYSIZE(parent_node->ChildNodes); n++)
17007 if (parent_node->ChildNodes[n] == node)
17008 node->ParentNode->ChildNodes[n] = NULL;
17009 dc->Nodes.SetVoidPtr(node->ID, NULL);
17014static int IMGUI_CDECL DockNodeComparerDepthMostFirst(
const void* lhs,
const void* rhs)
17016 const ImGuiDockNode* a = *(
const ImGuiDockNode*
const*)lhs;
17017 const ImGuiDockNode* b = *(
const ImGuiDockNode*
const*)rhs;
17018 return ImGui::DockNodeGetDepth(b) - ImGui::DockNodeGetDepth(a);
17030static void ImGui::DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx)
17032 ImGuiContext&
g = *ctx;
17033 ImGuiDockContext* dc = &ctx->DockContext;
17034 IM_ASSERT(
g.Windows.Size == 0);
17036 ImPool<ImGuiDockContextPruneNodeData> pool;
17037 pool.Reserve(dc->NodesSettings.Size);
17040 for (
int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
17044 pool.GetOrAddByKey(settings->
ID)->RootId = parent_data ? parent_data->
RootId : settings->
ID;
17046 pool.GetOrAddByKey(settings->
ParentNodeId)->CountChildNodes++;
17051 for (
int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
17055 if (ImGuiWindowSettings* window_settings = FindWindowSettingsByID(settings->
ParentWindowId))
17056 if (window_settings->DockId)
17058 data->CountChildNodes++;
17063 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
17064 if (ImGuiID dock_id = settings->DockId)
17067 data->CountWindows++;
17069 data_root->CountChildWindows++;
17073 for (
int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
17087 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextPruneUnusedSettingsNodes: Prune 0x%08X\n", settings->
ID);
17088 DockSettingsRemoveNodeReferences(&settings->
ID, 1);
17094static void ImGui::DockContextBuildNodesFromSettings(ImGuiContext* ctx,
ImGuiDockNodeSettings* node_settings_array,
int node_settings_count)
17097 for (
int node_n = 0; node_n < node_settings_count; node_n++)
17100 if (settings->
ID == 0)
17102 ImGuiDockNode* node = DockContextAddNode(ctx, settings->
ID);
17104 node->Pos = ImVec2(settings->
Pos.x, settings->
Pos.y);
17105 node->Size = ImVec2(settings->
Size.x, settings->
Size.y);
17106 node->SizeRef = ImVec2(settings->
SizeRef.x, settings->
SizeRef.y);
17107 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_DockNode;
17108 if (node->ParentNode && node->ParentNode->ChildNodes[0] == NULL)
17109 node->ParentNode->ChildNodes[0] = node;
17110 else if (node->ParentNode && node->ParentNode->ChildNodes[1] == NULL)
17111 node->ParentNode->ChildNodes[1] = node;
17113 node->SplitAxis = (ImGuiAxis)settings->
SplitAxis;
17114 node->SetLocalFlags(settings->
Flags & ImGuiDockNodeFlags_SavedFlagsMask_);
17118 char host_window_title[20];
17119 ImGuiDockNode* root_node = DockNodeGetRootNode(node);
17120 node->HostWindow = FindWindowByName(DockNodeGetHostWindowTitle(root_node, host_window_title, IM_ARRAYSIZE(host_window_title)));
17124void ImGui::DockContextBuildAddWindowsToNodes(ImGuiContext* ctx, ImGuiID root_id)
17127 ImGuiContext&
g = *ctx;
17128 for (ImGuiWindow* window :
g.Windows)
17130 if (window->DockId == 0 || window->LastFrameActive <
g.FrameCount - 1)
17132 if (window->DockNode != NULL)
17135 ImGuiDockNode* node = DockContextFindNodeByID(ctx, window->DockId);
17136 IM_ASSERT(node != NULL);
17137 if (root_id == 0 || DockNodeGetRootNode(node)->ID == root_id)
17138 DockNodeAddWindow(node, window,
true);
17155void ImGui::DockContextQueueDock(ImGuiContext* ctx, ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload, ImGuiDir split_dir,
float split_ratio,
bool split_outer)
17157 IM_ASSERT(target != payload);
17166 ctx->DockContext.Requests.push_back(req);
17169void ImGui::DockContextQueueUndockWindow(ImGuiContext* ctx, ImGuiWindow* window)
17174 ctx->DockContext.Requests.push_back(req);
17177void ImGui::DockContextQueueUndockNode(ImGuiContext* ctx, ImGuiDockNode* node)
17182 ctx->DockContext.Requests.push_back(req);
17185void ImGui::DockContextQueueNotifyRemovedNode(ImGuiContext* ctx, ImGuiDockNode* node)
17187 ImGuiDockContext* dc = &ctx->DockContext;
17189 if (req.DockTargetNode == node)
17193void ImGui::DockContextProcessDock(ImGuiContext* ctx,
ImGuiDockRequest* req)
17198 ImGuiContext&
g = *ctx;
17204 if (payload_window)
17205 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextProcessDock node 0x%08X target '%s' dock window '%s', split_dir %d\n", node ? node->ID : 0, target_window ? target_window->Name :
"NULL", payload_window->Name, req->DockSplitDir);
17207 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextProcessDock node 0x%08X, split_dir %d\n", node ? node->ID : 0, req->DockSplitDir);
17210 ImGuiID next_selected_id = 0;
17211 ImGuiDockNode* payload_node = NULL;
17212 if (payload_window)
17214 payload_node = payload_window->DockNodeAsHost;
17215 payload_window->DockNodeAsHost = NULL;
17216 if (payload_node && payload_node->IsLeafNode())
17217 next_selected_id = payload_node->TabBar->NextSelectedTabId ? payload_node->TabBar->NextSelectedTabId : payload_node->TabBar->SelectedTabId;
17218 if (payload_node == NULL)
17219 next_selected_id = payload_window->TabId;
17225 IM_ASSERT(node->LastFrameAlive <=
g.FrameCount);
17226 if (node && target_window && node == target_window->DockNodeAsHost)
17227 IM_ASSERT(node->Windows.Size > 0 || node->IsSplitNode() || node->IsCentralNode());
17232 node = DockContextAddNode(ctx, 0);
17233 node->Pos = target_window->Pos;
17234 node->Size = target_window->Size;
17235 if (target_window->DockNodeAsHost == NULL)
17237 DockNodeAddWindow(node, target_window,
true);
17238 node->TabBar->Tabs[0].Flags &= ~ImGuiTabItemFlags_Unsorted;
17239 target_window->DockIsActive =
true;
17244 if (split_dir != ImGuiDir_None)
17247 const ImGuiAxis split_axis = (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
17248 const int split_inheritor_child_idx = (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up) ? 1 : 0;
17250 DockNodeTreeSplit(ctx, node, split_axis, split_inheritor_child_idx, split_ratio, payload_node);
17251 ImGuiDockNode* new_node = node->ChildNodes[split_inheritor_child_idx ^ 1];
17252 new_node->HostWindow = node->HostWindow;
17255 node->SetLocalFlags(node->LocalFlags & ~ImGuiDockNodeFlags_HiddenTabBar);
17257 if (node != payload_node)
17260 if (node->Windows.Size > 0 && node->TabBar == NULL)
17262 DockNodeAddTabBar(node);
17263 for (
int n = 0; n < node->Windows.Size; n++)
17264 TabBarAddTab(node->TabBar, ImGuiTabItemFlags_None, node->Windows[n]);
17267 if (payload_node != NULL)
17270 if (payload_node->IsSplitNode())
17272 if (node->Windows.Size > 0)
17277 IM_ASSERT(payload_node->OnlyNodeWithWindows != NULL);
17278 ImGuiDockNode* visible_node = payload_node->OnlyNodeWithWindows;
17279 if (visible_node->TabBar)
17280 IM_ASSERT(visible_node->TabBar->Tabs.Size > 0);
17281 DockNodeMoveWindows(node, visible_node);
17282 DockNodeMoveWindows(visible_node, node);
17283 DockSettingsRenameNodeReferences(node->ID, visible_node->ID);
17285 if (node->IsCentralNode())
17289 ImGuiDockNode* last_focused_node = DockContextFindNodeByID(ctx, payload_node->LastFocusedNodeId);
17290 IM_ASSERT(last_focused_node != NULL);
17291 ImGuiDockNode* last_focused_root_node = DockNodeGetRootNode(last_focused_node);
17292 IM_ASSERT(last_focused_root_node == DockNodeGetRootNode(payload_node));
17293 last_focused_node->SetLocalFlags(last_focused_node->LocalFlags | ImGuiDockNodeFlags_CentralNode);
17294 node->SetLocalFlags(node->LocalFlags & ~ImGuiDockNodeFlags_CentralNode);
17295 last_focused_root_node->CentralNode = last_focused_node;
17298 IM_ASSERT(node->Windows.Size == 0);
17299 DockNodeMoveChildNodes(node, payload_node);
17303 const ImGuiID payload_dock_id = payload_node->ID;
17304 DockNodeMoveWindows(node, payload_node);
17305 DockSettingsRenameNodeReferences(payload_dock_id, node->ID);
17307 DockContextRemoveNode(ctx, payload_node,
true);
17309 else if (payload_window)
17312 const ImGuiID payload_dock_id = payload_window->DockId;
17313 node->VisibleWindow = payload_window;
17314 DockNodeAddWindow(node, payload_window,
true);
17315 if (payload_dock_id != 0)
17316 DockSettingsRenameNodeReferences(payload_dock_id, node->ID);
17322 node->WantHiddenTabBarUpdate =
true;
17326 if (ImGuiTabBar* tab_bar = node->TabBar)
17327 tab_bar->NextSelectedTabId = next_selected_id;
17328 MarkIniSettingsDirty();
17339static ImVec2 FixLargeWindowsWhenUndocking(
const ImVec2& size, ImGuiViewport* ref_viewport)
17341 if (ref_viewport == NULL)
17345 ImVec2 max_size = ImTrunc(ref_viewport->WorkSize * 0.90f);
17346 if (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
17348 const ImGuiPlatformMonitor* monitor = ImGui::GetViewportPlatformMonitor(ref_viewport);
17349 max_size = ImTrunc(monitor->WorkSize * 0.90f);
17351 return ImMin(size, max_size);
17354void ImGui::DockContextProcessUndockWindow(ImGuiContext* ctx, ImGuiWindow* window,
bool clear_persistent_docking_ref)
17356 ImGuiContext&
g = *ctx;
17357 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextProcessUndockWindow window '%s', clear_persistent_docking_ref = %d\n", window->Name, clear_persistent_docking_ref);
17358 if (window->DockNode)
17359 DockNodeRemoveWindow(window->DockNode, window, clear_persistent_docking_ref ? 0 : window->DockId);
17361 window->DockId = 0;
17362 window->Collapsed =
false;
17363 window->DockIsActive =
false;
17364 window->DockNodeIsVisible = window->DockTabIsVisible =
false;
17365 window->Size = window->SizeFull = FixLargeWindowsWhenUndocking(window->SizeFull, window->Viewport);
17367 MarkIniSettingsDirty();
17370void ImGui::DockContextProcessUndockNode(ImGuiContext* ctx, ImGuiDockNode* node)
17372 ImGuiContext&
g = *ctx;
17373 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextProcessUndockNode node %08X\n", node->ID);
17374 IM_ASSERT(node->IsLeafNode());
17375 IM_ASSERT(node->Windows.Size >= 1);
17377 if (node->IsRootNode() || node->IsCentralNode())
17380 ImGuiDockNode* new_node = DockContextAddNode(ctx, 0);
17381 new_node->Pos = node->Pos;
17382 new_node->Size = node->Size;
17383 new_node->SizeRef = node->SizeRef;
17384 DockNodeMoveWindows(new_node, node);
17385 DockSettingsRenameNodeReferences(node->ID, new_node->ID);
17391 IM_ASSERT(node->ParentNode->ChildNodes[0] == node || node->ParentNode->ChildNodes[1] == node);
17392 int index_in_parent = (node->ParentNode->ChildNodes[0] == node) ? 0 : 1;
17393 node->ParentNode->ChildNodes[index_in_parent] = NULL;
17394 DockNodeTreeMerge(ctx, node->ParentNode, node->ParentNode->ChildNodes[index_in_parent ^ 1]);
17395 node->ParentNode->AuthorityForViewport = ImGuiDataAuthority_Window;
17396 node->ParentNode = NULL;
17398 for (ImGuiWindow* window : node->Windows)
17400 window->Flags &= ~ImGuiWindowFlags_ChildWindow;
17401 if (window->ParentWindow)
17402 window->ParentWindow->DC.ChildWindows.find_erase(window);
17403 UpdateWindowParentAndRootLinks(window, window->Flags, NULL);
17405 node->AuthorityForPos = node->AuthorityForSize = ImGuiDataAuthority_DockNode;
17406 node->Size = FixLargeWindowsWhenUndocking(node->Size, node->Windows[0]->Viewport);
17407 node->WantMouseMove =
true;
17408 MarkIniSettingsDirty();
17412bool ImGui::DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload_window, ImGuiDockNode* payload_node, ImGuiDir split_dir,
bool split_outer, ImVec2* out_pos)
17414 if (target != NULL && target_node == NULL)
17415 target_node = target->DockNode;
17419 if (target_node && target_node->ParentNode == NULL && target_node->IsCentralNode() && split_dir != ImGuiDir_None)
17420 split_outer =
true;
17422 DockNodePreviewDockSetup(target, target_node, payload_window, payload_node, &split_data,
false, split_outer);
17425 *out_pos = split_data.
DropRectsDraw[split_dir+1].GetCenter();
17462ImGuiDockNode::ImGuiDockNode(ImGuiID
id)
17465 SharedFlags = LocalFlags = LocalFlagsInWindows = MergedFlags = ImGuiDockNodeFlags_None;
17466 ParentNode = ChildNodes[0] = ChildNodes[1] = NULL;
17468 SplitAxis = ImGuiAxis_None;
17470 State = ImGuiDockNodeState_Unknown;
17471 LastBgColor = IM_COL32_WHITE;
17472 HostWindow = VisibleWindow = NULL;
17473 CentralNode = OnlyNodeWithWindows = NULL;
17474 CountNodeWithWindows = 0;
17475 LastFrameAlive = LastFrameActive = LastFrameFocused = -1;
17476 LastFocusedNodeId = 0;
17478 WantCloseTabId = 0;
17480 AuthorityForPos = AuthorityForSize = ImGuiDataAuthority_DockNode;
17481 AuthorityForViewport = ImGuiDataAuthority_Auto;
17483 IsFocused = HasCloseButton = HasWindowMenuButton = HasCentralNodeChild =
false;
17484 IsBgDrawnThisFrame =
false;
17485 WantCloseAll = WantLockSizeOnce = WantMouseMove = WantHiddenTabBarUpdate = WantHiddenTabBarToggle =
false;
17488ImGuiDockNode::~ImGuiDockNode()
17492 ChildNodes[0] = ChildNodes[1] = NULL;
17495int ImGui::DockNodeGetTabOrder(ImGuiWindow* window)
17497 ImGuiTabBar* tab_bar = window->DockNode->TabBar;
17498 if (tab_bar == NULL)
17500 ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, window->TabId);
17501 return tab ? TabBarGetTabOrder(tab_bar, tab) : -1;
17504static void DockNodeHideWindowDuringHostWindowCreation(ImGuiWindow* window)
17506 window->Hidden =
true;
17507 window->HiddenFramesCanSkipItems = window->Active ? 1 : 2;
17510static void ImGui::DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window,
bool add_to_tab_bar)
17512 ImGuiContext&
g = *
GImGui; (void)
g;
17513 if (window->DockNode)
17516 IM_ASSERT(window->DockNode->ID != node->ID);
17517 DockNodeRemoveWindow(window->DockNode, window, 0);
17519 IM_ASSERT(window->DockNode == NULL || window->DockNodeAsHost == NULL);
17520 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockNodeAddWindow node 0x%08X window '%s'\n", node->ID, window->Name);
17525 if (node->HostWindow == NULL && node->Windows.Size == 1 && node->Windows[0]->WasActive ==
false)
17526 DockNodeHideWindowDuringHostWindowCreation(node->Windows[0]);
17528 node->Windows.push_back(window);
17529 node->WantHiddenTabBarUpdate =
true;
17530 window->DockNode = node;
17531 window->DockId = node->ID;
17532 window->DockIsActive = (node->Windows.Size > 1);
17533 window->DockTabWantClose =
false;
17537 if (node->HostWindow == NULL && node->IsFloatingNode())
17539 if (node->AuthorityForPos == ImGuiDataAuthority_Auto)
17540 node->AuthorityForPos = ImGuiDataAuthority_Window;
17541 if (node->AuthorityForSize == ImGuiDataAuthority_Auto)
17542 node->AuthorityForSize = ImGuiDataAuthority_Window;
17543 if (node->AuthorityForViewport == ImGuiDataAuthority_Auto)
17544 node->AuthorityForViewport = ImGuiDataAuthority_Window;
17548 if (add_to_tab_bar)
17550 if (node->TabBar == NULL)
17552 DockNodeAddTabBar(node);
17553 node->TabBar->SelectedTabId = node->TabBar->NextSelectedTabId = node->SelectedTabId;
17556 for (
int n = 0; n < node->Windows.Size - 1; n++)
17557 TabBarAddTab(node->TabBar, ImGuiTabItemFlags_None, node->Windows[n]);
17559 TabBarAddTab(node->TabBar, ImGuiTabItemFlags_Unsorted, window);
17562 DockNodeUpdateVisibleFlag(node);
17565 if (node->HostWindow)
17566 UpdateWindowParentAndRootLinks(window, window->Flags | ImGuiWindowFlags_ChildWindow, node->HostWindow);
17569static void ImGui::DockNodeRemoveWindow(ImGuiDockNode* node, ImGuiWindow* window, ImGuiID save_dock_id)
17572 IM_ASSERT(window->DockNode == node);
17575 IM_ASSERT(save_dock_id == 0 || save_dock_id == node->ID);
17576 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockNodeRemoveWindow node 0x%08X window '%s'\n", node->ID, window->Name);
17578 window->DockNode = NULL;
17579 window->DockIsActive = window->DockTabWantClose =
false;
17580 window->DockId = save_dock_id;
17581 window->Flags &= ~ImGuiWindowFlags_ChildWindow;
17582 if (window->ParentWindow)
17583 window->ParentWindow->DC.ChildWindows.find_erase(window);
17584 UpdateWindowParentAndRootLinks(window, window->Flags, NULL);
17586 if (node->HostWindow && node->HostWindow->ViewportOwned)
17590 window->Viewport = NULL;
17591 window->ViewportId = 0;
17592 window->ViewportOwned =
false;
17593 window->Hidden =
true;
17597 bool erased =
false;
17598 for (
int n = 0; n < node->Windows.Size; n++)
17599 if (node->Windows[n] == window)
17601 node->Windows.erase(node->Windows.Data + n);
17607 if (node->VisibleWindow == window)
17608 node->VisibleWindow = NULL;
17611 node->WantHiddenTabBarUpdate =
true;
17614 TabBarRemoveTab(node->TabBar, window->TabId);
17615 const int tab_count_threshold_for_tab_bar = node->IsCentralNode() ? 1 : 2;
17616 if (node->Windows.Size < tab_count_threshold_for_tab_bar)
17617 DockNodeRemoveTabBar(node);
17620 if (node->Windows.Size == 0 && !node->IsCentralNode() && !node->IsDockSpace() && window->DockId != node->ID)
17623 DockContextRemoveNode(&
g, node,
true);
17627 if (node->Windows.Size == 1 && !node->IsCentralNode() && node->HostWindow)
17629 ImGuiWindow* remaining_window = node->Windows[0];
17631 remaining_window->Collapsed = node->HostWindow->Collapsed;
17635 DockNodeUpdateVisibleFlag(node);
17638static void ImGui::DockNodeMoveChildNodes(ImGuiDockNode* dst_node, ImGuiDockNode* src_node)
17640 IM_ASSERT(dst_node->Windows.Size == 0);
17641 dst_node->ChildNodes[0] = src_node->ChildNodes[0];
17642 dst_node->ChildNodes[1] = src_node->ChildNodes[1];
17643 if (dst_node->ChildNodes[0])
17644 dst_node->ChildNodes[0]->ParentNode = dst_node;
17645 if (dst_node->ChildNodes[1])
17646 dst_node->ChildNodes[1]->ParentNode = dst_node;
17647 dst_node->SplitAxis = src_node->SplitAxis;
17648 dst_node->SizeRef = src_node->SizeRef;
17649 src_node->ChildNodes[0] = src_node->ChildNodes[1] = NULL;
17652static void ImGui::DockNodeMoveWindows(ImGuiDockNode* dst_node, ImGuiDockNode* src_node)
17655 IM_ASSERT(src_node && dst_node && dst_node != src_node);
17656 ImGuiTabBar* src_tab_bar = src_node->TabBar;
17657 if (src_tab_bar != NULL)
17658 IM_ASSERT(src_node->Windows.Size <= src_node->TabBar->Tabs.Size);
17661 bool move_tab_bar = (src_tab_bar != NULL) && (dst_node->TabBar == NULL);
17664 dst_node->TabBar = src_node->TabBar;
17665 src_node->TabBar = NULL;
17669 for (ImGuiWindow* window : src_node->Windows)
17671 window->DockNode = NULL;
17672 window->DockIsActive =
false;
17673 DockNodeAddWindow(dst_node, window, !move_tab_bar);
17675 src_node->Windows.clear();
17677 if (!move_tab_bar && src_node->TabBar)
17679 if (dst_node->TabBar)
17680 dst_node->TabBar->SelectedTabId = src_node->TabBar->SelectedTabId;
17681 DockNodeRemoveTabBar(src_node);
17685static void ImGui::DockNodeApplyPosSizeToWindows(ImGuiDockNode* node)
17687 for (ImGuiWindow* window : node->Windows)
17689 SetWindowPos(window, node->Pos, ImGuiCond_Always);
17690 SetWindowSize(window, node->Size, ImGuiCond_Always);
17694static void ImGui::DockNodeHideHostWindow(ImGuiDockNode* node)
17696 if (node->HostWindow)
17698 if (node->HostWindow->DockNodeAsHost == node)
17699 node->HostWindow->DockNodeAsHost = NULL;
17700 node->HostWindow = NULL;
17703 if (node->Windows.Size == 1)
17705 node->VisibleWindow = node->Windows[0];
17706 node->Windows[0]->DockIsActive =
false;
17710 DockNodeRemoveTabBar(node);
17726 if (node->Windows.Size > 0)
17732 if (node->IsCentralNode())
17735 IM_ASSERT(node->IsLeafNode() &&
"If you get this assert: please submit .ini file + repro of actions leading to this.");
17740 if (node->ChildNodes[0])
17741 DockNodeFindInfo(node->ChildNodes[0], info);
17742 if (node->ChildNodes[1])
17743 DockNodeFindInfo(node->ChildNodes[1], info);
17746static ImGuiWindow* ImGui::DockNodeFindWindowByID(ImGuiDockNode* node, ImGuiID
id)
17748 IM_ASSERT(
id != 0);
17749 for (ImGuiWindow* window : node->Windows)
17750 if (window->
ID ==
id)
17757static void ImGui::DockNodeUpdateFlagsAndCollapse(ImGuiDockNode* node)
17760 IM_ASSERT(node->ParentNode == NULL || node->ParentNode->ChildNodes[0] == node || node->ParentNode->ChildNodes[1] == node);
17763 if (node->ParentNode)
17764 node->SharedFlags = node->ParentNode->SharedFlags & ImGuiDockNodeFlags_SharedFlagsInheritMask_;
17770 node->HasCentralNodeChild =
false;
17771 if (node->ChildNodes[0])
17772 DockNodeUpdateFlagsAndCollapse(node->ChildNodes[0]);
17773 if (node->ChildNodes[1])
17774 DockNodeUpdateFlagsAndCollapse(node->ChildNodes[1]);
17778 node->LocalFlagsInWindows = ImGuiDockNodeFlags_None;
17779 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
17781 ImGuiWindow* window = node->Windows[window_n];
17782 IM_ASSERT(window->DockNode == node);
17784 bool node_was_active = (node->LastFrameActive + 1 ==
g.FrameCount);
17786 remove |= node_was_active && (window->LastFrameActive + 1 <
g.FrameCount);
17787 remove |= node_was_active && (node->WantCloseAll || node->WantCloseTabId == window->TabId) && window->HasCloseButton && !(window->Flags & ImGuiWindowFlags_UnsavedDocument);
17788 remove |= (window->DockTabWantClose);
17791 window->DockTabWantClose =
false;
17792 if (node->Windows.Size == 1 && !node->IsCentralNode())
17794 DockNodeHideHostWindow(node);
17795 node->State = ImGuiDockNodeState_HostWindowHiddenBecauseSingleWindow;
17796 DockNodeRemoveWindow(node, window, node->ID);
17799 DockNodeRemoveWindow(node, window, node->ID);
17806 node->LocalFlagsInWindows |= window->WindowClass.DockNodeFlagsOverrideSet;
17808 node->UpdateMergedFlags();
17811 ImGuiDockNodeFlags node_flags = node->MergedFlags;
17812 if (node->WantHiddenTabBarUpdate && node->Windows.Size == 1 && (node_flags & ImGuiDockNodeFlags_AutoHideTabBar) && !node->IsHiddenTabBar())
17813 node->WantHiddenTabBarToggle =
true;
17814 node->WantHiddenTabBarUpdate =
false;
17817 if (node->WantHiddenTabBarToggle && node->VisibleWindow && (node->VisibleWindow->WindowClass.DockNodeFlagsOverrideSet & ImGuiDockNodeFlags_HiddenTabBar))
17818 node->WantHiddenTabBarToggle =
false;
17821 if (node->Windows.Size > 1)
17822 node->SetLocalFlags(node->LocalFlags & ~ImGuiDockNodeFlags_HiddenTabBar);
17823 else if (node->WantHiddenTabBarToggle)
17824 node->SetLocalFlags(node->LocalFlags ^ ImGuiDockNodeFlags_HiddenTabBar);
17825 node->WantHiddenTabBarToggle =
false;
17827 DockNodeUpdateVisibleFlag(node);
17831static void ImGui::DockNodeUpdateHasCentralNodeChild(ImGuiDockNode* node)
17833 node->HasCentralNodeChild =
false;
17834 if (node->ChildNodes[0])
17835 DockNodeUpdateHasCentralNodeChild(node->ChildNodes[0]);
17836 if (node->ChildNodes[1])
17837 DockNodeUpdateHasCentralNodeChild(node->ChildNodes[1]);
17838 if (node->IsRootNode())
17840 ImGuiDockNode* mark_node = node->CentralNode;
17843 mark_node->HasCentralNodeChild =
true;
17844 mark_node = mark_node->ParentNode;
17849static void ImGui::DockNodeUpdateVisibleFlag(ImGuiDockNode* node)
17852 bool is_visible = (node->ParentNode == NULL) ? node->IsDockSpace() : node->IsCentralNode();
17853 is_visible |= (node->Windows.Size > 0);
17854 is_visible |= (node->ChildNodes[0] && node->ChildNodes[0]->IsVisible);
17855 is_visible |= (node->ChildNodes[1] && node->ChildNodes[1]->IsVisible);
17856 node->IsVisible = is_visible;
17859static void ImGui::DockNodeStartMouseMovingWindow(ImGuiDockNode* node, ImGuiWindow* window)
17862 IM_ASSERT(node->WantMouseMove ==
true);
17863 StartMouseMovingWindow(window);
17864 g.ActiveIdClickOffset =
g.IO.MouseClickedPos[0] - node->Pos;
17865 g.MovingWindow = window;
17866 node->WantMouseMove =
false;
17870static void ImGui::DockNodeUpdateForRootNode(ImGuiDockNode* node)
17872 DockNodeUpdateFlagsAndCollapse(node);
17878 DockNodeFindInfo(node, &info);
17890 node->WindowClass = first_node_with_windows->Windows[0]->WindowClass;
17891 for (
int n = 1; n < first_node_with_windows->Windows.Size; n++)
17892 if (first_node_with_windows->Windows[n]->WindowClass.DockingAllowUnclassed ==
false)
17894 node->WindowClass = first_node_with_windows->Windows[n]->WindowClass;
17899 ImGuiDockNode* mark_node = node->CentralNode;
17902 mark_node->HasCentralNodeChild =
true;
17903 mark_node = mark_node->ParentNode;
17907static void DockNodeSetupHostWindow(ImGuiDockNode* node, ImGuiWindow* host_window)
17914 if (node->HostWindow && node->HostWindow != host_window && node->HostWindow->DockNodeAsHost == node)
17915 node->HostWindow->DockNodeAsHost = NULL;
17917 host_window->DockNodeAsHost = node;
17918 node->HostWindow = host_window;
17921static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
17924 IM_ASSERT(node->LastFrameActive !=
g.FrameCount);
17925 node->LastFrameAlive =
g.FrameCount;
17926 node->IsBgDrawnThisFrame =
false;
17928 node->CentralNode = node->OnlyNodeWithWindows = NULL;
17929 if (node->IsRootNode())
17930 DockNodeUpdateForRootNode(node);
17933 if (node->TabBar && node->IsNoTabBar())
17934 DockNodeRemoveTabBar(node);
17937 bool want_to_hide_host_window =
false;
17938 if (node->IsFloatingNode())
17940 if (node->Windows.Size <= 1 && node->IsLeafNode())
17941 if (!
g.IO.ConfigDockingAlwaysTabBar && (node->Windows.Size == 0 || !node->Windows[0]->WindowClass.DockingAlwaysTabBar))
17942 want_to_hide_host_window =
true;
17943 if (node->CountNodeWithWindows == 0)
17944 want_to_hide_host_window =
true;
17946 if (want_to_hide_host_window)
17948 if (node->Windows.Size == 1)
17951 ImGuiWindow* single_window = node->Windows[0];
17952 node->Pos = single_window->Pos;
17953 node->Size = single_window->SizeFull;
17954 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Window;
17957 if (node->HostWindow &&
g.NavWindow == node->HostWindow)
17958 FocusWindow(single_window);
17959 if (node->HostWindow)
17961 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Node %08X transfer Viewport %08X->%08X to Window '%s'\n", node->ID, node->HostWindow->Viewport->ID, single_window->ID, single_window->Name);
17962 single_window->Viewport = node->HostWindow->Viewport;
17963 single_window->ViewportId = node->HostWindow->ViewportId;
17964 if (node->HostWindow->ViewportOwned)
17966 single_window->Viewport->ID = single_window->ID;
17967 single_window->Viewport->Window = single_window;
17968 single_window->ViewportOwned =
true;
17971 node->RefViewportId = single_window->ViewportId;
17974 DockNodeHideHostWindow(node);
17975 node->State = ImGuiDockNodeState_HostWindowHiddenBecauseSingleWindow;
17976 node->WantCloseAll =
false;
17977 node->WantCloseTabId = 0;
17978 node->HasCloseButton = node->HasWindowMenuButton =
false;
17979 node->LastFrameActive =
g.FrameCount;
17981 if (node->WantMouseMove && node->Windows.Size == 1)
17982 DockNodeStartMouseMovingWindow(node, node->Windows[0]);
17996 if (node->IsVisible && node->HostWindow == NULL && node->IsFloatingNode() && node->IsLeafNode())
17998 IM_ASSERT(node->Windows.Size > 0);
17999 ImGuiWindow* ref_window = NULL;
18000 if (node->SelectedTabId != 0)
18001 ref_window = DockNodeFindWindowByID(node, node->SelectedTabId);
18002 if (ref_window == NULL)
18003 ref_window = node->Windows[0];
18004 if (ref_window->AutoFitFramesX > 0 || ref_window->AutoFitFramesY > 0)
18006 node->State = ImGuiDockNodeState_HostWindowHiddenBecauseWindowsAreResizing;
18011 const ImGuiDockNodeFlags node_flags = node->MergedFlags;
18014 node->HasWindowMenuButton = (node->Windows.Size > 0) && (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0;
18015 node->HasCloseButton =
false;
18016 for (ImGuiWindow* window : node->Windows)
18019 node->HasCloseButton |= window->HasCloseButton;
18020 window->DockIsActive = (node->Windows.Size > 1);
18022 if (node_flags & ImGuiDockNodeFlags_NoCloseButton)
18023 node->HasCloseButton =
false;
18026 ImGuiWindow* host_window = NULL;
18027 bool beginned_into_host_window =
false;
18028 if (node->IsDockSpace())
18031 IM_ASSERT(node->HostWindow);
18032 host_window = node->HostWindow;
18037 if (node->IsRootNode() && node->IsVisible)
18039 ImGuiWindow* ref_window = (node->Windows.Size > 0) ? node->Windows[0] : NULL;
18042 if (node->AuthorityForPos == ImGuiDataAuthority_Window && ref_window)
18043 SetNextWindowPos(ref_window->Pos);
18044 else if (node->AuthorityForPos == ImGuiDataAuthority_DockNode)
18045 SetNextWindowPos(node->Pos);
18048 if (node->AuthorityForSize == ImGuiDataAuthority_Window && ref_window)
18049 SetNextWindowSize(ref_window->SizeFull);
18050 else if (node->AuthorityForSize == ImGuiDataAuthority_DockNode)
18051 SetNextWindowSize(node->Size);
18054 if (node->AuthorityForSize == ImGuiDataAuthority_Window && ref_window)
18055 SetNextWindowCollapsed(ref_window->Collapsed);
18058 if (node->AuthorityForViewport == ImGuiDataAuthority_Window && ref_window)
18059 SetNextWindowViewport(ref_window->ViewportId);
18060 else if (node->AuthorityForViewport == ImGuiDataAuthority_Window && node->RefViewportId != 0)
18061 SetNextWindowViewport(node->RefViewportId);
18063 SetNextWindowClass(&node->WindowClass);
18066 char window_label[20];
18067 DockNodeGetHostWindowTitle(node, window_label, IM_ARRAYSIZE(window_label));
18068 ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_DockNodeHost;
18069 window_flags |= ImGuiWindowFlags_NoFocusOnAppearing;
18070 window_flags |= ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoCollapse;
18071 window_flags |= ImGuiWindowFlags_NoTitleBar;
18073 SetNextWindowBgAlpha(0.0f);
18074 PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
18075 Begin(window_label, NULL, window_flags);
18077 beginned_into_host_window =
true;
18079 host_window =
g.CurrentWindow;
18080 DockNodeSetupHostWindow(node, host_window);
18081 host_window->DC.CursorPos = host_window->Pos;
18082 node->Pos = host_window->Pos;
18083 node->Size = host_window->Size;
18091 if (node->HostWindow->Appearing)
18092 BringWindowToDisplayFront(node->HostWindow);
18094 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Auto;
18096 else if (node->ParentNode)
18098 node->HostWindow = host_window = node->ParentNode->HostWindow;
18099 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Auto;
18101 if (node->WantMouseMove && node->HostWindow)
18102 DockNodeStartMouseMovingWindow(node, node->HostWindow);
18104 node->RefViewportId = 0;
18107 if (node->IsSplitNode())
18108 IM_ASSERT(node->TabBar == NULL);
18109 if (node->IsRootNode())
18110 if (ImGuiWindow* p_window =
g.NavWindow ?
g.NavWindow->RootWindow : NULL)
18111 while (p_window != NULL && p_window->DockNode != NULL)
18113 ImGuiDockNode* p_node = DockNodeGetRootNode(p_window->DockNode);
18114 if (p_node == node)
18116 node->LastFocusedNodeId = p_window->DockNode->ID;
18119 p_window = p_node->HostWindow ? p_node->HostWindow->RootWindow : NULL;
18123 ImGuiDockNode* central_node = node->CentralNode;
18124 const bool central_node_hole = node->IsRootNode() && host_window && (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0 && central_node != NULL && central_node->IsEmpty();
18125 bool central_node_hole_register_hit_test_hole = central_node_hole;
18126 if (central_node_hole)
18127 if (
const ImGuiPayload* payload = ImGui::GetDragDropPayload())
18128 if (payload->IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) && DockNodeIsDropAllowed(host_window, *(ImGuiWindow**)payload->Data))
18129 central_node_hole_register_hit_test_hole =
false;
18130 if (central_node_hole_register_hit_test_hole)
18135 IM_ASSERT(node->IsDockSpace());
18136 ImGuiDockNode* root_node = DockNodeGetRootNode(central_node);
18137 ImRect root_rect(root_node->Pos, root_node->Pos + root_node->Size);
18138 ImRect hole_rect(central_node->Pos, central_node->Pos + central_node->Size);
18139 if (hole_rect.Min.x > root_rect.Min.x) { hole_rect.Min.x += WINDOWS_HOVER_PADDING; }
18140 if (hole_rect.Max.x < root_rect.Max.x) { hole_rect.Max.x -= WINDOWS_HOVER_PADDING; }
18141 if (hole_rect.Min.y > root_rect.Min.y) { hole_rect.Min.y += WINDOWS_HOVER_PADDING; }
18142 if (hole_rect.Max.y < root_rect.Max.y) { hole_rect.Max.y -= WINDOWS_HOVER_PADDING; }
18144 if (central_node_hole && !hole_rect.IsInverted())
18146 SetWindowHitTestHole(host_window, hole_rect.Min, hole_rect.Max - hole_rect.Min);
18147 if (host_window->ParentWindow)
18148 SetWindowHitTestHole(host_window->ParentWindow, hole_rect.Min, hole_rect.Max - hole_rect.Min);
18153 if (node->IsRootNode() && host_window)
18155 DockNodeTreeUpdatePosSize(node, host_window->Pos, host_window->Size);
18156 PushStyleColor(ImGuiCol_Separator,
g.Style.Colors[ImGuiCol_Border]);
18157 PushStyleColor(ImGuiCol_SeparatorActive,
g.Style.Colors[ImGuiCol_ResizeGripActive]);
18158 PushStyleColor(ImGuiCol_SeparatorHovered,
g.Style.Colors[ImGuiCol_ResizeGripHovered]);
18159 DockNodeTreeUpdateSplitter(node);
18164 if (host_window && node->IsEmpty() && node->IsVisible)
18166 host_window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
18167 node->LastBgColor = (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) ? 0 : GetColorU32(ImGuiCol_DockingEmptyBg);
18168 if (node->LastBgColor != 0)
18169 host_window->DrawList->AddRectFilled(node->Pos, node->Pos + node->Size, node->LastBgColor);
18170 node->IsBgDrawnThisFrame =
true;
18176 const bool render_dockspace_bg = node->IsRootNode() && host_window && (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0;
18177 if (render_dockspace_bg && node->IsVisible)
18179 host_window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
18180 if (central_node_hole)
18181 RenderRectFilledWithHole(host_window->DrawList, node->Rect(), central_node->Rect(), GetColorU32(ImGuiCol_WindowBg), 0.0f);
18183 host_window->DrawList->AddRectFilled(node->Pos, node->Pos + node->Size, GetColorU32(ImGuiCol_WindowBg), 0.0f);
18188 host_window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_FG);
18189 if (host_window && node->Windows.Size > 0)
18191 DockNodeUpdateTabBar(node, host_window);
18195 node->WantCloseAll =
false;
18196 node->WantCloseTabId = 0;
18197 node->IsFocused =
false;
18199 if (node->TabBar && node->TabBar->SelectedTabId)
18200 node->SelectedTabId = node->TabBar->SelectedTabId;
18201 else if (node->Windows.Size > 0)
18202 node->SelectedTabId = node->Windows[0]->TabId;
18205 if (host_window && node->IsVisible)
18206 if (node->IsRootNode() && (
g.MovingWindow == NULL ||
g.MovingWindow->RootWindowDockTree != host_window))
18207 BeginDockableDragDropTarget(host_window);
18210 node->LastFrameActive =
g.FrameCount;
18216 if (node->ChildNodes[0])
18217 DockNodeUpdate(node->ChildNodes[0]);
18218 if (node->ChildNodes[1])
18219 DockNodeUpdate(node->ChildNodes[1]);
18222 if (node->IsRootNode())
18223 RenderWindowOuterBorders(host_window);
18227 if (beginned_into_host_window)
18232static int IMGUI_CDECL TabItemComparerByDockOrder(
const void* lhs,
const void* rhs)
18234 ImGuiWindow* a = ((
const ImGuiTabItem*)lhs)->Window;
18235 ImGuiWindow* b = ((
const ImGuiTabItem*)rhs)->Window;
18236 if (
int d = ((a->DockOrder == -1) ? INT_MAX : a->DockOrder) - ((b->DockOrder == -1) ? INT_MAX : b->DockOrder))
18238 return (a->BeginOrderWithinContext - b->BeginOrderWithinContext);
18246void ImGui::DockNodeWindowMenuHandler_Default(ImGuiContext* ctx, ImGuiDockNode* node, ImGuiTabBar* tab_bar)
18249 if (tab_bar->Tabs.Size == 1)
18252 if (MenuItem(LocalizeGetMsg(ImGuiLocKey_DockingHideTabBar), NULL, node->IsHiddenTabBar()))
18253 node->WantHiddenTabBarToggle =
true;
18258 for (
int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
18260 ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
18261 if (tab->Flags & ImGuiTabItemFlags_Button)
18263 if (Selectable(TabBarGetTabName(tab_bar, tab), tab->ID == tab_bar->SelectedTabId))
18264 TabBarQueueFocus(tab_bar, tab);
18271static void ImGui::DockNodeWindowMenuUpdate(ImGuiDockNode* node, ImGuiTabBar* tab_bar)
18275 if (
g.Style.WindowMenuButtonPosition == ImGuiDir_Left)
18276 SetNextWindowPos(ImVec2(node->Pos.x, node->Pos.y + GetFrameHeight()), ImGuiCond_Always, ImVec2(0.0f, 0.0f));
18278 SetNextWindowPos(ImVec2(node->Pos.x + node->Size.x, node->Pos.y + GetFrameHeight()), ImGuiCond_Always, ImVec2(1.0f, 0.0f));
18279 if (BeginPopup(
"#WindowMenu"))
18281 node->IsFocused =
true;
18282 g.DockNodeWindowMenuHandler(&
g, node, tab_bar);
18288bool ImGui::DockNodeBeginAmendTabBar(ImGuiDockNode* node)
18290 if (node->TabBar == NULL || node->HostWindow == NULL)
18292 if (node->MergedFlags & ImGuiDockNodeFlags_KeepAliveOnly)
18294 if (node->TabBar->ID == 0)
18296 Begin(node->HostWindow->Name);
18297 PushOverrideID(node->ID);
18298 bool ret = BeginTabBarEx(node->TabBar, node->TabBar->BarRect, node->TabBar->Flags);
18304void ImGui::DockNodeEndAmendTabBar()
18311static bool IsDockNodeTitleBarHighlighted(ImGuiDockNode* node, ImGuiDockNode* root_node)
18315 if (
g.NavWindowingTarget)
18316 return (
g.NavWindowingTarget->DockNode == node);
18319 if (
g.NavWindow && root_node->LastFocusedNodeId == node->ID)
18322 ImGuiWindow* parent_window =
g.NavWindow->RootWindow;
18323 while (parent_window->Flags & ImGuiWindowFlags_ChildMenu)
18324 parent_window = parent_window->ParentWindow->RootWindow;
18325 ImGuiDockNode* start_parent_node = parent_window->DockNodeAsHost ? parent_window->DockNodeAsHost : parent_window->DockNode;
18326 for (ImGuiDockNode* parent_node = start_parent_node; parent_node != NULL; parent_node = parent_node->HostWindow ? parent_node->HostWindow->RootWindow->DockNode : NULL)
18327 if ((parent_node = ImGui::DockNodeGetRootNode(parent_node)) == root_node)
18334static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_window)
18337 ImGuiStyle& style =
g.Style;
18339 const bool node_was_active = (node->LastFrameActive + 1 ==
g.FrameCount);
18340 const bool closed_all = node->WantCloseAll && node_was_active;
18341 const ImGuiID closed_one = node->WantCloseTabId && node_was_active;
18342 node->WantCloseAll =
false;
18343 node->WantCloseTabId = 0;
18346 bool is_focused =
false;
18347 ImGuiDockNode* root_node = DockNodeGetRootNode(node);
18348 if (IsDockNodeTitleBarHighlighted(node, root_node))
18352 if (node->IsHiddenTabBar() || node->IsNoTabBar())
18354 node->VisibleWindow = (node->Windows.Size > 0) ? node->Windows[0] : NULL;
18355 node->IsFocused = is_focused;
18357 node->LastFrameFocused =
g.FrameCount;
18358 if (node->VisibleWindow)
18361 if (is_focused || root_node->VisibleWindow == NULL)
18362 root_node->VisibleWindow = node->VisibleWindow;
18364 node->TabBar->VisibleTabId = node->VisibleWindow->TabId;
18370 bool backup_skip_item = host_window->SkipItems;
18371 if (!node->IsDockSpace())
18373 host_window->SkipItems =
false;
18374 host_window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
18380 PushOverrideID(node->ID);
18381 ImGuiTabBar* tab_bar = node->TabBar;
18382 bool tab_bar_is_recreated = (tab_bar == NULL);
18383 if (tab_bar == NULL)
18385 DockNodeAddTabBar(node);
18386 tab_bar = node->TabBar;
18389 ImGuiID focus_tab_id = 0;
18390 node->IsFocused = is_focused;
18392 const ImGuiDockNodeFlags node_flags = node->MergedFlags;
18393 const bool has_window_menu_button = (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0 && (style.WindowMenuButtonPosition != ImGuiDir_None);
18397 if (has_window_menu_button && IsPopupOpen(
"#WindowMenu"))
18399 ImGuiID next_selected_tab_id = tab_bar->NextSelectedTabId;
18400 DockNodeWindowMenuUpdate(node, tab_bar);
18401 if (tab_bar->NextSelectedTabId != 0 && tab_bar->NextSelectedTabId != next_selected_tab_id)
18402 focus_tab_id = tab_bar->NextSelectedTabId;
18403 is_focused |= node->IsFocused;
18407 ImRect title_bar_rect, tab_bar_rect;
18408 ImVec2 window_menu_button_pos;
18409 ImVec2 close_button_pos;
18410 DockNodeCalcTabBarLayout(node, &title_bar_rect, &tab_bar_rect, &window_menu_button_pos, &close_button_pos);
18413 const int tabs_count_old = tab_bar->Tabs.Size;
18414 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
18416 ImGuiWindow* window = node->Windows[window_n];
18417 if (TabBarFindTabByID(tab_bar, window->TabId) == NULL)
18418 TabBarAddTab(tab_bar, ImGuiTabItemFlags_Unsorted, window);
18423 node->LastFrameFocused =
g.FrameCount;
18424 ImU32 title_bar_col = GetColorU32(host_window->Collapsed ? ImGuiCol_TitleBgCollapsed : is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
18425 ImDrawFlags rounding_flags = CalcRoundingFlagsForRectInRect(title_bar_rect, host_window->Rect(),
g.Style.DockingSeparatorSize);
18426 host_window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, host_window->WindowRounding, rounding_flags);
18429 if (has_window_menu_button)
18431 if (CollapseButton(host_window->GetID(
"#COLLAPSE"), window_menu_button_pos, node))
18432 OpenPopup(
"#WindowMenu");
18433 if (IsItemActive())
18434 focus_tab_id = tab_bar->SelectedTabId;
18435 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_DelayNormal) &&
g.HoveredIdTimer > 0.5f)
18436 SetTooltip(
"%s", LocalizeGetMsg(ImGuiLocKey_DockingDragToUndockOrMoveNode));
18440 int tabs_unsorted_start = tab_bar->Tabs.Size;
18441 for (
int tab_n = tab_bar->Tabs.Size - 1; tab_n >= 0 && (tab_bar->Tabs[tab_n].Flags & ImGuiTabItemFlags_Unsorted); tab_n--)
18444 tab_bar->Tabs[tab_n].Flags &= ~ImGuiTabItemFlags_Unsorted;
18445 tabs_unsorted_start = tab_n;
18447 if (tab_bar->Tabs.Size > tabs_unsorted_start)
18449 IMGUI_DEBUG_LOG_DOCKING(
"[docking] In node 0x%08X: %d new appearing tabs:%s\n", node->ID, tab_bar->Tabs.Size - tabs_unsorted_start, (tab_bar->Tabs.Size > tabs_unsorted_start + 1) ?
" (will sort)" :
"");
18450 for (
int tab_n = tabs_unsorted_start; tab_n < tab_bar->Tabs.Size; tab_n++)
18452 ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
18453 IMGUI_DEBUG_LOG_DOCKING(
"[docking] - Tab 0x%08X '%s' Order %d\n", tab->ID, TabBarGetTabName(tab_bar, tab), tab->Window ? tab->Window->DockOrder : -1);
18455 IMGUI_DEBUG_LOG_DOCKING(
"[docking] SelectedTabId = 0x%08X, NavWindow->TabId = 0x%08X\n", node->SelectedTabId,
g.NavWindow ?
g.NavWindow->TabId : -1);
18456 if (tab_bar->Tabs.Size > tabs_unsorted_start + 1)
18457 ImQsort(tab_bar->Tabs.Data + tabs_unsorted_start, tab_bar->Tabs.Size - tabs_unsorted_start,
sizeof(ImGuiTabItem), TabItemComparerByDockOrder);
18461 if (
g.NavWindow &&
g.NavWindow->RootWindow->DockNode == node)
18462 tab_bar->SelectedTabId =
g.NavWindow->RootWindow->TabId;
18465 if (tab_bar_is_recreated && TabBarFindTabByID(tab_bar, node->SelectedTabId) != NULL)
18466 tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = node->SelectedTabId;
18467 else if (tab_bar->Tabs.Size > tabs_count_old)
18468 tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = tab_bar->Tabs.back().Window->TabId;
18471 ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_AutoSelectNewTabs;
18472 tab_bar_flags |= ImGuiTabBarFlags_SaveSettings | ImGuiTabBarFlags_DockNode;
18473 tab_bar_flags |= ImGuiTabBarFlags_DrawSelectedOverline;
18474 if (!host_window->Collapsed && is_focused)
18475 tab_bar_flags |= ImGuiTabBarFlags_IsFocused;
18476 tab_bar->ID = GetID(
"#TabBar");
18477 tab_bar->SeparatorMinX = node->Pos.x + host_window->WindowBorderSize;
18478 tab_bar->SeparatorMaxX = node->Pos.x + node->Size.x - host_window->WindowBorderSize;
18479 BeginTabBarEx(tab_bar, tab_bar_rect, tab_bar_flags);
18483 ImVec4 backup_style_cols[ImGuiWindowDockStyleCol_COUNT];
18484 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
18485 backup_style_cols[color_n] =
g.Style.Colors[GWindowDockStyleColors[color_n]];
18488 node->VisibleWindow = NULL;
18489 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
18491 ImGuiWindow* window = node->Windows[window_n];
18492 if ((closed_all || closed_one == window->TabId) && window->HasCloseButton && !(window->Flags & ImGuiWindowFlags_UnsavedDocument))
18494 if (window->LastFrameActive + 1 >=
g.FrameCount || !node_was_active)
18496 ImGuiTabItemFlags tab_item_flags = 0;
18497 tab_item_flags |= window->WindowClass.TabItemFlagsOverrideSet;
18498 if (window->Flags & ImGuiWindowFlags_UnsavedDocument)
18499 tab_item_flags |= ImGuiTabItemFlags_UnsavedDocument;
18500 if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
18501 tab_item_flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
18504 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
18505 g.Style.Colors[GWindowDockStyleColors[color_n]] = ColorConvertU32ToFloat4(window->DockStyle.Colors[color_n]);
18508 bool tab_open =
true;
18509 TabItemEx(tab_bar, window->Name, window->HasCloseButton ? &tab_open : NULL, tab_item_flags, window);
18511 node->WantCloseTabId = window->TabId;
18512 if (tab_bar->VisibleTabId == window->TabId)
18513 node->VisibleWindow = window;
18516 window->DockTabItemStatusFlags =
g.LastItemData.StatusFlags;
18517 window->DockTabItemRect =
g.LastItemData.Rect;
18520 if (
g.NavWindow &&
g.NavWindow->RootWindow == window && (window->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) == 0)
18521 host_window->NavLastIds[1] = window->TabId;
18526 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
18527 g.Style.Colors[GWindowDockStyleColors[color_n]] = backup_style_cols[color_n];
18530 if (node->VisibleWindow)
18531 if (is_focused || root_node->VisibleWindow == NULL)
18532 root_node->VisibleWindow = node->VisibleWindow;
18536 const bool close_button_is_enabled = node->HasCloseButton && node->VisibleWindow && node->VisibleWindow->HasCloseButton;
18537 const bool close_button_is_visible = node->HasCloseButton;
18539 if (close_button_is_visible)
18541 if (!close_button_is_enabled)
18543 PushItemFlag(ImGuiItemFlags_Disabled,
true);
18544 PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_Text] * ImVec4(1.0f,1.0f,1.0f,0.4f));
18546 if (CloseButton(host_window->GetID(
"#CLOSE"), close_button_pos))
18548 node->WantCloseAll =
true;
18549 for (
int n = 0; n < tab_bar->Tabs.Size; n++)
18550 TabBarCloseTab(tab_bar, &tab_bar->Tabs[n]);
18554 if (!close_button_is_enabled)
18563 ImGuiID title_bar_id = host_window->GetID(
"#TITLEBAR");
18564 if (
g.HoveredId == 0 ||
g.HoveredId == title_bar_id ||
g.ActiveId == title_bar_id)
18569 KeepAliveID(title_bar_id);
18570 ButtonBehavior(title_bar_rect, title_bar_id, NULL, &held, ImGuiButtonFlags_AllowOverlap);
18571 if (
g.HoveredId == title_bar_id)
18573 g.LastItemData.ID = title_bar_id;
18577 if (IsMouseClicked(0))
18578 focus_tab_id = tab_bar->SelectedTabId;
18581 if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
18582 StartMouseMovingWindowOrNode(tab->Window ? tab->Window : node->HostWindow, node, false);
18592 if (tab_bar->NextSelectedTabId)
18593 focus_tab_id = tab_bar->NextSelectedTabId;
18596 if (focus_tab_id != 0)
18597 if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, focus_tab_id))
18600 FocusWindow(tab->Window);
18601 NavInitWindow(tab->Window,
false);
18608 if (!node->IsDockSpace())
18610 host_window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
18611 host_window->SkipItems = backup_skip_item;
18615static void ImGui::DockNodeAddTabBar(ImGuiDockNode* node)
18617 IM_ASSERT(node->TabBar == NULL);
18618 node->TabBar = IM_NEW(ImGuiTabBar);
18621static void ImGui::DockNodeRemoveTabBar(ImGuiDockNode* node)
18623 if (node->TabBar == NULL)
18625 IM_DELETE(node->TabBar);
18626 node->TabBar = NULL;
18629static bool DockNodeIsDropAllowedOne(ImGuiWindow* payload, ImGuiWindow* host_window)
18631 if (host_window->DockNodeAsHost && host_window->DockNodeAsHost->IsDockSpace() && payload->BeginOrderWithinContext < host_window->BeginOrderWithinContext)
18634 ImGuiWindowClass* host_class = host_window->DockNodeAsHost ? &host_window->DockNodeAsHost->WindowClass : &host_window->WindowClass;
18635 ImGuiWindowClass* payload_class = &payload->WindowClass;
18636 if (host_class->ClassId != payload_class->ClassId)
18639 if (host_class->ClassId != 0 && host_class->DockingAllowUnclassed && payload_class->ClassId == 0)
18641 if (payload_class->ClassId != 0 && payload_class->DockingAllowUnclassed && host_class->ClassId == 0)
18653 for (
int i =
g.OpenPopupStack.Size - 1; i >= 0; i--)
18654 if (ImGuiWindow* popup_window =
g.OpenPopupStack[i].Window)
18655 if (ImGui::IsWindowWithinBeginStackOf(payload, popup_window))
18661static bool ImGui::DockNodeIsDropAllowed(ImGuiWindow* host_window, ImGuiWindow* root_payload)
18663 if (root_payload->DockNodeAsHost && root_payload->DockNodeAsHost->IsSplitNode())
18666 const int payload_count = root_payload->DockNodeAsHost ? root_payload->DockNodeAsHost->Windows.Size : 1;
18667 for (
int payload_n = 0; payload_n < payload_count; payload_n++)
18669 ImGuiWindow* payload = root_payload->DockNodeAsHost ? root_payload->DockNodeAsHost->Windows[payload_n] : root_payload;
18670 if (DockNodeIsDropAllowedOne(payload, host_window))
18678static void ImGui::DockNodeCalcTabBarLayout(
const ImGuiDockNode* node, ImRect* out_title_rect, ImRect* out_tab_bar_rect, ImVec2* out_window_menu_button_pos, ImVec2* out_close_button_pos)
18681 ImGuiStyle& style =
g.Style;
18683 ImRect r = ImRect(node->Pos.x, node->Pos.y, node->Pos.x + node->Size.x, node->Pos.y +
g.FontSize +
g.Style.FramePadding.y * 2.0f);
18684 if (out_title_rect) { *out_title_rect = r; }
18686 r.Min.x += style.WindowBorderSize;
18687 r.Max.x -= style.WindowBorderSize;
18689 float button_sz =
g.FontSize;
18690 r.Min.x += style.FramePadding.x;
18691 r.Max.x -= style.FramePadding.x;
18692 ImVec2 window_menu_button_pos = ImVec2(r.Min.x, r.Min.y + style.FramePadding.y);
18693 if (node->HasCloseButton)
18695 if (out_close_button_pos) *out_close_button_pos = ImVec2(r.Max.x - button_sz, r.Min.y + style.FramePadding.y);
18696 r.Max.x -= button_sz + style.ItemInnerSpacing.x;
18698 if (node->HasWindowMenuButton && style.WindowMenuButtonPosition == ImGuiDir_Left)
18700 r.Min.x += button_sz + style.ItemInnerSpacing.x;
18702 else if (node->HasWindowMenuButton && style.WindowMenuButtonPosition == ImGuiDir_Right)
18704 window_menu_button_pos = ImVec2(r.Max.x - button_sz, r.Min.y + style.FramePadding.y);
18705 r.Max.x -= button_sz + style.ItemInnerSpacing.x;
18707 if (out_tab_bar_rect) { *out_tab_bar_rect = r; }
18708 if (out_window_menu_button_pos) { *out_window_menu_button_pos = window_menu_button_pos; }
18711void ImGui::DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& pos_new, ImVec2& size_new, ImGuiDir dir, ImVec2 size_new_desired)
18714 const float dock_spacing =
g.Style.ItemInnerSpacing.x;
18715 const ImGuiAxis axis = (dir == ImGuiDir_Left || dir == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
18716 pos_new[axis ^ 1] = pos_old[axis ^ 1];
18717 size_new[axis ^ 1] = size_old[axis ^ 1];
18720 const float w_avail = size_old[axis] - dock_spacing;
18721 if (size_new_desired[axis] > 0.0f && size_new_desired[axis] <= w_avail * 0.5f)
18723 size_new[axis] = size_new_desired[axis];
18724 size_old[axis] = IM_TRUNC(w_avail - size_new[axis]);
18728 size_new[axis] = IM_TRUNC(w_avail * 0.5f);
18729 size_old[axis] = IM_TRUNC(w_avail - size_new[axis]);
18733 if (dir == ImGuiDir_Right || dir == ImGuiDir_Down)
18735 pos_new[axis] = pos_old[axis] + size_old[axis] + dock_spacing;
18737 else if (dir == ImGuiDir_Left || dir == ImGuiDir_Up)
18739 pos_new[axis] = pos_old[axis];
18740 pos_old[axis] = pos_new[axis] + size_new[axis] + dock_spacing;
18745bool ImGui::DockNodeCalcDropRectsAndTestMousePos(
const ImRect& parent, ImGuiDir dir, ImRect& out_r,
bool outer_docking, ImVec2* test_mouse_pos)
18749 const float parent_smaller_axis = ImMin(parent.GetWidth(), parent.GetHeight());
18750 const float hs_for_central_nodes = ImMin(
g.FontSize * 1.5f, ImMax(
g.FontSize * 0.5f, parent_smaller_axis / 8.0f));
18759 hs_w = ImTrunc(hs_for_central_nodes * 1.50f);
18760 hs_h = ImTrunc(hs_for_central_nodes * 0.80f);
18761 off = ImTrunc(ImVec2(parent.GetWidth() * 0.5f - hs_h, parent.GetHeight() * 0.5f - hs_h));
18765 hs_w = ImTrunc(hs_for_central_nodes);
18766 hs_h = ImTrunc(hs_for_central_nodes * 0.90f);
18767 off = ImTrunc(ImVec2(hs_w * 2.40f, hs_w * 2.40f));
18770 ImVec2 c = ImTrunc(parent.GetCenter());
18771 if (dir == ImGuiDir_None) { out_r = ImRect(c.x - hs_w, c.y - hs_w, c.x + hs_w, c.y + hs_w); }
18772 else if (dir == ImGuiDir_Up) { out_r = ImRect(c.x - hs_w, c.y - off.y - hs_h, c.x + hs_w, c.y - off.y + hs_h); }
18773 else if (dir == ImGuiDir_Down) { out_r = ImRect(c.x - hs_w, c.y + off.y - hs_h, c.x + hs_w, c.y + off.y + hs_h); }
18774 else if (dir == ImGuiDir_Left) { out_r = ImRect(c.x - off.x - hs_h, c.y - hs_w, c.x - off.x + hs_h, c.y + hs_w); }
18775 else if (dir == ImGuiDir_Right) { out_r = ImRect(c.x + off.x - hs_h, c.y - hs_w, c.x + off.x + hs_h, c.y + hs_w); }
18777 if (test_mouse_pos == NULL)
18780 ImRect hit_r = out_r;
18781 if (!outer_docking)
18784 hit_r.Expand(ImTrunc(hs_w * 0.30f));
18785 ImVec2 mouse_delta = (*test_mouse_pos - c);
18786 float mouse_delta_len2 = ImLengthSqr(mouse_delta);
18787 float r_threshold_center = hs_w * 1.4f;
18788 float r_threshold_sides = hs_w * (1.4f + 1.2f);
18789 if (mouse_delta_len2 < r_threshold_center * r_threshold_center)
18790 return (dir == ImGuiDir_None);
18791 if (mouse_delta_len2 < r_threshold_sides * r_threshold_sides)
18792 return (dir == ImGetDirQuadrantFromDelta(mouse_delta.x, mouse_delta.y));
18794 return hit_r.Contains(*test_mouse_pos);
18799static void ImGui::DockNodePreviewDockSetup(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window, ImGuiDockNode* payload_node,
ImGuiDockPreviewData* data,
bool is_explicit_target,
bool is_outer_docking)
18806 if (payload_node == NULL)
18807 payload_node = payload_window->DockNodeAsHost;
18808 ImGuiDockNode* ref_node_for_rect = (host_node && !host_node->IsVisible) ? DockNodeGetRootNode(host_node) : host_node;
18809 if (ref_node_for_rect)
18810 IM_ASSERT(ref_node_for_rect->IsVisible ==
true);
18813 ImGuiDockNodeFlags src_node_flags = payload_node ? payload_node->MergedFlags : payload_window->WindowClass.DockNodeFlagsOverrideSet;
18814 ImGuiDockNodeFlags dst_node_flags = host_node ? host_node->MergedFlags : host_window->WindowClass.DockNodeFlagsOverrideSet;
18816 if (is_outer_docking)
18818 else if (dst_node_flags & ImGuiDockNodeFlags_NoDockingOverMe)
18820 else if (host_node && (dst_node_flags & ImGuiDockNodeFlags_NoDockingOverCentralNode) && host_node->IsCentralNode())
18822 else if ((!host_node || !host_node->IsEmpty()) && payload_node && payload_node->IsSplitNode() && (payload_node->OnlyNodeWithWindows == NULL))
18824 else if ((src_node_flags & ImGuiDockNodeFlags_NoDockingOverOther) && (!host_node || !host_node->IsEmpty()))
18826 else if ((src_node_flags & ImGuiDockNodeFlags_NoDockingOverEmpty) && host_node && host_node->IsEmpty())
18830 if ((dst_node_flags & ImGuiDockNodeFlags_NoDockingSplit) ||
g.IO.ConfigDockingNoSplit)
18832 else if (!is_outer_docking && host_node && host_node->ParentNode == NULL && host_node->IsCentralNode())
18834 else if (src_node_flags & ImGuiDockNodeFlags_NoDockingSplitOther)
18838 data->
FutureNode.HasCloseButton = (host_node ? host_node->HasCloseButton : host_window->HasCloseButton) || (payload_window->HasCloseButton);
18839 data->
FutureNode.HasWindowMenuButton = host_node ? true : ((host_window->Flags & ImGuiWindowFlags_NoCollapse) == 0);
18840 data->
FutureNode.Pos = ref_node_for_rect ? ref_node_for_rect->Pos : host_window->Pos;
18841 data->
FutureNode.Size = ref_node_for_rect ? ref_node_for_rect->Size : host_window->Size;
18844 IM_ASSERT(ImGuiDir_None == -1);
18848 if (!host_window->Collapsed)
18849 for (
int dir = ImGuiDir_None; dir < ImGuiDir_COUNT; dir++)
18855 if (DockNodeCalcDropRectsAndTestMousePos(data->
FutureNode.Rect(), (ImGuiDir)dir, data->
DropRectsDraw[dir+1], is_outer_docking, &
g.IO.MousePos))
18869 if (data->
SplitDir != ImGuiDir_None)
18871 ImGuiDir split_dir = data->
SplitDir;
18872 ImGuiAxis split_axis = (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
18873 ImVec2 pos_new, pos_old = data->
FutureNode.Pos;
18874 ImVec2 size_new, size_old = data->
FutureNode.Size;
18875 DockNodeCalcSplitRects(pos_old, size_old, pos_new, size_new, split_dir, payload_window->Size);
18878 float split_ratio = ImSaturate(size_new[split_axis] / data->
FutureNode.Size[split_axis]);
18881 data->
SplitRatio = (split_dir == ImGuiDir_Right || split_dir == ImGuiDir_Down) ? (1.0f - split_ratio) : (split_ratio);
18885static void ImGui::DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* root_payload,
const ImGuiDockPreviewData* data)
18888 IM_ASSERT(
g.CurrentWindow == host_window);
18892 const bool is_transparent_payload =
g.IO.ConfigDockingTransparentPayload;
18895 int overlay_draw_lists_count = 0;
18896 ImDrawList* overlay_draw_lists[2];
18897 overlay_draw_lists[overlay_draw_lists_count++] = GetForegroundDrawList(host_window->Viewport);
18898 if (host_window->Viewport != root_payload->Viewport && !is_transparent_payload)
18899 overlay_draw_lists[overlay_draw_lists_count++] = GetForegroundDrawList(root_payload->Viewport);
18902 const ImU32 overlay_col_main = GetColorU32(ImGuiCol_DockingPreview, is_transparent_payload ? 0.60f : 0.40f);
18903 const ImU32 overlay_col_drop = GetColorU32(ImGuiCol_DockingPreview, is_transparent_payload ? 0.90f : 0.70f);
18904 const ImU32 overlay_col_drop_hovered = GetColorU32(ImGuiCol_DockingPreview, is_transparent_payload ? 1.20f : 1.00f);
18905 const ImU32 overlay_col_lines = GetColorU32(ImGuiCol_NavWindowingHighlight, is_transparent_payload ? 0.80f : 0.60f);
18908 const bool can_preview_tabs = (root_payload->DockNodeAsHost == NULL || root_payload->DockNodeAsHost->Windows.Size > 0);
18911 ImRect overlay_rect = data->
FutureNode.Rect();
18912 if (data->
SplitDir == ImGuiDir_None && can_preview_tabs)
18913 overlay_rect.Min.y += GetFrameHeight();
18915 for (
int overlay_n = 0; overlay_n < overlay_draw_lists_count; overlay_n++)
18916 overlay_draw_lists[overlay_n]->AddRectFilled(overlay_rect.Min, overlay_rect.Max, overlay_col_main, host_window->WindowRounding, CalcRoundingFlagsForRectInRect(overlay_rect, host_window->Rect(),
g.Style.DockingSeparatorSize));
18923 ImRect tab_bar_rect;
18924 DockNodeCalcTabBarLayout(&data->
FutureNode, NULL, &tab_bar_rect, NULL, NULL);
18925 ImVec2 tab_pos = tab_bar_rect.Min;
18926 if (host_node && host_node->TabBar)
18928 if (!host_node->IsHiddenTabBar() && !host_node->IsNoTabBar())
18929 tab_pos.x += host_node->TabBar->WidthAllTabs +
g.Style.ItemInnerSpacing.x;
18931 tab_pos.x +=
g.Style.ItemInnerSpacing.x + TabItemCalcSize(host_node->Windows[0]).x;
18933 else if (!(host_window->Flags & ImGuiWindowFlags_DockNodeHost))
18935 tab_pos.x +=
g.Style.ItemInnerSpacing.x + TabItemCalcSize(host_window).x;
18939 if (root_payload->DockNodeAsHost)
18940 IM_ASSERT(root_payload->DockNodeAsHost->Windows.Size <= root_payload->DockNodeAsHost->TabBar->Tabs.Size);
18941 ImGuiTabBar* tab_bar_with_payload = root_payload->DockNodeAsHost ? root_payload->DockNodeAsHost->TabBar : NULL;
18942 const int payload_count = tab_bar_with_payload ? tab_bar_with_payload->Tabs.Size : 1;
18943 for (
int payload_n = 0; payload_n < payload_count; payload_n++)
18946 ImGuiWindow* payload_window = tab_bar_with_payload ? tab_bar_with_payload->Tabs[payload_n].Window : root_payload;
18947 if (tab_bar_with_payload && payload_window == NULL)
18949 if (!DockNodeIsDropAllowedOne(payload_window, host_window))
18953 ImVec2 tab_size = TabItemCalcSize(payload_window);
18954 ImRect tab_bb(tab_pos.x, tab_pos.y, tab_pos.x + tab_size.x, tab_pos.y + tab_size.y);
18955 tab_pos.x += tab_size.x +
g.Style.ItemInnerSpacing.x;
18956 const ImU32 overlay_col_text = GetColorU32(payload_window->DockStyle.Colors[ImGuiWindowDockStyleCol_Text]);
18957 const ImU32 overlay_col_tabs = GetColorU32(payload_window->DockStyle.Colors[ImGuiWindowDockStyleCol_TabSelected]);
18958 PushStyleColor(ImGuiCol_Text, overlay_col_text);
18959 for (
int overlay_n = 0; overlay_n < overlay_draw_lists_count; overlay_n++)
18961 ImGuiTabItemFlags tab_flags = (payload_window->Flags & ImGuiWindowFlags_UnsavedDocument) ? ImGuiTabItemFlags_UnsavedDocument : 0;
18962 if (!tab_bar_rect.Contains(tab_bb))
18963 overlay_draw_lists[overlay_n]->PushClipRect(tab_bar_rect.Min, tab_bar_rect.Max);
18964 TabItemBackground(overlay_draw_lists[overlay_n], tab_bb, tab_flags, overlay_col_tabs);
18965 TabItemLabelAndCloseButton(overlay_draw_lists[overlay_n], tab_bb, tab_flags,
g.Style.FramePadding, payload_window->Name, 0, 0,
false, NULL, NULL);
18966 if (!tab_bar_rect.Contains(tab_bb))
18967 overlay_draw_lists[overlay_n]->PopClipRect();
18974 const float overlay_rounding = ImMax(3.0f,
g.Style.FrameRounding);
18975 for (
int dir = ImGuiDir_None; dir < ImGuiDir_COUNT; dir++)
18980 ImRect draw_r_in = draw_r;
18981 draw_r_in.Expand(-2.0f);
18982 ImU32 overlay_col = (data->
SplitDir == (ImGuiDir)dir && data->
IsSplitDirExplicit) ? overlay_col_drop_hovered : overlay_col_drop;
18983 for (
int overlay_n = 0; overlay_n < overlay_draw_lists_count; overlay_n++)
18985 ImVec2 center = ImFloor(draw_r_in.GetCenter());
18986 overlay_draw_lists[overlay_n]->AddRectFilled(draw_r.Min, draw_r.Max, overlay_col, overlay_rounding);
18987 overlay_draw_lists[overlay_n]->AddRect(draw_r_in.Min, draw_r_in.Max, overlay_col_lines, overlay_rounding);
18988 if (dir == ImGuiDir_Left || dir == ImGuiDir_Right)
18989 overlay_draw_lists[overlay_n]->AddLine(ImVec2(center.x, draw_r_in.Min.y), ImVec2(center.x, draw_r_in.Max.y), overlay_col_lines);
18990 if (dir == ImGuiDir_Up || dir == ImGuiDir_Down)
18991 overlay_draw_lists[overlay_n]->AddLine(ImVec2(draw_r_in.Min.x, center.y), ImVec2(draw_r_in.Max.x, center.y), overlay_col_lines);
18996 if ((host_node && (host_node->MergedFlags & ImGuiDockNodeFlags_NoDockingSplit)) ||
g.IO.ConfigDockingNoSplit)
19013void ImGui::DockNodeTreeSplit(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiAxis split_axis,
int split_inheritor_child_idx,
float split_ratio, ImGuiDockNode* new_node)
19016 IM_ASSERT(split_axis != ImGuiAxis_None);
19018 ImGuiDockNode* child_0 = (new_node && split_inheritor_child_idx != 0) ? new_node : DockContextAddNode(ctx, 0);
19019 child_0->ParentNode = parent_node;
19021 ImGuiDockNode* child_1 = (new_node && split_inheritor_child_idx != 1) ? new_node : DockContextAddNode(ctx, 0);
19022 child_1->ParentNode = parent_node;
19024 ImGuiDockNode* child_inheritor = (split_inheritor_child_idx == 0) ? child_0 : child_1;
19025 DockNodeMoveChildNodes(child_inheritor, parent_node);
19026 parent_node->ChildNodes[0] = child_0;
19027 parent_node->ChildNodes[1] = child_1;
19028 parent_node->ChildNodes[split_inheritor_child_idx]->VisibleWindow = parent_node->VisibleWindow;
19029 parent_node->SplitAxis = split_axis;
19030 parent_node->VisibleWindow = NULL;
19031 parent_node->AuthorityForPos = parent_node->AuthorityForSize = ImGuiDataAuthority_DockNode;
19033 float size_avail = (parent_node->Size[split_axis] -
g.Style.DockingSeparatorSize);
19034 size_avail = ImMax(size_avail,
g.Style.WindowMinSize[split_axis] * 2.0f);
19035 IM_ASSERT(size_avail > 0.0f);
19036 child_0->SizeRef = child_1->SizeRef = parent_node->Size;
19037 child_0->SizeRef[split_axis] = ImTrunc(size_avail * split_ratio);
19038 child_1->SizeRef[split_axis] = ImTrunc(size_avail - child_0->SizeRef[split_axis]);
19040 DockNodeMoveWindows(parent_node->ChildNodes[split_inheritor_child_idx], parent_node);
19041 DockSettingsRenameNodeReferences(parent_node->ID, parent_node->ChildNodes[split_inheritor_child_idx]->ID);
19042 DockNodeUpdateHasCentralNodeChild(DockNodeGetRootNode(parent_node));
19043 DockNodeTreeUpdatePosSize(parent_node, parent_node->Pos, parent_node->Size);
19046 child_0->SharedFlags = parent_node->SharedFlags & ImGuiDockNodeFlags_SharedFlagsInheritMask_;
19047 child_1->SharedFlags = parent_node->SharedFlags & ImGuiDockNodeFlags_SharedFlagsInheritMask_;
19048 child_inheritor->LocalFlags = parent_node->LocalFlags & ImGuiDockNodeFlags_LocalFlagsTransferMask_;
19049 parent_node->LocalFlags &= ~ImGuiDockNodeFlags_LocalFlagsTransferMask_;
19050 child_0->UpdateMergedFlags();
19051 child_1->UpdateMergedFlags();
19052 parent_node->UpdateMergedFlags();
19053 if (child_inheritor->IsCentralNode())
19054 DockNodeGetRootNode(parent_node)->CentralNode = child_inheritor;
19057void ImGui::DockNodeTreeMerge(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiDockNode* merge_lead_child)
19061 ImGuiDockNode* child_0 = parent_node->ChildNodes[0];
19062 ImGuiDockNode* child_1 = parent_node->ChildNodes[1];
19063 IM_ASSERT(child_0 || child_1);
19064 IM_ASSERT(merge_lead_child == child_0 || merge_lead_child == child_1);
19065 if ((child_0 && child_0->Windows.Size > 0) || (child_1 && child_1->Windows.Size > 0))
19067 IM_ASSERT(parent_node->TabBar == NULL);
19068 IM_ASSERT(parent_node->Windows.Size == 0);
19070 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockNodeTreeMerge: 0x%08X + 0x%08X back into parent 0x%08X\n", child_0 ? child_0->ID : 0, child_1 ? child_1->
ID : 0, parent_node->
ID);
19072 ImVec2 backup_last_explicit_size = parent_node->SizeRef;
19073 DockNodeMoveChildNodes(parent_node, merge_lead_child);
19076 DockNodeMoveWindows(parent_node, child_0);
19077 DockSettingsRenameNodeReferences(child_0->ID, parent_node->ID);
19081 DockNodeMoveWindows(parent_node, child_1);
19082 DockSettingsRenameNodeReferences(child_1->ID, parent_node->ID);
19084 DockNodeApplyPosSizeToWindows(parent_node);
19085 parent_node->AuthorityForPos = parent_node->AuthorityForSize = parent_node->AuthorityForViewport = ImGuiDataAuthority_Auto;
19086 parent_node->VisibleWindow = merge_lead_child->VisibleWindow;
19087 parent_node->SizeRef = backup_last_explicit_size;
19090 parent_node->LocalFlags &= ~ImGuiDockNodeFlags_LocalFlagsTransferMask_;
19091 parent_node->LocalFlags |= (child_0 ? child_0->LocalFlags : 0) & ImGuiDockNodeFlags_LocalFlagsTransferMask_;
19092 parent_node->LocalFlags |= (child_1 ? child_1->LocalFlags : 0) & ImGuiDockNodeFlags_LocalFlagsTransferMask_;
19093 parent_node->LocalFlagsInWindows = (child_0 ? child_0->LocalFlagsInWindows : 0) | (child_1 ? child_1->LocalFlagsInWindows : 0);
19094 parent_node->UpdateMergedFlags();
19098 ctx->DockContext.Nodes.SetVoidPtr(child_0->ID, NULL);
19099 IM_DELETE(child_0);
19103 ctx->DockContext.Nodes.SetVoidPtr(child_1->ID, NULL);
19104 IM_DELETE(child_1);
19110void ImGui::DockNodeTreeUpdatePosSize(ImGuiDockNode* node, ImVec2 pos, ImVec2 size, ImGuiDockNode* only_write_to_single_node)
19115 const bool write_to_node = only_write_to_single_node == NULL || only_write_to_single_node == node;
19122 if (node->IsLeafNode())
19125 ImGuiDockNode* child_0 = node->ChildNodes[0];
19126 ImGuiDockNode* child_1 = node->ChildNodes[1];
19127 ImVec2 child_0_pos = pos, child_1_pos = pos;
19128 ImVec2 child_0_size =
size, child_1_size =
size;
19130 const bool child_0_is_toward_single_node = (only_write_to_single_node != NULL && DockNodeIsInHierarchyOf(only_write_to_single_node, child_0));
19131 const bool child_1_is_toward_single_node = (only_write_to_single_node != NULL && DockNodeIsInHierarchyOf(only_write_to_single_node, child_1));
19132 const bool child_0_is_or_will_be_visible = child_0->IsVisible || child_0_is_toward_single_node;
19133 const bool child_1_is_or_will_be_visible = child_1->IsVisible || child_1_is_toward_single_node;
19135 if (child_0_is_or_will_be_visible && child_1_is_or_will_be_visible)
19137 const float spacing =
g.Style.DockingSeparatorSize;
19138 const ImGuiAxis axis = (ImGuiAxis)node->SplitAxis;
19139 const float size_avail = ImMax(size[axis] - spacing, 0.0f);
19143 const float size_min_each = ImTrunc(ImMin(size_avail,
g.Style.WindowMinSize[axis] * 2.0f) * 0.5f);
19150 if (child_0->WantLockSizeOnce && !child_1->WantLockSizeOnce)
19152 child_0_size[axis] = child_0->SizeRef[axis] = ImMin(size_avail - 1.0f, child_0->Size[axis]);
19153 child_1_size[axis] = child_1->SizeRef[axis] = (size_avail - child_0_size[axis]);
19154 IM_ASSERT(child_0->SizeRef[axis] > 0.0f && child_1->SizeRef[axis] > 0.0f);
19156 else if (child_1->WantLockSizeOnce && !child_0->WantLockSizeOnce)
19158 child_1_size[axis] = child_1->SizeRef[axis] = ImMin(size_avail - 1.0f, child_1->Size[axis]);
19159 child_0_size[axis] = child_0->SizeRef[axis] = (size_avail - child_1_size[axis]);
19160 IM_ASSERT(child_0->SizeRef[axis] > 0.0f && child_1->SizeRef[axis] > 0.0f);
19162 else if (child_0->WantLockSizeOnce && child_1->WantLockSizeOnce)
19166 float split_ratio = child_0_size[axis] / (child_0_size[axis] + child_1_size[axis]);
19167 child_0_size[axis] = child_0->SizeRef[axis] = ImTrunc(size_avail * split_ratio);
19168 child_1_size[axis] = child_1->SizeRef[axis] = (size_avail - child_0_size[axis]);
19169 IM_ASSERT(child_0->SizeRef[axis] > 0.0f && child_1->SizeRef[axis] > 0.0f);
19173 else if (child_0->SizeRef[axis] != 0.0f && child_1->HasCentralNodeChild)
19175 child_0_size[axis] = ImMin(size_avail - size_min_each, child_0->SizeRef[axis]);
19176 child_1_size[axis] = (size_avail - child_0_size[axis]);
19178 else if (child_1->SizeRef[axis] != 0.0f && child_0->HasCentralNodeChild)
19180 child_1_size[axis] = ImMin(size_avail - size_min_each, child_1->SizeRef[axis]);
19181 child_0_size[axis] = (size_avail - child_1_size[axis]);
19186 float split_ratio = child_0->SizeRef[axis] / (child_0->SizeRef[axis] + child_1->SizeRef[axis]);
19187 child_0_size[axis] = ImMax(size_min_each, ImTrunc(size_avail * split_ratio + 0.5f));
19188 child_1_size[axis] = (size_avail - child_0_size[axis]);
19191 child_1_pos[axis] += spacing + child_0_size[axis];
19194 if (only_write_to_single_node == NULL)
19195 child_0->WantLockSizeOnce = child_1->WantLockSizeOnce =
false;
19197 const bool child_0_recurse = only_write_to_single_node ? child_0_is_toward_single_node : child_0->IsVisible;
19198 const bool child_1_recurse = only_write_to_single_node ? child_1_is_toward_single_node : child_1->IsVisible;
19199 if (child_0_recurse)
19200 DockNodeTreeUpdatePosSize(child_0, child_0_pos, child_0_size);
19201 if (child_1_recurse)
19202 DockNodeTreeUpdatePosSize(child_1, child_1_pos, child_1_size);
19205static void DockNodeTreeUpdateSplitterFindTouchingNode(ImGuiDockNode* node, ImGuiAxis axis,
int side, ImVector<ImGuiDockNode*>* touching_nodes)
19207 if (node->IsLeafNode())
19209 touching_nodes->push_back(node);
19212 if (node->ChildNodes[0]->IsVisible)
19213 if (node->SplitAxis != axis || side == 0 || !node->ChildNodes[1]->IsVisible)
19214 DockNodeTreeUpdateSplitterFindTouchingNode(node->ChildNodes[0], axis, side, touching_nodes);
19215 if (node->ChildNodes[1]->IsVisible)
19216 if (node->SplitAxis != axis || side == 1 || !node->ChildNodes[0]->IsVisible)
19217 DockNodeTreeUpdateSplitterFindTouchingNode(node->ChildNodes[1], axis, side, touching_nodes);
19221void ImGui::DockNodeTreeUpdateSplitter(ImGuiDockNode* node)
19223 if (node->IsLeafNode())
19228 ImGuiDockNode* child_0 = node->ChildNodes[0];
19229 ImGuiDockNode* child_1 = node->ChildNodes[1];
19230 if (child_0->IsVisible && child_1->IsVisible)
19233 const ImGuiAxis axis = (ImGuiAxis)node->SplitAxis;
19234 IM_ASSERT(axis != ImGuiAxis_None);
19236 bb.Min = child_0->Pos;
19237 bb.Max = child_1->Pos;
19238 bb.Min[axis] += child_0->Size[axis];
19239 bb.Max[axis ^ 1] += child_1->Size[axis ^ 1];
19242 const ImGuiDockNodeFlags merged_flags = child_0->MergedFlags | child_1->MergedFlags;
19243 const ImGuiDockNodeFlags no_resize_axis_flag = (axis == ImGuiAxis_X) ? ImGuiDockNodeFlags_NoResizeX : ImGuiDockNodeFlags_NoResizeY;
19244 if ((merged_flags & ImGuiDockNodeFlags_NoResize) || (merged_flags & no_resize_axis_flag))
19246 ImGuiWindow* window =
g.CurrentWindow;
19247 window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Separator),
g.Style.FrameRounding);
19256 ImVector<ImGuiDockNode*> touching_nodes[2];
19257 float min_size =
g.Style.WindowMinSize[axis];
19258 float resize_limits[2];
19259 resize_limits[0] = node->ChildNodes[0]->Pos[axis] + min_size;
19260 resize_limits[1] = node->ChildNodes[1]->Pos[axis] + node->ChildNodes[1]->Size[axis] - min_size;
19262 ImGuiID splitter_id = GetID(
"##Splitter");
19263 if (
g.ActiveId == splitter_id)
19265 DockNodeTreeUpdateSplitterFindTouchingNode(child_0, axis, 1, &touching_nodes[0]);
19266 DockNodeTreeUpdateSplitterFindTouchingNode(child_1, axis, 0, &touching_nodes[1]);
19267 for (
int touching_node_n = 0; touching_node_n < touching_nodes[0].Size; touching_node_n++)
19268 resize_limits[0] = ImMax(resize_limits[0], touching_nodes[0][touching_node_n]->Rect().Min[axis] + min_size);
19269 for (
int touching_node_n = 0; touching_node_n < touching_nodes[1].Size; touching_node_n++)
19270 resize_limits[1] = ImMin(resize_limits[1], touching_nodes[1][touching_node_n]->Rect().Max[axis] - min_size);
19288 float cur_size_0 = child_0->Size[axis];
19289 float cur_size_1 = child_1->Size[axis];
19290 float min_size_0 = resize_limits[0] - child_0->Pos[axis];
19291 float min_size_1 = child_1->Pos[axis] + child_1->Size[axis] - resize_limits[1];
19292 ImU32 bg_col = GetColorU32(ImGuiCol_WindowBg);
19293 if (SplitterBehavior(bb, GetID(
"##Splitter"), axis, &cur_size_0, &cur_size_1, min_size_0, min_size_1, WINDOWS_HOVER_PADDING, WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER, bg_col))
19295 if (touching_nodes[0].Size > 0 && touching_nodes[1].Size > 0)
19297 child_0->Size[axis] = child_0->SizeRef[axis] = cur_size_0;
19298 child_1->Pos[axis] -= cur_size_1 - child_1->Size[axis];
19299 child_1->Size[axis] = child_1->SizeRef[axis] = cur_size_1;
19303 for (
int side_n = 0; side_n < 2; side_n++)
19304 for (
int touching_node_n = 0; touching_node_n < touching_nodes[side_n].Size; touching_node_n++)
19306 ImGuiDockNode* touching_node = touching_nodes[side_n][touching_node_n];
19309 while (touching_node->ParentNode != node)
19311 if (touching_node->ParentNode->SplitAxis == axis)
19314 ImGuiDockNode* node_to_preserve = touching_node->ParentNode->ChildNodes[side_n];
19315 node_to_preserve->WantLockSizeOnce =
true;
19319 touching_node = touching_node->ParentNode;
19323 DockNodeTreeUpdatePosSize(child_0, child_0->Pos, child_0->Size);
19324 DockNodeTreeUpdatePosSize(child_1, child_1->Pos, child_1->Size);
19325 MarkIniSettingsDirty();
19332 if (child_0->IsVisible)
19333 DockNodeTreeUpdateSplitter(child_0);
19334 if (child_1->IsVisible)
19335 DockNodeTreeUpdateSplitter(child_1);
19338ImGuiDockNode* ImGui::DockNodeTreeFindFallbackLeafNode(ImGuiDockNode* node)
19340 if (node->IsLeafNode())
19342 if (ImGuiDockNode* leaf_node = DockNodeTreeFindFallbackLeafNode(node->ChildNodes[0]))
19344 if (ImGuiDockNode* leaf_node = DockNodeTreeFindFallbackLeafNode(node->ChildNodes[1]))
19349ImGuiDockNode* ImGui::DockNodeTreeFindVisibleNodeByPos(ImGuiDockNode* node, ImVec2 pos)
19351 if (!node->IsVisible)
19354 const float dock_spacing = 0.0f;
19355 ImRect r(node->Pos, node->Pos + node->Size);
19356 r.Expand(dock_spacing * 0.5f);
19357 bool inside = r.Contains(pos);
19361 if (node->IsLeafNode())
19363 if (ImGuiDockNode* hovered_node = DockNodeTreeFindVisibleNodeByPos(node->ChildNodes[0], pos))
19364 return hovered_node;
19365 if (ImGuiDockNode* hovered_node = DockNodeTreeFindVisibleNodeByPos(node->ChildNodes[1], pos))
19366 return hovered_node;
19381void ImGui::SetWindowDock(ImGuiWindow* window, ImGuiID dock_id, ImGuiCond cond)
19384 if (cond && (window->SetWindowDockAllowFlags & cond) == 0)
19386 window->SetWindowDockAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
19388 if (window->DockId == dock_id)
19393 if (ImGuiDockNode* new_node = DockContextFindNodeByID(&
g, dock_id))
19394 if (new_node->IsSplitNode())
19397 new_node = DockNodeGetRootNode(new_node);
19398 if (new_node->CentralNode)
19400 IM_ASSERT(new_node->CentralNode->IsCentralNode());
19401 dock_id = new_node->CentralNode->ID;
19405 dock_id = new_node->LastFocusedNodeId;
19409 if (window->DockId == dock_id)
19412 if (window->DockNode)
19413 DockNodeRemoveWindow(window->DockNode, window, 0);
19414 window->DockId = dock_id;
19421ImGuiID ImGui::DockSpace(ImGuiID dockspace_id,
const ImVec2& size_arg, ImGuiDockNodeFlags flags,
const ImGuiWindowClass* window_class)
19424 ImGuiWindow* window = GetCurrentWindowRead();
19425 if (!(
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
19431 if (window->SkipItems)
19432 flags |= ImGuiDockNodeFlags_KeepAliveOnly;
19433 if ((flags & ImGuiDockNodeFlags_KeepAliveOnly) == 0)
19434 window = GetCurrentWindow();
19436 IM_ASSERT((flags & ImGuiDockNodeFlags_DockSpace) == 0);
19437 IM_ASSERT(dockspace_id != 0);
19438 ImGuiDockNode* node = DockContextFindNodeByID(&
g, dockspace_id);
19441 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockSpace: dockspace node 0x%08X created\n", dockspace_id);
19442 node = DockContextAddNode(&
g, dockspace_id);
19443 node->SetLocalFlags(ImGuiDockNodeFlags_CentralNode);
19445 if (window_class && window_class->ClassId != node->WindowClass.ClassId)
19446 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockSpace: dockspace node 0x%08X: setup WindowClass 0x%08X -> 0x%08X\n", dockspace_id, node->WindowClass.ClassId, window_class->ClassId);
19447 node->SharedFlags = flags;
19448 node->WindowClass = window_class ? *window_class : ImGuiWindowClass();
19452 if (node->LastFrameActive ==
g.FrameCount && !(flags & ImGuiDockNodeFlags_KeepAliveOnly))
19454 IM_ASSERT(node->IsDockSpace() ==
false &&
"Cannot call DockSpace() twice a frame with the same ID");
19455 node->SetLocalFlags(node->LocalFlags | ImGuiDockNodeFlags_DockSpace);
19456 return dockspace_id;
19458 node->SetLocalFlags(node->LocalFlags | ImGuiDockNodeFlags_DockSpace);
19461 if (flags & ImGuiDockNodeFlags_KeepAliveOnly)
19463 node->LastFrameAlive =
g.FrameCount;
19464 return dockspace_id;
19467 const ImVec2 content_avail = GetContentRegionAvail();
19468 ImVec2
size = ImTrunc(size_arg);
19469 if (
size.x <= 0.0f)
19470 size.x = ImMax(content_avail.x +
size.x, 4.0f);
19471 if (
size.y <= 0.0f)
19472 size.y = ImMax(content_avail.y +
size.y, 4.0f);
19473 IM_ASSERT(
size.x > 0.0f &&
size.y > 0.0f);
19475 node->Pos = window->DC.CursorPos;
19476 node->Size = node->SizeRef =
size;
19477 SetNextWindowPos(node->Pos);
19478 SetNextWindowSize(node->Size);
19479 g.NextWindowData.PosUndock =
false;
19483 ImGuiWindowFlags window_flags = ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_DockNodeHost;
19484 window_flags |= ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar;
19485 window_flags |= ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
19486 window_flags |= ImGuiWindowFlags_NoBackground;
19489 ImFormatString(title, IM_ARRAYSIZE(title),
"%s/DockSpace_%08X", window->Name, dockspace_id);
19491 PushStyleVar(ImGuiStyleVar_ChildBorderSize, 0.0f);
19492 Begin(title, NULL, window_flags);
19495 ImGuiWindow* host_window =
g.CurrentWindow;
19496 DockNodeSetupHostWindow(node, host_window);
19497 host_window->ChildId = window->GetID(title);
19498 node->OnlyNodeWithWindows = NULL;
19500 IM_ASSERT(node->IsRootNode());
19508 if (node->IsLeafNode() && !node->IsCentralNode())
19509 node->SetLocalFlags(node->LocalFlags | ImGuiDockNodeFlags_CentralNode);
19512 DockNodeUpdate(node);
19516 ImRect bb(node->Pos, node->Pos + size);
19518 ItemAdd(bb, dockspace_id, NULL, ImGuiItemFlags_NoNav);
19519 if ((
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && IsWindowChildOf(
g.HoveredWindow, host_window,
false,
true))
19520 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
19522 return dockspace_id;
19529ImGuiID ImGui::DockSpaceOverViewport(ImGuiID dockspace_id,
const ImGuiViewport* viewport, ImGuiDockNodeFlags dockspace_flags,
const ImGuiWindowClass* window_class)
19531 if (viewport == NULL)
19532 viewport = GetMainViewport();
19535 SetNextWindowPos(viewport->WorkPos);
19536 SetNextWindowSize(viewport->WorkSize);
19537 SetNextWindowViewport(viewport->ID);
19539 ImGuiWindowFlags host_window_flags = 0;
19540 host_window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking;
19541 host_window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
19542 if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
19543 host_window_flags |= ImGuiWindowFlags_NoBackground;
19546 ImFormatString(label, IM_ARRAYSIZE(label),
"WindowOverViewport_%08X", viewport->ID);
19548 PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
19549 PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
19550 PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
19551 Begin(label, NULL, host_window_flags);
19555 if (dockspace_id == 0)
19556 dockspace_id = GetID(
"DockSpace");
19557 DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags, window_class);
19561 return dockspace_id;
19587void ImGui::DockBuilderDockWindow(
const char* window_name, ImGuiID node_id)
19590 ImGuiContext&
g = *
GImGui; IM_UNUSED(
g);
19591 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderDockWindow '%s' to node 0x%08X\n", window_name, node_id);
19592 ImGuiID window_id =
ImHashStr(window_name);
19593 if (ImGuiWindow* window = FindWindowByID(window_id))
19596 ImGuiID prev_node_id = window->DockId;
19597 SetWindowDock(window, node_id, ImGuiCond_Always);
19598 if (window->DockId != prev_node_id)
19599 window->DockOrder = -1;
19604 ImGuiWindowSettings* settings = FindWindowSettingsByID(window_id);
19605 if (settings == NULL)
19606 settings = CreateNewWindowSettings(window_name);
19607 if (settings->DockId != node_id)
19608 settings->DockOrder = -1;
19609 settings->DockId = node_id;
19613ImGuiDockNode* ImGui::DockBuilderGetNode(ImGuiID node_id)
19616 return DockContextFindNodeByID(&
g, node_id);
19619void ImGui::DockBuilderSetNodePos(ImGuiID node_id, ImVec2 pos)
19622 ImGuiDockNode* node = DockContextFindNodeByID(&
g, node_id);
19626 node->AuthorityForPos = ImGuiDataAuthority_DockNode;
19629void ImGui::DockBuilderSetNodeSize(ImGuiID node_id, ImVec2 size)
19632 ImGuiDockNode* node = DockContextFindNodeByID(&
g, node_id);
19635 IM_ASSERT(
size.x > 0.0f &&
size.y > 0.0f);
19636 node->Size = node->SizeRef =
size;
19637 node->AuthorityForSize = ImGuiDataAuthority_DockNode;
19647ImGuiID ImGui::DockBuilderAddNode(ImGuiID node_id, ImGuiDockNodeFlags flags)
19649 ImGuiContext&
g = *
GImGui; IM_UNUSED(
g);
19650 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderAddNode 0x%08X flags=%08X\n", node_id, flags);
19653 DockBuilderRemoveNode(node_id);
19655 ImGuiDockNode* node = NULL;
19656 if (flags & ImGuiDockNodeFlags_DockSpace)
19658 DockSpace(node_id, ImVec2(0, 0), (flags & ~ImGuiDockNodeFlags_DockSpace) | ImGuiDockNodeFlags_KeepAliveOnly);
19659 node = DockContextFindNodeByID(&
g, node_id);
19663 node = DockContextAddNode(&
g, node_id);
19664 node->SetLocalFlags(flags);
19666 node->LastFrameAlive =
g.FrameCount;
19670void ImGui::DockBuilderRemoveNode(ImGuiID node_id)
19672 ImGuiContext&
g = *
GImGui; IM_UNUSED(
g);
19673 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderRemoveNode 0x%08X\n", node_id);
19675 ImGuiDockNode* node = DockContextFindNodeByID(&
g, node_id);
19678 DockBuilderRemoveNodeDockedWindows(node_id,
true);
19679 DockBuilderRemoveNodeChildNodes(node_id);
19681 node = DockContextFindNodeByID(&
g, node_id);
19684 if (node->IsCentralNode() && node->ParentNode)
19685 node->ParentNode->SetLocalFlags(node->ParentNode->LocalFlags | ImGuiDockNodeFlags_CentralNode);
19686 DockContextRemoveNode(&
g, node,
true);
19690void ImGui::DockBuilderRemoveNodeChildNodes(ImGuiID root_id)
19693 ImGuiDockContext* dc = &
g.DockContext;
19695 ImGuiDockNode* root_node = root_id ? DockContextFindNodeByID(&
g, root_id) : NULL;
19696 if (root_id && root_node == NULL)
19698 bool has_central_node =
false;
19700 ImGuiDataAuthority backup_root_node_authority_for_pos = root_node ? root_node->AuthorityForPos : ImGuiDataAuthority_Auto;
19701 ImGuiDataAuthority backup_root_node_authority_for_size = root_node ? root_node->AuthorityForSize : ImGuiDataAuthority_Auto;
19704 ImVector<ImGuiDockNode*> nodes_to_remove;
19705 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
19706 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
19708 bool want_removal = (root_id == 0) || (node->ID != root_id && DockNodeGetRootNode(node)->ID == root_id);
19711 if (node->IsCentralNode())
19712 has_central_node =
true;
19714 DockContextQueueNotifyRemovedNode(&
g, node);
19717 DockNodeMoveWindows(root_node, node);
19718 DockSettingsRenameNodeReferences(node->ID, root_node->ID);
19720 nodes_to_remove.push_back(node);
19728 root_node->AuthorityForPos = backup_root_node_authority_for_pos;
19729 root_node->AuthorityForSize = backup_root_node_authority_for_size;
19733 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
19734 if (ImGuiID window_settings_dock_id = settings->DockId)
19735 for (
int n = 0; n < nodes_to_remove.Size; n++)
19736 if (nodes_to_remove[n]->ID == window_settings_dock_id)
19738 settings->DockId = root_id;
19743 if (nodes_to_remove.Size > 1)
19744 ImQsort(nodes_to_remove.Data, nodes_to_remove.Size,
sizeof(ImGuiDockNode*), DockNodeComparerDepthMostFirst);
19745 for (
int n = 0; n < nodes_to_remove.Size; n++)
19746 DockContextRemoveNode(&
g, nodes_to_remove[n],
false);
19751 dc->Requests.clear();
19753 else if (has_central_node)
19755 root_node->CentralNode = root_node;
19756 root_node->SetLocalFlags(root_node->LocalFlags | ImGuiDockNodeFlags_CentralNode);
19760void ImGui::DockBuilderRemoveNodeDockedWindows(ImGuiID root_id,
bool clear_settings_refs)
19764 if (clear_settings_refs)
19766 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
19768 bool want_removal = (root_id == 0) || (settings->DockId == root_id);
19769 if (!want_removal && settings->DockId != 0)
19770 if (ImGuiDockNode* node = DockContextFindNodeByID(&
g, settings->DockId))
19771 if (DockNodeGetRootNode(node)->ID == root_id)
19772 want_removal =
true;
19774 settings->DockId = 0;
19779 for (
int n = 0; n <
g.Windows.Size; n++)
19781 ImGuiWindow* window =
g.Windows[n];
19782 bool want_removal = (root_id == 0) || (window->DockNode && DockNodeGetRootNode(window->DockNode)->ID == root_id) || (window->DockNodeAsHost && window->DockNodeAsHost->ID == root_id);
19785 const ImGuiID backup_dock_id = window->DockId;
19786 IM_UNUSED(backup_dock_id);
19787 DockContextProcessUndockWindow(&
g, window, clear_settings_refs);
19788 if (!clear_settings_refs)
19789 IM_ASSERT(window->DockId == backup_dock_id);
19797ImGuiID ImGui::DockBuilderSplitNode(ImGuiID
id, ImGuiDir split_dir,
float size_ratio_for_node_at_dir, ImGuiID* out_id_at_dir, ImGuiID* out_id_at_opposite_dir)
19800 IM_ASSERT(split_dir != ImGuiDir_None);
19801 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderSplitNode: node 0x%08X, split_dir %d\n",
id, split_dir);
19803 ImGuiDockNode* node = DockContextFindNodeByID(&
g,
id);
19806 IM_ASSERT(node != NULL);
19810 IM_ASSERT(!node->IsSplitNode());
19818 req.
DockSplitRatio = ImSaturate((split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up) ? size_ratio_for_node_at_dir : 1.0f - size_ratio_for_node_at_dir);
19820 DockContextProcessDock(&
g, &req);
19822 ImGuiID id_at_dir = node->ChildNodes[(split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up) ? 0 : 1]->
ID;
19823 ImGuiID id_at_opposite_dir = node->ChildNodes[(split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up) ? 1 : 0]->
ID;
19825 *out_id_at_dir = id_at_dir;
19826 if (out_id_at_opposite_dir)
19827 *out_id_at_opposite_dir = id_at_opposite_dir;
19831static ImGuiDockNode* DockBuilderCopyNodeRec(ImGuiDockNode* src_node, ImGuiID dst_node_id_if_known, ImVector<ImGuiID>* out_node_remap_pairs)
19834 ImGuiDockNode* dst_node = ImGui::DockContextAddNode(&
g, dst_node_id_if_known);
19835 dst_node->SharedFlags = src_node->SharedFlags;
19836 dst_node->LocalFlags = src_node->LocalFlags;
19837 dst_node->LocalFlagsInWindows = ImGuiDockNodeFlags_None;
19838 dst_node->Pos = src_node->Pos;
19839 dst_node->Size = src_node->Size;
19840 dst_node->SizeRef = src_node->SizeRef;
19841 dst_node->SplitAxis = src_node->SplitAxis;
19842 dst_node->UpdateMergedFlags();
19844 out_node_remap_pairs->push_back(src_node->ID);
19845 out_node_remap_pairs->push_back(dst_node->ID);
19847 for (
int child_n = 0; child_n < IM_ARRAYSIZE(src_node->ChildNodes); child_n++)
19848 if (src_node->ChildNodes[child_n])
19850 dst_node->ChildNodes[child_n] = DockBuilderCopyNodeRec(src_node->ChildNodes[child_n], 0, out_node_remap_pairs);
19851 dst_node->ChildNodes[child_n]->ParentNode = dst_node;
19854 IMGUI_DEBUG_LOG_DOCKING(
"[docking] Fork node %08X -> %08X (%d childs)\n", src_node->ID, dst_node->ID, dst_node->IsSplitNode() ? 2 : 0);
19858void ImGui::DockBuilderCopyNode(ImGuiID src_node_id, ImGuiID dst_node_id, ImVector<ImGuiID>* out_node_remap_pairs)
19861 IM_ASSERT(src_node_id != 0);
19862 IM_ASSERT(dst_node_id != 0);
19863 IM_ASSERT(out_node_remap_pairs != NULL);
19865 DockBuilderRemoveNode(dst_node_id);
19867 ImGuiDockNode* src_node = DockContextFindNodeByID(&
g, src_node_id);
19868 IM_ASSERT(src_node != NULL);
19870 out_node_remap_pairs->clear();
19871 DockBuilderCopyNodeRec(src_node, dst_node_id, out_node_remap_pairs);
19873 IM_ASSERT((out_node_remap_pairs->Size % 2) == 0);
19876void ImGui::DockBuilderCopyWindowSettings(
const char* src_name,
const char* dst_name)
19878 ImGuiWindow* src_window = FindWindowByName(src_name);
19879 if (src_window == NULL)
19881 if (ImGuiWindow* dst_window = FindWindowByName(dst_name))
19883 dst_window->Pos = src_window->Pos;
19884 dst_window->Size = src_window->Size;
19885 dst_window->SizeFull = src_window->SizeFull;
19886 dst_window->Collapsed = src_window->Collapsed;
19890 ImGuiWindowSettings* dst_settings = FindWindowSettingsByID(
ImHashStr(dst_name));
19892 dst_settings = CreateNewWindowSettings(dst_name);
19893 ImVec2ih window_pos_2ih = ImVec2ih(src_window->Pos);
19894 if (src_window->ViewportId != 0 && src_window->ViewportId != IMGUI_VIEWPORT_DEFAULT_ID)
19896 dst_settings->ViewportPos = window_pos_2ih;
19897 dst_settings->ViewportId = src_window->ViewportId;
19898 dst_settings->Pos = ImVec2ih(0, 0);
19902 dst_settings->Pos = window_pos_2ih;
19904 dst_settings->Size = ImVec2ih(src_window->SizeFull);
19905 dst_settings->Collapsed = src_window->Collapsed;
19910void ImGui::DockBuilderCopyDockSpace(ImGuiID src_dockspace_id, ImGuiID dst_dockspace_id, ImVector<const char*>* in_window_remap_pairs)
19913 IM_ASSERT(src_dockspace_id != 0);
19914 IM_ASSERT(dst_dockspace_id != 0);
19915 IM_ASSERT(in_window_remap_pairs != NULL);
19916 IM_ASSERT((in_window_remap_pairs->Size % 2) == 0);
19921 ImVector<ImGuiID> node_remap_pairs;
19922 DockBuilderCopyNode(src_dockspace_id, dst_dockspace_id, &node_remap_pairs);
19926 ImVector<ImGuiID> src_windows;
19927 for (
int remap_window_n = 0; remap_window_n < in_window_remap_pairs->Size; remap_window_n += 2)
19929 const char* src_window_name = (*in_window_remap_pairs)[remap_window_n];
19930 const char* dst_window_name = (*in_window_remap_pairs)[remap_window_n + 1];
19931 ImGuiID src_window_id =
ImHashStr(src_window_name);
19932 src_windows.push_back(src_window_id);
19935 ImGuiID src_dock_id = 0;
19936 if (ImGuiWindow* src_window = FindWindowByID(src_window_id))
19937 src_dock_id = src_window->DockId;
19938 else if (ImGuiWindowSettings* src_window_settings = FindWindowSettingsByID(src_window_id))
19939 src_dock_id = src_window_settings->DockId;
19940 ImGuiID dst_dock_id = 0;
19941 for (
int dock_remap_n = 0; dock_remap_n < node_remap_pairs.Size; dock_remap_n += 2)
19942 if (node_remap_pairs[dock_remap_n] == src_dock_id)
19944 dst_dock_id = node_remap_pairs[dock_remap_n + 1];
19949 if (dst_dock_id != 0)
19952 IMGUI_DEBUG_LOG_DOCKING(
"[docking] Remap live window '%s' 0x%08X -> '%s' 0x%08X\n", src_window_name, src_dock_id, dst_window_name, dst_dock_id);
19953 DockBuilderDockWindow(dst_window_name, dst_dock_id);
19959 IMGUI_DEBUG_LOG_DOCKING(
"[docking] Remap window settings '%s' -> '%s'\n", src_window_name, dst_window_name);
19960 DockBuilderCopyWindowSettings(src_window_name, dst_window_name);
19967 struct DockRemainingWindowTask { ImGuiWindow*
Window; ImGuiID DockId; DockRemainingWindowTask(ImGuiWindow* window, ImGuiID dock_id) {
Window = window; DockId = dock_id; } };
19968 ImVector<DockRemainingWindowTask> dock_remaining_windows;
19969 for (
int dock_remap_n = 0; dock_remap_n < node_remap_pairs.Size; dock_remap_n += 2)
19970 if (ImGuiID src_dock_id = node_remap_pairs[dock_remap_n])
19972 ImGuiID dst_dock_id = node_remap_pairs[dock_remap_n + 1];
19973 ImGuiDockNode* node = DockBuilderGetNode(src_dock_id);
19974 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
19976 ImGuiWindow* window = node->Windows[window_n];
19977 if (src_windows.contains(window->ID))
19981 IMGUI_DEBUG_LOG_DOCKING(
"[docking] Remap window '%s' %08X -> %08X\n", window->Name, src_dock_id, dst_dock_id);
19982 dock_remaining_windows.push_back(DockRemainingWindowTask(window, dst_dock_id));
19985 for (
const DockRemainingWindowTask& task : dock_remaining_windows)
19986 DockBuilderDockWindow(task.
Window->Name, task.DockId);
19990void ImGui::DockBuilderFinish(ImGuiID root_id)
19994 DockContextBuildAddWindowsToNodes(&
g, root_id);
20007bool ImGui::GetWindowAlwaysWantOwnTabBar(ImGuiWindow* window)
20010 if (
g.IO.ConfigDockingAlwaysTabBar || window->WindowClass.DockingAlwaysTabBar)
20011 if ((window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDocking)) == 0)
20012 if (!window->IsFallbackWindow)
20017static ImGuiDockNode* ImGui::DockContextBindNodeToWindow(ImGuiContext* ctx, ImGuiWindow* window)
20019 ImGuiContext&
g = *ctx;
20020 ImGuiDockNode* node = DockContextFindNodeByID(ctx, window->DockId);
20021 IM_ASSERT(window->DockNode == NULL);
20024 if (node && node->IsSplitNode())
20026 DockContextProcessUndockWindow(ctx, window);
20033 node = DockContextAddNode(ctx, window->DockId);
20034 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Window;
20035 node->LastFrameAlive =
g.FrameCount;
20042 if (!node->IsVisible)
20044 ImGuiDockNode* ancestor_node = node;
20045 while (!ancestor_node->IsVisible && ancestor_node->ParentNode)
20046 ancestor_node = ancestor_node->ParentNode;
20047 IM_ASSERT(ancestor_node->Size.x > 0.0f && ancestor_node->Size.y > 0.0f);
20048 DockNodeUpdateHasCentralNodeChild(DockNodeGetRootNode(ancestor_node));
20049 DockNodeTreeUpdatePosSize(ancestor_node, ancestor_node->Pos, ancestor_node->Size, node);
20053 bool node_was_visible = node->IsVisible;
20054 DockNodeAddWindow(node, window,
true);
20055 node->IsVisible = node_was_visible;
20056 IM_ASSERT(node == window->DockNode);
20060static void StoreDockStyleForWindow(ImGuiWindow* window)
20063 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
20064 window->DockStyle.Colors[color_n] = ImGui::ColorConvertFloat4ToU32(
g.Style.Colors[GWindowDockStyleColors[color_n]]);
20067void ImGui::BeginDocked(ImGuiWindow* window,
bool* p_open)
20072 window->DockIsActive = window->DockNodeIsVisible = window->DockTabIsVisible =
false;
20074 const bool auto_dock_node = GetWindowAlwaysWantOwnTabBar(window);
20075 if (auto_dock_node)
20077 if (window->DockId == 0)
20079 IM_ASSERT(window->DockNode == NULL);
20080 window->DockId = DockContextGenNodeID(&
g);
20086 bool want_undock =
false;
20087 want_undock |= (window->Flags & ImGuiWindowFlags_NoDocking) != 0;
20088 want_undock |= (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) && (window->SetWindowPosAllowFlags &
g.NextWindowData.PosCond) &&
g.NextWindowData.PosUndock;
20091 DockContextProcessUndockWindow(&
g, window);
20097 ImGuiDockNode* node = window->DockNode;
20099 IM_ASSERT(window->DockId == node->ID);
20100 if (window->DockId != 0 && node == NULL)
20102 node = DockContextBindNodeToWindow(&
g, window);
20109 if (node->IsCentralNode && (node->Flags & ImGuiDockNodeFlags_NoDockingInCentralNode))
20111 DockContextProcessUndockWindow(ctx, window);
20118 if (node->LastFrameAlive <
g.FrameCount)
20121 ImGuiDockNode* root_node = DockNodeGetRootNode(node);
20122 if (root_node->LastFrameAlive <
g.FrameCount)
20123 DockContextProcessUndockWindow(&
g, window);
20125 window->DockIsActive =
true;
20130 StoreDockStyleForWindow(window);
20135 if (node->HostWindow == NULL)
20137 if (node->State == ImGuiDockNodeState_HostWindowHiddenBecauseWindowsAreResizing)
20138 window->DockIsActive =
true;
20139 if (node->Windows.Size > 1 && window->Appearing)
20140 DockNodeHideWindowDuringHostWindowCreation(window);
20145 IM_ASSERT(node->HostWindow);
20146 IM_ASSERT(node->IsLeafNode());
20147 IM_ASSERT(node->Size.x >= 0.0f && node->Size.y >= 0.0f);
20148 node->State = ImGuiDockNodeState_HostWindowVisible;
20151 if (!(node->MergedFlags & ImGuiDockNodeFlags_KeepAliveOnly) && window->BeginOrderWithinContext < node->HostWindow->BeginOrderWithinContext)
20153 DockContextProcessUndockWindow(&
g, window);
20158 SetNextWindowPos(node->Pos);
20159 SetNextWindowSize(node->Size);
20160 g.NextWindowData.PosUndock =
false;
20161 window->DockIsActive =
true;
20162 window->DockNodeIsVisible =
true;
20163 window->DockTabIsVisible =
false;
20164 if (node->MergedFlags & ImGuiDockNodeFlags_KeepAliveOnly)
20168 if (node->VisibleWindow == window)
20169 window->DockTabIsVisible =
true;
20172 IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) == 0);
20173 window->Flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoResize;
20174 window->ChildFlags |= ImGuiChildFlags_AlwaysUseWindowPadding;
20175 if (node->IsHiddenTabBar() || node->IsNoTabBar())
20176 window->Flags |= ImGuiWindowFlags_NoTitleBar;
20178 window->Flags &= ~ImGuiWindowFlags_NoTitleBar;
20182 if (node->TabBar && window->WasActive)
20183 window->DockOrder = (short)DockNodeGetTabOrder(window);
20185 if ((node->WantCloseAll || node->WantCloseTabId == window->TabId) && p_open != NULL)
20189 ImGuiWindow* parent_window = window->DockNode->HostWindow;
20190 window->ChildId = parent_window->GetID(window->Name);
20193void ImGui::BeginDockableDragDropSource(ImGuiWindow* window)
20196 IM_ASSERT(
g.ActiveId == window->MoveId);
20197 IM_ASSERT(
g.MovingWindow == window);
20198 IM_ASSERT(
g.CurrentWindow == window);
20201 if (
g.IO.ConfigDockingWithShift !=
g.IO.KeyShift)
20206 IM_ASSERT(
g.NextWindowData.Flags == 0);
20207 if (
g.IO.ConfigDockingWithShift &&
g.MouseStationaryTimer >= 1.0f &&
g.ActiveId >= 1.0f)
20208 SetTooltip(
"%s", LocalizeGetMsg(ImGuiLocKey_DockingHoldShiftToDock));
20212 g.LastItemData.ID = window->MoveId;
20213 window = window->RootWindowDockTree;
20214 IM_ASSERT((window->Flags & ImGuiWindowFlags_NoDocking) == 0);
20215 bool is_drag_docking = (
g.IO.ConfigDockingWithShift) || ImRect(0, 0, window->SizeFull.x, GetFrameHeight()).Contains(
g.ActiveIdClickOffset);
20216 ImGuiDragDropFlags drag_drop_flags = ImGuiDragDropFlags_SourceNoPreviewTooltip | ImGuiDragDropFlags_SourceNoHoldToOpenOthers | ImGuiDragDropFlags_PayloadAutoExpire | ImGuiDragDropFlags_PayloadNoCrossContext | ImGuiDragDropFlags_PayloadNoCrossProcess;
20217 if (is_drag_docking && BeginDragDropSource(drag_drop_flags))
20219 SetDragDropPayload(IMGUI_PAYLOAD_TYPE_WINDOW, &window,
sizeof(window));
20220 EndDragDropSource();
20221 StoreDockStyleForWindow(window);
20225void ImGui::BeginDockableDragDropTarget(ImGuiWindow* window)
20230 IM_ASSERT((window->Flags & ImGuiWindowFlags_NoDocking) == 0);
20231 if (!
g.DragDropActive)
20234 if (!BeginDragDropTargetCustom(window->Rect(), window->ID))
20239 const ImGuiPayload* payload = &
g.DragDropPayload;
20240 if (!payload->IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) || !DockNodeIsDropAllowed(window, *(ImGuiWindow**)payload->Data))
20242 EndDragDropTarget();
20246 ImGuiWindow* payload_window = *(ImGuiWindow**)payload->Data;
20247 if (AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_WINDOW, ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect))
20251 bool dock_into_floating_window =
false;
20252 ImGuiDockNode* node = NULL;
20253 if (window->DockNodeAsHost)
20256 node = DockNodeTreeFindVisibleNodeByPos(window->DockNodeAsHost,
g.IO.MousePos);
20261 if (node && node->IsDockSpace() && node->IsRootNode())
20262 node = (node->CentralNode && node->IsLeafNode()) ? node->CentralNode : DockNodeTreeFindFallbackLeafNode(node);
20266 if (window->DockNode)
20267 node = window->DockNode;
20269 dock_into_floating_window =
true;
20272 const ImRect explicit_target_rect = (node && node->TabBar && !node->IsHiddenTabBar() && !node->IsNoTabBar()) ? node->TabBar->BarRect : ImRect(window->Pos, window->Pos + ImVec2(window->Size.x, GetFrameHeight()));
20273 const bool is_explicit_target =
g.IO.ConfigDockingWithShift || IsMouseHoveringRect(explicit_target_rect.Min, explicit_target_rect.Max);
20277 const bool do_preview = payload->IsPreview() || payload->IsDelivery();
20278 if (do_preview && (node != NULL || dock_into_floating_window))
20284 if (node && (node->ParentNode || node->IsCentralNode() || !node->IsLeafNode()))
20285 if (ImGuiDockNode* root_node = DockNodeGetRootNode(node))
20287 DockNodePreviewDockSetup(window, root_node, payload_window, NULL, &split_outer, is_explicit_target,
true);
20289 split_data = &split_outer;
20291 if (!node || node->IsLeafNode())
20292 DockNodePreviewDockSetup(window, node, payload_window, NULL, &split_inner, is_explicit_target,
false);
20293 if (split_data == &split_outer)
20297 DockNodePreviewDockRender(window, node, payload_window, &split_inner);
20298 DockNodePreviewDockRender(window, node, payload_window, &split_outer);
20302 DockContextQueueDock(&
g, window, split_data->
SplitNode, payload_window, split_data->
SplitDir, split_data->
SplitRatio, split_data == &split_outer);
20305 EndDragDropTarget();
20321static void ImGui::DockSettingsRenameNodeReferences(ImGuiID old_node_id, ImGuiID new_node_id)
20324 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockSettingsRenameNodeReferences: from 0x%08X -> to 0x%08X\n", old_node_id, new_node_id);
20325 for (
int window_n = 0; window_n <
g.Windows.Size; window_n++)
20327 ImGuiWindow* window =
g.Windows[window_n];
20328 if (window->DockId == old_node_id && window->DockNode == NULL)
20329 window->DockId = new_node_id;
20332 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
20333 if (settings->DockId == old_node_id)
20334 settings->DockId = new_node_id;
20338static void ImGui::DockSettingsRemoveNodeReferences(ImGuiID* node_ids,
int node_ids_count)
20343 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
20344 for (
int node_n = 0; node_n < node_ids_count; node_n++)
20345 if (settings->DockId == node_ids[node_n])
20347 settings->DockId = 0;
20348 settings->DockOrder = -1;
20349 if (++found < node_ids_count)
20358 ImGuiDockContext* dc = &ctx->DockContext;
20359 for (
int n = 0; n < dc->NodesSettings.Size; n++)
20360 if (dc->NodesSettings[n].ID ==
id)
20361 return &dc->NodesSettings[n];
20366static void ImGui::DockSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
20368 ImGuiDockContext* dc = &ctx->DockContext;
20369 dc->NodesSettings.clear();
20370 DockContextClearNodes(ctx, 0,
true);
20374static void ImGui::DockSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
20377 ImGuiDockContext* dc = &ctx->DockContext;
20378 if (ctx->Windows.Size == 0)
20379 DockContextPruneUnusedSettingsNodes(ctx);
20380 DockContextBuildNodesFromSettings(ctx, dc->NodesSettings.Data, dc->NodesSettings.Size);
20381 DockContextBuildAddWindowsToNodes(ctx, 0);
20384static void* ImGui::DockSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*,
const char* name)
20386 if (strcmp(name,
"Data") != 0)
20391static void ImGui::DockSettingsHandler_ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler*,
void*,
const char* line)
20403 if (strncmp(line,
"DockNode", 8) == 0) { line =
ImStrSkipBlank(line + strlen(
"DockNode")); }
20404 else if (strncmp(line,
"DockSpace", 9) == 0) { line =
ImStrSkipBlank(line + strlen(
"DockSpace")); node.
Flags |= ImGuiDockNodeFlags_DockSpace; }
20406 if (sscanf(line,
"ID=0x%08X%n", &node.
ID, &r) == 1) { line += r; }
else return;
20407 if (sscanf(line,
" Parent=0x%08X%n", &node.
ParentNodeId, &r) == 1) { line += r;
if (node.
ParentNodeId == 0)
return; }
20411 if (sscanf(line,
" Pos=%i,%i%n", &x, &y, &r) == 2) { line += r; node.
Pos = ImVec2ih((
short)x, (
short)y); }
else return;
20412 if (sscanf(line,
" Size=%i,%i%n", &x, &y, &r) == 2) { line += r; node.
Size = ImVec2ih((
short)x, (
short)y); }
else return;
20416 if (sscanf(line,
" SizeRef=%i,%i%n", &x, &y, &r) == 2) { line += r; node.
SizeRef = ImVec2ih((
short)x, (
short)y); }
20418 if (sscanf(line,
" Split=%c%n", &c, &r) == 1) { line += r;
if (c ==
'X') node.
SplitAxis = ImGuiAxis_X;
else if (c ==
'Y') node.
SplitAxis = ImGuiAxis_Y; }
20419 if (sscanf(line,
" NoResize=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_NoResize; }
20420 if (sscanf(line,
" CentralNode=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_CentralNode; }
20421 if (sscanf(line,
" NoTabBar=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_NoTabBar; }
20422 if (sscanf(line,
" HiddenTabBar=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_HiddenTabBar; }
20423 if (sscanf(line,
" NoWindowMenuButton=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_NoWindowMenuButton; }
20424 if (sscanf(line,
" NoCloseButton=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_NoCloseButton; }
20425 if (sscanf(line,
" Selected=0x%08X%n", &node.
SelectedTabId,&r) == 1) { line += r; }
20428 node.
Depth = parent_settings->Depth + 1;
20429 ctx->DockContext.NodesSettings.push_back(node);
20432static void DockSettingsHandler_DockNodeToSettings(ImGuiDockContext* dc, ImGuiDockNode* node,
int depth)
20435 IM_ASSERT(depth < (1 << (
sizeof(node_settings.
Depth) << 3)));
20436 node_settings.
ID = node->ID;
20437 node_settings.
ParentNodeId = node->ParentNode ? node->ParentNode->ID : 0;
20438 node_settings.
ParentWindowId = (node->IsDockSpace() && node->HostWindow && node->HostWindow->ParentWindow) ? node->HostWindow->ParentWindow->ID : 0;
20440 node_settings.
SplitAxis = (
signed char)(node->IsSplitNode() ? node->SplitAxis : ImGuiAxis_None);
20441 node_settings.
Depth = (char)depth;
20442 node_settings.
Flags = (node->LocalFlags & ImGuiDockNodeFlags_SavedFlagsMask_);
20443 node_settings.
Pos = ImVec2ih(node->Pos);
20444 node_settings.
Size = ImVec2ih(node->Size);
20445 node_settings.
SizeRef = ImVec2ih(node->SizeRef);
20446 dc->NodesSettings.push_back(node_settings);
20447 if (node->ChildNodes[0])
20448 DockSettingsHandler_DockNodeToSettings(dc, node->ChildNodes[0], depth + 1);
20449 if (node->ChildNodes[1])
20450 DockSettingsHandler_DockNodeToSettings(dc, node->ChildNodes[1], depth + 1);
20453static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
20455 ImGuiContext&
g = *ctx;
20456 ImGuiDockContext* dc = &ctx->DockContext;
20457 if (!(
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
20462 dc->NodesSettings.resize(0);
20463 dc->NodesSettings.reserve(dc->Nodes.Data.Size);
20464 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
20465 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
20466 if (node->IsRootNode())
20467 DockSettingsHandler_DockNodeToSettings(dc, node, 0);
20470 for (
int node_n = 0; node_n < dc->NodesSettings.Size; node_n++)
20471 max_depth = ImMax((
int)dc->NodesSettings[node_n].Depth, max_depth);
20474 buf->appendf(
"[%s][Data]\n", handler->TypeName);
20475 for (
int node_n = 0; node_n < dc->NodesSettings.Size; node_n++)
20477 const int line_start_pos = buf->size(); (void)line_start_pos;
20479 buf->appendf(
"%*s%s%*s", node_settings->
Depth * 2,
"", (node_settings->
Flags & ImGuiDockNodeFlags_DockSpace) ?
"DockSpace" :
"DockNode ", (max_depth - node_settings->
Depth) * 2,
"");
20480 buf->appendf(
" ID=0x%08X", node_settings->
ID);
20483 buf->appendf(
" Parent=0x%08X SizeRef=%d,%d", node_settings->
ParentNodeId, node_settings->
SizeRef.x, node_settings->
SizeRef.y);
20489 buf->appendf(
" Pos=%d,%d Size=%d,%d", node_settings->
Pos.x, node_settings->
Pos.y, node_settings->
Size.x, node_settings->
Size.y);
20491 if (node_settings->
SplitAxis != ImGuiAxis_None)
20492 buf->appendf(
" Split=%c", (node_settings->
SplitAxis == ImGuiAxis_X) ?
'X' :
'Y');
20493 if (node_settings->
Flags & ImGuiDockNodeFlags_NoResize)
20494 buf->appendf(
" NoResize=1");
20495 if (node_settings->
Flags & ImGuiDockNodeFlags_CentralNode)
20496 buf->appendf(
" CentralNode=1");
20497 if (node_settings->
Flags & ImGuiDockNodeFlags_NoTabBar)
20498 buf->appendf(
" NoTabBar=1");
20499 if (node_settings->
Flags & ImGuiDockNodeFlags_HiddenTabBar)
20500 buf->appendf(
" HiddenTabBar=1");
20501 if (node_settings->
Flags & ImGuiDockNodeFlags_NoWindowMenuButton)
20502 buf->appendf(
" NoWindowMenuButton=1");
20503 if (node_settings->
Flags & ImGuiDockNodeFlags_NoCloseButton)
20504 buf->appendf(
" NoCloseButton=1");
20506 buf->appendf(
" Selected=0x%08X", node_settings->
SelectedTabId);
20509 if (
g.IO.ConfigDebugIniSettings)
20510 if (ImGuiDockNode* node = DockContextFindNodeByID(ctx, node_settings->
ID))
20512 buf->appendf(
"%*s", ImMax(2, (line_start_pos + 92) - buf->size()),
"");
20513 if (node->IsDockSpace() && node->HostWindow && node->HostWindow->ParentWindow)
20514 buf->appendf(
" ; in '%s'", node->HostWindow->ParentWindow->Name);
20516 int contains_window = 0;
20517 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
20518 if (settings->DockId == node_settings->
ID)
20520 if (contains_window++ == 0)
20521 buf->appendf(
" ; contains ");
20522 buf->appendf(
"'%s' ", settings->GetName());
20526 buf->appendf(
"\n");
20528 buf->appendf(
"\n");
20540#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS)
20543#pragma comment(lib, "user32")
20544#pragma comment(lib, "kernel32")
20549static const char* Platform_GetClipboardTextFn_DefaultImpl(ImGuiContext* ctx)
20551 ImGuiContext&
g = *ctx;
20552 g.ClipboardHandlerData.clear();
20553 if (!::OpenClipboard(NULL))
20555 HANDLE wbuf_handle = ::GetClipboardData(CF_UNICODETEXT);
20556 if (wbuf_handle == NULL)
20558 ::CloseClipboard();
20561 if (
const WCHAR* wbuf_global = (
const WCHAR*)::GlobalLock(wbuf_handle))
20563 int buf_len = ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, NULL, 0, NULL, NULL);
20564 g.ClipboardHandlerData.resize(buf_len);
20565 ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1,
g.ClipboardHandlerData.Data, buf_len, NULL, NULL);
20567 ::GlobalUnlock(wbuf_handle);
20568 ::CloseClipboard();
20569 return g.ClipboardHandlerData.Data;
20572static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext*,
const char* text)
20574 if (!::OpenClipboard(NULL))
20576 const int wbuf_length = ::MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
20577 HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length *
sizeof(WCHAR));
20578 if (wbuf_handle == NULL)
20580 ::CloseClipboard();
20583 WCHAR* wbuf_global = (WCHAR*)::GlobalLock(wbuf_handle);
20584 ::MultiByteToWideChar(CP_UTF8, 0, text, -1, wbuf_global, wbuf_length);
20585 ::GlobalUnlock(wbuf_handle);
20586 ::EmptyClipboard();
20587 if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL)
20588 ::GlobalFree(wbuf_handle);
20589 ::CloseClipboard();
20592#elif defined(__APPLE__) && TARGET_OS_OSX && defined(IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS)
20594#include <Carbon/Carbon.h>
20595static PasteboardRef main_clipboard = 0;
20599static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext*,
const char* text)
20601 if (!main_clipboard)
20602 PasteboardCreate(kPasteboardClipboard, &main_clipboard);
20603 PasteboardClear(main_clipboard);
20604 CFDataRef cf_data = CFDataCreate(kCFAllocatorDefault, (
const UInt8*)text, strlen(text));
20607 PasteboardPutItemFlavor(main_clipboard, (PasteboardItemID)1, CFSTR(
"public.utf8-plain-text"), cf_data, 0);
20608 CFRelease(cf_data);
20612static const char* Platform_GetClipboardTextFn_DefaultImpl(ImGuiContext* ctx)
20614 ImGuiContext&
g = *ctx;
20615 if (!main_clipboard)
20616 PasteboardCreate(kPasteboardClipboard, &main_clipboard);
20617 PasteboardSynchronize(main_clipboard);
20619 ItemCount item_count = 0;
20620 PasteboardGetItemCount(main_clipboard, &item_count);
20621 for (ItemCount i = 0; i < item_count; i++)
20623 PasteboardItemID item_id = 0;
20624 PasteboardGetItemIdentifier(main_clipboard, i + 1, &item_id);
20625 CFArrayRef flavor_type_array = 0;
20626 PasteboardCopyItemFlavors(main_clipboard, item_id, &flavor_type_array);
20627 for (CFIndex j = 0, nj = CFArrayGetCount(flavor_type_array); j < nj; j++)
20630 if (PasteboardCopyItemFlavorData(main_clipboard, item_id, CFSTR(
"public.utf8-plain-text"), &cf_data) == noErr)
20632 g.ClipboardHandlerData.clear();
20633 int length = (int)CFDataGetLength(cf_data);
20634 g.ClipboardHandlerData.resize(length + 1);
20635 CFDataGetBytes(cf_data, CFRangeMake(0, length), (UInt8*)
g.ClipboardHandlerData.Data);
20636 g.ClipboardHandlerData[
length] = 0;
20637 CFRelease(cf_data);
20638 return g.ClipboardHandlerData.Data;
20648static const char* Platform_GetClipboardTextFn_DefaultImpl(ImGuiContext* ctx)
20650 ImGuiContext&
g = *ctx;
20651 return g.ClipboardHandlerData.empty() ? NULL :
g.ClipboardHandlerData.begin();
20654static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext* ctx,
const char* text)
20656 ImGuiContext&
g = *ctx;
20657 g.ClipboardHandlerData.clear();
20658 const char* text_end = text + strlen(text);
20659 g.ClipboardHandlerData.resize((
int)(text_end - text) + 1);
20660 memcpy(&
g.ClipboardHandlerData[0], text, (
size_t)(text_end - text));
20661 g.ClipboardHandlerData[(int)(text_end - text)] = 0;
20668#ifndef IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
20669#if defined(__APPLE__) && TARGET_OS_IPHONE
20670#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
20673#if defined(_WIN32) && defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
20674#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
20678#ifndef IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
20680#include <shellapi.h>
20682#pragma comment(lib, "shell32")
20684static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext*,
const char* path)
20686 return (INT_PTR)::ShellExecuteA(NULL,
"open", path, NULL, NULL, SW_SHOWDEFAULT) > 32;
20689#include <sys/wait.h>
20691static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext*,
const char* path)
20693#if defined(__APPLE__)
20694 const char* args[] {
"open",
"--", path, NULL };
20696 const char* args[] {
"xdg-open", path, NULL };
20698 pid_t pid = fork();
20703 execvp(args[0],
const_cast<char **
>(args));
20709 waitpid(pid, &status, 0);
20710 return WEXITSTATUS(status) == 0;
20715static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext*,
const char*) {
return false; }
20721#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
20725#pragma comment(lib, "imm32")
20728static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport* viewport, ImGuiPlatformImeData* data)
20731 HWND hwnd = (HWND)viewport->PlatformHandleRaw;
20736 if (HIMC himc = ::ImmGetContext(hwnd))
20738 COMPOSITIONFORM composition_form = {};
20739 composition_form.ptCurrentPos.x = (LONG)(data->InputPos.x - viewport->Pos.x);
20740 composition_form.ptCurrentPos.y = (LONG)(data->InputPos.y - viewport->Pos.y);
20741 composition_form.dwStyle = CFS_FORCE_POSITION;
20742 ::ImmSetCompositionWindow(himc, &composition_form);
20743 CANDIDATEFORM candidate_form = {};
20744 candidate_form.dwStyle = CFS_CANDIDATEPOS;
20745 candidate_form.ptCurrentPos.x = (LONG)(data->InputPos.x - viewport->Pos.x);
20746 candidate_form.ptCurrentPos.y = (LONG)(data->InputPos.y - viewport->Pos.y);
20747 ::ImmSetCandidateWindow(himc, &candidate_form);
20748 ::ImmReleaseContext(hwnd, himc);
20754static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport*, ImGuiPlatformImeData*) {}
20782#ifndef IMGUI_DISABLE_DEBUG_TOOLS
20784void ImGui::DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport,
const ImRect& bb)
20787 ImGuiWindow* window =
g.CurrentWindow;
20789 ImVec2
scale = bb.GetSize() / viewport->Size;
20790 ImVec2 off = bb.Min - viewport->Pos *
scale;
20791 float alpha_mul = (viewport->Flags & ImGuiViewportFlags_IsMinimized) ? 0.30f : 1.00f;
20792 window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul * 0.40f));
20793 for (ImGuiWindow* thumb_window :
g.Windows)
20795 if (!thumb_window->WasActive || (thumb_window->Flags & ImGuiWindowFlags_ChildWindow))
20797 if (thumb_window->Viewport != viewport)
20800 ImRect thumb_r = thumb_window->Rect();
20801 ImRect title_r = thumb_window->TitleBarRect();
20802 thumb_r = ImRect(ImTrunc(off + thumb_r.Min * scale), ImTrunc(off + thumb_r.Max * scale));
20803 title_r = ImRect(ImTrunc(off + title_r.Min * scale), ImTrunc(off + ImVec2(title_r.Max.x, title_r.Min.y + title_r.GetHeight() * 3.0f) * scale));
20804 thumb_r.ClipWithFull(bb);
20805 title_r.ClipWithFull(bb);
20806 const bool window_is_focused = (
g.NavWindow && thumb_window->RootWindowForTitleBarHighlight ==
g.NavWindow->RootWindowForTitleBarHighlight);
20807 window->DrawList->AddRectFilled(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_WindowBg, alpha_mul));
20808 window->DrawList->AddRectFilled(title_r.Min, title_r.Max, GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg, alpha_mul));
20809 window->DrawList->AddRect(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_Border, alpha_mul));
20810 window->DrawList->AddText(
g.Font,
g.FontSize * 1.0f, title_r.Min, GetColorU32(ImGuiCol_Text, alpha_mul), thumb_window->Name, FindRenderedTextEnd(thumb_window->Name));
20812 draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul));
20813 if (viewport->ID ==
g.DebugMetricsConfig.HighlightViewportID)
20814 window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
20817static void RenderViewportsThumbnails()
20820 ImGuiWindow* window =
g.CurrentWindow;
20823 float SCALE = 1.0f / 8.0f;
20824 ImRect bb_full(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
20825 for (ImGuiPlatformMonitor& monitor :
g.PlatformIO.Monitors)
20826 bb_full.Add(ImRect(monitor.MainPos, monitor.MainPos + monitor.MainSize));
20827 ImVec2 p = window->DC.CursorPos;
20828 ImVec2 off = p - bb_full.Min * SCALE;
20829 for (ImGuiPlatformMonitor& monitor :
g.PlatformIO.Monitors)
20831 ImRect monitor_draw_bb(off + (monitor.MainPos) * SCALE, off + (monitor.MainPos + monitor.MainSize) * SCALE);
20832 window->DrawList->AddRect(monitor_draw_bb.Min, monitor_draw_bb.Max, (
g.DebugMetricsConfig.HighlightMonitorIdx ==
g.PlatformIO.Monitors.index_from_ptr(&monitor)) ? IM_COL32(255, 255, 0, 255) :
ImGui::GetColorU32(ImGuiCol_Border), 4.0f);
20833 window->DrawList->AddRectFilled(monitor_draw_bb.Min, monitor_draw_bb.Max, ImGui::GetColorU32(ImGuiCol_Border, 0.10f), 4.0f);
20837 for (ImGuiViewportP* viewport :
g.Viewports)
20839 ImRect viewport_draw_bb(off + (viewport->Pos) * SCALE, off + (viewport->Pos + viewport->Size) * SCALE);
20840 ImGui::DebugRenderViewportThumbnail(window->DrawList, viewport, viewport_draw_bb);
20842 ImGui::Dummy(bb_full.GetSize() * SCALE);
20845static int IMGUI_CDECL ViewportComparerByLastFocusedStampCount(
const void* lhs,
const void* rhs)
20847 const ImGuiViewportP* a = *(
const ImGuiViewportP*
const*)lhs;
20848 const ImGuiViewportP* b = *(
const ImGuiViewportP*
const*)rhs;
20849 return b->LastFocusedStampCount - a->LastFocusedStampCount;
20853void ImGui::DebugRenderKeyboardPreview(ImDrawList* draw_list)
20855 const float scale = ImGui::GetFontSize() / 13.0f;
20856 const ImVec2 key_size = ImVec2(35.0f, 35.0f) *
scale;
20857 const float key_rounding = 3.0f *
scale;
20858 const ImVec2 key_face_size = ImVec2(25.0f, 25.0f) *
scale;
20859 const ImVec2 key_face_pos = ImVec2(5.0f, 3.0f) *
scale;
20860 const float key_face_rounding = 2.0f *
scale;
20861 const ImVec2 key_label_pos = ImVec2(7.0f, 4.0f) *
scale;
20862 const ImVec2 key_step = ImVec2(key_size.x - 1.0f, key_size.y - 1.0f);
20863 const float key_row_offset = 9.0f *
scale;
20865 ImVec2 board_min = GetCursorScreenPos();
20866 ImVec2 board_max = ImVec2(board_min.x + 3 * key_step.x + 2 * key_row_offset + 10.0f, board_min.y + 3 * key_step.y + 10.0f);
20867 ImVec2 start_pos = ImVec2(board_min.x + 5.0f - key_step.x, board_min.y);
20869 struct KeyLayoutData {
int Row, Col;
const char* Label; ImGuiKey Key; };
20870 const KeyLayoutData keys_to_display[] =
20872 { 0, 0,
"", ImGuiKey_Tab }, { 0, 1,
"Q", ImGuiKey_Q }, { 0, 2,
"W", ImGuiKey_W }, { 0, 3,
"E", ImGuiKey_E }, { 0, 4,
"R", ImGuiKey_R },
20873 { 1, 0,
"", ImGuiKey_CapsLock }, { 1, 1,
"A", ImGuiKey_A }, { 1, 2,
"S", ImGuiKey_S }, { 1, 3,
"D", ImGuiKey_D }, { 1, 4,
"F", ImGuiKey_F },
20874 { 2, 0,
"", ImGuiKey_LeftShift },{ 2, 1,
"Z", ImGuiKey_Z }, { 2, 2,
"X", ImGuiKey_X }, { 2, 3,
"C", ImGuiKey_C }, { 2, 4,
"V", ImGuiKey_V }
20879 Dummy(board_max - board_min);
20880 if (!IsItemVisible())
20882 draw_list->PushClipRect(board_min, board_max,
true);
20883 for (
int n = 0; n < IM_ARRAYSIZE(keys_to_display); n++)
20885 const KeyLayoutData* key_data = &keys_to_display[n];
20886 ImVec2 key_min = ImVec2(start_pos.x + key_data->Col * key_step.x + key_data->Row * key_row_offset, start_pos.y + key_data->Row * key_step.y);
20887 ImVec2 key_max = key_min + key_size;
20888 draw_list->AddRectFilled(key_min, key_max, IM_COL32(204, 204, 204, 255), key_rounding);
20889 draw_list->AddRect(key_min, key_max, IM_COL32(24, 24, 24, 255), key_rounding);
20890 ImVec2 face_min = ImVec2(key_min.x + key_face_pos.x, key_min.y + key_face_pos.y);
20891 ImVec2 face_max = ImVec2(face_min.x + key_face_size.x, face_min.y + key_face_size.y);
20892 draw_list->AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, ImDrawFlags_None, 2.0f);
20893 draw_list->AddRectFilled(face_min, face_max, IM_COL32(252, 252, 252, 255), key_face_rounding);
20894 ImVec2 label_min = ImVec2(key_min.x + key_label_pos.x, key_min.y + key_label_pos.y);
20895 draw_list->AddText(label_min, IM_COL32(64, 64, 64, 255), key_data->Label);
20896 if (IsKeyDown(key_data->Key))
20897 draw_list->AddRectFilled(key_min, key_max, IM_COL32(255, 0, 0, 128), key_rounding);
20899 draw_list->PopClipRect();
20903void ImGui::DebugTextEncoding(
const char* str)
20905 Text(
"Text: \"%s\"", str);
20906 if (!BeginTable(
"##DebugTextEncoding", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable))
20908 TableSetupColumn(
"Offset");
20909 TableSetupColumn(
"UTF-8");
20910 TableSetupColumn(
"Glyph");
20911 TableSetupColumn(
"Codepoint");
20913 for (
const char* p = str; *p != 0; )
20918 Text(
"%d", (
int)(p - str));
20920 for (
int byte_index = 0; byte_index < c_utf8_len; byte_index++)
20922 if (byte_index > 0)
20924 Text(
"0x%02X", (
int)(
unsigned char)p[byte_index]);
20927 if (GetFont()->FindGlyphNoFallback((ImWchar)c))
20930 TextUnformatted((c == IM_UNICODE_CODEPOINT_INVALID) ?
"[invalid]" :
"[missing]");
20932 Text(
"U+%04X", (
int)c);
20938static void DebugFlashStyleColorStop()
20941 if (
g.DebugFlashStyleColorIdx != ImGuiCol_COUNT)
20942 g.Style.Colors[
g.DebugFlashStyleColorIdx] =
g.DebugFlashStyleColorBackup;
20943 g.DebugFlashStyleColorIdx = ImGuiCol_COUNT;
20947void ImGui::DebugFlashStyleColor(ImGuiCol idx)
20950 DebugFlashStyleColorStop();
20951 g.DebugFlashStyleColorTime = 0.5f;
20952 g.DebugFlashStyleColorIdx = idx;
20953 g.DebugFlashStyleColorBackup =
g.Style.Colors[idx];
20956void ImGui::UpdateDebugToolFlashStyleColor()
20959 if (
g.DebugFlashStyleColorTime <= 0.0f)
20961 ColorConvertHSVtoRGB(ImCos(
g.DebugFlashStyleColorTime * 6.0f) * 0.5f + 0.5f, 0.5f, 0.5f,
g.Style.Colors[
g.DebugFlashStyleColorIdx].x,
g.Style.Colors[
g.DebugFlashStyleColorIdx].y,
g.Style.Colors[
g.DebugFlashStyleColorIdx].z);
20962 g.Style.Colors[
g.DebugFlashStyleColorIdx].w = 1.0f;
20963 if ((
g.DebugFlashStyleColorTime -=
g.IO.DeltaTime) <= 0.0f)
20964 DebugFlashStyleColorStop();
20968static void MetricsHelpMarker(
const char* desc)
20970 ImGui::TextDisabled(
"(?)");
20971 if (ImGui::BeginItemTooltip())
20973 ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
20975 ImGui::PopTextWrapPos();
20976 ImGui::EndTooltip();
20983 for (ImFont* font : atlas->Fonts)
20986 DebugNodeFont(font);
20989 if (TreeNode(
"Font Atlas",
"Font Atlas (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
20992 ImGuiMetricsConfig* cfg = &
g.DebugMetricsConfig;
20993 Checkbox(
"Tint with Text Color", &cfg->ShowAtlasTintedWithTextColor);
20994 ImVec4 tint_col = cfg->ShowAtlasTintedWithTextColor ? GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
20995 ImVec4 border_col = GetStyleColorVec4(ImGuiCol_Border);
20996 Image(atlas->TexID, ImVec2((
float)atlas->TexWidth, (
float)atlas->TexHeight), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), tint_col, border_col);
21001void ImGui::ShowMetricsWindow(
bool* p_open)
21004 ImGuiIO& io =
g.IO;
21005 ImGuiMetricsConfig* cfg = &
g.DebugMetricsConfig;
21006 if (cfg->ShowDebugLog)
21007 ShowDebugLogWindow(&cfg->ShowDebugLog);
21008 if (cfg->ShowIDStackTool)
21009 ShowIDStackToolWindow(&cfg->ShowIDStackTool);
21011 if (!Begin(
"Dear ImGui Metrics/Debugger", p_open) || GetCurrentWindow()->BeginCount > 1)
21018 DebugBreakClearData();
21021 Text(
"Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
21022 if (
g.ContextName[0] != 0)
21025 Text(
"(Context Name: \"%s\")",
g.ContextName);
21027 Text(
"Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
21028 Text(
"%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3);
21029 Text(
"%d visible windows, %d current allocations", io.MetricsRenderWindows,
g.DebugAllocInfo.TotalAllocCount -
g.DebugAllocInfo.TotalFreeCount);
21035 enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentIdeal, WRT_ContentRegionRect, WRT_Count };
21036 const char* wrt_rects_names[WRT_Count] = {
"OuterRect",
"OuterRectClipped",
"InnerRect",
"InnerClipRect",
"WorkRect",
"Content",
"ContentIdeal",
"ContentRegionRect" };
21037 enum { TRT_OuterRect, TRT_InnerRect, TRT_WorkRect, TRT_HostClipRect, TRT_InnerClipRect, TRT_BackgroundClipRect, TRT_ColumnsRect, TRT_ColumnsWorkRect, TRT_ColumnsClipRect, TRT_ColumnsContentHeadersUsed, TRT_ColumnsContentHeadersIdeal, TRT_ColumnsContentFrozen, TRT_ColumnsContentUnfrozen, TRT_Count };
21038 const char* trt_rects_names[TRT_Count] = {
"OuterRect",
"InnerRect",
"WorkRect",
"HostClipRect",
"InnerClipRect",
"BackgroundClipRect",
"ColumnsRect",
"ColumnsWorkRect",
"ColumnsClipRect",
"ColumnsContentHeadersUsed",
"ColumnsContentHeadersIdeal",
"ColumnsContentFrozen",
"ColumnsContentUnfrozen" };
21039 if (cfg->ShowWindowsRectsType < 0)
21040 cfg->ShowWindowsRectsType = WRT_WorkRect;
21041 if (cfg->ShowTablesRectsType < 0)
21042 cfg->ShowTablesRectsType = TRT_WorkRect;
21046 static ImRect GetTableRect(ImGuiTable* table,
int rect_type,
int n)
21048 ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
21049 if (rect_type == TRT_OuterRect) {
return table->OuterRect; }
21050 else if (rect_type == TRT_InnerRect) {
return table->InnerRect; }
21051 else if (rect_type == TRT_WorkRect) {
return table->WorkRect; }
21052 else if (rect_type == TRT_HostClipRect) {
return table->HostClipRect; }
21053 else if (rect_type == TRT_InnerClipRect) {
return table->InnerClipRect; }
21054 else if (rect_type == TRT_BackgroundClipRect) {
return table->BgClipRect; }
21055 else if (rect_type == TRT_ColumnsRect) { ImGuiTableColumn* c = &table->Columns[n];
return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MaxX, table->InnerClipRect.Min.y + table_instance->LastOuterHeight); }
21056 else if (rect_type == TRT_ColumnsWorkRect) { ImGuiTableColumn* c = &table->Columns[n];
return ImRect(c->WorkMinX, table->WorkRect.Min.y, c->WorkMaxX, table->WorkRect.Max.y); }
21057 else if (rect_type == TRT_ColumnsClipRect) { ImGuiTableColumn* c = &table->Columns[n];
return c->ClipRect; }
21058 else if (rect_type == TRT_ColumnsContentHeadersUsed){ ImGuiTableColumn* c = &table->Columns[n];
return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersUsed, table->InnerClipRect.Min.y + table_instance->LastTopHeadersRowHeight); }
21059 else if (rect_type == TRT_ColumnsContentHeadersIdeal){ImGuiTableColumn* c = &table->Columns[n];
return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersIdeal, table->InnerClipRect.Min.y + table_instance->LastTopHeadersRowHeight); }
21060 else if (rect_type == TRT_ColumnsContentFrozen) { ImGuiTableColumn* c = &table->Columns[n];
return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXFrozen, table->InnerClipRect.Min.y + table_instance->LastFrozenHeight); }
21061 else if (rect_type == TRT_ColumnsContentUnfrozen) { ImGuiTableColumn* c = &table->Columns[n];
return ImRect(c->WorkMinX, table->InnerClipRect.Min.y + table_instance->LastFrozenHeight, c->ContentMaxXUnfrozen, table->InnerClipRect.Max.y); }
21066 static ImRect GetWindowRect(ImGuiWindow* window,
int rect_type)
21068 if (rect_type == WRT_OuterRect) {
return window->Rect(); }
21069 else if (rect_type == WRT_OuterRectClipped) {
return window->OuterRectClipped; }
21070 else if (rect_type == WRT_InnerRect) {
return window->InnerRect; }
21071 else if (rect_type == WRT_InnerClipRect) {
return window->InnerClipRect; }
21072 else if (rect_type == WRT_WorkRect) {
return window->WorkRect; }
21073 else if (rect_type == WRT_Content) { ImVec2
min = window->InnerRect.Min - window->Scroll + window->WindowPadding;
return ImRect(min, min + window->ContentSize); }
21074 else if (rect_type == WRT_ContentIdeal) { ImVec2
min = window->InnerRect.Min - window->Scroll + window->WindowPadding;
return ImRect(min, min + window->ContentSizeIdeal); }
21075 else if (rect_type == WRT_ContentRegionRect) {
return window->ContentRegionRect; }
21086 SeparatorTextEx(0,
"Debug breaks", NULL,
CalcTextSize(
"(?)").x +
g.Style.SeparatorTextPadding.x);
21088 MetricsHelpMarker(
"Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash.");
21089 if (
Checkbox(
"Show Item Picker", &
g.DebugItemPickerActive) &&
g.DebugItemPickerActive)
21090 DebugStartItemPicker();
21091 Checkbox(
"Show \"Debug Break\" buttons in other sections (io.ConfigDebugIsDebuggerPresent)", &
g.IO.ConfigDebugIsDebuggerPresent);
21093 SeparatorText(
"Visualize");
21095 Checkbox(
"Show Debug Log", &cfg->ShowDebugLog);
21097 MetricsHelpMarker(
"You can also call ImGui::ShowDebugLogWindow() from your code.");
21099 Checkbox(
"Show ID Stack Tool", &cfg->ShowIDStackTool);
21101 MetricsHelpMarker(
"You can also call ImGui::ShowIDStackToolWindow() from your code.");
21103 Checkbox(
"Show windows begin order", &cfg->ShowWindowsBeginOrder);
21104 Checkbox(
"Show windows rectangles", &cfg->ShowWindowsRects);
21106 SetNextItemWidth(GetFontSize() * 12);
21107 cfg->ShowWindowsRects |=
Combo(
"##show_windows_rect_type", &cfg->ShowWindowsRectsType, wrt_rects_names, WRT_Count, WRT_Count);
21108 if (cfg->ShowWindowsRects &&
g.NavWindow != NULL)
21110 BulletText(
"'%s':",
g.NavWindow->Name);
21112 for (
int rect_n = 0; rect_n < WRT_Count; rect_n++)
21114 ImRect r = Funcs::GetWindowRect(
g.NavWindow, rect_n);
21115 Text(
"(%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(), wrt_rects_names[rect_n]);
21120 Checkbox(
"Show tables rectangles", &cfg->ShowTablesRects);
21122 SetNextItemWidth(GetFontSize() * 12);
21123 cfg->ShowTablesRects |=
Combo(
"##show_table_rects_type", &cfg->ShowTablesRectsType, trt_rects_names, TRT_Count, TRT_Count);
21124 if (cfg->ShowTablesRects &&
g.NavWindow != NULL)
21126 for (
int table_n = 0; table_n <
g.Tables.GetMapSize(); table_n++)
21128 ImGuiTable* table =
g.Tables.TryGetMapData(table_n);
21129 if (table == NULL || table->LastFrameActive <
g.FrameCount - 1 || (table->OuterWindow !=
g.NavWindow && table->InnerWindow !=
g.NavWindow))
21132 BulletText(
"Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);
21133 if (IsItemHovered())
21134 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);
21137 for (
int rect_n = 0; rect_n < TRT_Count; rect_n++)
21139 if (rect_n >= TRT_ColumnsRect)
21141 if (rect_n != TRT_ColumnsRect && rect_n != TRT_ColumnsClipRect)
21143 for (
int column_n = 0; column_n < table->ColumnsCount; column_n++)
21145 ImRect r = Funcs::GetTableRect(table, rect_n, column_n);
21146 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]);
21148 if (IsItemHovered())
21149 GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
21154 ImRect r = Funcs::GetTableRect(table, rect_n, -1);
21155 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]);
21157 if (IsItemHovered())
21158 GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
21164 Checkbox(
"Show groups rectangles", &
g.DebugShowGroupRects);
21166 SeparatorText(
"Validate");
21168 Checkbox(
"Debug Begin/BeginChild return value", &io.ConfigDebugBeginReturnValueLoop);
21170 MetricsHelpMarker(
"Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running.");
21172 Checkbox(
"UTF-8 Encoding viewer", &cfg->ShowTextEncodingViewer);
21174 MetricsHelpMarker(
"You can also call ImGui::DebugTextEncoding() from your code with a given string to test that your UTF-8 encoding settings are correct.");
21175 if (cfg->ShowTextEncodingViewer)
21177 static char buf[64] =
"";
21178 SetNextItemWidth(-FLT_MIN);
21179 InputText(
"##DebugTextEncodingBuf", buf, IM_ARRAYSIZE(buf));
21181 DebugTextEncoding(buf);
21188 if (
TreeNode(
"Windows",
"Windows (%d)",
g.Windows.Size))
21191 DebugNodeWindowsList(&
g.Windows,
"By display order");
21192 DebugNodeWindowsList(&
g.WindowsFocusOrder,
"By focus order (root windows)");
21193 if (
TreeNode(
"By submission order (begin stack)"))
21196 ImVector<ImGuiWindow*>& temp_buffer =
g.WindowsTempSortBuffer;
21197 temp_buffer.resize(0);
21198 for (ImGuiWindow* window :
g.Windows)
21199 if (window->LastFrameActive + 1 >=
g.FrameCount)
21200 temp_buffer.push_back(window);
21201 struct Func {
static int IMGUI_CDECL WindowComparerByBeginOrder(
const void* lhs,
const void* rhs) {
return ((
int)(*(
const ImGuiWindow*
const *)lhs)->BeginOrderWithinContext - (*(
const ImGuiWindow*
const*)rhs)->BeginOrderWithinContext); } };
21202 ImQsort(temp_buffer.Data, (
size_t)temp_buffer.Size,
sizeof(ImGuiWindow*), Func::WindowComparerByBeginOrder);
21203 DebugNodeWindowsListByBeginStackParent(temp_buffer.Data, temp_buffer.Size, NULL);
21211 int drawlist_count = 0;
21212 for (ImGuiViewportP* viewport :
g.Viewports)
21213 drawlist_count += viewport->DrawDataP.CmdLists.Size;
21214 if (
TreeNode(
"DrawLists",
"DrawLists (%d)", drawlist_count))
21216 Checkbox(
"Show ImDrawCmd mesh when hovering", &cfg->ShowDrawCmdMesh);
21217 Checkbox(
"Show ImDrawCmd bounding boxes when hovering", &cfg->ShowDrawCmdBoundingBoxes);
21218 for (ImGuiViewportP* viewport :
g.Viewports)
21220 bool viewport_has_drawlist =
false;
21221 for (ImDrawList* draw_list : viewport->DrawDataP.CmdLists)
21223 if (!viewport_has_drawlist)
21224 Text(
"Active DrawLists in Viewport #%d, ID: 0x%08X", viewport->Idx, viewport->ID);
21225 viewport_has_drawlist =
true;
21226 DebugNodeDrawList(NULL, viewport, draw_list,
"DrawList");
21233 if (
TreeNode(
"Viewports",
"Viewports (%d)",
g.Viewports.Size))
21235 cfg->HighlightMonitorIdx = -1;
21236 bool open =
TreeNode(
"Monitors",
"Monitors (%d)",
g.PlatformIO.Monitors.Size);
21238 MetricsHelpMarker(
"Dear ImGui uses monitor data:\n- to query DPI settings on a per monitor basis\n- to position popup/tooltips so they don't straddle monitors.");
21241 for (
int i = 0; i <
g.PlatformIO.Monitors.Size; i++)
21243 DebugNodePlatformMonitor(&
g.PlatformIO.Monitors[i],
"Monitor", i);
21244 if (IsItemHovered())
21245 cfg->HighlightMonitorIdx = i;
21247 DebugNodePlatformMonitor(&
g.FallbackMonitor,
"Fallback", 0);
21251 SetNextItemOpen(
true, ImGuiCond_Once);
21254 RenderViewportsThumbnails();
21257 cfg->HighlightViewportID = 0;
21259 BulletText(
"MouseViewport: 0x%08X (UserHovered 0x%08X, LastHovered 0x%08X)",
g.MouseViewport ?
g.MouseViewport->ID : 0,
g.IO.MouseHoveredViewport,
g.MouseLastHoveredViewport ?
g.MouseLastHoveredViewport->
ID : 0);
21260 if (
TreeNode(
"Inferred Z order (front-to-back)"))
21262 static ImVector<ImGuiViewportP*> viewports;
21263 viewports.resize(
g.Viewports.Size);
21264 memcpy(viewports.Data,
g.Viewports.Data,
g.Viewports.size_in_bytes());
21265 if (viewports.Size > 1)
21266 ImQsort(viewports.Data, viewports.Size,
sizeof(ImGuiViewport*), ViewportComparerByLastFocusedStampCount);
21267 for (ImGuiViewportP* viewport : viewports)
21269 BulletText(
"Viewport #%d, ID: 0x%08X, LastFocused = %08d, PlatformFocused = %s, Window: \"%s\"",
21270 viewport->Idx, viewport->ID, viewport->LastFocusedStampCount,
21271 (
g.PlatformIO.Platform_GetWindowFocus && viewport->PlatformWindowCreated) ? (
g.PlatformIO.Platform_GetWindowFocus(viewport) ?
"1" :
"0") :
"N/A",
21273 if (IsItemHovered())
21274 cfg->HighlightViewportID = viewport->ID;
21279 for (ImGuiViewportP* viewport :
g.Viewports)
21280 DebugNodeViewport(viewport);
21285 if (
TreeNode(
"Popups",
"Popups (%d)",
g.OpenPopupStack.Size))
21287 for (
const ImGuiPopupData& popup_data :
g.OpenPopupStack)
21290 ImGuiWindow* window = popup_data.Window;
21291 BulletText(
"PopupID: %08x, Window: '%s' (%s%s), RestoreNavWindow '%s', ParentWindow '%s'",
21292 popup_data.PopupId, window ? window->Name :
"NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ?
"Child;" :
"", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ?
"Menu;" :
"",
21293 popup_data.RestoreNavWindow ? popup_data.RestoreNavWindow->Name :
"NULL", window && window->ParentWindow ? window->ParentWindow->Name :
"NULL");
21299 if (
TreeNode(
"TabBars",
"Tab Bars (%d)",
g.TabBars.GetAliveCount()))
21301 for (
int n = 0; n <
g.TabBars.GetMapSize(); n++)
21302 if (ImGuiTabBar* tab_bar =
g.TabBars.TryGetMapData(n))
21305 DebugNodeTabBar(tab_bar,
"TabBar");
21312 if (
TreeNode(
"Tables",
"Tables (%d)",
g.Tables.GetAliveCount()))
21314 for (
int n = 0; n <
g.Tables.GetMapSize(); n++)
21315 if (ImGuiTable* table =
g.Tables.TryGetMapData(n))
21316 DebugNodeTable(table);
21321 ImFontAtlas* atlas =
g.IO.Fonts;
21322 if (
TreeNode(
"Fonts",
"Fonts (%d)", atlas->Fonts.Size))
21331 DebugNodeInputTextState(&
g.InputTextState);
21336 if (
TreeNode(
"TypingSelect",
"TypingSelect (%d)",
g.TypingSelectState.SearchBuffer[0] != 0 ? 1 : 0))
21338 DebugNodeTypingSelectState(&
g.TypingSelectState);
21343 if (
TreeNode(
"MultiSelect",
"MultiSelect (%d)",
g.MultiSelectStorage.GetAliveCount()))
21345 ImGuiBoxSelectState* bs = &
g.BoxSelectState;
21346 BulletText(
"BoxSelect ID=0x%08X, Starting = %d, Active %d", bs->ID, bs->IsStarting, bs->IsActive);
21347 for (
int n = 0; n <
g.MultiSelectStorage.GetMapSize(); n++)
21348 if (ImGuiMultiSelectState* state =
g.MultiSelectStorage.TryGetMapData(n))
21349 DebugNodeMultiSelectState(state);
21354#ifdef IMGUI_HAS_DOCK
21357 static bool root_nodes_only =
true;
21358 ImGuiDockContext* dc = &
g.DockContext;
21359 Checkbox(
"List root nodes", &root_nodes_only);
21360 Checkbox(
"Ctrl shows window dock info", &cfg->ShowDockingNodes);
21361 if (SmallButton(
"Clear nodes")) { DockContextClearNodes(&
g, 0,
true); }
21363 if (SmallButton(
"Rebuild all")) { dc->WantFullRebuild =
true; }
21364 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
21365 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
21366 if (!root_nodes_only || node->IsRootNode())
21367 DebugNodeDockNode(node,
"Node");
21375 if (SmallButton(
"Clear"))
21376 ClearIniSettings();
21378 if (SmallButton(
"Save to memory"))
21379 SaveIniSettingsToMemory();
21381 if (SmallButton(
"Save to disk"))
21382 SaveIniSettingsToDisk(
g.IO.IniFilename);
21384 if (
g.IO.IniFilename)
21385 Text(
"\"%s\"",
g.IO.IniFilename);
21388 Checkbox(
"io.ConfigDebugIniSettings", &io.ConfigDebugIniSettings);
21389 Text(
"SettingsDirtyTimer %.2f",
g.SettingsDirtyTimer);
21390 if (
TreeNode(
"SettingsHandlers",
"Settings handlers: (%d)",
g.SettingsHandlers.Size))
21392 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
21393 BulletText(
"\"%s\"", handler.TypeName);
21396 if (
TreeNode(
"SettingsWindows",
"Settings packed data: Windows: %d bytes",
g.SettingsWindows.size()))
21398 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
21399 DebugNodeWindowSettings(settings);
21403 if (
TreeNode(
"SettingsTables",
"Settings packed data: Tables: %d bytes",
g.SettingsTables.size()))
21405 for (ImGuiTableSettings* settings =
g.SettingsTables.begin(); settings != NULL; settings =
g.SettingsTables.next_chunk(settings))
21406 DebugNodeTableSettings(settings);
21410#ifdef IMGUI_HAS_DOCK
21411 if (
TreeNode(
"SettingsDocking",
"Settings packed data: Docking"))
21413 ImGuiDockContext* dc = &
g.DockContext;
21414 Text(
"In SettingsWindows:");
21415 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
21416 if (settings->DockId != 0)
21417 BulletText(
"Window '%s' -> DockId %08X DockOrder=%d", settings->GetName(), settings->DockId, settings->DockOrder);
21418 Text(
"In SettingsNodes:");
21419 for (
int n = 0; n < dc->NodesSettings.Size; n++)
21422 const char* selected_tab_name = NULL;
21425 if (ImGuiWindow* window = FindWindowByID(settings->
SelectedTabId))
21426 selected_tab_name = window->Name;
21427 else if (ImGuiWindowSettings* window_settings = FindWindowSettingsByID(settings->
SelectedTabId))
21428 selected_tab_name = window_settings->GetName();
21430 BulletText(
"Node %08X, Parent %08X, SelectedTab %08X ('%s')", settings->
ID, settings->
ParentNodeId, settings->
SelectedTabId, selected_tab_name ? selected_tab_name : settings->SelectedTabId ?
"N/A" :
"");
21436 if (
TreeNode(
"SettingsIniData",
"Settings unpacked data (.ini): %d bytes",
g.SettingsIniData.size()))
21438 InputTextMultiline(
"##Ini", (
char*)(
void*)
g.SettingsIniData.c_str(),
g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, GetTextLineHeight() * 20), ImGuiInputTextFlags_ReadOnly);
21445 if (
TreeNode(
"Memory allocations"))
21447 ImGuiDebugAllocInfo* info = &
g.DebugAllocInfo;
21448 Text(
"%d current allocations", info->TotalAllocCount - info->TotalFreeCount);
21449 if (SmallButton(
"GC now")) {
g.GcCompactAll =
true; }
21450 Text(
"Recent frames with allocations:");
21451 int buf_size = IM_ARRAYSIZE(info->LastEntriesBuf);
21452 for (
int n = buf_size - 1; n >= 0; n--)
21454 ImGuiDebugAllocEntry* entry = &info->LastEntriesBuf[(info->LastEntriesIdx - n + buf_size) % buf_size];
21455 BulletText(
"Frame %06d: %+3d ( %2d alloc, %2d free )", entry->FrameCount, entry->AllocCount - entry->FreeCount, entry->AllocCount, entry->FreeCount);
21459 Text(
"<- %d frames ago",
g.FrameCount - entry->FrameCount);
21467 Text(
"KEYBOARD/GAMEPAD/MOUSE KEYS");
21472#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
21473 struct funcs {
static bool IsLegacyNativeDupe(ImGuiKey) {
return false; } };
21475 struct funcs {
static bool IsLegacyNativeDupe(ImGuiKey key) {
return key >= 0 && key < 512 && GetIO().KeyMap[key] != -1; } };
21478 Text(
"Keys down:");
for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) {
if (funcs::IsLegacyNativeDupe(key) || !IsKeyDown(key))
continue; SameLine(); Text(IsNamedKey(key) ?
"\"%s\"" :
"\"%s\" %d", GetKeyName(key), key); SameLine(); Text(
"(%.02f)", GetKeyData(key)->DownDuration); }
21479 Text(
"Keys pressed:");
for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) {
if (funcs::IsLegacyNativeDupe(key) || !IsKeyPressed(key))
continue; SameLine(); Text(IsNamedKey(key) ?
"\"%s\"" :
"\"%s\" %d", GetKeyName(key), key); }
21480 Text(
"Keys released:");
for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) {
if (funcs::IsLegacyNativeDupe(key) || !IsKeyReleased(key))
continue; SameLine(); Text(IsNamedKey(key) ?
"\"%s\"" :
"\"%s\" %d", GetKeyName(key), key); }
21481 Text(
"Keys mods: %s%s%s%s", io.KeyCtrl ?
"CTRL " :
"", io.KeyShift ?
"SHIFT " :
"", io.KeyAlt ?
"ALT " :
"", io.KeySuper ?
"SUPER " :
"");
21482 Text(
"Chars queue:");
for (
int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; SameLine(); Text(
"\'%c\' (0x%04X)", (c >
' ' && c <= 255) ? (
char)c :
'?', c); }
21483 DebugRenderKeyboardPreview(GetWindowDrawList());
21487 Text(
"MOUSE STATE");
21490 if (IsMousePosValid())
21491 Text(
"Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
21493 Text(
"Mouse pos: <INVALID>");
21494 Text(
"Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
21495 int count = IM_ARRAYSIZE(io.MouseDown);
21496 Text(
"Mouse down:");
for (
int i = 0; i <
count; i++)
if (IsMouseDown(i)) { SameLine(); Text(
"b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
21497 Text(
"Mouse clicked:");
for (
int i = 0; i <
count; i++)
if (IsMouseClicked(i)) { SameLine(); Text(
"b%d (%d)", i, io.MouseClickedCount[i]); }
21498 Text(
"Mouse released:");
for (
int i = 0; i <
count; i++)
if (IsMouseReleased(i)) { SameLine(); Text(
"b%d", i); }
21499 Text(
"Mouse wheel: %.1f", io.MouseWheel);
21500 Text(
"MouseStationaryTimer: %.2f",
g.MouseStationaryTimer);
21501 Text(
"Mouse source: %s", GetMouseSourceName(io.MouseSource));
21502 Text(
"Pen Pressure: %.1f", io.PenPressure);
21506 Text(
"MOUSE WHEELING");
21509 Text(
"WheelingWindow: '%s'",
g.WheelingWindow ?
g.WheelingWindow->Name :
"NULL");
21510 Text(
"WheelingWindowReleaseTimer: %.2f",
g.WheelingWindowReleaseTimer);
21511 Text(
"WheelingAxisAvg[] = { %.3f, %.3f }, Main Axis: %s",
g.WheelingAxisAvg.x,
g.WheelingAxisAvg.y, (
g.WheelingAxisAvg.x >
g.WheelingAxisAvg.y) ?
"X" : (
g.WheelingAxisAvg.x <
g.WheelingAxisAvg.y) ?
"Y" :
"<none>");
21515 Text(
"KEY OWNERS");
21518 if (BeginChild(
"##owners", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_NoSavedSettings))
21519 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
21521 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
21522 if (owner_data->OwnerCurr == ImGuiKeyOwner_NoOwner)
21524 Text(
"%s: 0x%08X%s", GetKeyName(key), owner_data->OwnerCurr,
21525 owner_data->LockUntilRelease ?
" LockUntilRelease" : owner_data->LockThisFrame ?
" LockThisFrame" :
"");
21526 DebugLocateItemOnHover(owner_data->OwnerCurr);
21531 Text(
"SHORTCUT ROUTING");
21533 MetricsHelpMarker(
"Declared shortcut routes automatically set key owner when mods matches.");
21536 if (BeginChild(
"##routes", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_NoSavedSettings))
21537 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
21539 ImGuiKeyRoutingTable* rt = &
g.KeysRoutingTable;
21540 for (ImGuiKeyRoutingIndex idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; idx != -1; )
21542 ImGuiKeyRoutingData* routing_data = &rt->Entries[idx];
21543 ImGuiKeyChord key_chord = key | routing_data->Mods;
21544 Text(
"%s: 0x%08X (scored %d)", GetKeyChordName(key_chord), routing_data->RoutingCurr, routing_data->RoutingCurrScore);
21545 DebugLocateItemOnHover(routing_data->RoutingCurr);
21546 if (
g.IO.ConfigDebugIsDebuggerPresent)
21549 if (DebugBreakButton(
"**DebugBreak**",
"in SetShortcutRouting() for this KeyChord"))
21550 g.DebugBreakInShortcutRouting = key_chord;
21552 idx = routing_data->NextEntryIndex;
21556 Text(
"(ActiveIdUsing: AllKeyboardKeys: %d, NavDirMask: 0x%X)",
g.ActiveIdUsingAllKeyboardKeys,
g.ActiveIdUsingNavDirMask);
21566 Text(
"HoveredWindow: '%s'",
g.HoveredWindow ?
g.HoveredWindow->Name :
"NULL");
21567 Text(
"HoveredWindow->Root: '%s'",
g.HoveredWindow ?
g.HoveredWindow->RootWindowDockTree->Name :
"NULL");
21568 Text(
"HoveredWindowUnderMovingWindow: '%s'",
g.HoveredWindowUnderMovingWindow ?
g.HoveredWindowUnderMovingWindow->Name :
"NULL");
21569 Text(
"HoveredDockNode: 0x%08X",
g.DebugHoveredDockNode ?
g.DebugHoveredDockNode->ID : 0);
21570 Text(
"MovingWindow: '%s'",
g.MovingWindow ?
g.MovingWindow->Name :
"NULL");
21571 Text(
"MouseViewport: 0x%08X (UserHovered 0x%08X, LastHovered 0x%08X)",
g.MouseViewport->ID,
g.IO.MouseHoveredViewport,
g.MouseLastHoveredViewport ?
g.MouseLastHoveredViewport->ID : 0);
21576 Text(
"ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s",
g.ActiveId,
g.ActiveIdPreviousFrame,
g.ActiveIdTimer,
g.ActiveIdAllowOverlap, GetInputSourceName(
g.ActiveIdSource));
21577 DebugLocateItemOnHover(
g.ActiveId);
21578 Text(
"ActiveIdWindow: '%s'",
g.ActiveIdWindow ?
g.ActiveIdWindow->Name :
"NULL");
21579 Text(
"ActiveIdUsing: AllKeyboardKeys: %d, NavDirMask: %X",
g.ActiveIdUsingAllKeyboardKeys,
g.ActiveIdUsingNavDirMask);
21580 Text(
"HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d",
g.HoveredIdPreviousFrame,
g.HoveredIdTimer,
g.HoveredIdAllowOverlap);
21581 Text(
"HoverItemDelayId: 0x%08X, Timer: %.2f, ClearTimer: %.2f",
g.HoverItemDelayId,
g.HoverItemDelayTimer,
g.HoverItemDelayClearTimer);
21582 Text(
"DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)",
g.DragDropActive,
g.DragDropPayload.SourceId,
g.DragDropPayload.DataType,
g.DragDropPayload.DataSize);
21583 DebugLocateItemOnHover(
g.DragDropPayload.SourceId);
21588 Text(
"NavWindow: '%s'",
g.NavWindow ?
g.NavWindow->Name :
"NULL");
21589 Text(
"NavId: 0x%08X, NavLayer: %d",
g.NavId,
g.NavLayer);
21590 DebugLocateItemOnHover(
g.NavId);
21591 Text(
"NavInputSource: %s", GetInputSourceName(
g.NavInputSource));
21592 Text(
"NavLastValidSelectionUserData = %" IM_PRId64
" (0x%" IM_PRIX64
")",
g.NavLastValidSelectionUserData,
g.NavLastValidSelectionUserData);
21593 Text(
"NavActive: %d, NavVisible: %d",
g.IO.NavActive,
g.IO.NavVisible);
21594 Text(
"NavActivateId/DownId/PressedId: %08X/%08X/%08X",
g.NavActivateId,
g.NavActivateDownId,
g.NavActivatePressedId);
21595 Text(
"NavActivateFlags: %04X",
g.NavActivateFlags);
21596 Text(
"NavCursorVisible: %d, NavHighlightItemUnderNav: %d",
g.NavCursorVisible,
g.NavHighlightItemUnderNav);
21597 Text(
"NavFocusScopeId = 0x%08X",
g.NavFocusScopeId);
21598 Text(
"NavFocusRoute[] = ");
21599 for (
int path_n =
g.NavFocusRoute.Size - 1; path_n >= 0; path_n--)
21601 const ImGuiFocusScopeData& focus_scope =
g.NavFocusRoute[path_n];
21602 SameLine(0.0f, 0.0f);
21603 Text(
"0x%08X/", focus_scope.ID);
21604 SetItemTooltip(
"In window \"%s\"", FindWindowByID(focus_scope.WindowID)->Name);
21606 Text(
"NavWindowingTarget: '%s'",
g.NavWindowingTarget ?
g.NavWindowingTarget->Name :
"NULL");
21613 if (cfg->ShowWindowsRects || cfg->ShowWindowsBeginOrder)
21615 for (ImGuiWindow* window :
g.Windows)
21617 if (!window->WasActive)
21619 ImDrawList* draw_list = GetForegroundDrawList(window);
21620 if (cfg->ShowWindowsRects)
21622 ImRect r = Funcs::GetWindowRect(window, cfg->ShowWindowsRectsType);
21623 draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255));
21625 if (cfg->ShowWindowsBeginOrder && !(window->Flags & ImGuiWindowFlags_ChildWindow))
21628 ImFormatString(buf, IM_ARRAYSIZE(buf),
"%d", window->BeginOrderWithinContext);
21629 float font_size = GetFontSize();
21630 draw_list->AddRectFilled(window->Pos, window->Pos + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255));
21631 draw_list->AddText(window->Pos, IM_COL32(255, 255, 255, 255), buf);
21637 if (cfg->ShowTablesRects)
21639 for (
int table_n = 0; table_n <
g.Tables.GetMapSize(); table_n++)
21641 ImGuiTable* table =
g.Tables.TryGetMapData(table_n);
21642 if (table == NULL || table->LastFrameActive <
g.FrameCount - 1)
21644 ImDrawList* draw_list = GetForegroundDrawList(table->OuterWindow);
21645 if (cfg->ShowTablesRectsType >= TRT_ColumnsRect)
21647 for (
int column_n = 0; column_n < table->ColumnsCount; column_n++)
21649 ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, column_n);
21650 ImU32 col = (table->HoveredColumnBody == column_n) ? IM_COL32(255, 255, 128, 255) : IM_COL32(255, 0, 128, 255);
21651 float thickness = (table->HoveredColumnBody == column_n) ? 3.0f : 1.0f;
21652 draw_list->AddRect(r.Min, r.Max, col, 0.0f, 0, thickness);
21657 ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, -1);
21658 draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255));
21663#ifdef IMGUI_HAS_DOCK
21665 if (cfg->ShowDockingNodes &&
g.IO.KeyCtrl &&
g.DebugHoveredDockNode)
21669 ImGuiDockNode* node =
g.DebugHoveredDockNode;
21670 ImDrawList* overlay_draw_list = node->HostWindow ? GetForegroundDrawList(node->HostWindow) : GetForegroundDrawList(GetMainViewport());
21671 p +=
ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"DockId: %X%s\n", node->ID, node->IsCentralNode() ?
" *CentralNode*" :
"");
21672 p +=
ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"WindowClass: %08X\n", node->WindowClass.ClassId);
21673 p +=
ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"Size: (%.0f, %.0f)\n", node->Size.x, node->Size.y);
21674 p +=
ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"SizeRef: (%.0f, %.0f)\n", node->SizeRef.x, node->SizeRef.y);
21675 int depth = DockNodeGetDepth(node);
21676 overlay_draw_list->AddRect(node->Pos + ImVec2(3, 3) * (
float)depth, node->Pos + node->Size - ImVec2(3, 3) * (
float)depth, IM_COL32(200, 100, 100, 255));
21677 ImVec2 pos = node->Pos + ImVec2(3, 3) * (float)depth;
21678 overlay_draw_list->AddRectFilled(pos - ImVec2(1, 1), pos +
CalcTextSize(buf) + ImVec2(1, 1), IM_COL32(200, 100, 100, 255));
21679 overlay_draw_list->AddText(NULL, 0.0f, pos, IM_COL32(255, 255, 255, 255), buf);
21686void ImGui::DebugBreakClearData()
21690 g.DebugBreakInWindow = 0;
21691 g.DebugBreakInTable = 0;
21692 g.DebugBreakInShortcutRouting = ImGuiKey_None;
21695void ImGui::DebugBreakButtonTooltip(
bool keyboard_only,
const char* description_of_location)
21697 if (!BeginItemTooltip())
21699 Text(
"To call IM_DEBUG_BREAK() %s:", description_of_location);
21701 TextUnformatted(keyboard_only ?
"- Press 'Pause/Break' on keyboard." :
"- Press 'Pause/Break' on keyboard.\n- or Click (may alter focus/active id).\n- or navigate using keyboard and press space.");
21703 TextUnformatted(
"Choose one way that doesn't interfere with what you are trying to debug!\nYou need a debugger attached or this will crash!");
21709bool ImGui::DebugBreakButton(
const char* label,
const char* description_of_location)
21711 ImGuiWindow* window = GetCurrentWindow();
21712 if (window->SkipItems)
21716 const ImGuiID
id = window->GetID(label);
21717 const ImVec2 label_size =
CalcTextSize(label, NULL,
true);
21718 ImVec2 pos = window->DC.CursorPos + ImVec2(0.0f, window->DC.CurrLineTextBaseOffset);
21719 ImVec2
size = ImVec2(label_size.x +
g.Style.FramePadding.x * 2.0f, label_size.y);
21721 const ImRect bb(pos, pos + size);
21722 ItemSize(size, 0.0f);
21723 if (!ItemAdd(bb,
id))
21727 bool hovered = ItemHoverable(bb,
id,
g.CurrentItemFlags);
21728 bool pressed = hovered && (IsKeyChordPressed(
g.DebugBreakKeyChord) || IsMouseClicked(0) ||
g.NavActivateId ==
id);
21729 DebugBreakButtonTooltip(
false, description_of_location);
21731 ImVec4 col4f = GetStyleColorVec4(hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
21733 ColorConvertRGBtoHSV(col4f.x, col4f.y, col4f.z, hsv.x, hsv.y, hsv.z);
21734 ColorConvertHSVtoRGB(hsv.x + 0.20f, hsv.y, hsv.z, col4f.x, col4f.y, col4f.z);
21736 RenderNavCursor(bb,
id);
21737 RenderFrame(bb.Min, bb.Max, GetColorU32(col4f),
true,
g.Style.FrameRounding);
21738 RenderTextClipped(bb.Min, bb.Max, label, NULL, &label_size,
g.Style.ButtonTextAlign, &bb);
21740 IMGUI_TEST_ENGINE_ITEM_INFO(
id, label,
g.LastItemData.StatusFlags);
21745void ImGui::DebugNodeColumns(ImGuiOldColumns* columns)
21747 if (!
TreeNode((
void*)(uintptr_t)columns->ID,
"Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags))
21749 BulletText(
"Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->OffMaxX - columns->OffMinX, columns->OffMinX, columns->OffMaxX);
21750 for (ImGuiOldColumnData& column : columns->Columns)
21751 BulletText(
"Column %02d: OffsetNorm %.3f (= %.1f px)", (int)columns->Columns.index_from_ptr(&column), column.OffsetNorm, GetColumnOffsetFromNorm(columns, column.OffsetNorm));
21755static void DebugNodeDockNodeFlags(ImGuiDockNodeFlags* p_flags,
const char* label,
bool enabled)
21757 using namespace ImGui;
21759 PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
21760 Text(
"%s:", label);
21763 CheckboxFlags(
"NoResize", p_flags, ImGuiDockNodeFlags_NoResize);
21764 CheckboxFlags(
"NoResizeX", p_flags, ImGuiDockNodeFlags_NoResizeX);
21765 CheckboxFlags(
"NoResizeY",p_flags, ImGuiDockNodeFlags_NoResizeY);
21766 CheckboxFlags(
"NoTabBar", p_flags, ImGuiDockNodeFlags_NoTabBar);
21767 CheckboxFlags(
"HiddenTabBar", p_flags, ImGuiDockNodeFlags_HiddenTabBar);
21768 CheckboxFlags(
"NoWindowMenuButton", p_flags, ImGuiDockNodeFlags_NoWindowMenuButton);
21769 CheckboxFlags(
"NoCloseButton", p_flags, ImGuiDockNodeFlags_NoCloseButton);
21770 CheckboxFlags(
"DockedWindowsInFocusRoute", p_flags, ImGuiDockNodeFlags_DockedWindowsInFocusRoute);
21771 CheckboxFlags(
"NoDocking", p_flags, ImGuiDockNodeFlags_NoDocking);
21772 CheckboxFlags(
"NoDockingSplit", p_flags, ImGuiDockNodeFlags_NoDockingSplit);
21773 CheckboxFlags(
"NoDockingSplitOther", p_flags, ImGuiDockNodeFlags_NoDockingSplitOther);
21774 CheckboxFlags(
"NoDockingOver", p_flags, ImGuiDockNodeFlags_NoDockingOverMe);
21775 CheckboxFlags(
"NoDockingOverOther", p_flags, ImGuiDockNodeFlags_NoDockingOverOther);
21776 CheckboxFlags(
"NoDockingOverEmpty", p_flags, ImGuiDockNodeFlags_NoDockingOverEmpty);
21777 CheckboxFlags(
"NoUndocking", p_flags, ImGuiDockNodeFlags_NoUndocking);
21785void ImGui::DebugNodeDockNode(ImGuiDockNode* node,
const char* label)
21788 const bool is_alive = (
g.FrameCount - node->LastFrameAlive < 2);
21789 const bool is_active = (
g.FrameCount - node->LastFrameActive < 2);
21790 if (!is_alive) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
21792 ImGuiTreeNodeFlags tree_node_flags = node->IsFocused ? ImGuiTreeNodeFlags_Selected : ImGuiTreeNodeFlags_None;
21793 if (node->Windows.Size > 0)
21794 open = TreeNodeEx((
void*)(intptr_t)node->ID, tree_node_flags,
"%s 0x%04X%s: %d windows (vis: '%s')", label, node->ID, node->IsVisible ?
"" :
" (hidden)", node->Windows.Size, node->VisibleWindow ? node->VisibleWindow->Name :
"NULL");
21796 open = TreeNodeEx((
void*)(intptr_t)node->ID, tree_node_flags,
"%s 0x%04X%s: %s (vis: '%s')", label, node->ID, node->IsVisible ?
"" :
" (hidden)", (node->SplitAxis == ImGuiAxis_X) ?
"horizontal split" : (node->SplitAxis == ImGuiAxis_Y) ?
"vertical split" :
"empty", node->VisibleWindow ? node->VisibleWindow->Name :
"NULL");
21797 if (!is_alive) { PopStyleColor(); }
21798 if (is_active && IsItemHovered())
21799 if (ImGuiWindow* window = node->HostWindow ? node->HostWindow : node->VisibleWindow)
21800 GetForegroundDrawList(window)->AddRect(node->Pos, node->Pos + node->Size, IM_COL32(255, 255, 0, 255));
21803 IM_ASSERT(node->ChildNodes[0] == NULL || node->ChildNodes[0]->ParentNode == node);
21804 IM_ASSERT(node->ChildNodes[1] == NULL || node->ChildNodes[1]->ParentNode == node);
21805 BulletText(
"Pos (%.0f,%.0f), Size (%.0f, %.0f) Ref (%.0f, %.0f)",
21806 node->Pos.x, node->Pos.y, node->Size.x, node->Size.y, node->SizeRef.x, node->SizeRef.y);
21807 DebugNodeWindow(node->HostWindow,
"HostWindow");
21808 DebugNodeWindow(node->VisibleWindow,
"VisibleWindow");
21809 BulletText(
"SelectedTabID: 0x%08X, LastFocusedNodeID: 0x%08X", node->SelectedTabId, node->LastFocusedNodeId);
21810 BulletText(
"Misc:%s%s%s%s%s%s%s",
21811 node->IsDockSpace() ?
" IsDockSpace" :
"",
21812 node->IsCentralNode() ?
" IsCentralNode" :
"",
21813 is_alive ?
" IsAlive" :
"", is_active ?
" IsActive" :
"", node->IsFocused ?
" IsFocused" :
"",
21814 node->WantLockSizeOnce ?
" WantLockSizeOnce" :
"",
21815 node->HasCentralNodeChild ?
" HasCentralNodeChild" :
"");
21816 if (
TreeNode(
"flags",
"Flags Merged: 0x%04X, Local: 0x%04X, InWindows: 0x%04X, Shared: 0x%04X", node->MergedFlags, node->LocalFlags, node->LocalFlagsInWindows, node->SharedFlags))
21818 if (BeginTable(
"flags", 4))
21820 TableNextColumn(); DebugNodeDockNodeFlags(&node->MergedFlags,
"MergedFlags",
false);
21821 TableNextColumn(); DebugNodeDockNodeFlags(&node->LocalFlags,
"LocalFlags",
true);
21822 TableNextColumn(); DebugNodeDockNodeFlags(&node->LocalFlagsInWindows,
"LocalFlagsInWindows",
false);
21823 TableNextColumn(); DebugNodeDockNodeFlags(&node->SharedFlags,
"SharedFlags",
true);
21828 if (node->ParentNode)
21829 DebugNodeDockNode(node->ParentNode,
"ParentNode");
21830 if (node->ChildNodes[0])
21831 DebugNodeDockNode(node->ChildNodes[0],
"Child[0]");
21832 if (node->ChildNodes[1])
21833 DebugNodeDockNode(node->ChildNodes[1],
"Child[1]");
21835 DebugNodeTabBar(node->TabBar,
"TabBar");
21836 DebugNodeWindowsList(&node->Windows,
"Windows");
21842static void FormatTextureIDForDebugDisplay(
char* buf,
int buf_size, ImTextureID tex_id)
21844 union {
void* ptr;
int integer; } tex_id_opaque;
21845 memcpy(&tex_id_opaque, &tex_id, ImMin(
sizeof(
void*),
sizeof(tex_id)));
21846 if (
sizeof(tex_id) >=
sizeof(
void*))
21854void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport,
const ImDrawList* draw_list,
const char* label)
21857 ImGuiMetricsConfig* cfg = &
g.DebugMetricsConfig;
21858 int cmd_count = draw_list->CmdBuffer.Size;
21859 if (cmd_count > 0 && draw_list->CmdBuffer.back().ElemCount == 0 && draw_list->CmdBuffer.back().UserCallback == NULL)
21861 bool node_open =
TreeNode(draw_list,
"%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName :
"", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, cmd_count);
21862 if (draw_list == GetWindowDrawList())
21865 TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f),
"CURRENTLY APPENDING");
21871 ImDrawList* fg_draw_list = viewport ? GetForegroundDrawList(viewport) : NULL;
21872 if (window && IsItemHovered() && fg_draw_list)
21873 fg_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
21877 if (window && !window->WasActive)
21878 TextDisabled(
"Warning: owning Window is inactive. This DrawList is not being rendered!");
21880 for (
const ImDrawCmd* pcmd = draw_list->CmdBuffer.Data; pcmd < draw_list->CmdBuffer.Data + cmd_count; pcmd++)
21882 if (pcmd->UserCallback)
21884 BulletText(
"Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData);
21888 char texid_desc[20];
21889 FormatTextureIDForDebugDisplay(texid_desc, IM_ARRAYSIZE(texid_desc), pcmd->TextureId);
21891 ImFormatString(buf, IM_ARRAYSIZE(buf),
"DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
21892 pcmd->ElemCount / 3, texid_desc, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
21893 bool pcmd_node_open =
TreeNode((
void*)(pcmd - draw_list->CmdBuffer.begin()),
"%s", buf);
21894 if (IsItemHovered() && (cfg->ShowDrawCmdMesh || cfg->ShowDrawCmdBoundingBoxes) && fg_draw_list)
21895 DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, cfg->ShowDrawCmdMesh, cfg->ShowDrawCmdBoundingBoxes);
21896 if (!pcmd_node_open)
21901 const ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
21902 const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + pcmd->VtxOffset;
21903 float total_area = 0.0f;
21904 for (
unsigned int idx_n = pcmd->IdxOffset; idx_n < pcmd->IdxOffset + pcmd->ElemCount; )
21906 ImVec2 triangle[3];
21907 for (
int n = 0; n < 3; n++, idx_n++)
21908 triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos;
21909 total_area += ImTriangleArea(triangle[0], triangle[1], triangle[2]);
21913 ImFormatString(buf, IM_ARRAYSIZE(buf),
"Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area);
21915 if (IsItemHovered() && fg_draw_list)
21916 DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd,
true,
false);
21919 ImGuiListClipper clipper;
21920 clipper.Begin(pcmd->ElemCount / 3);
21921 while (clipper.Step())
21922 for (
int prim = clipper.DisplayStart, idx_i = pcmd->IdxOffset + clipper.DisplayStart * 3; prim < clipper.DisplayEnd; prim++)
21924 char* buf_p = buf, * buf_end = buf + IM_ARRAYSIZE(buf);
21925 ImVec2 triangle[3];
21926 for (
int n = 0; n < 3; n++, idx_i++)
21928 const ImDrawVert& v = vtx_buffer[idx_buffer ? idx_buffer[idx_i] : idx_i];
21929 triangle[n] = v.pos;
21930 buf_p +=
ImFormatString(buf_p, buf_end - buf_p,
"%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n",
21931 (n == 0) ?
"Vert:" :
" ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);
21934 Selectable(buf,
false);
21935 if (fg_draw_list && IsItemHovered())
21937 ImDrawListFlags backup_flags = fg_draw_list->Flags;
21938 fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines;
21939 fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f);
21940 fg_draw_list->Flags = backup_flags;
21949void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list,
const ImDrawList* draw_list,
const ImDrawCmd* draw_cmd,
bool show_mesh,
bool show_aabb)
21951 IM_ASSERT(show_mesh || show_aabb);
21954 ImRect clip_rect = draw_cmd->ClipRect;
21955 ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
21956 ImDrawListFlags backup_flags = out_draw_list->Flags;
21957 out_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines;
21958 for (
unsigned int idx_n = draw_cmd->IdxOffset, idx_end = draw_cmd->IdxOffset + draw_cmd->ElemCount; idx_n < idx_end; )
21960 ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
21961 ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + draw_cmd->VtxOffset;
21963 ImVec2 triangle[3];
21964 for (
int n = 0; n < 3; n++, idx_n++)
21965 vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos));
21967 out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f);
21972 out_draw_list->AddRect(ImTrunc(clip_rect.Min), ImTrunc(clip_rect.Max), IM_COL32(255, 0, 255, 255));
21973 out_draw_list->AddRect(ImTrunc(vtxs_rect.Min), ImTrunc(vtxs_rect.Max), IM_COL32(0, 255, 255, 255));
21975 out_draw_list->Flags = backup_flags;
21979void ImGui::DebugNodeFont(ImFont* font)
21981 bool opened =
TreeNode(font,
"Font: \"%s\"\n%.2f px, %d glyphs, %d file(s)",
21982 font->ConfigData ? font->ConfigData[0].Name :
"", font->FontSize, font->Glyphs.Size, font->ConfigDataCount);
21984 if (SmallButton(
"Set as default"))
21985 GetIO().FontDefault = font;
21991 Text(
"The quick brown fox jumps over the lazy dog");
21995 SetNextItemWidth(GetFontSize() * 8);
21996 DragFloat(
"Font scale", &font->Scale, 0.005f, 0.3f, 2.0f,
"%.1f");
21997 SameLine(); MetricsHelpMarker(
21998 "Note that the default embedded font is NOT meant to be scaled.\n\n"
21999 "Font are currently rendered into bitmaps at a given size at the time of building the atlas. "
22000 "You may oversample them to get some flexibility with scaling. "
22001 "You can also render at multiple sizes and select which one to use at runtime.\n\n"
22002 "(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)");
22003 Text(
"Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
22005 Text(
"Fallback character: '%s' (U+%04X)",
ImTextCharToUtf8(c_str, font->FallbackChar), font->FallbackChar);
22006 Text(
"Ellipsis character: '%s' (U+%04X)",
ImTextCharToUtf8(c_str, font->EllipsisChar), font->EllipsisChar);
22007 const int surface_sqrt = (int)ImSqrt((
float)font->MetricsTotalSurface);
22008 Text(
"Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt);
22009 for (
int config_i = 0; config_i < font->ConfigDataCount; config_i++)
22010 if (font->ConfigData)
22011 if (
const ImFontConfig* cfg = &font->ConfigData[config_i])
22012 BulletText(
"Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d, Offset: (%.1f,%.1f)",
22013 config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y);
22016 if (
TreeNode(
"Glyphs",
"Glyphs (%d)", font->Glyphs.Size))
22018 ImDrawList* draw_list = GetWindowDrawList();
22019 const ImU32 glyph_col = GetColorU32(ImGuiCol_Text);
22020 const float cell_size = font->FontSize * 1;
22021 const float cell_spacing = GetStyle().ItemSpacing.y;
22022 for (
unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256)
22027 if (!(base & 4095) && font->IsGlyphRangeUnused(base, base + 4095))
22029 base += 4096 - 256;
22034 for (
unsigned int n = 0; n < 256; n++)
22035 if (font->FindGlyphNoFallback((ImWchar)(base + n)))
22039 if (!
TreeNode((
void*)(intptr_t)base,
"U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ?
"glyphs" :
"glyph"))
22043 ImVec2 base_pos = GetCursorScreenPos();
22044 for (
unsigned int n = 0; n < 256; n++)
22048 ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));
22049 ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
22050 const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));
22051 draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
22054 font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n));
22055 if (IsMouseHoveringRect(cell_p1, cell_p2) && BeginTooltip())
22057 DebugNodeFontGlyph(font, glyph);
22061 Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));
22069void ImGui::DebugNodeFontGlyph(ImFont*,
const ImFontGlyph* glyph)
22071 Text(
"Codepoint: U+%04X", glyph->Codepoint);
22073 Text(
"Visible: %d", glyph->Visible);
22074 Text(
"AdvanceX: %.1f", glyph->AdvanceX);
22075 Text(
"Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
22076 Text(
"UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
22080void ImGui::DebugNodeStorage(ImGuiStorage* storage,
const char* label)
22082 if (!
TreeNode(label,
"%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes()))
22084 for (
const ImGuiStoragePair& p : storage->Data)
22086 BulletText(
"Key 0x%08X Value { i: %d }", p.key, p.val_i);
22087 DebugLocateItemOnHover(p.key);
22093void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar,
const char* label)
22098 const char* buf_end = buf + IM_ARRAYSIZE(buf);
22099 const bool is_active = (tab_bar->PrevFrameVisible >= GetFrameCount() - 2);
22100 p +=
ImFormatString(p, buf_end - p,
"%s 0x%08X (%d tabs)%s {", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ?
"" :
" *Inactive*");
22101 for (
int tab_n = 0; tab_n < ImMin(tab_bar->Tabs.Size, 3); tab_n++)
22103 ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
22104 p +=
ImFormatString(p, buf_end - p,
"%s'%s'", tab_n > 0 ?
", " :
"", TabBarGetTabName(tab_bar, tab));
22106 p +=
ImFormatString(p, buf_end - p, (tab_bar->Tabs.Size > 3) ?
" ... }" :
" } ");
22107 if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
22108 bool open =
TreeNode(label,
"%s", buf);
22109 if (!is_active) { PopStyleColor(); }
22110 if (is_active && IsItemHovered())
22112 ImDrawList* draw_list = GetForegroundDrawList();
22113 draw_list->AddRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, IM_COL32(255, 255, 0, 255));
22114 draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255));
22115 draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255));
22119 for (
int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
22121 ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
22123 if (SmallButton(
"<")) { TabBarQueueReorder(tab_bar, tab, -1); } SameLine(0, 2);
22124 if (SmallButton(
">")) { TabBarQueueReorder(tab_bar, tab, +1); } SameLine();
22125 Text(
"%02d%c Tab 0x%08X '%s' Offset: %.2f, Width: %.2f/%.2f",
22126 tab_n, (tab->ID == tab_bar->SelectedTabId) ?
'*' :
' ', tab->
ID, TabBarGetTabName(tab_bar, tab), tab->Offset, tab->Width, tab->ContentWidth);
22133void ImGui::DebugNodeViewport(ImGuiViewportP* viewport)
22136 SetNextItemOpen(
true, ImGuiCond_Once);
22137 bool open =
TreeNode((
void*)(intptr_t)viewport->ID,
"Viewport #%d, ID: 0x%08X, Parent: 0x%08X, Window: \"%s\"", viewport->Idx, viewport->ID, viewport->ParentViewportId, viewport->Window ? viewport->Window->Name :
"N/A");
22138 if (IsItemHovered())
22139 g.DebugMetricsConfig.HighlightViewportID = viewport->ID;
22142 ImGuiWindowFlags flags = viewport->Flags;
22143 BulletText(
"Main Pos: (%.0f,%.0f), Size: (%.0f,%.0f)\nWorkArea Inset Left: %.0f Top: %.0f, Right: %.0f, Bottom: %.0f\nMonitor: %d, DpiScale: %.0f%%",
22144 viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y,
22145 viewport->WorkInsetMin.x, viewport->WorkInsetMin.y, viewport->WorkInsetMax.x, viewport->WorkInsetMax.y,
22146 viewport->PlatformMonitor, viewport->DpiScale * 100.0f);
22147 if (viewport->Idx > 0) { SameLine();
if (SmallButton(
"Reset Pos")) { viewport->Pos = ImVec2(200, 200); viewport->UpdateWorkRect();
if (viewport->Window) viewport->Window->Pos = viewport->Pos; } }
22148 BulletText(
"Flags: 0x%04X =%s%s%s%s%s%s%s%s%s%s%s%s%s", viewport->Flags,
22150 (flags & ImGuiViewportFlags_IsPlatformMonitor) ?
" IsPlatformMonitor" :
"",
22151 (flags & ImGuiViewportFlags_IsMinimized) ?
" IsMinimized" :
"",
22152 (flags & ImGuiViewportFlags_IsFocused) ?
" IsFocused" :
"",
22153 (flags & ImGuiViewportFlags_OwnedByApp) ?
" OwnedByApp" :
"",
22154 (flags & ImGuiViewportFlags_NoDecoration) ?
" NoDecoration" :
"",
22155 (flags & ImGuiViewportFlags_NoTaskBarIcon) ?
" NoTaskBarIcon" :
"",
22156 (flags & ImGuiViewportFlags_NoFocusOnAppearing) ?
" NoFocusOnAppearing" :
"",
22157 (flags & ImGuiViewportFlags_NoFocusOnClick) ?
" NoFocusOnClick" :
"",
22158 (flags & ImGuiViewportFlags_NoInputs) ?
" NoInputs" :
"",
22159 (flags & ImGuiViewportFlags_NoRendererClear) ?
" NoRendererClear" :
"",
22160 (flags & ImGuiViewportFlags_NoAutoMerge) ?
" NoAutoMerge" :
"",
22161 (flags & ImGuiViewportFlags_TopMost) ?
" TopMost" :
"",
22162 (flags & ImGuiViewportFlags_CanHostOtherWindows) ?
" CanHostOtherWindows" :
"");
22163 for (ImDrawList* draw_list : viewport->DrawDataP.CmdLists)
22164 DebugNodeDrawList(NULL, viewport, draw_list,
"DrawList");
22169void ImGui::DebugNodePlatformMonitor(ImGuiPlatformMonitor* monitor,
const char* label,
int idx)
22171 BulletText(
"%s %d: DPI %.0f%%\n MainMin (%.0f,%.0f), MainMax (%.0f,%.0f), MainSize (%.0f,%.0f)\n WorkMin (%.0f,%.0f), WorkMax (%.0f,%.0f), WorkSize (%.0f,%.0f)",
22172 label, idx, monitor->DpiScale * 100.0f,
22173 monitor->MainPos.x, monitor->MainPos.y, monitor->MainPos.x + monitor->MainSize.x, monitor->MainPos.y + monitor->MainSize.y, monitor->MainSize.x, monitor->MainSize.y,
22174 monitor->WorkPos.x, monitor->WorkPos.y, monitor->WorkPos.x + monitor->WorkSize.x, monitor->WorkPos.y + monitor->WorkSize.y, monitor->WorkSize.x, monitor->WorkSize.y);
22177void ImGui::DebugNodeWindow(ImGuiWindow* window,
const char* label)
22179 if (window == NULL)
22181 BulletText(
"%s: NULL", label);
22186 const bool is_active = window->WasActive;
22187 ImGuiTreeNodeFlags tree_node_flags = (window ==
g.NavWindow) ? ImGuiTreeNodeFlags_Selected : ImGuiTreeNodeFlags_None;
22188 if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
22189 const bool open = TreeNodeEx(label, tree_node_flags,
"%s '%s'%s", label, window->Name, is_active ?
"" :
" *Inactive*");
22190 if (!is_active) { PopStyleColor(); }
22191 if (IsItemHovered() && is_active)
22192 GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
22196 if (window->MemoryCompacted)
22197 TextDisabled(
"Note: some memory buffers have been compacted/freed.");
22199 if (
g.IO.ConfigDebugIsDebuggerPresent && DebugBreakButton(
"**DebugBreak**",
"in Begin()"))
22200 g.DebugBreakInWindow = window->ID;
22202 ImGuiWindowFlags flags = window->Flags;
22203 DebugNodeDrawList(window, window->Viewport, window->DrawList,
"DrawList");
22204 BulletText(
"Pos: (%.1f,%.1f), Size: (%.1f,%.1f), ContentSize (%.1f,%.1f) Ideal (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->ContentSize.x, window->ContentSize.y, window->ContentSizeIdeal.x, window->ContentSizeIdeal.y);
22205 BulletText(
"Flags: 0x%08X (%s%s%s%s%s%s%s%s%s..)", flags,
22206 (flags & ImGuiWindowFlags_ChildWindow) ?
"Child " :
"", (flags & ImGuiWindowFlags_Tooltip) ?
"Tooltip " :
"", (flags & ImGuiWindowFlags_Popup) ?
"Popup " :
"",
22207 (flags & ImGuiWindowFlags_Modal) ?
"Modal " :
"", (flags & ImGuiWindowFlags_ChildMenu) ?
"ChildMenu " :
"", (flags & ImGuiWindowFlags_NoSavedSettings) ?
"NoSavedSettings " :
"",
22208 (flags & ImGuiWindowFlags_NoMouseInputs)?
"NoMouseInputs":
"", (flags & ImGuiWindowFlags_NoNavInputs) ?
"NoNavInputs" :
"", (flags & ImGuiWindowFlags_AlwaysAutoResize) ?
"AlwaysAutoResize" :
"");
22209 if (flags & ImGuiWindowFlags_ChildWindow)
22210 BulletText(
"ChildFlags: 0x%08X (%s%s%s%s..)", window->ChildFlags,
22211 (window->ChildFlags & ImGuiChildFlags_Borders) ?
"Borders " :
"",
22212 (window->ChildFlags & ImGuiChildFlags_ResizeX) ?
"ResizeX " :
"",
22213 (window->ChildFlags & ImGuiChildFlags_ResizeY) ?
"ResizeY " :
"",
22214 (window->ChildFlags & ImGuiChildFlags_NavFlattened) ?
"NavFlattened " :
"");
22215 BulletText(
"WindowClassId: 0x%08X", window->WindowClass.ClassId);
22216 BulletText(
"Scroll: (%.2f/%.2f,%.2f/%.2f) Scrollbar:%s%s", window->Scroll.x, window->ScrollMax.x, window->Scroll.y, window->ScrollMax.y, window->ScrollbarX ?
"X" :
"", window->ScrollbarY ?
"Y" :
"");
22217 BulletText(
"Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1);
22218 BulletText(
"Appearing: %d, Hidden: %d (CanSkip %d Cannot %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesCanSkipItems, window->HiddenFramesCannotSkipItems, window->SkipItems);
22219 for (
int layer = 0; layer < ImGuiNavLayer_COUNT; layer++)
22221 ImRect r = window->NavRectRel[layer];
22222 if (r.Min.x >= r.Max.x && r.Min.y >= r.Max.y)
22223 BulletText(
"NavLastIds[%d]: 0x%08X", layer, window->NavLastIds[layer]);
22225 BulletText(
"NavLastIds[%d]: 0x%08X at +(%.1f,%.1f)(%.1f,%.1f)", layer, window->NavLastIds[layer], r.Min.x, r.Min.y, r.Max.x, r.Max.y);
22226 DebugLocateItemOnHover(window->NavLastIds[layer]);
22228 const ImVec2* pr = window->NavPreferredScoringPosRel;
22229 for (
int layer = 0; layer < ImGuiNavLayer_COUNT; layer++)
22230 BulletText(
"NavPreferredScoringPosRel[%d] = {%.1f,%.1f)", layer, (pr[layer].x == FLT_MAX ? -99999.0f : pr[layer].x), (pr[layer].y == FLT_MAX ? -99999.0f : pr[layer].y));
22231 BulletText(
"NavLayersActiveMask: %X, NavLastChildNavWindow: %s", window->DC.NavLayersActiveMask, window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name :
"NULL");
22233 BulletText(
"Viewport: %d%s, ViewportId: 0x%08X, ViewportPos: (%.1f,%.1f)", window->Viewport ? window->Viewport->Idx : -1, window->ViewportOwned ?
" (Owned)" :
"", window->ViewportId, window->ViewportPos.x, window->ViewportPos.y);
22234 BulletText(
"ViewportMonitor: %d", window->Viewport ? window->Viewport->PlatformMonitor : -1);
22235 BulletText(
"DockId: 0x%04X, DockOrder: %d, Act: %d, Vis: %d", window->DockId, window->DockOrder, window->DockIsActive, window->DockTabIsVisible);
22236 if (window->DockNode || window->DockNodeAsHost)
22237 DebugNodeDockNode(window->DockNodeAsHost ? window->DockNodeAsHost : window->DockNode, window->DockNodeAsHost ?
"DockNodeAsHost" :
"DockNode");
22239 if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow,
"RootWindow"); }
22240 if (window->RootWindowDockTree != window->RootWindow) { DebugNodeWindow(window->RootWindowDockTree,
"RootWindowDockTree"); }
22241 if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow,
"ParentWindow"); }
22242 if (window->ParentWindowForFocusRoute != NULL) { DebugNodeWindow(window->ParentWindowForFocusRoute,
"ParentWindowForFocusRoute"); }
22243 if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows,
"ChildWindows"); }
22244 if (window->ColumnsStorage.Size > 0 &&
TreeNode(
"Columns",
"Columns sets (%d)", window->ColumnsStorage.Size))
22246 for (ImGuiOldColumns& columns : window->ColumnsStorage)
22247 DebugNodeColumns(&columns);
22250 DebugNodeStorage(&window->StateStorage,
"Storage");
22254void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings* settings)
22256 if (settings->WantDelete)
22258 Text(
"0x%08X \"%s\" Pos (%d,%d) Size (%d,%d) Collapsed=%d",
22259 settings->ID, settings->GetName(), settings->Pos.x, settings->Pos.y, settings->Size.x, settings->Size.y, settings->Collapsed);
22260 if (settings->WantDelete)
22264void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows,
const char* label)
22266 if (!
TreeNode(label,
"%s (%d)", label, windows->Size))
22268 for (
int i = windows->Size - 1; i >= 0; i--)
22270 PushID((*windows)[i]);
22271 DebugNodeWindow((*windows)[i],
"Window");
22278void ImGui::DebugNodeWindowsListByBeginStackParent(ImGuiWindow** windows,
int windows_size, ImGuiWindow* parent_in_begin_stack)
22280 for (
int i = 0; i < windows_size; i++)
22282 ImGuiWindow* window = windows[i];
22283 if (window->ParentWindowInBeginStack != parent_in_begin_stack)
22286 ImFormatString(buf, IM_ARRAYSIZE(buf),
"[%04d] Window", window->BeginOrderWithinContext);
22288 DebugNodeWindow(window, buf);
22290 DebugNodeWindowsListByBeginStackParent(windows + i + 1, windows_size - i - 1, window);
22299void ImGui::DebugLog(
const char* fmt, ...)
22302 va_start(args, fmt);
22303 DebugLogV(fmt, args);
22307void ImGui::DebugLogV(
const char* fmt, va_list args)
22310 const int old_size =
g.DebugLogBuf.size();
22311 if (
g.ContextName[0] != 0)
22312 g.DebugLogBuf.appendf(
"[%s] [%05d] ",
g.ContextName,
g.FrameCount);
22314 g.DebugLogBuf.appendf(
"[%05d] ",
g.FrameCount);
22315 g.DebugLogBuf.appendfv(fmt, args);
22316 g.DebugLogIndex.append(
g.DebugLogBuf.c_str(), old_size,
g.DebugLogBuf.size());
22317 if (
g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTTY)
22318 IMGUI_DEBUG_PRINTF(
"%s",
g.DebugLogBuf.begin() + old_size);
22319#ifdef IMGUI_ENABLE_TEST_ENGINE
22321 const int new_size =
g.DebugLogBuf.size();
22322 const bool trailing_carriage_return = (
g.DebugLogBuf[new_size - 1] ==
'\n');
22323 if (
g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTestEngine)
22324 IMGUI_TEST_ENGINE_LOG(
"%.*s", new_size - old_size - (trailing_carriage_return ? 1 : 0),
g.DebugLogBuf.
begin() + old_size);
22329static void SameLineOrWrap(
const ImVec2& size)
22332 ImGuiWindow* window =
g.CurrentWindow;
22333 ImVec2 pos(window->DC.CursorPosPrevLine.x +
g.Style.ItemSpacing.x, window->DC.CursorPosPrevLine.y);
22334 if (window->WorkRect.Contains(ImRect(pos, pos + size)))
22338static void ShowDebugLogFlag(
const char* name, ImGuiDebugLogFlags flags)
22341 ImVec2
size(ImGui::GetFrameHeight() +
g.Style.ItemInnerSpacing.x +
ImGui::CalcTextSize(name).x, ImGui::GetFrameHeight());
22342 SameLineOrWrap(size);
22344 bool highlight_errors = (flags == ImGuiDebugLogFlags_EventError &&
g.DebugLogSkippedErrors > 0);
22345 if (highlight_errors)
22346 ImGui::PushStyleColor(ImGuiCol_Text, ImLerp(
g.Style.Colors[ImGuiCol_Text], ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.30f));
22347 if (ImGui::CheckboxFlags(name, &
g.DebugLogFlags, flags) &&
g.IO.KeyShift && (
g.DebugLogFlags & flags) != 0)
22349 g.DebugLogAutoDisableFrames = 2;
22350 g.DebugLogAutoDisableFlags |= flags;
22352 if (highlight_errors)
22354 ImGui::PopStyleColor();
22355 ImGui::SetItemTooltip(
"%d past errors skipped.",
g.DebugLogSkippedErrors);
22359 ImGui::SetItemTooltip(
"Hold SHIFT when clicking to enable for 2 frames only (useful for spammy log entries)");
22363void ImGui::ShowDebugLogWindow(
bool* p_open)
22366 if ((
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0)
22367 SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 12.0f), ImGuiCond_FirstUseEver);
22368 if (!Begin(
"Dear ImGui Debug Log", p_open) || GetCurrentWindow()->BeginCount > 1)
22374 ImGuiDebugLogFlags all_enable_flags = ImGuiDebugLogFlags_EventMask_ & ~ImGuiDebugLogFlags_EventInputRouting;
22375 CheckboxFlags(
"All", &
g.DebugLogFlags, all_enable_flags);
22376 SetItemTooltip(
"(except InputRouting which is spammy)");
22378 ShowDebugLogFlag(
"Errors", ImGuiDebugLogFlags_EventError);
22379 ShowDebugLogFlag(
"ActiveId", ImGuiDebugLogFlags_EventActiveId);
22380 ShowDebugLogFlag(
"Clipper", ImGuiDebugLogFlags_EventClipper);
22381 ShowDebugLogFlag(
"Docking", ImGuiDebugLogFlags_EventDocking);
22382 ShowDebugLogFlag(
"Focus", ImGuiDebugLogFlags_EventFocus);
22383 ShowDebugLogFlag(
"IO", ImGuiDebugLogFlags_EventIO);
22384 ShowDebugLogFlag(
"Nav", ImGuiDebugLogFlags_EventNav);
22385 ShowDebugLogFlag(
"Popup", ImGuiDebugLogFlags_EventPopup);
22386 ShowDebugLogFlag(
"Selection", ImGuiDebugLogFlags_EventSelection);
22387 ShowDebugLogFlag(
"Viewport", ImGuiDebugLogFlags_EventViewport);
22388 ShowDebugLogFlag(
"InputRouting", ImGuiDebugLogFlags_EventInputRouting);
22390 if (SmallButton(
"Clear"))
22392 g.DebugLogBuf.clear();
22393 g.DebugLogIndex.clear();
22394 g.DebugLogSkippedErrors = 0;
22397 if (SmallButton(
"Copy"))
22398 SetClipboardText(
g.DebugLogBuf.c_str());
22400 if (SmallButton(
"Configure Outputs.."))
22401 OpenPopup(
"Outputs");
22402 if (BeginPopup(
"Outputs"))
22404 CheckboxFlags(
"OutputToTTY", &
g.DebugLogFlags, ImGuiDebugLogFlags_OutputToTTY);
22405#ifndef IMGUI_ENABLE_TEST_ENGINE
22408 CheckboxFlags(
"OutputToTestEngine", &
g.DebugLogFlags, ImGuiDebugLogFlags_OutputToTestEngine);
22409#ifndef IMGUI_ENABLE_TEST_ENGINE
22415 BeginChild(
"##log", ImVec2(0.0f, 0.0f), ImGuiChildFlags_Borders, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar);
22417 const ImGuiDebugLogFlags backup_log_flags =
g.DebugLogFlags;
22418 g.DebugLogFlags &= ~ImGuiDebugLogFlags_EventClipper;
22420 ImGuiListClipper clipper;
22421 clipper.Begin(
g.DebugLogIndex.size());
22422 while (clipper.Step())
22423 for (
int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
22424 DebugTextUnformattedWithLocateItem(
g.DebugLogIndex.get_line_begin(
g.DebugLogBuf.c_str(), line_no),
g.DebugLogIndex.get_line_end(
g.DebugLogBuf.c_str(), line_no));
22425 g.DebugLogFlags = backup_log_flags;
22426 if (GetScrollY() >= GetScrollMaxY())
22427 SetScrollHereY(1.0f);
22434void ImGui::DebugTextUnformattedWithLocateItem(
const char* line_begin,
const char* line_end)
22437 if (!IsItemHovered())
22440 ImRect text_rect =
g.LastItemData.Rect;
22441 for (
const char* p = line_begin; p <= line_end - 10; p++)
22444 if (p[0] !=
'0' || (p[1] !=
'x' && p[1] !=
'X') || sscanf(p + 2,
"%X", &
id) != 1 || ImCharIsXdigitA(p[10]))
22448 g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0f), text_rect.Min + ImVec2(p0.x + p1.x, p1.y));
22449 if (IsMouseHoveringRect(
g.LastItemData.Rect.Min,
g.LastItemData.Rect.Max,
true))
22450 DebugLocateItemOnHover(
id);
22460void ImGui::DebugDrawCursorPos(ImU32 col)
22463 ImGuiWindow* window =
g.CurrentWindow;
22464 ImVec2 pos = window->DC.CursorPos;
22465 window->DrawList->AddLine(ImVec2(pos.x, pos.y - 3.0f), ImVec2(pos.x, pos.y + 4.0f), col, 1.0f);
22466 window->DrawList->AddLine(ImVec2(pos.x - 3.0f, pos.y), ImVec2(pos.x + 4.0f, pos.y), col, 1.0f);
22470void ImGui::DebugDrawLineExtents(ImU32 col)
22473 ImGuiWindow* window =
g.CurrentWindow;
22474 float curr_x = window->DC.CursorPos.x;
22475 float line_y1 = (window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y);
22476 float line_y2 = line_y1 + (window->DC.IsSameLine ? window->DC.PrevLineSize.y : window->DC.CurrLineSize.y);
22477 window->DrawList->AddLine(ImVec2(curr_x - 5.0f, line_y1), ImVec2(curr_x + 5.0f, line_y1), col, 1.0f);
22478 window->DrawList->AddLine(ImVec2(curr_x - 0.5f, line_y1), ImVec2(curr_x - 0.5f, line_y2), col, 1.0f);
22479 window->DrawList->AddLine(ImVec2(curr_x - 5.0f, line_y2), ImVec2(curr_x + 5.0f, line_y2), col, 1.0f);
22483void ImGui::DebugDrawItemRect(ImU32 col)
22486 ImGuiWindow* window =
g.CurrentWindow;
22487 GetForegroundDrawList(window)->AddRect(
g.LastItemData.Rect.Min,
g.LastItemData.Rect.Max, col);
22491static const ImU32 DEBUG_LOCATE_ITEM_COLOR = IM_COL32(0, 255, 0, 255);
22493void ImGui::DebugLocateItem(ImGuiID target_id)
22496 g.DebugLocateId = target_id;
22497 g.DebugLocateFrames = 2;
22498 g.DebugBreakInLocateId =
false;
22502void ImGui::DebugLocateItemOnHover(ImGuiID target_id)
22504 if (target_id == 0 || !IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenBlockedByPopup))
22507 DebugLocateItem(target_id);
22508 GetForegroundDrawList(
g.CurrentWindow)->AddRect(
g.LastItemData.Rect.Min - ImVec2(3.0f, 3.0f),
g.LastItemData.Rect.Max + ImVec2(3.0f, 3.0f), DEBUG_LOCATE_ITEM_COLOR);
22511 if (
g.IO.ConfigDebugIsDebuggerPresent &&
g.MouseStationaryTimer > 1.0f)
22513 DebugBreakButtonTooltip(
false,
"in ItemAdd()");
22514 if (IsKeyChordPressed(
g.DebugBreakKeyChord))
22515 g.DebugBreakInLocateId =
true;
22519void ImGui::DebugLocateItemResolveWithLastItem()
22524 if (
g.DebugBreakInLocateId)
22527 ImGuiLastItemData item_data =
g.LastItemData;
22528 g.DebugLocateId = 0;
22529 ImDrawList* draw_list = GetForegroundDrawList(
g.CurrentWindow);
22530 ImRect r = item_data.Rect;
22532 ImVec2 p1 =
g.IO.MousePos;
22533 ImVec2 p2 = ImVec2((p1.x < r.Min.x) ? r.Min.x : (p1.x > r.Max.x) ? r.Max.x : p1.x, (p1.y < r.Min.y) ? r.Min.y : (p1.y > r.Max.y) ? r.Max.y : p1.y);
22534 draw_list->AddRect(r.Min, r.Max, DEBUG_LOCATE_ITEM_COLOR);
22535 draw_list->AddLine(p1, p2, DEBUG_LOCATE_ITEM_COLOR);
22538void ImGui::DebugStartItemPicker()
22541 g.DebugItemPickerActive =
true;
22545void ImGui::UpdateDebugToolItemPicker()
22548 g.DebugItemPickerBreakId = 0;
22549 if (!
g.DebugItemPickerActive)
22552 const ImGuiID hovered_id =
g.HoveredIdPreviousFrame;
22553 SetMouseCursor(ImGuiMouseCursor_Hand);
22554 if (IsKeyPressed(ImGuiKey_Escape))
22555 g.DebugItemPickerActive =
false;
22556 const bool change_mapping =
g.IO.KeyMods == (ImGuiMod_Ctrl | ImGuiMod_Shift);
22557 if (!change_mapping && IsMouseClicked(
g.DebugItemPickerMouseButton) && hovered_id)
22559 g.DebugItemPickerBreakId = hovered_id;
22560 g.DebugItemPickerActive =
false;
22562 for (
int mouse_button = 0; mouse_button < 3; mouse_button++)
22563 if (change_mapping && IsMouseClicked(mouse_button))
22564 g.DebugItemPickerMouseButton = (ImU8)mouse_button;
22565 SetNextWindowBgAlpha(0.70f);
22566 if (!BeginTooltip())
22568 Text(
"HoveredId: 0x%08X", hovered_id);
22569 Text(
"Press ESC to abort picking.");
22570 const char* mouse_button_names[] = {
"Left",
"Right",
"Middle" };
22571 if (change_mapping)
22572 Text(
"Remap w/ Ctrl+Shift: click anywhere to select new mouse button.");
22574 TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled),
"Click %s Button to break in debugger! (remap w/ Ctrl+Shift)", mouse_button_names[
g.DebugItemPickerMouseButton]);
22579void ImGui::UpdateDebugToolStackQueries()
22582 ImGuiIDStackTool* tool = &
g.DebugIDStackTool;
22585 g.DebugHookIdInfo = 0;
22586 if (
g.FrameCount != tool->LastActiveFrame + 1)
22591 const ImGuiID query_id =
g.HoveredIdPreviousFrame ?
g.HoveredIdPreviousFrame :
g.ActiveId;
22592 if (tool->QueryId != query_id)
22594 tool->QueryId = query_id;
22595 tool->StackLevel = -1;
22596 tool->Results.resize(0);
22602 int stack_level = tool->StackLevel;
22603 if (stack_level >= 0 && stack_level < tool->Results.Size)
22604 if (tool->Results[stack_level].QuerySuccess || tool->Results[stack_level].QueryFrameCount > 2)
22605 tool->StackLevel++;
22608 stack_level = tool->StackLevel;
22609 if (stack_level == -1)
22610 g.DebugHookIdInfo = query_id;
22611 if (stack_level >= 0 && stack_level < tool->Results.Size)
22613 g.DebugHookIdInfo = tool->Results[stack_level].ID;
22614 tool->Results[stack_level].QueryFrameCount++;
22619void ImGui::DebugHookIdInfo(ImGuiID
id, ImGuiDataType data_type,
const void* data_id,
const void* data_id_end)
22622 ImGuiWindow* window =
g.CurrentWindow;
22623 ImGuiIDStackTool* tool = &
g.DebugIDStackTool;
22627 if (tool->StackLevel == -1)
22629 tool->StackLevel++;
22630 tool->Results.resize(window->IDStack.Size + 1, ImGuiStackLevelInfo());
22631 for (
int n = 0; n < window->IDStack.Size + 1; n++)
22632 tool->Results[n].ID = (n < window->IDStack.Size) ? window->IDStack[n] :
id;
22637 IM_ASSERT(tool->StackLevel >= 0);
22638 if (tool->StackLevel != window->IDStack.Size)
22640 ImGuiStackLevelInfo* info = &tool->Results[tool->StackLevel];
22641 IM_ASSERT(info->ID ==
id && info->QueryFrameCount > 0);
22645 case ImGuiDataType_S32:
22646 ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc),
"%d", (
int)(intptr_t)data_id);
22648 case ImGuiDataType_String:
22649 ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc),
"%.*s", data_id_end ? (
int)((
const char*)data_id_end - (
const char*)data_id) : (int)strlen((const char*)data_id), (const char*)data_id);
22651 case ImGuiDataType_Pointer:
22652 ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc),
"(void*)0x%p", data_id);
22654 case ImGuiDataType_ID:
22655 if (info->Desc[0] != 0)
22657 ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc),
"0x%08X [override]",
id);
22662 info->QuerySuccess =
true;
22663 info->DataType = data_type;
22666static int StackToolFormatLevelInfo(ImGuiIDStackTool* tool,
int n,
bool format_for_ui,
char* buf,
size_t buf_size)
22668 ImGuiStackLevelInfo* info = &tool->Results[n];
22669 ImGuiWindow* window = (info->Desc[0] == 0 && n == 0) ? ImGui::FindWindowByID(info->ID) : NULL;
22671 return ImFormatString(buf, buf_size, format_for_ui ?
"\"%s\" [window]" :
"%s", window->Name);
22672 if (info->QuerySuccess)
22673 return ImFormatString(buf, buf_size, (format_for_ui && info->DataType == ImGuiDataType_String) ?
"\"%s\"" :
"%s", info->Desc);
22674 if (tool->StackLevel < tool->Results.Size)
22676#ifdef IMGUI_ENABLE_TEST_ENGINE
22677 if (
const char* label = ImGuiTestEngine_FindItemDebugLabel(
GImGui, info->ID))
22678 return ImFormatString(buf, buf_size, format_for_ui ?
"??? \"%s\"" :
"%s", label);
22684void ImGui::ShowIDStackToolWindow(
bool* p_open)
22687 if ((
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0)
22688 SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 8.0f), ImGuiCond_FirstUseEver);
22689 if (!Begin(
"Dear ImGui ID Stack Tool", p_open) || GetCurrentWindow()->BeginCount > 1)
22696 ImGuiIDStackTool* tool = &
g.DebugIDStackTool;
22697 const ImGuiID hovered_id =
g.HoveredIdPreviousFrame;
22698 const ImGuiID active_id =
g.ActiveId;
22699#ifdef IMGUI_ENABLE_TEST_ENGINE
22700 Text(
"HoveredId: 0x%08X (\"%s\"), ActiveId: 0x%08X (\"%s\")", hovered_id, hovered_id ? ImGuiTestEngine_FindItemDebugLabel(&
g, hovered_id) :
"", active_id, active_id ? ImGuiTestEngine_FindItemDebugLabel(&
g, active_id) :
"");
22702 Text(
"HoveredId: 0x%08X, ActiveId: 0x%08X", hovered_id, active_id);
22705 MetricsHelpMarker(
"Hover an item with the mouse to display elements of the ID Stack leading to the item's final ID.\nEach level of the stack correspond to a PushID() call.\nAll levels of the stack are hashed together to make the final ID of a widget (ID displayed at the bottom level of the stack).\nRead FAQ entry about the ID stack for details.");
22708 const float time_since_copy = (float)
g.Time - tool->CopyToClipboardLastTime;
22709 Checkbox(
"Ctrl+C: copy path to clipboard", &tool->CopyToClipboardOnCtrlC);
22711 TextColored((time_since_copy >= 0.0f && time_since_copy < 0.75f && ImFmod(time_since_copy, 0.25f) < 0.25f * 0.5f) ? ImVec4(1.f, 1.f, 0.3f, 1.f) : ImVec4(),
"*COPIED*");
22712 if (tool->CopyToClipboardOnCtrlC && Shortcut(ImGuiMod_Ctrl | ImGuiKey_C, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused))
22714 tool->CopyToClipboardLastTime = (float)
g.Time;
22715 char* p =
g.TempBuffer.Data;
22716 char* p_end = p +
g.TempBuffer.Size;
22717 for (
int stack_n = 0; stack_n < tool->Results.Size && p + 3 < p_end; stack_n++)
22720 char level_desc[256];
22721 StackToolFormatLevelInfo(tool, stack_n,
false, level_desc, IM_ARRAYSIZE(level_desc));
22722 for (
int n = 0; level_desc[n] && p + 2 < p_end; n++)
22724 if (level_desc[n] ==
'/')
22726 *p++ = level_desc[n];
22730 SetClipboardText(
g.TempBuffer.Data);
22734 tool->LastActiveFrame =
g.FrameCount;
22735 if (tool->Results.Size > 0 && BeginTable(
"##table", 3, ImGuiTableFlags_Borders))
22738 TableSetupColumn(
"Seed", ImGuiTableColumnFlags_WidthFixed, id_width);
22739 TableSetupColumn(
"PushID", ImGuiTableColumnFlags_WidthStretch);
22740 TableSetupColumn(
"Result", ImGuiTableColumnFlags_WidthFixed, id_width);
22742 for (
int n = 0; n < tool->Results.Size; n++)
22744 ImGuiStackLevelInfo* info = &tool->Results[n];
22746 Text(
"0x%08X", (n > 0) ? tool->Results[n - 1].ID : 0);
22748 StackToolFormatLevelInfo(tool, n,
true,
g.TempBuffer.Data,
g.TempBuffer.Size);
22751 Text(
"0x%08X", info->ID);
22752 if (n == tool->Results.Size - 1)
22753 TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_Header));
22762void ImGui::ShowMetricsWindow(
bool*) {}
22764void ImGui::DebugNodeColumns(ImGuiOldColumns*) {}
22765void ImGui::DebugNodeDrawList(ImGuiWindow*, ImGuiViewportP*,
const ImDrawList*,
const char*) {}
22766void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList*,
const ImDrawList*,
const ImDrawCmd*,
bool,
bool) {}
22767void ImGui::DebugNodeFont(ImFont*) {}
22768void ImGui::DebugNodeStorage(ImGuiStorage*,
const char*) {}
22769void ImGui::DebugNodeTabBar(ImGuiTabBar*,
const char*) {}
22770void ImGui::DebugNodeWindow(ImGuiWindow*,
const char*) {}
22771void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings*) {}
22772void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>*,
const char*) {}
22773void ImGui::DebugNodeViewport(ImGuiViewportP*) {}
22775void ImGui::ShowDebugLogWindow(
bool*) {}
22776void ImGui::ShowIDStackToolWindow(
bool*) {}
22777void ImGui::DebugStartItemPicker() {}
22778void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType,
const void*,
const void*) {}
22786#ifdef IMGUI_INCLUDE_IMGUI_USER_INL
22787#include "imgui_user.inl"
mat4 p4(vec4(1, 2, 3, 4), vec4(3, 4, 5, 6), vec4(5, 0, 7, 8), vec4(7, 8, 9, 0))
mat3 p3(vec3(1, 2, 3), vec3(4, 5, 6), vec3(7, 0, 9))
const char * ImStreolRange(const char *str, const char *str_end)
char * ImStrdupcpy(char *dst, size_t *p_dst_size, const char *src)
const char * ImStrbol(const char *buf_mid_line, const char *buf_begin)
#define va_copy(dest, src)
char * ImStrdup(const char *str)
int ImFormatStringV(char *buf, size_t buf_size, const char *fmt, va_list args)
ImVec2 ImBezierCubicClosestPointCasteljau(const ImVec2 &p1, const ImVec2 &p2, const ImVec2 &p3, const ImVec2 &p4, const ImVec2 &p, float tess_tol)
ImGuiStoragePair * ImLowerBound(ImGuiStoragePair *in_begin, ImGuiStoragePair *in_end, ImGuiID key)
void ImTriangleBarycentricCoords(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &p, float &out_u, float &out_v, float &out_w)
void ImFormatStringToTempBuffer(const char **out_buf, const char **out_buf_end, const char *fmt,...)
int ImTextStrToUtf8(char *out_buf, int out_buf_size, const ImWchar *in_text, const ImWchar *in_text_end)
int ImStrnicmp(const char *str1, const char *str2, size_t count)
int ImStrlenW(const ImWchar *str)
const char * ImStrchrRange(const char *str, const char *str_end, char c)
int ImFormatString(char *buf, size_t buf_size, const char *fmt,...)
ImVec2 ImLineClosestPoint(const ImVec2 &a, const ImVec2 &b, const ImVec2 &p)
void ImStrTrimBlanks(char *buf)
void ImFormatStringToTempBufferV(const char **out_buf, const char **out_buf_end, const char *fmt, va_list args)
IM_MSVC_RUNTIME_CHECKS_RESTORE IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b)
const char * ImStrSkipBlank(const char *str)
const char * ImTextCharToUtf8(char out_buf[5], unsigned int c)
bool ImTriangleContainsPoint(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &p)
ImU64 ImFileWrite(const void *data, ImU64 sz, ImU64 count, ImFileHandle f)
#define IMGUI_DEBUG_NAV_SCORING
int ImTextCountUtf8BytesFromStr(const ImWchar *in_text, const ImWchar *in_text_end)
ImU64 ImFileRead(void *data, ImU64 sz, ImU64 count, ImFileHandle f)
ImGuiID ImHashStr(const char *data_p, size_t data_size, ImGuiID seed)
const char * ImTextFindPreviousUtf8Codepoint(const char *in_text_start, const char *in_text_curr)
IM_MSVC_RUNTIME_CHECKS_OFF int ImTextCharFromUtf8(unsigned int *out_char, const char *in_text, const char *in_text_end)
int ImTextCountCharsFromUtf8(const char *in_text, const char *in_text_end)
@ ImGuiDockRequestType_Split
@ ImGuiDockRequestType_Dock
@ ImGuiDockRequestType_None
@ ImGuiDockRequestType_Undock
bool ImFileClose(ImFileHandle f)
void * ImFileLoadToMemory(const char *filename, const char *mode, size_t *out_file_size, int padding_bytes)
const char * ImStristr(const char *haystack, const char *haystack_end, const char *needle, const char *needle_end)
ImVec2 ImBezierCubicClosestPoint(const ImVec2 &p1, const ImVec2 &p2, const ImVec2 &p3, const ImVec2 &p4, const ImVec2 &p, int num_segments)
ImGuiID ImHashData(const void *data_p, size_t data_size, ImGuiID seed)
ImU64 ImFileGetSize(ImFileHandle f)
int ImStricmp(const char *str1, const char *str2)
int ImTextCountUtf8BytesFromChar(const char *in_text, const char *in_text_end)
ImFileHandle ImFileOpen(const char *filename, const char *mode)
IM_STATIC_ASSERT(ImGuiKey_NamedKey_COUNT==IM_ARRAYSIZE(GKeyNames))
int ImTextStrFromUtf8(ImWchar *buf, int buf_size, const char *in_text, const char *in_text_end, const char **in_text_remaining)
void ImStrncpy(char *dst, const char *src, size_t count)
ImVec2 ImTriangleClosestPoint(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &p)
int ImTextCountLines(const char *in_text, const char *in_text_end)
ImVec2 ImBezierCubicCalc(const ImVec2 &p1, const ImVec2 &p2, const ImVec2 &p3, const ImVec2 &p4, float t)
IMGUI_API void ShowFontAtlas(ImFontAtlas *atlas)
auto CalcTextSize(std::string_view str)
const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID
void TextUnformatted(const std::string &str)
T length(const vecN< N, T > &x)
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
constexpr mat4 scale(const vec3 &xyz)
void Window(const char *name, bool *p_open, ImGuiWindowFlags flags, std::invocable<> auto next)
void ID(const char *str_id, std::invocable<> auto next)
void TabBar(const char *str_id, ImGuiTabBarFlags flags, std::invocable<> auto next)
bool TreeNode(const char *label, ImGuiTreeNodeFlags flags, std::invocable<> auto next)
void Combo(const char *label, const char *preview_value, ImGuiComboFlags flags, std::invocable<> auto next)
void Font(ImFont *font, std::invocable<> auto next)
void Indent(float indent_w, std::invocable<> auto next)
bool Checkbox(const HotKey &hotKey, BooleanSetting &setting)
bool SliderInt(IntegerSetting &setting, ImGuiSliderFlags flags)
bool InputText(Setting &setting)
auto remove(ForwardRange &&range, const T &value)
auto count(InputRange &&range, const T &value)
size_t size(std::string_view utf8)
auto distance(octet_iterator first, octet_iterator last)
ImGuiDockContextPruneNodeData()
ImGuiDockNode * CentralNode
ImGuiDockNode * FirstNodeWithWindows
int CountNodesWithWindows
ImGuiDockNode * SplitNode
ImRect DropRectsDraw[ImGuiDir_COUNT+1]
ImGuiDockNode * UndockTargetNode
ImGuiWindow * DockPayload
ImGuiDockNode * DockTargetNode
ImGuiWindow * UndockTargetWindow
ImGuiDockRequestType Type
ImGuiWindow * DockTargetWindow
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
constexpr auto begin(const zstring_view &x)