998#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
999#define _CRT_SECURE_NO_WARNINGS
1002#ifndef IMGUI_DEFINE_MATH_OPERATORS
1003#define IMGUI_DEFINE_MATH_OPERATORS
1007#ifndef IMGUI_DISABLE
1008#include "imgui_internal.h"
1015#if defined(_WIN32) && !defined(_MSC_VER) && !defined(IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
1016#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
1020#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_WIN32_FUNCTIONS)
1021#define IMGUI_DISABLE_WIN32_FUNCTIONS
1023#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
1024#ifndef WIN32_LEAN_AND_MEAN
1025#define WIN32_LEAN_AND_MEAN
1035#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP || WINAPI_FAMILY == WINAPI_FAMILY_GAMES)
1037#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
1038#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
1043#if defined(__APPLE__)
1044#include <TargetConditionals.h>
1049#pragma warning (disable: 4127)
1050#pragma warning (disable: 4996)
1051#if defined(_MSC_VER) && _MSC_VER >= 1922
1052#pragma warning (disable: 5054)
1054#pragma warning (disable: 26451)
1055#pragma warning (disable: 26495)
1056#pragma warning (disable: 26812)
1060#if defined(__clang__)
1061#if __has_warning("-Wunknown-warning-option")
1062#pragma clang diagnostic ignored "-Wunknown-warning-option"
1064#pragma clang diagnostic ignored "-Wunknown-pragmas"
1065#pragma clang diagnostic ignored "-Wold-style-cast"
1066#pragma clang diagnostic ignored "-Wfloat-equal"
1067#pragma clang diagnostic ignored "-Wformat-nonliteral"
1068#pragma clang diagnostic ignored "-Wexit-time-destructors"
1069#pragma clang diagnostic ignored "-Wglobal-constructors"
1070#pragma clang diagnostic ignored "-Wsign-conversion"
1071#pragma clang diagnostic ignored "-Wformat-pedantic"
1072#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"
1073#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
1074#pragma clang diagnostic ignored "-Wdouble-promotion"
1075#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
1076#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
1077#elif defined(__GNUC__)
1079#pragma GCC diagnostic ignored "-Wpragmas"
1080#pragma GCC diagnostic ignored "-Wunused-function"
1081#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
1082#pragma GCC diagnostic ignored "-Wformat"
1083#pragma GCC diagnostic ignored "-Wdouble-promotion"
1084#pragma GCC diagnostic ignored "-Wconversion"
1085#pragma GCC diagnostic ignored "-Wformat-nonliteral"
1086#pragma GCC diagnostic ignored "-Wstrict-overflow"
1087#pragma GCC diagnostic ignored "-Wclass-memaccess"
1091#define IMGUI_DEBUG_NAV_SCORING 0
1092#define IMGUI_DEBUG_NAV_RECTS 0
1095static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f;
1096static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f;
1098static const float NAV_ACTIVATE_HIGHLIGHT_TIMER = 0.10f;
1101static const float WINDOWS_HOVER_PADDING = 4.0f;
1102static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f;
1103static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 0.70f;
1106static const ImVec2 TOOLTIP_DEFAULT_OFFSET = ImVec2(16, 10);
1109static const float DOCKING_TRANSPARENT_PAYLOAD_ALPHA = 0.50f;
1115static void SetCurrentWindow(ImGuiWindow* window);
1116static ImGuiWindow* CreateNewWindow(
const char* name, ImGuiWindowFlags flags);
1117static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window);
1119static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
1122static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*);
1123static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*,
const char* name);
1124static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
void* entry,
const char* line);
1125static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*);
1126static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf);
1129static const char* GetClipboardTextFn_DefaultImpl(
void* user_data_ctx);
1130static void SetClipboardTextFn_DefaultImpl(
void* user_data_ctx,
const char* text);
1131static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatformImeData* data);
1136static void ItemHandleShortcut(ImGuiID
id);
1139static void NavUpdate();
1140static void NavUpdateWindowing();
1141static void NavUpdateWindowingOverlay();
1142static void NavUpdateCancelRequest();
1143static void NavUpdateCreateMoveRequest();
1144static void NavUpdateCreateTabbingRequest();
1145static float NavUpdatePageUpPageDown();
1146static inline void NavUpdateAnyRequestFlag();
1147static void NavUpdateCreateWrappingRequest();
1148static void NavEndFrame();
1149static bool NavScoreItem(ImGuiNavItemData* result);
1150static void NavApplyItemToResult(ImGuiNavItemData* result);
1151static void NavProcessItem();
1152static void NavProcessItemForTabbingRequest(ImGuiID
id, ImGuiItemFlags item_flags, ImGuiNavMoveFlags move_flags);
1153static ImVec2 NavCalcPreferredRefPos();
1154static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
1155static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
1156static void NavRestoreLayer(ImGuiNavLayer layer);
1157static int FindWindowFocusIndex(ImGuiWindow* window);
1160static void ErrorCheckNewFrameSanityChecks();
1161static void ErrorCheckEndFrameSanityChecks();
1162static void UpdateDebugToolItemPicker();
1163static void UpdateDebugToolStackQueries();
1164static void UpdateDebugToolFlashStyleColor();
1167static void UpdateKeyboardInputs();
1168static void UpdateMouseInputs();
1169static void UpdateMouseWheel();
1170static void UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt);
1173static void UpdateSettings();
1174static 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);
1175static void RenderWindowOuterBorders(ImGuiWindow* window);
1176static 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);
1177static void RenderWindowTitleBarContents(ImGuiWindow* window,
const ImRect& title_bar_rect,
const char* name,
bool* p_open);
1178static void RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col);
1179static void RenderDimmedBackgrounds();
1180static void SetLastItemDataForWindow(ImGuiWindow* window,
const ImRect& rect);
1184static ImGuiViewportP* AddUpdateViewport(ImGuiWindow* window, ImGuiID
id,
const ImVec2& platform_pos,
const ImVec2& size, ImGuiViewportFlags flags);
1185static void DestroyViewport(ImGuiViewportP* viewport);
1186static void UpdateViewportsNewFrame();
1187static void UpdateViewportsEndFrame();
1188static void WindowSelectViewport(ImGuiWindow* window);
1189static void WindowSyncOwnedViewport(ImGuiWindow* window, ImGuiWindow* parent_window_in_stack);
1190static bool UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* host_viewport);
1191static bool UpdateTryMergeWindowIntoHostViewports(ImGuiWindow* window);
1192static bool GetWindowAlwaysWantOwnViewport(ImGuiWindow* window);
1193static int FindPlatformMonitorForPos(
const ImVec2& pos);
1194static int FindPlatformMonitorForRect(
const ImRect& r);
1195static void UpdateViewportPlatformMonitor(ImGuiViewportP* viewport);
1230#ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS
1231static void* MallocWrapper(
size_t size,
void* user_data) { IM_UNUSED(user_data);
return malloc(size); }
1232static void FreeWrapper(
void* ptr,
void* user_data) { IM_UNUSED(user_data); free(ptr); }
1234static void* MallocWrapper(
size_t size,
void* user_data) { IM_UNUSED(user_data); IM_UNUSED(size); IM_ASSERT(0);
return NULL; }
1235static void FreeWrapper(
void* ptr,
void* user_data) { IM_UNUSED(user_data); IM_UNUSED(ptr); IM_ASSERT(0); }
1237static ImGuiMemAllocFunc GImAllocatorAllocFunc = MallocWrapper;
1238static ImGuiMemFreeFunc GImAllocatorFreeFunc = FreeWrapper;
1239static void* GImAllocatorUserData = NULL;
1245ImGuiStyle::ImGuiStyle()
1248 DisabledAlpha = 0.60f;
1249 WindowPadding = ImVec2(8,8);
1250 WindowRounding = 0.0f;
1251 WindowBorderSize = 1.0f;
1252 WindowMinSize = ImVec2(32,32);
1253 WindowTitleAlign = ImVec2(0.0f,0.5f);
1254 WindowMenuButtonPosition = ImGuiDir_Left;
1255 ChildRounding = 0.0f;
1256 ChildBorderSize = 1.0f;
1257 PopupRounding = 0.0f;
1258 PopupBorderSize = 1.0f;
1259 FramePadding = ImVec2(4,3);
1260 FrameRounding = 0.0f;
1261 FrameBorderSize = 0.0f;
1262 ItemSpacing = ImVec2(8,4);
1263 ItemInnerSpacing = ImVec2(4,4);
1264 CellPadding = ImVec2(4,2);
1265 TouchExtraPadding = ImVec2(0,0);
1266 IndentSpacing = 21.0f;
1267 ColumnsMinSpacing = 6.0f;
1268 ScrollbarSize = 14.0f;
1269 ScrollbarRounding = 9.0f;
1270 GrabMinSize = 12.0f;
1271 GrabRounding = 0.0f;
1272 LogSliderDeadzone = 4.0f;
1274 TabBorderSize = 0.0f;
1275 TabMinWidthForCloseButton = 0.0f;
1276 TabBarBorderSize = 1.0f;
1277 TableAngledHeadersAngle = 35.0f * (IM_PI / 180.0f);
1278 TableAngledHeadersTextAlign = ImVec2(0.5f,0.0f);
1279 ColorButtonPosition = ImGuiDir_Right;
1280 ButtonTextAlign = ImVec2(0.5f,0.5f);
1281 SelectableTextAlign = ImVec2(0.0f,0.0f);
1282 SeparatorTextBorderSize = 3.0f;
1283 SeparatorTextAlign = ImVec2(0.0f,0.5f);
1284 SeparatorTextPadding = ImVec2(20.0f,3.f);
1285 DisplayWindowPadding = ImVec2(19,19);
1286 DisplaySafeAreaPadding = ImVec2(3,3);
1287 DockingSeparatorSize = 2.0f;
1288 MouseCursorScale = 1.0f;
1289 AntiAliasedLines =
true;
1290 AntiAliasedLinesUseTex =
true;
1291 AntiAliasedFill =
true;
1292 CurveTessellationTol = 1.25f;
1293 CircleTessellationMaxError = 0.30f;
1296 HoverStationaryDelay = 0.15f;
1297 HoverDelayShort = 0.15f;
1298 HoverDelayNormal = 0.40f;
1299 HoverFlagsForTooltipMouse = ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_AllowWhenDisabled;
1300 HoverFlagsForTooltipNav = ImGuiHoveredFlags_NoSharedDelay | ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_AllowWhenDisabled;
1303 ImGui::StyleColorsDark(
this);
1308void ImGuiStyle::ScaleAllSizes(
float scale_factor)
1310 WindowPadding = ImTrunc(WindowPadding * scale_factor);
1311 WindowRounding = ImTrunc(WindowRounding * scale_factor);
1312 WindowMinSize = ImTrunc(WindowMinSize * scale_factor);
1313 ChildRounding = ImTrunc(ChildRounding * scale_factor);
1314 PopupRounding = ImTrunc(PopupRounding * scale_factor);
1315 FramePadding = ImTrunc(FramePadding * scale_factor);
1316 FrameRounding = ImTrunc(FrameRounding * scale_factor);
1317 ItemSpacing = ImTrunc(ItemSpacing * scale_factor);
1318 ItemInnerSpacing = ImTrunc(ItemInnerSpacing * scale_factor);
1319 CellPadding = ImTrunc(CellPadding * scale_factor);
1320 TouchExtraPadding = ImTrunc(TouchExtraPadding * scale_factor);
1321 IndentSpacing = ImTrunc(IndentSpacing * scale_factor);
1322 ColumnsMinSpacing = ImTrunc(ColumnsMinSpacing * scale_factor);
1323 ScrollbarSize = ImTrunc(ScrollbarSize * scale_factor);
1324 ScrollbarRounding = ImTrunc(ScrollbarRounding * scale_factor);
1325 GrabMinSize = ImTrunc(GrabMinSize * scale_factor);
1326 GrabRounding = ImTrunc(GrabRounding * scale_factor);
1327 LogSliderDeadzone = ImTrunc(LogSliderDeadzone * scale_factor);
1328 TabRounding = ImTrunc(TabRounding * scale_factor);
1329 TabMinWidthForCloseButton = (TabMinWidthForCloseButton != FLT_MAX) ? ImTrunc(TabMinWidthForCloseButton * scale_factor) : FLT_MAX;
1330 SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor);
1331 DockingSeparatorSize = ImTrunc(DockingSeparatorSize * scale_factor);
1332 DisplayWindowPadding = ImTrunc(DisplayWindowPadding * scale_factor);
1333 DisplaySafeAreaPadding = ImTrunc(DisplaySafeAreaPadding * scale_factor);
1334 MouseCursorScale = ImTrunc(MouseCursorScale * scale_factor);
1340 memset(
this, 0,
sizeof(*
this));
1341 IM_STATIC_ASSERT(IM_ARRAYSIZE(ImGuiIO::MouseDown) == ImGuiMouseButton_COUNT && IM_ARRAYSIZE(ImGuiIO::MouseClicked) == ImGuiMouseButton_COUNT);
1344 ConfigFlags = ImGuiConfigFlags_None;
1345 BackendFlags = ImGuiBackendFlags_None;
1346 DisplaySize = ImVec2(-1.0f, -1.0f);
1347 DeltaTime = 1.0f / 60.0f;
1348 IniSavingRate = 5.0f;
1349 IniFilename =
"imgui.ini";
1350 LogFilename =
"imgui_log.txt";
1351#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
1352 for (
int i = 0; i < ImGuiKey_COUNT; i++)
1358 FontGlobalScale = 1.0f;
1360 FontAllowUserScaling =
false;
1361 DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
1364 ConfigDockingNoSplit =
false;
1365 ConfigDockingWithShift =
false;
1366 ConfigDockingAlwaysTabBar =
false;
1367 ConfigDockingTransparentPayload =
false;
1370 ConfigViewportsNoAutoMerge =
false;
1371 ConfigViewportsNoTaskBarIcon =
false;
1372 ConfigViewportsNoDecoration =
true;
1373 ConfigViewportsNoDefaultParent =
false;
1376 MouseDrawCursor =
false;
1378 ConfigMacOSXBehaviors =
true;
1380 ConfigMacOSXBehaviors =
false;
1382 ConfigInputTrickleEventQueue =
true;
1383 ConfigInputTextCursorBlink =
true;
1384 ConfigInputTextEnterKeepActive =
false;
1385 ConfigDragClickToInputText =
false;
1386 ConfigWindowsResizeFromEdges =
true;
1387 ConfigWindowsMoveFromTitleBarOnly =
false;
1388 ConfigMemoryCompactTimer = 60.0f;
1389 ConfigDebugBeginReturnValueOnce =
false;
1390 ConfigDebugBeginReturnValueLoop =
false;
1393 MouseDoubleClickTime = 0.30f;
1394 MouseDoubleClickMaxDist = 6.0f;
1395 MouseDragThreshold = 6.0f;
1396 KeyRepeatDelay = 0.275f;
1397 KeyRepeatRate = 0.050f;
1401 BackendPlatformName = BackendRendererName = NULL;
1402 BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL;
1403 PlatformLocaleDecimalPoint =
'.';
1406 MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
1407 MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX);
1408 MouseSource = ImGuiMouseSource_Mouse;
1409 for (
int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
1410 for (
int i = 0; i < IM_ARRAYSIZE(KeysData); i++) { KeysData[i].DownDuration = KeysData[i].DownDurationPrev = -1.0f; }
1411 AppAcceptingEvents =
true;
1412 BackendUsingLegacyKeyArrays = (ImS8)-1;
1413 BackendUsingLegacyNavInputArray =
true;
1420void ImGuiIO::AddInputCharacter(
unsigned int c)
1422 IM_ASSERT(Ctx != NULL);
1423 ImGuiContext&
g = *Ctx;
1424 if (c == 0 || !AppAcceptingEvents)
1428 e.Type = ImGuiInputEventType_Text;
1429 e.Source = ImGuiInputSource_Keyboard;
1430 e.EventId =
g.InputEventsNextEventId++;
1432 g.InputEventsQueue.push_back(e);
1437void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c)
1439 if ((c == 0 && InputQueueSurrogate == 0) || !AppAcceptingEvents)
1442 if ((c & 0xFC00) == 0xD800)
1444 if (InputQueueSurrogate != 0)
1445 AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID);
1446 InputQueueSurrogate = c;
1451 if (InputQueueSurrogate != 0)
1453 if ((c & 0xFC00) != 0xDC00)
1455 AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID);
1459#if IM_UNICODE_CODEPOINT_MAX == 0xFFFF
1460 cp = IM_UNICODE_CODEPOINT_INVALID;
1462 cp = (ImWchar)(((InputQueueSurrogate - 0xD800) << 10) + (c - 0xDC00) + 0x10000);
1466 InputQueueSurrogate = 0;
1468 AddInputCharacter((
unsigned)cp);
1471void ImGuiIO::AddInputCharactersUTF8(
const char* utf8_chars)
1473 if (!AppAcceptingEvents)
1475 while (*utf8_chars != 0)
1479 AddInputCharacter(c);
1484void ImGuiIO::ClearEventsQueue()
1486 IM_ASSERT(Ctx != NULL);
1487 ImGuiContext&
g = *Ctx;
1488 g.InputEventsQueue.clear();
1492void ImGuiIO::ClearInputKeys()
1494#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
1495 memset(KeysDown, 0,
sizeof(KeysDown));
1497 for (
int n = 0; n < IM_ARRAYSIZE(KeysData); n++)
1499 KeysData[n].Down =
false;
1500 KeysData[n].DownDuration = -1.0f;
1501 KeysData[n].DownDurationPrev = -1.0f;
1503 KeyCtrl = KeyShift = KeyAlt = KeySuper =
false;
1504 KeyMods = ImGuiMod_None;
1505 MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
1506 for (
int n = 0; n < IM_ARRAYSIZE(MouseDown); n++)
1508 MouseDown[n] =
false;
1509 MouseDownDuration[n] = MouseDownDurationPrev[n] = -1.0f;
1511 MouseWheel = MouseWheelH = 0.0f;
1512 InputQueueCharacters.resize(0);
1517#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
1518void ImGuiIO::ClearInputCharacters()
1520 InputQueueCharacters.resize(0);
1524static ImGuiInputEvent* FindLatestInputEvent(ImGuiContext* ctx, ImGuiInputEventType type,
int arg = -1)
1526 ImGuiContext&
g = *ctx;
1527 for (
int n =
g.InputEventsQueue.Size - 1; n >= 0; n--)
1529 ImGuiInputEvent*
e = &
g.InputEventsQueue[n];
1530 if (
e->Type != type)
1532 if (type == ImGuiInputEventType_Key &&
e->Key.Key != arg)
1534 if (type == ImGuiInputEventType_MouseButton &&
e->MouseButton.Button != arg)
1547void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key,
bool down,
float analog_value)
1550 IM_ASSERT(Ctx != NULL);
1551 if (key == ImGuiKey_None || !AppAcceptingEvents)
1553 ImGuiContext&
g = *Ctx;
1554 IM_ASSERT(ImGui::IsNamedKeyOrMod(key));
1555 IM_ASSERT(ImGui::IsAliasKey(key) ==
false);
1558 if (
g.IO.ConfigMacOSXBehaviors)
1560 if (key == ImGuiMod_Super) { key = ImGuiMod_Ctrl; }
1561 else if (key == ImGuiMod_Ctrl) { key = ImGuiMod_Super; }
1562 else if (key == ImGuiKey_LeftSuper) { key = ImGuiKey_LeftCtrl; }
1563 else if (key == ImGuiKey_RightSuper){ key = ImGuiKey_RightCtrl; }
1564 else if (key == ImGuiKey_LeftCtrl) { key = ImGuiKey_LeftSuper; }
1565 else if (key == ImGuiKey_RightCtrl) { key = ImGuiKey_RightSuper; }
1569#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
1570 IM_ASSERT((BackendUsingLegacyKeyArrays == -1 || BackendUsingLegacyKeyArrays == 0) &&
"Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
1571 if (BackendUsingLegacyKeyArrays == -1)
1572 for (
int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++)
1573 IM_ASSERT(KeyMap[n] == -1 &&
"Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
1574 BackendUsingLegacyKeyArrays = 0;
1576 if (ImGui::IsGamepadKey(key))
1577 BackendUsingLegacyNavInputArray =
false;
1580 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_Key, (
int)key);
1581 const ImGuiKeyData* key_data = ImGui::GetKeyData(&
g, key);
1582 const bool latest_key_down = latest_event ? latest_event->Key.Down : key_data->Down;
1583 const float latest_key_analog = latest_event ? latest_event->Key.AnalogValue : key_data->AnalogValue;
1584 if (latest_key_down == down && latest_key_analog == analog_value)
1589 e.Type = ImGuiInputEventType_Key;
1590 e.Source = ImGui::IsGamepadKey(key) ? ImGuiInputSource_Gamepad : ImGuiInputSource_Keyboard;
1591 e.EventId =
g.InputEventsNextEventId++;
1594 e.Key.AnalogValue = analog_value;
1595 g.InputEventsQueue.push_back(e);
1598void ImGuiIO::AddKeyEvent(ImGuiKey key,
bool down)
1600 if (!AppAcceptingEvents)
1602 AddKeyAnalogEvent(key, down, down ? 1.0f : 0.0f);
1608void ImGuiIO::SetKeyEventNativeData(ImGuiKey key,
int native_keycode,
int native_scancode,
int native_legacy_index)
1610 if (key == ImGuiKey_None)
1612 IM_ASSERT(ImGui::IsNamedKey(key));
1613 IM_ASSERT(native_legacy_index == -1 || ImGui::IsLegacyKey((ImGuiKey)native_legacy_index));
1614 IM_UNUSED(native_keycode);
1615 IM_UNUSED(native_scancode);
1618#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
1619 const int legacy_key = (native_legacy_index != -1) ? native_legacy_index : native_keycode;
1620 if (!ImGui::IsLegacyKey((ImGuiKey)legacy_key))
1622 KeyMap[legacy_key] = key;
1623 KeyMap[key] = legacy_key;
1626 IM_UNUSED(native_legacy_index);
1631void ImGuiIO::SetAppAcceptingEvents(
bool accepting_events)
1633 AppAcceptingEvents = accepting_events;
1637void ImGuiIO::AddMousePosEvent(
float x,
float y)
1639 IM_ASSERT(Ctx != NULL);
1640 ImGuiContext&
g = *Ctx;
1641 if (!AppAcceptingEvents)
1645 ImVec2 pos((x > -FLT_MAX) ? ImFloor(x) : x, (y > -FLT_MAX) ? ImFloor(y) : y);
1648 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_MousePos);
1649 const ImVec2 latest_pos = latest_event ? ImVec2(latest_event->MousePos.PosX, latest_event->MousePos.PosY) :
g.IO.MousePos;
1650 if (latest_pos.x == pos.x && latest_pos.y == pos.y)
1654 e.Type = ImGuiInputEventType_MousePos;
1655 e.Source = ImGuiInputSource_Mouse;
1656 e.EventId =
g.InputEventsNextEventId++;
1657 e.MousePos.PosX = pos.x;
1658 e.MousePos.PosY = pos.y;
1659 e.MousePos.MouseSource =
g.InputEventsNextMouseSource;
1660 g.InputEventsQueue.push_back(e);
1663void ImGuiIO::AddMouseButtonEvent(
int mouse_button,
bool down)
1665 IM_ASSERT(Ctx != NULL);
1666 ImGuiContext&
g = *Ctx;
1667 IM_ASSERT(mouse_button >= 0 && mouse_button < ImGuiMouseButton_COUNT);
1668 if (!AppAcceptingEvents)
1672 if (ConfigMacOSXBehaviors && mouse_button == 0 && MouseCtrlLeftAsRightClick)
1677 MouseCtrlLeftAsRightClick =
false;
1681 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_MouseButton, (
int)mouse_button);
1682 const bool latest_button_down = latest_event ? latest_event->MouseButton.Down :
g.IO.MouseDown[mouse_button];
1683 if (latest_button_down == down)
1689 if (ConfigMacOSXBehaviors && mouse_button == 0 && down)
1691 const ImGuiInputEvent* latest_super_event = FindLatestInputEvent(&
g, ImGuiInputEventType_Key, (
int)ImGuiMod_Super);
1692 if (latest_super_event ? latest_super_event->Key.Down :
g.IO.KeySuper)
1694 IMGUI_DEBUG_LOG_IO(
"[io] Super+Left Click aliased into Right Click\n");
1695 MouseCtrlLeftAsRightClick =
true;
1696 AddMouseButtonEvent(1,
true);
1702 e.Type = ImGuiInputEventType_MouseButton;
1703 e.Source = ImGuiInputSource_Mouse;
1704 e.EventId =
g.InputEventsNextEventId++;
1705 e.MouseButton.Button = mouse_button;
1706 e.MouseButton.Down = down;
1707 e.MouseButton.MouseSource =
g.InputEventsNextMouseSource;
1708 g.InputEventsQueue.push_back(e);
1712void ImGuiIO::AddMouseWheelEvent(
float wheel_x,
float wheel_y)
1714 IM_ASSERT(Ctx != NULL);
1715 ImGuiContext&
g = *Ctx;
1718 if (!AppAcceptingEvents || (wheel_x == 0.0f && wheel_y == 0.0f))
1722 e.Type = ImGuiInputEventType_MouseWheel;
1723 e.Source = ImGuiInputSource_Mouse;
1724 e.EventId =
g.InputEventsNextEventId++;
1725 e.MouseWheel.WheelX = wheel_x;
1726 e.MouseWheel.WheelY = wheel_y;
1727 e.MouseWheel.MouseSource =
g.InputEventsNextMouseSource;
1728 g.InputEventsQueue.push_back(e);
1733void ImGuiIO::AddMouseSourceEvent(ImGuiMouseSource source)
1735 IM_ASSERT(Ctx != NULL);
1736 ImGuiContext&
g = *Ctx;
1737 g.InputEventsNextMouseSource = source;
1740void ImGuiIO::AddMouseViewportEvent(ImGuiID viewport_id)
1742 IM_ASSERT(Ctx != NULL);
1743 ImGuiContext&
g = *Ctx;
1745 if (!AppAcceptingEvents)
1749 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_MouseViewport);
1750 const ImGuiID latest_viewport_id = latest_event ? latest_event->MouseViewport.HoveredViewportID :
g.IO.MouseHoveredViewport;
1751 if (latest_viewport_id == viewport_id)
1755 e.Type = ImGuiInputEventType_MouseViewport;
1756 e.Source = ImGuiInputSource_Mouse;
1757 e.MouseViewport.HoveredViewportID = viewport_id;
1758 g.InputEventsQueue.push_back(e);
1761void ImGuiIO::AddFocusEvent(
bool focused)
1763 IM_ASSERT(Ctx != NULL);
1764 ImGuiContext&
g = *Ctx;
1767 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_Focus);
1768 const bool latest_focused = latest_event ? latest_event->AppFocused.Focused : !
g.IO.AppFocusLost;
1769 if (latest_focused == focused || (ConfigDebugIgnoreFocusLoss && !focused))
1773 e.Type = ImGuiInputEventType_Focus;
1774 e.EventId =
g.InputEventsNextEventId++;
1775 e.AppFocused.Focused = focused;
1776 g.InputEventsQueue.push_back(e);
1785 IM_ASSERT(num_segments > 0);
1788 float p_closest_dist2 = FLT_MAX;
1789 float t_step = 1.0f / (float)num_segments;
1790 for (
int i_step = 1; i_step <= num_segments; i_step++)
1794 float dist2 = ImLengthSqr(p - p_line);
1795 if (dist2 < p_closest_dist2)
1798 p_closest_dist2 = dist2;
1806static 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)
1810 float d2 = ((x2 - x4) * dy - (y2 - y4) * dx);
1811 float d3 = ((x3 - x4) * dy - (y3 - y4) * dx);
1812 d2 = (d2 >= 0) ? d2 : -d2;
1813 d3 = (d3 >= 0) ? d3 : -d3;
1814 if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy))
1816 ImVec2 p_current(x4, y4);
1818 float dist2 = ImLengthSqr(p - p_line);
1819 if (dist2 < p_closest_dist2)
1822 p_closest_dist2 = dist2;
1826 else if (level < 10)
1828 float x12 = (x1 + x2)*0.5f, y12 = (y1 + y2)*0.5f;
1829 float x23 = (x2 + x3)*0.5f, y23 = (y2 + y3)*0.5f;
1830 float x34 = (x3 + x4)*0.5f, y34 = (y3 + y4)*0.5f;
1831 float x123 = (x12 + x23)*0.5f, y123 = (y12 + y23)*0.5f;
1832 float x234 = (x23 + x34)*0.5f, y234 = (y23 + y34)*0.5f;
1833 float x1234 = (x123 + x234)*0.5f, y1234 = (y123 + y234)*0.5f;
1834 ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1);
1835 ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1);
1843 IM_ASSERT(tess_tol > 0.0f);
1846 float p_closest_dist2 = FLT_MAX;
1847 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);
1854 ImVec2 ab_dir = b - a;
1855 float dot = ap.x * ab_dir.x + ap.y * ab_dir.y;
1858 float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y;
1859 if (dot > ab_len_sqr)
1861 return a + ab_dir * dot / ab_len_sqr;
1866 bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f;
1867 bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f;
1868 bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f;
1869 return ((b1 == b2) && (b2 == b3));
1877 const float denom = v0.x * v1.y - v1.x * v0.y;
1878 out_v = (v2.x * v1.y - v1.x * v2.y) / denom;
1879 out_w = (v0.x * v2.y - v2.x * v0.y) / denom;
1880 out_u = 1.0f - out_v - out_w;
1888 float dist2_ab = ImLengthSqr(p - proj_ab);
1889 float dist2_bc = ImLengthSqr(p - proj_bc);
1890 float dist2_ca = ImLengthSqr(p - proj_ca);
1891 float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca));
1907 while ((d = ImToUpper(*str2) - ImToUpper(*str1)) == 0 && *str1) { str1++; str2++; }
1914 while (count > 0 && (d = ImToUpper(*str2) - ImToUpper(*str1)) == 0 && *str1) { str1++; str2++; count--; }
1923 strncpy(dst, src, count - 1);
1929 size_t len = strlen(str);
1930 void* buf = IM_ALLOC(len + 1);
1931 return (
char*)memcpy(buf, (
const void*)str, len + 1);
1936 size_t dst_buf_size = p_dst_size ? *p_dst_size : strlen(dst) + 1;
1937 size_t src_size = strlen(src) + 1;
1938 if (dst_buf_size < src_size)
1941 dst = (
char*)IM_ALLOC(src_size);
1943 *p_dst_size = src_size;
1945 return (
char*)memcpy(dst, (
const void*)src, src_size);
1950 const char* p = (
const char*)memchr(str, (
int)c, str_end - str);
1965 const char* p = (
const char*)memchr(str,
'\n', str_end - str);
1966 return p ? p : str_end;
1969const ImWchar*
ImStrbolW(
const ImWchar* buf_mid_line,
const ImWchar* buf_begin)
1971 while (buf_mid_line > buf_begin && buf_mid_line[-1] !=
'\n')
1973 return buf_mid_line;
1976const char*
ImStristr(
const char* haystack,
const char* haystack_end,
const char* needle,
const char* needle_end)
1979 needle_end = needle + strlen(needle);
1981 const char un0 = (char)ImToUpper(*needle);
1982 while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))
1984 if (ImToUpper(*haystack) == un0)
1986 const char* b = needle + 1;
1987 for (
const char* a = haystack + 1; b < needle_end; a++, b++)
1988 if (ImToUpper(*a) != ImToUpper(*b))
1990 if (b == needle_end)
2002 while (p[0] ==
' ' || p[0] ==
'\t')
2007 while (p > p_start && (p[-1] ==
' ' || p[-1] ==
'\t'))
2010 memmove(buf, p_start, p - p_start);
2011 buf[p - p_start] = 0;
2016 while (str[0] ==
' ' || str[0] ==
'\t')
2024#ifndef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
2030#ifdef IMGUI_USE_STB_SPRINTF
2031#ifndef IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION
2032#define STB_SPRINTF_IMPLEMENTATION
2034#ifdef IMGUI_STB_SPRINTF_FILENAME
2035#include IMGUI_STB_SPRINTF_FILENAME
2037#include "stb_sprintf.h"
2041#if defined(_MSC_VER) && !defined(vsnprintf)
2042#define vsnprintf _vsnprintf
2048 va_start(args, fmt);
2049#ifdef IMGUI_USE_STB_SPRINTF
2050 int w = stbsp_vsnprintf(buf, (
int)buf_size, fmt, args);
2052 int w = vsnprintf(buf, buf_size, fmt, args);
2057 if (w == -1 || w >= (
int)buf_size)
2058 w = (int)buf_size - 1;
2065#ifdef IMGUI_USE_STB_SPRINTF
2066 int w = stbsp_vsnprintf(buf, (
int)buf_size, fmt, args);
2068 int w = vsnprintf(buf, buf_size, fmt, args);
2072 if (w == -1 || w >= (
int)buf_size)
2073 w = (int)buf_size - 1;
2082 va_start(args, fmt);
2090 if (fmt[0] ==
'%' && fmt[1] ==
's' && fmt[2] == 0)
2092 const char* buf = va_arg(args,
const char*);
2096 if (out_buf_end) { *out_buf_end = buf + strlen(buf); }
2098 else if (fmt[0] ==
'%' && fmt[1] ==
'.' && fmt[2] ==
'*' && fmt[3] ==
's' && fmt[4] == 0)
2100 int buf_len = va_arg(args,
int);
2101 const char* buf = va_arg(args,
const char*);
2105 buf_len = ImMin(buf_len, 6);
2108 *out_buf_end = buf + buf_len;
2113 *out_buf =
g.TempBuffer.Data;
2114 if (out_buf_end) { *out_buf_end =
g.TempBuffer.Data + buf_len; }
2121static const ImU32 GCrc32LookupTable[256] =
2123 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,
2124 0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,
2125 0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,
2126 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,
2127 0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01,
2128 0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,
2129 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,
2130 0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD,
2131 0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
2132 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,
2133 0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79,
2134 0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,
2135 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,
2136 0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,
2137 0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,
2138 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D,
2144ImGuiID
ImHashData(
const void* data_p,
size_t data_size, ImGuiID seed)
2147 const unsigned char* data = (
const unsigned char*)data_p;
2148 const ImU32* crc32_lut = GCrc32LookupTable;
2149 while (data_size-- != 0)
2150 crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *data++];
2160ImGuiID
ImHashStr(
const char* data_p,
size_t data_size, ImGuiID seed)
2164 const unsigned char* data = (
const unsigned char*)data_p;
2165 const ImU32* crc32_lut = GCrc32LookupTable;
2168 while (data_size-- != 0)
2170 unsigned char c = *data++;
2171 if (c ==
'#' && data_size >= 2 && data[0] ==
'#' && data[1] ==
'#')
2173 crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
2178 while (
unsigned char c = *data++)
2180 if (c ==
'#' && data[0] ==
'#' && data[1] ==
'#')
2182 crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
2193#ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
2197#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(__CYGWIN__) && !defined(__GNUC__)
2200 const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
2201 const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
2205 wchar_t local_temp_stack[FILENAME_MAX];
2206 ImVector<wchar_t> local_temp_heap;
2207 if (filename_wsize + mode_wsize > IM_ARRAYSIZE(local_temp_stack))
2208 local_temp_heap.resize(filename_wsize + mode_wsize);
2209 wchar_t* filename_wbuf = local_temp_heap.Data ? local_temp_heap.Data : local_temp_stack;
2210 wchar_t* mode_wbuf = filename_wbuf + filename_wsize;
2211 ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, filename_wbuf, filename_wsize);
2212 ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, mode_wbuf, mode_wsize);
2213 return ::_wfopen(filename_wbuf, mode_wbuf);
2215 return fopen(filename, mode);
2221ImU64
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; }
2222ImU64
ImFileRead(
void* data, ImU64 sz, ImU64 count, ImFileHandle f) {
return fread(data, (
size_t)sz, (
size_t)count, f); }
2223ImU64
ImFileWrite(
const void* data, ImU64 sz, ImU64 count, ImFileHandle f) {
return fwrite(data, (
size_t)sz, (
size_t)count, f); }
2229void*
ImFileLoadToMemory(
const char* filename,
const char* mode,
size_t* out_file_size,
int padding_bytes)
2231 IM_ASSERT(filename && mode);
2236 if ((f =
ImFileOpen(filename, mode)) == NULL)
2240 if (file_size == (
size_t)-1)
2246 void* file_data = IM_ALLOC(file_size + padding_bytes);
2247 if (file_data == NULL)
2252 if (
ImFileRead(file_data, 1, file_size, f) != file_size)
2258 if (padding_bytes > 0)
2259 memset((
void*)(((
char*)file_data) + file_size), 0, (
size_t)padding_bytes);
2263 *out_file_size = file_size;
2272IM_MSVC_RUNTIME_CHECKS_OFF
2279 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 };
2280 static const int masks[] = { 0x00, 0x7f, 0x1f, 0x0f, 0x07 };
2281 static const uint32_t mins[] = { 0x400000, 0, 0x80, 0x800, 0x10000 };
2282 static const int shiftc[] = { 0, 18, 12, 6, 0 };
2283 static const int shifte[] = { 0, 6, 4, 2, 0 };
2284 int len = lengths[*(
const unsigned char*)in_text >> 3];
2285 int wanted = len + (len ? 0 : 1);
2287 if (in_text_end == NULL)
2288 in_text_end = in_text + wanted;
2293 s[0] = in_text + 0 < in_text_end ? in_text[0] : 0;
2294 s[1] = in_text + 1 < in_text_end ? in_text[1] : 0;
2295 s[2] = in_text + 2 < in_text_end ? in_text[2] : 0;
2296 s[3] = in_text + 3 < in_text_end ? in_text[3] : 0;
2299 *out_char = (uint32_t)(s[0] & masks[len]) << 18;
2300 *out_char |= (uint32_t)(s[1] & 0x3f) << 12;
2301 *out_char |= (uint32_t)(s[2] & 0x3f) << 6;
2302 *out_char |= (uint32_t)(s[3] & 0x3f) << 0;
2303 *out_char >>= shiftc[len];
2307 e = (*out_char < mins[len]) << 6;
2308 e |= ((*out_char >> 11) == 0x1b) << 7;
2309 e |= (*out_char > IM_UNICODE_CODEPOINT_MAX) << 8;
2310 e |= (s[1] & 0xc0) >> 2;
2311 e |= (s[2] & 0xc0) >> 4;
2322 wanted = ImMin(wanted, !!s[0] + !!s[1] + !!s[2] + !!s[3]);
2323 *out_char = IM_UNICODE_CODEPOINT_INVALID;
2329int ImTextStrFromUtf8(ImWchar* buf,
int buf_size,
const char* in_text,
const char* in_text_end,
const char** in_text_remaining)
2331 ImWchar* buf_out = buf;
2332 ImWchar* buf_end = buf + buf_size;
2333 while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
2337 *buf_out++ = (ImWchar)c;
2340 if (in_text_remaining)
2341 *in_text_remaining = in_text;
2342 return (
int)(buf_out - buf);
2348 while ((!in_text_end || in_text < in_text_end) && *in_text)
2358static inline int ImTextCharToUtf8_inline(
char* buf,
int buf_size,
unsigned int c)
2367 if (buf_size < 2)
return 0;
2368 buf[0] = (char)(0xc0 + (c >> 6));
2369 buf[1] = (char)(0x80 + (c & 0x3f));
2374 if (buf_size < 3)
return 0;
2375 buf[0] = (char)(0xe0 + (c >> 12));
2376 buf[1] = (char)(0x80 + ((c >> 6) & 0x3f));
2377 buf[2] = (char)(0x80 + ((c ) & 0x3f));
2382 if (buf_size < 4)
return 0;
2383 buf[0] = (char)(0xf0 + (c >> 18));
2384 buf[1] = (char)(0x80 + ((c >> 12) & 0x3f));
2385 buf[2] = (char)(0x80 + ((c >> 6) & 0x3f));
2386 buf[3] = (char)(0x80 + ((c ) & 0x3f));
2395 int count = ImTextCharToUtf8_inline(out_buf, 5, c);
2403 unsigned int unused = 0;
2409 if (c < 0x80)
return 1;
2410 if (c < 0x800)
return 2;
2411 if (c < 0x10000)
return 3;
2412 if (c <= 0x10FFFF)
return 4;
2416int ImTextStrToUtf8(
char* out_buf,
int out_buf_size,
const ImWchar* in_text,
const ImWchar* in_text_end)
2418 char* buf_p = out_buf;
2419 const char* buf_end = out_buf + out_buf_size;
2420 while (buf_p < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
2422 unsigned int c = (
unsigned int)(*in_text++);
2426 buf_p += ImTextCharToUtf8_inline(buf_p, (
int)(buf_end - buf_p - 1), c);
2429 return (
int)(buf_p - out_buf);
2434 int bytes_count = 0;
2435 while ((!in_text_end || in_text < in_text_end) && *in_text)
2437 unsigned int c = (
unsigned int)(*in_text++);
2448 while (in_text_curr > in_text_start)
2451 if ((*in_text_curr & 0xC0) != 0x80)
2452 return in_text_curr;
2454 return in_text_start;
2459 if (in_text_end == NULL)
2460 in_text_end = in_text + strlen(in_text);
2462 while (in_text < in_text_end)
2464 const char* line_end = (
const char*)memchr(in_text,
'\n', in_text_end - in_text);
2465 in_text = line_end ? line_end + 1 : in_text_end;
2471IM_MSVC_RUNTIME_CHECKS_RESTORE
2480 float t = ((col_b >> IM_COL32_A_SHIFT) & 0xFF) / 255.f;
2481 int r = ImLerp((
int)(col_a >> IM_COL32_R_SHIFT) & 0xFF, (
int)(col_b >> IM_COL32_R_SHIFT) & 0xFF,
t);
2482 int g = ImLerp((
int)(col_a >> IM_COL32_G_SHIFT) & 0xFF, (
int)(col_b >> IM_COL32_G_SHIFT) & 0xFF,
t);
2483 int b = ImLerp((
int)(col_a >> IM_COL32_B_SHIFT) & 0xFF, (
int)(col_b >> IM_COL32_B_SHIFT) & 0xFF,
t);
2484 return IM_COL32(r,
g, b, 0xFF);
2487ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in)
2489 float s = 1.0f / 255.0f;
2491 ((in >> IM_COL32_R_SHIFT) & 0xFF) * s,
2492 ((in >> IM_COL32_G_SHIFT) & 0xFF) * s,
2493 ((in >> IM_COL32_B_SHIFT) & 0xFF) * s,
2494 ((in >> IM_COL32_A_SHIFT) & 0xFF) * s);
2497ImU32 ImGui::ColorConvertFloat4ToU32(
const ImVec4& in)
2500 out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT;
2501 out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT;
2502 out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT;
2503 out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT;
2509void ImGui::ColorConvertRGBtoHSV(
float r,
float g,
float b,
float& out_h,
float& out_s,
float& out_v)
2523 const float chroma = r - (
g < b ?
g : b);
2524 out_h = ImFabs(K + (
g - b) / (6.f * chroma + 1e-20f));
2525 out_s = chroma / (r + 1e-20f);
2531void ImGui::ColorConvertHSVtoRGB(
float h,
float s,
float v,
float& out_r,
float& out_g,
float& out_b)
2536 out_r = out_g = out_b = v;
2540 h = ImFmod(h, 1.0f) / (60.0f / 360.0f);
2542 float f = h - (float)i;
2543 float p = v * (1.0f - s);
2544 float q = v * (1.0f - s * f);
2545 float t = v * (1.0f - s * (1.0f - f));
2549 case 0: out_r = v; out_g =
t; out_b = p;
break;
2550 case 1: out_r = q; out_g = v; out_b = p;
break;
2551 case 2: out_r = p; out_g = v; out_b =
t;
break;
2552 case 3: out_r = p; out_g = q; out_b = v;
break;
2553 case 4: out_r =
t; out_g = p; out_b = v;
break;
2554 case 5:
default: out_r = v; out_g = p; out_b = q;
break;
2564static ImGuiStorage::ImGuiStoragePair* LowerBound(ImVector<ImGuiStorage::ImGuiStoragePair>& data, ImGuiID key)
2566 ImGuiStorage::ImGuiStoragePair* first = data.Data;
2567 ImGuiStorage::ImGuiStoragePair* last = data.Data + data.Size;
2568 size_t count = (size_t)(last - first);
2571 size_t count2 =
count >> 1;
2572 ImGuiStorage::ImGuiStoragePair* mid = first + count2;
2576 count -= count2 + 1;
2587void ImGuiStorage::BuildSortByKey()
2591 static int IMGUI_CDECL PairComparerByID(
const void* lhs,
const void* rhs)
2594 if (((
const ImGuiStoragePair*)lhs)->key > ((
const ImGuiStoragePair*)rhs)->key)
return +1;
2595 if (((
const ImGuiStoragePair*)lhs)->key < ((
const ImGuiStoragePair*)rhs)->key)
return -1;
2599 ImQsort(Data.Data, (
size_t)Data.Size,
sizeof(ImGuiStoragePair), StaticFunc::PairComparerByID);
2602int ImGuiStorage::GetInt(ImGuiID key,
int default_val)
const
2604 ImGuiStoragePair* it = LowerBound(
const_cast<ImVector<ImGuiStoragePair>&
>(Data), key);
2605 if (it == Data.end() || it->key != key)
2610bool ImGuiStorage::GetBool(ImGuiID key,
bool default_val)
const
2612 return GetInt(key, default_val ? 1 : 0) != 0;
2615float ImGuiStorage::GetFloat(ImGuiID key,
float default_val)
const
2617 ImGuiStoragePair* it = LowerBound(
const_cast<ImVector<ImGuiStoragePair>&
>(Data), key);
2618 if (it == Data.end() || it->key != key)
2623void* ImGuiStorage::GetVoidPtr(ImGuiID key)
const
2625 ImGuiStoragePair* it = LowerBound(
const_cast<ImVector<ImGuiStoragePair>&
>(Data), key);
2626 if (it == Data.end() || it->key != key)
2632int* ImGuiStorage::GetIntRef(ImGuiID key,
int default_val)
2634 ImGuiStoragePair* it = LowerBound(Data, key);
2635 if (it == Data.end() || it->key != key)
2636 it = Data.insert(it, ImGuiStoragePair(key, default_val));
2640bool* ImGuiStorage::GetBoolRef(ImGuiID key,
bool default_val)
2642 return (
bool*)GetIntRef(key, default_val ? 1 : 0);
2645float* ImGuiStorage::GetFloatRef(ImGuiID key,
float default_val)
2647 ImGuiStoragePair* it = LowerBound(Data, key);
2648 if (it == Data.end() || it->key != key)
2649 it = Data.insert(it, ImGuiStoragePair(key, default_val));
2653void** ImGuiStorage::GetVoidPtrRef(ImGuiID key,
void* default_val)
2655 ImGuiStoragePair* it = LowerBound(Data, key);
2656 if (it == Data.end() || it->key != key)
2657 it = Data.insert(it, ImGuiStoragePair(key, default_val));
2662void ImGuiStorage::SetInt(ImGuiID key,
int val)
2664 ImGuiStoragePair* it = LowerBound(Data, key);
2665 if (it == Data.end() || it->key != key)
2666 Data.insert(it, ImGuiStoragePair(key, val));
2671void ImGuiStorage::SetBool(ImGuiID key,
bool val)
2673 SetInt(key, val ? 1 : 0);
2676void ImGuiStorage::SetFloat(ImGuiID key,
float val)
2678 ImGuiStoragePair* it = LowerBound(Data, key);
2679 if (it == Data.end() || it->key != key)
2680 Data.insert(it, ImGuiStoragePair(key, val));
2685void ImGuiStorage::SetVoidPtr(ImGuiID key,
void* val)
2687 ImGuiStoragePair* it = LowerBound(Data, key);
2688 if (it == Data.end() || it->key != key)
2689 Data.insert(it, ImGuiStoragePair(key, val));
2694void ImGuiStorage::SetAllInt(
int v)
2696 for (
int i = 0; i < Data.Size; i++)
2705ImGuiTextFilter::ImGuiTextFilter(
const char* default_filter)
2711 ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf));
2716bool ImGuiTextFilter::Draw(
const char* label,
float width)
2719 ImGui::SetNextItemWidth(width);
2720 bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
2723 return value_changed;
2726void ImGuiTextFilter::ImGuiTextRange::split(
char separator, ImVector<ImGuiTextRange>* out)
const
2730 const char* we = wb;
2733 if (*we == separator)
2735 out->push_back(ImGuiTextRange(wb, we));
2741 out->push_back(ImGuiTextRange(wb, we));
2744void ImGuiTextFilter::Build()
2747 ImGuiTextRange input_range(InputBuf, InputBuf + strlen(InputBuf));
2748 input_range.split(
',', &Filters);
2751 for (ImGuiTextRange& f : Filters)
2753 while (f.b < f.e && ImCharIsBlankA(f.b[0]))
2755 while (f.e > f.b && ImCharIsBlankA(f.e[-1]))
2764bool ImGuiTextFilter::PassFilter(
const char* text,
const char* text_end)
const
2766 if (Filters.empty())
2772 for (
const ImGuiTextRange& f : Filters)
2779 if (
ImStristr(text, text_end, f.b + 1, f.e) != NULL)
2785 if (
ImStristr(text, text_end, f.b, f.e) != NULL)
2804#if defined(__GNUC__) || defined(__clang__)
2805#define va_copy(dest, src) __builtin_va_copy(dest, src)
2807#define va_copy(dest, src) (dest = src)
2811char ImGuiTextBuffer::EmptyString[1] = { 0 };
2813void ImGuiTextBuffer::append(
const char* str,
const char* str_end)
2815 int len = str_end ? (int)(str_end - str) : (int)strlen(str);
2818 const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
2819 const int needed_sz = write_off + len;
2820 if (write_off + len >= Buf.Capacity)
2822 int new_capacity = Buf.Capacity * 2;
2823 Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity);
2826 Buf.resize(needed_sz);
2827 memcpy(&Buf[write_off - 1], str, (
size_t)len);
2828 Buf[write_off - 1 + len] = 0;
2831void ImGuiTextBuffer::appendf(
const char* fmt, ...)
2834 va_start(args, fmt);
2835 appendfv(fmt, args);
2840void ImGuiTextBuffer::appendfv(
const char* fmt, va_list args)
2853 const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
2854 const int needed_sz = write_off + len;
2855 if (write_off + len >= Buf.Capacity)
2857 int new_capacity = Buf.Capacity * 2;
2858 Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity);
2861 Buf.resize(needed_sz);
2862 ImFormatStringV(&Buf[write_off - 1], (
size_t)len + 1, fmt, args_copy);
2866void ImGuiTextIndex::append(
const char* base,
int old_size,
int new_size)
2868 IM_ASSERT(old_size >= 0 && new_size >= old_size && new_size >= EndOffset);
2869 if (old_size == new_size)
2871 if (EndOffset == 0 || base[EndOffset - 1] ==
'\n')
2872 LineOffsets.push_back(EndOffset);
2873 const char* base_end = base + new_size;
2874 for (
const char* p = base + old_size; (p = (
const char*)memchr(p,
'\n', base_end - p)) != 0; )
2876 LineOffsets.push_back((
int)(intptr_t)(p - base));
2877 EndOffset = ImMax(EndOffset, new_size);
2886static bool GetSkipItemForListClipping()
2889 return (
g.CurrentTable ?
g.CurrentTable->HostSkipItems :
g.CurrentWindow->SkipItems);
2892static void ImGuiListClipper_SortAndFuseRanges(ImVector<ImGuiListClipperRange>&
ranges,
int offset = 0)
2894 if (
ranges.Size - offset <= 1)
2898 for (
int sort_end =
ranges.Size - offset - 1; sort_end > 0; --sort_end)
2899 for (
int i = offset; i < sort_end + offset; ++i)
2904 for (
int i = 1 + offset; i <
ranges.Size; i++)
2906 IM_ASSERT(!
ranges[i].PosToIndexConvert && !
ranges[i - 1].PosToIndexConvert);
2916static void ImGuiListClipper_SeekCursorAndSetupPrevLine(
float pos_y,
float line_height)
2922 ImGuiWindow* window =
g.CurrentWindow;
2923 float off_y = pos_y - window->DC.CursorPos.y;
2924 window->DC.CursorPos.y = pos_y;
2925 window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, pos_y -
g.Style.ItemSpacing.y);
2926 window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height;
2927 window->DC.PrevLineSize.y = (line_height -
g.Style.ItemSpacing.y);
2928 if (ImGuiOldColumns* columns = window->DC.CurrentColumns)
2929 columns->LineMinY = window->DC.CursorPos.y;
2930 if (ImGuiTable* table =
g.CurrentTable)
2932 if (table->IsInsideRow)
2933 ImGui::TableEndRow(table);
2934 table->RowPosY2 = window->DC.CursorPos.y;
2935 const int row_increase = (int)((off_y / line_height) + 0.5f);
2937 table->RowBgColorCounter += row_increase;
2941static void ImGuiListClipper_SeekCursorForItem(ImGuiListClipper* clipper,
int item_n)
2945 ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData;
2946 float pos_y = (float)((
double)clipper->StartPosY + data->LossynessOffset + (double)(item_n - data->ItemsFrozen) * clipper->ItemsHeight);
2947 ImGuiListClipper_SeekCursorAndSetupPrevLine(pos_y, clipper->ItemsHeight);
2950ImGuiListClipper::ImGuiListClipper()
2952 memset(
this, 0,
sizeof(*
this));
2955ImGuiListClipper::~ImGuiListClipper()
2960void ImGuiListClipper::Begin(
int items_count,
float items_height)
2963 Ctx = ImGui::GetCurrentContext();
2965 ImGuiContext&
g = *Ctx;
2966 ImGuiWindow* window =
g.CurrentWindow;
2967 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Begin(%d,%.2f) in '%s'\n", items_count, items_height, window->Name);
2969 if (ImGuiTable* table =
g.CurrentTable)
2970 if (table->IsInsideRow)
2971 ImGui::TableEndRow(table);
2973 StartPosY = window->DC.CursorPos.y;
2974 ItemsHeight = items_height;
2975 ItemsCount = items_count;
2980 if (++
g.ClipperTempDataStacked >
g.ClipperTempData.Size)
2981 g.ClipperTempData.resize(
g.ClipperTempDataStacked, ImGuiListClipperData());
2982 ImGuiListClipperData* data = &
g.ClipperTempData[
g.ClipperTempDataStacked - 1];
2984 data->LossynessOffset = window->DC.CursorStartPosLossyness.y;
2988void ImGuiListClipper::End()
2990 if (ImGuiListClipperData* data = (ImGuiListClipperData*)TempData)
2993 ImGuiContext&
g = *Ctx;
2994 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: End() in '%s'\n",
g.CurrentWindow->Name);
2995 if (ItemsCount >= 0 && ItemsCount < INT_MAX && DisplayStart >= 0)
2996 ImGuiListClipper_SeekCursorForItem(
this, ItemsCount);
2999 IM_ASSERT(data->ListClipper ==
this);
3000 data->StepNo = data->Ranges.Size;
3001 if (--
g.ClipperTempDataStacked > 0)
3003 data = &
g.ClipperTempData[
g.ClipperTempDataStacked - 1];
3004 data->ListClipper->TempData = data;
3011void ImGuiListClipper::IncludeItemsByIndex(
int item_begin,
int item_end)
3013 ImGuiListClipperData* data = (ImGuiListClipperData*)TempData;
3014 IM_ASSERT(DisplayStart < 0);
3015 IM_ASSERT(item_begin <= item_end);
3016 if (item_begin < item_end)
3017 data->Ranges.push_back(ImGuiListClipperRange::FromIndices(item_begin, item_end));
3020static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
3022 ImGuiContext&
g = *clipper->Ctx;
3023 ImGuiWindow* window =
g.CurrentWindow;
3024 ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData;
3025 IM_ASSERT(data != NULL &&
"Called ImGuiListClipper::Step() too many times, or before ImGuiListClipper::Begin() ?");
3027 ImGuiTable* table =
g.CurrentTable;
3028 if (table && table->IsInsideRow)
3029 ImGui::TableEndRow(table);
3032 if (clipper->ItemsCount == 0 || GetSkipItemForListClipping())
3037 if (data->StepNo == 0 && table != NULL && !table->IsUnfrozenRows)
3039 clipper->DisplayStart = data->ItemsFrozen;
3040 clipper->DisplayEnd = ImMin(data->ItemsFrozen + 1, clipper->ItemsCount);
3041 if (clipper->DisplayStart < clipper->DisplayEnd)
3042 data->ItemsFrozen++;
3047 bool calc_clipping =
false;
3048 if (data->StepNo == 0)
3050 clipper->StartPosY = window->DC.CursorPos.y;
3051 if (clipper->ItemsHeight <= 0.0f)
3054 data->Ranges.push_front(ImGuiListClipperRange::FromIndices(data->ItemsFrozen, data->ItemsFrozen + 1));
3055 clipper->DisplayStart = ImMax(data->Ranges[0].Min, data->ItemsFrozen);
3056 clipper->DisplayEnd = ImMin(data->Ranges[0].Max, clipper->ItemsCount);
3060 calc_clipping =
true;
3064 if (clipper->ItemsHeight <= 0.0f)
3066 IM_ASSERT(data->StepNo == 1);
3068 IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y);
3070 clipper->ItemsHeight = (window->DC.CursorPos.y - clipper->StartPosY) / (
float)(clipper->DisplayEnd - clipper->DisplayStart);
3071 bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision(clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y);
3072 if (affected_by_floating_point_precision)
3073 clipper->ItemsHeight = window->DC.PrevLineSize.y +
g.Style.ItemSpacing.y;
3075 IM_ASSERT(clipper->ItemsHeight > 0.0f &&
"Unable to calculate item height! First item hasn't moved the cursor vertically!");
3076 calc_clipping =
true;
3080 const int already_submitted = clipper->DisplayEnd;
3086 data->Ranges.push_back(ImGuiListClipperRange::FromIndices(0, clipper->ItemsCount));
3091 const bool is_nav_request = (
g.NavMoveScoringItems &&
g.NavWindow &&
g.NavWindow->RootWindowForNav == window->RootWindowForNav);
3093 data->Ranges.push_back(ImGuiListClipperRange::FromPositions(
g.NavScoringNoClipRect.Min.y,
g.NavScoringNoClipRect.Max.y, 0, 0));
3094 if (is_nav_request && (
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) &&
g.NavTabbingDir == -1)
3095 data->Ranges.push_back(ImGuiListClipperRange::FromIndices(clipper->ItemsCount - 1, clipper->ItemsCount));
3098 ImRect nav_rect_abs = ImGui::WindowRectRelToAbs(window, window->NavRectRel[0]);
3099 if (
g.NavId != 0 && window->NavLastIds[0] ==
g.NavId)
3100 data->Ranges.push_back(ImGuiListClipperRange::FromPositions(nav_rect_abs.Min.y, nav_rect_abs.Max.y, 0, 0));
3103 const int off_min = (is_nav_request &&
g.NavMoveClipDir == ImGuiDir_Up) ? -1 : 0;
3104 const int off_max = (is_nav_request &&
g.NavMoveClipDir == ImGuiDir_Down) ? 1 : 0;
3105 data->Ranges.push_back(ImGuiListClipperRange::FromPositions(window->ClipRect.Min.y, window->ClipRect.Max.y, off_min, off_max));
3112 for (ImGuiListClipperRange& range : data->Ranges)
3113 if (range.PosToIndexConvert)
3115 int m1 = (int)(((
double)range.Min - window->DC.CursorPos.y - data->LossynessOffset) / clipper->ItemsHeight);
3116 int m2 = (int)((((
double)range.Max - window->DC.CursorPos.y - data->LossynessOffset) / clipper->ItemsHeight) + 0.999999f);
3117 range.Min = ImClamp(already_submitted + m1 + range.PosToIndexOffsetMin, already_submitted, clipper->ItemsCount - 1);
3118 range.Max = ImClamp(already_submitted + m2 + range.PosToIndexOffsetMax, range.Min + 1, clipper->ItemsCount);
3119 range.PosToIndexConvert =
false;
3121 ImGuiListClipper_SortAndFuseRanges(data->Ranges, data->StepNo);
3125 while (data->StepNo < data->Ranges.Size)
3127 clipper->DisplayStart = ImMax(data->Ranges[data->StepNo].Min, already_submitted);
3128 clipper->DisplayEnd = ImMin(data->Ranges[data->StepNo].Max, clipper->ItemsCount);
3129 if (clipper->DisplayStart > already_submitted)
3130 ImGuiListClipper_SeekCursorForItem(clipper, clipper->DisplayStart);
3132 if (clipper->DisplayStart == clipper->DisplayEnd && data->StepNo < data->Ranges.Size)
3139 if (clipper->ItemsCount < INT_MAX)
3140 ImGuiListClipper_SeekCursorForItem(clipper, clipper->ItemsCount);
3145bool ImGuiListClipper::Step()
3147 ImGuiContext&
g = *Ctx;
3148 bool need_items_height = (ItemsHeight <= 0.0f);
3149 bool ret = ImGuiListClipper_StepInternal(
this);
3150 if (ret && (DisplayStart == DisplayEnd))
3152 if (
g.CurrentTable &&
g.CurrentTable->IsUnfrozenRows ==
false)
3153 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): inside frozen table row.\n");
3154 if (need_items_height && ItemsHeight > 0.0f)
3155 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): computed ItemsHeight: %.2f.\n", ItemsHeight);
3158 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): display %d to %d.\n", DisplayStart, DisplayEnd);
3162 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): End.\n");
3172ImGuiStyle& ImGui::GetStyle()
3174 IM_ASSERT(
GImGui != NULL &&
"No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
3178ImU32 ImGui::GetColorU32(ImGuiCol idx,
float alpha_mul)
3180 ImGuiStyle& style =
GImGui->Style;
3181 ImVec4 c = style.Colors[idx];
3182 c.w *= style.Alpha * alpha_mul;
3183 return ColorConvertFloat4ToU32(c);
3186ImU32 ImGui::GetColorU32(
const ImVec4& col)
3188 ImGuiStyle& style =
GImGui->Style;
3191 return ColorConvertFloat4ToU32(c);
3194const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx)
3196 ImGuiStyle& style =
GImGui->Style;
3197 return style.Colors[idx];
3200ImU32 ImGui::GetColorU32(ImU32 col,
float alpha_mul)
3202 ImGuiStyle& style =
GImGui->Style;
3203 alpha_mul *= style.Alpha;
3204 if (alpha_mul >= 1.0f)
3206 ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
3207 a = (ImU32)(a * alpha_mul);
3208 return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT);
3212void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col)
3215 ImGuiColorMod backup;
3217 backup.BackupValue =
g.Style.Colors[idx];
3218 g.ColorStack.push_back(backup);
3219 if (
g.DebugFlashStyleColorIdx != idx)
3220 g.Style.Colors[idx] = ColorConvertU32ToFloat4(col);
3223void ImGui::PushStyleColor(ImGuiCol idx,
const ImVec4& col)
3226 ImGuiColorMod backup;
3228 backup.BackupValue =
g.Style.Colors[idx];
3229 g.ColorStack.push_back(backup);
3230 if (
g.DebugFlashStyleColorIdx != idx)
3231 g.Style.Colors[idx] = col;
3234void ImGui::PopStyleColor(
int count)
3237 if (
g.ColorStack.Size < count)
3239 IM_ASSERT_USER_ERROR(
g.ColorStack.Size > count,
"Calling PopStyleColor() too many times!");
3240 count =
g.ColorStack.Size;
3244 ImGuiColorMod& backup =
g.ColorStack.back();
3245 g.Style.Colors[backup.Col] = backup.BackupValue;
3246 g.ColorStack.pop_back();
3251static const ImGuiCol GWindowDockStyleColors[ImGuiWindowDockStyleCol_COUNT] =
3253 ImGuiCol_Text, ImGuiCol_Tab, ImGuiCol_TabHovered, ImGuiCol_TabActive, ImGuiCol_TabUnfocused, ImGuiCol_TabUnfocusedActive
3256static const ImGuiDataVarInfo GStyleVarInfo[] =
3258 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, Alpha) },
3259 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, DisabledAlpha) },
3260 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowPadding) },
3261 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, WindowRounding) },
3262 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, WindowBorderSize) },
3263 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowMinSize) },
3264 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowTitleAlign) },
3265 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ChildRounding) },
3266 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ChildBorderSize) },
3267 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, PopupRounding) },
3268 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, PopupBorderSize) },
3269 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, FramePadding) },
3270 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, FrameRounding) },
3271 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, FrameBorderSize) },
3272 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ItemSpacing) },
3273 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ItemInnerSpacing) },
3274 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, IndentSpacing) },
3275 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, CellPadding) },
3276 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ScrollbarSize) },
3277 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ScrollbarRounding) },
3278 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, GrabMinSize) },
3279 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, GrabRounding) },
3280 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabRounding) },
3281 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBorderSize) },
3282 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBarBorderSize) },
3283 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersAngle)},
3284 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersTextAlign)},
3285 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) },
3286 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) },
3287 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, SeparatorTextBorderSize)},
3288 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SeparatorTextAlign) },
3289 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SeparatorTextPadding) },
3290 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, DockingSeparatorSize) },
3293const ImGuiDataVarInfo* ImGui::GetStyleVarInfo(ImGuiStyleVar idx)
3295 IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT);
3297 return &GStyleVarInfo[idx];
3300void ImGui::PushStyleVar(ImGuiStyleVar idx,
float val)
3303 const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx);
3304 if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1)
3306 float* pvar = (
float*)var_info->GetVarPtr(&
g.Style);
3307 g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
3311 IM_ASSERT_USER_ERROR(0,
"Calling PushStyleVar() variant with wrong type!");
3314void ImGui::PushStyleVar(ImGuiStyleVar idx,
const ImVec2& val)
3317 const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx);
3318 if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2)
3320 ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&
g.Style);
3321 g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
3325 IM_ASSERT_USER_ERROR(0,
"Calling PushStyleVar() variant with wrong type!");
3328void ImGui::PopStyleVar(
int count)
3331 if (
g.StyleVarStack.Size < count)
3333 IM_ASSERT_USER_ERROR(
g.StyleVarStack.Size > count,
"Calling PopStyleVar() too many times!");
3334 count =
g.StyleVarStack.Size;
3339 ImGuiStyleMod& backup =
g.StyleVarStack.back();
3340 const ImGuiDataVarInfo* info = GetStyleVarInfo(backup.VarIdx);
3341 void* data = info->GetVarPtr(&
g.Style);
3342 if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((
float*)data)[0] = backup.BackupFloat[0]; }
3343 else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((
float*)data)[0] = backup.BackupFloat[0]; ((
float*)data)[1] = backup.BackupFloat[1]; }
3344 g.StyleVarStack.pop_back();
3349const char* ImGui::GetStyleColorName(ImGuiCol idx)
3354 case ImGuiCol_Text:
return "Text";
3355 case ImGuiCol_TextDisabled:
return "TextDisabled";
3356 case ImGuiCol_WindowBg:
return "WindowBg";
3357 case ImGuiCol_ChildBg:
return "ChildBg";
3358 case ImGuiCol_PopupBg:
return "PopupBg";
3359 case ImGuiCol_Border:
return "Border";
3360 case ImGuiCol_BorderShadow:
return "BorderShadow";
3361 case ImGuiCol_FrameBg:
return "FrameBg";
3362 case ImGuiCol_FrameBgHovered:
return "FrameBgHovered";
3363 case ImGuiCol_FrameBgActive:
return "FrameBgActive";
3364 case ImGuiCol_TitleBg:
return "TitleBg";
3365 case ImGuiCol_TitleBgActive:
return "TitleBgActive";
3366 case ImGuiCol_TitleBgCollapsed:
return "TitleBgCollapsed";
3367 case ImGuiCol_MenuBarBg:
return "MenuBarBg";
3368 case ImGuiCol_ScrollbarBg:
return "ScrollbarBg";
3369 case ImGuiCol_ScrollbarGrab:
return "ScrollbarGrab";
3370 case ImGuiCol_ScrollbarGrabHovered:
return "ScrollbarGrabHovered";
3371 case ImGuiCol_ScrollbarGrabActive:
return "ScrollbarGrabActive";
3372 case ImGuiCol_CheckMark:
return "CheckMark";
3373 case ImGuiCol_SliderGrab:
return "SliderGrab";
3374 case ImGuiCol_SliderGrabActive:
return "SliderGrabActive";
3375 case ImGuiCol_Button:
return "Button";
3376 case ImGuiCol_ButtonHovered:
return "ButtonHovered";
3377 case ImGuiCol_ButtonActive:
return "ButtonActive";
3378 case ImGuiCol_Header:
return "Header";
3379 case ImGuiCol_HeaderHovered:
return "HeaderHovered";
3380 case ImGuiCol_HeaderActive:
return "HeaderActive";
3381 case ImGuiCol_Separator:
return "Separator";
3382 case ImGuiCol_SeparatorHovered:
return "SeparatorHovered";
3383 case ImGuiCol_SeparatorActive:
return "SeparatorActive";
3384 case ImGuiCol_ResizeGrip:
return "ResizeGrip";
3385 case ImGuiCol_ResizeGripHovered:
return "ResizeGripHovered";
3386 case ImGuiCol_ResizeGripActive:
return "ResizeGripActive";
3387 case ImGuiCol_Tab:
return "Tab";
3388 case ImGuiCol_TabHovered:
return "TabHovered";
3389 case ImGuiCol_TabActive:
return "TabActive";
3390 case ImGuiCol_TabUnfocused:
return "TabUnfocused";
3391 case ImGuiCol_TabUnfocusedActive:
return "TabUnfocusedActive";
3392 case ImGuiCol_DockingPreview:
return "DockingPreview";
3393 case ImGuiCol_DockingEmptyBg:
return "DockingEmptyBg";
3394 case ImGuiCol_PlotLines:
return "PlotLines";
3395 case ImGuiCol_PlotLinesHovered:
return "PlotLinesHovered";
3396 case ImGuiCol_PlotHistogram:
return "PlotHistogram";
3397 case ImGuiCol_PlotHistogramHovered:
return "PlotHistogramHovered";
3398 case ImGuiCol_TableHeaderBg:
return "TableHeaderBg";
3399 case ImGuiCol_TableBorderStrong:
return "TableBorderStrong";
3400 case ImGuiCol_TableBorderLight:
return "TableBorderLight";
3401 case ImGuiCol_TableRowBg:
return "TableRowBg";
3402 case ImGuiCol_TableRowBgAlt:
return "TableRowBgAlt";
3403 case ImGuiCol_TextSelectedBg:
return "TextSelectedBg";
3404 case ImGuiCol_DragDropTarget:
return "DragDropTarget";
3405 case ImGuiCol_NavHighlight:
return "NavHighlight";
3406 case ImGuiCol_NavWindowingHighlight:
return "NavWindowingHighlight";
3407 case ImGuiCol_NavWindowingDimBg:
return "NavWindowingDimBg";
3408 case ImGuiCol_ModalWindowDimBg:
return "ModalWindowDimBg";
3422const char* ImGui::FindRenderedTextEnd(
const char* text,
const char* text_end)
3424 const char* text_display_end = text;
3426 text_end = (
const char*)-1;
3428 while (text_display_end < text_end && *text_display_end !=
'\0' && (text_display_end[0] !=
'#' || text_display_end[1] !=
'#'))
3430 return text_display_end;
3435void ImGui::RenderText(ImVec2 pos,
const char* text,
const char* text_end,
bool hide_text_after_hash)
3438 ImGuiWindow* window =
g.CurrentWindow;
3441 const char* text_display_end;
3442 if (hide_text_after_hash)
3444 text_display_end = FindRenderedTextEnd(text, text_end);
3449 text_end = text + strlen(text);
3450 text_display_end = text_end;
3453 if (text != text_display_end)
3455 window->DrawList->AddText(
g.Font,
g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
3457 LogRenderedText(&pos, text, text_display_end);
3461void ImGui::RenderTextWrapped(ImVec2 pos,
const char* text,
const char* text_end,
float wrap_width)
3464 ImGuiWindow* window =
g.CurrentWindow;
3467 text_end = text + strlen(text);
3469 if (text != text_end)
3471 window->DrawList->AddText(
g.Font,
g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width);
3473 LogRenderedText(&pos, text, text_end);
3482void 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)
3485 ImVec2 pos = pos_min;
3486 const ImVec2 text_size = text_size_if_known ? *text_size_if_known :
CalcTextSize(text, text_display_end,
false, 0.0f);
3488 const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min;
3489 const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max;
3490 bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y);
3492 need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y);
3495 if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x);
3496 if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y);
3501 ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y);
3502 draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect);
3506 draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL);
3510void 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)
3513 const char* text_display_end = FindRenderedTextEnd(text, text_end);
3514 const int text_len = (int)(text_display_end - text);
3519 ImGuiWindow* window =
g.CurrentWindow;
3520 RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect);
3522 LogRenderedText(&pos_min, text, text_display_end);
3528void 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)
3531 if (text_end_full == NULL)
3532 text_end_full = FindRenderedTextEnd(text);
3533 const ImVec2 text_size = text_size_if_known ? *text_size_if_known :
CalcTextSize(text, text_end_full,
false, 0.0f);
3539 if (text_size.x > pos_max.x - pos_min.x)
3546 const ImFont* font = draw_list->_Data->Font;
3547 const float font_size = draw_list->_Data->FontSize;
3548 const float font_scale = font_size / font->FontSize;
3549 const char* text_end_ellipsis = NULL;
3550 const float ellipsis_width = font->EllipsisWidth * font_scale;
3553 const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_width) - pos_min.x, 1.0f);
3554 float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
3555 if (text == text_end_ellipsis && text_end_ellipsis < text_end_full)
3559 text_size_clipped_x = font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text, text_end_ellipsis).x;
3561 while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1]))
3564 text_end_ellipsis--;
3565 text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x;
3569 RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f));
3570 ImVec2 ellipsis_pos = ImTrunc(ImVec2(pos_min.x + text_size_clipped_x, pos_min.y));
3571 if (ellipsis_pos.x + ellipsis_width <= ellipsis_max_x)
3572 for (
int i = 0; i < font->EllipsisCharCount; i++, ellipsis_pos.x += font->EllipsisCharStep * font_scale)
3573 font->RenderChar(draw_list, font_size, ellipsis_pos, GetColorU32(ImGuiCol_Text), font->EllipsisChar);
3577 RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_full, &text_size, ImVec2(0.0f, 0.0f));
3581 LogRenderedText(&pos_min, text, text_end_full);
3585void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col,
bool border,
float rounding)
3588 ImGuiWindow* window =
g.CurrentWindow;
3589 window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
3590 const float border_size =
g.Style.FrameBorderSize;
3591 if (border && border_size > 0.0f)
3593 window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
3594 window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
3598void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max,
float rounding)
3601 ImGuiWindow* window =
g.CurrentWindow;
3602 const float border_size =
g.Style.FrameBorderSize;
3603 if (border_size > 0.0f)
3605 window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
3606 window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
3610void ImGui::RenderNavHighlight(
const ImRect& bb, ImGuiID
id, ImGuiNavHighlightFlags flags)
3615 if (
g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw))
3617 ImGuiWindow* window =
g.CurrentWindow;
3618 if (window->DC.NavHideHighlightOneFrame)
3621 float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f :
g.Style.FrameRounding;
3622 ImRect display_rect = bb;
3623 display_rect.ClipWith(window->ClipRect);
3624 const float thickness = 2.0f;
3625 if (flags & ImGuiNavHighlightFlags_Compact)
3627 window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, thickness);
3631 const float distance = 3.0f + thickness * 0.5f;
3632 display_rect.Expand(ImVec2(distance, distance));
3633 bool fully_visible = window->ClipRect.Contains(display_rect);
3635 window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
3636 window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, thickness);
3638 window->DrawList->PopClipRect();
3642void ImGui::RenderMouseCursor(ImVec2 base_pos,
float base_scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow)
3645 IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT);
3646 ImFontAtlas* font_atlas =
g.DrawListSharedData.Font->ContainerAtlas;
3647 for (ImGuiViewportP* viewport :
g.Viewports)
3650 ImVec2 offset,
size, uv[4];
3651 if (!font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2]))
3653 const ImVec2 pos = base_pos - offset;
3654 const float scale = base_scale * viewport->DpiScale;
3655 if (!viewport->GetMainRect().Overlaps(ImRect(pos, pos + ImVec2(
size.x + 2,
size.y + 2) * scale)))
3657 ImDrawList* draw_list = GetForegroundDrawList(viewport);
3658 ImTextureID tex_id = font_atlas->TexID;
3659 draw_list->PushTextureID(tex_id);
3660 draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow);
3661 draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow);
3662 draw_list->AddImage(tex_id, pos, pos + size * scale, uv[2], uv[3], col_border);
3663 draw_list->AddImage(tex_id, pos, pos + size * scale, uv[0], uv[1], col_fill);
3664 draw_list->PopTextureID();
3674ImGuiContext* ImGui::GetCurrentContext()
3679void ImGui::SetCurrentContext(ImGuiContext* ctx)
3681#ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC
3682 IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx);
3688void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func,
void* user_data)
3690 GImAllocatorAllocFunc = alloc_func;
3691 GImAllocatorFreeFunc = free_func;
3692 GImAllocatorUserData = user_data;
3696void ImGui::GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func,
void** p_user_data)
3698 *p_alloc_func = GImAllocatorAllocFunc;
3699 *p_free_func = GImAllocatorFreeFunc;
3700 *p_user_data = GImAllocatorUserData;
3703ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas)
3705 ImGuiContext* prev_ctx = GetCurrentContext();
3706 ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);
3707 SetCurrentContext(ctx);
3709 if (prev_ctx != NULL)
3710 SetCurrentContext(prev_ctx);
3714void ImGui::DestroyContext(ImGuiContext* ctx)
3716 ImGuiContext* prev_ctx = GetCurrentContext();
3719 SetCurrentContext(ctx);
3721 SetCurrentContext((prev_ctx != ctx) ? prev_ctx : NULL);
3726static const ImGuiLocEntry GLocalizationEntriesEnUS[] =
3728 { ImGuiLocKey_VersionStr,
"Dear ImGui " IMGUI_VERSION
" (" IM_STRINGIFY(IMGUI_VERSION_NUM)
")" },
3729 { ImGuiLocKey_TableSizeOne,
"Size column to fit###SizeOne" },
3730 { ImGuiLocKey_TableSizeAllFit,
"Size all columns to fit###SizeAll" },
3731 { ImGuiLocKey_TableSizeAllDefault,
"Size all columns to default###SizeAll" },
3732 { ImGuiLocKey_TableResetOrder,
"Reset order###ResetOrder" },
3733 { ImGuiLocKey_WindowingMainMenuBar,
"(Main menu bar)" },
3734 { ImGuiLocKey_WindowingPopup,
"(Popup)" },
3735 { ImGuiLocKey_WindowingUntitled,
"(Untitled)" },
3736 { ImGuiLocKey_DockingHideTabBar,
"Hide tab bar###HideTabBar" },
3737 { ImGuiLocKey_DockingHoldShiftToDock,
"Hold SHIFT to enable Docking window." },
3738 { ImGuiLocKey_DockingDragToUndockOrMoveNode,
"Click and drag to move or undock whole node." },
3741void ImGui::Initialize()
3744 IM_ASSERT(!
g.Initialized && !
g.SettingsLoaded);
3748 ImGuiSettingsHandler ini_handler;
3749 ini_handler.TypeName =
"Window";
3750 ini_handler.TypeHash =
ImHashStr(
"Window");
3751 ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll;
3752 ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen;
3753 ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine;
3754 ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll;
3755 ini_handler.WriteAllFn = WindowSettingsHandler_WriteAll;
3756 AddSettingsHandler(&ini_handler);
3758 TableSettingsAddSettingsHandler();
3761 LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_ARRAYSIZE(GLocalizationEntriesEnUS));
3764 g.IO.GetClipboardTextFn = GetClipboardTextFn_DefaultImpl;
3765 g.IO.SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
3766 g.IO.ClipboardUserData = (
void*)&
g;
3767 g.IO.SetPlatformImeDataFn = SetPlatformImeDataFn_DefaultImpl;
3770 ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)();
3773 viewport->PlatformWindowCreated =
true;
3774 viewport->Flags = ImGuiViewportFlags_OwnedByApp;
3775 g.Viewports.push_back(viewport);
3776 g.TempBuffer.resize(1024 * 3 + 1, 0);
3777 g.ViewportCreatedCount++;
3778 g.PlatformIO.Viewports.push_back(
g.Viewports[0]);
3781 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
3782 if ((key >= ImGuiKey_0 && key <= ImGuiKey_9) || (key >= ImGuiKey_A && key <= ImGuiKey_Z) || (key >= ImGuiKey_Keypad0 && key <= ImGuiKey_Keypad9)
3783 || key == ImGuiKey_Tab || key == ImGuiKey_Space || key == ImGuiKey_Apostrophe || key == ImGuiKey_Comma || key == ImGuiKey_Minus || key == ImGuiKey_Period
3784 || key == ImGuiKey_Slash || key == ImGuiKey_Semicolon || key == ImGuiKey_Equal || key == ImGuiKey_LeftBracket || key == ImGuiKey_RightBracket || key == ImGuiKey_GraveAccent
3785 || key == ImGuiKey_KeypadDecimal || key == ImGuiKey_KeypadDivide || key == ImGuiKey_KeypadMultiply || key == ImGuiKey_KeypadSubtract || key == ImGuiKey_KeypadAdd || key == ImGuiKey_KeypadEqual)
3786 g.KeysMayBeCharInput.SetBit(key);
3788#ifdef IMGUI_HAS_DOCK
3790 DockContextInitialize(&
g);
3793 g.Initialized =
true;
3797void ImGui::Shutdown()
3800 IM_ASSERT_USER_ERROR(
g.IO.BackendPlatformUserData == NULL,
"Forgot to shutdown Platform backend?");
3801 IM_ASSERT_USER_ERROR(
g.IO.BackendRendererUserData == NULL,
"Forgot to shutdown Renderer backend?");
3804 if (
g.IO.Fonts &&
g.FontAtlasOwnedByContext)
3806 g.IO.Fonts->Locked =
false;
3807 IM_DELETE(
g.IO.Fonts);
3810 g.DrawListSharedData.TempBuffer.clear();
3817 if (
g.SettingsLoaded &&
g.IO.IniFilename != NULL)
3818 SaveIniSettingsToDisk(
g.IO.IniFilename);
3821 DestroyPlatformWindows();
3824 DockContextShutdown(&
g);
3826 CallContextHooks(&
g, ImGuiContextHookType_Shutdown);
3829 g.Windows.clear_delete();
3830 g.WindowsFocusOrder.clear();
3831 g.WindowsTempSortBuffer.clear();
3832 g.CurrentWindow = NULL;
3833 g.CurrentWindowStack.clear();
3834 g.WindowsById.Clear();
3836 g.HoveredWindow =
g.HoveredWindowUnderMovingWindow = NULL;
3837 g.ActiveIdWindow =
g.ActiveIdPreviousFrameWindow = NULL;
3838 g.MovingWindow = NULL;
3840 g.KeysRoutingTable.Clear();
3842 g.ColorStack.clear();
3843 g.StyleVarStack.clear();
3844 g.FontStack.clear();
3845 g.OpenPopupStack.clear();
3846 g.BeginPopupStack.clear();
3847 g.NavTreeNodeStack.clear();
3849 g.CurrentViewport =
g.MouseViewport =
g.MouseLastHoveredViewport = NULL;
3850 g.Viewports.clear_delete();
3853 g.CurrentTabBarStack.clear();
3854 g.ShrinkWidthBuffer.clear();
3856 g.ClipperTempData.clear_destruct();
3859 g.TablesTempData.clear_destruct();
3860 g.DrawChannelsTempMergeBuffer.clear();
3862 g.ClipboardHandlerData.clear();
3863 g.MenusIdSubmittedThisFrame.clear();
3864 g.InputTextState.ClearFreeMemory();
3865 g.InputTextDeactivatedState.ClearFreeMemory();
3867 g.SettingsWindows.clear();
3868 g.SettingsHandlers.clear();
3872#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
3873 if (
g.LogFile != stdout)
3878 g.LogBuffer.clear();
3879 g.DebugLogBuf.clear();
3880 g.DebugLogIndex.clear();
3882 g.Initialized =
false;
3886ImGuiID ImGui::AddContextHook(ImGuiContext* ctx,
const ImGuiContextHook* hook)
3888 ImGuiContext&
g = *ctx;
3889 IM_ASSERT(hook->Callback != NULL && hook->HookId == 0 && hook->Type != ImGuiContextHookType_PendingRemoval_);
3890 g.Hooks.push_back(*hook);
3891 g.Hooks.back().HookId = ++
g.HookIdNext;
3892 return g.HookIdNext;
3896void ImGui::RemoveContextHook(ImGuiContext* ctx, ImGuiID hook_id)
3898 ImGuiContext&
g = *ctx;
3899 IM_ASSERT(hook_id != 0);
3900 for (ImGuiContextHook& hook :
g.Hooks)
3901 if (hook.HookId == hook_id)
3902 hook.Type = ImGuiContextHookType_PendingRemoval_;
3907void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type)
3909 ImGuiContext&
g = *ctx;
3910 for (ImGuiContextHook& hook :
g.Hooks)
3911 if (hook.Type == hook_type)
3912 hook.Callback(&
g, &hook);
3921ImGuiWindow::ImGuiWindow(ImGuiContext* ctx,
const char* name) : DrawListInst(NULL)
3923 memset(
this, 0,
sizeof(*
this));
3926 NameBufLen = (int)strlen(name) + 1;
3928 IDStack.push_back(ID);
3929 ViewportAllowPlatformMonitorExtend = -1;
3930 ViewportPos = ImVec2(FLT_MAX, FLT_MAX);
3931 MoveId = GetID(
"#MOVE");
3932 TabId = GetID(
"#TAB");
3933 ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
3934 ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
3935 AutoFitFramesX = AutoFitFramesY = -1;
3936 AutoPosLastDirection = ImGuiDir_None;
3937 SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = SetWindowDockAllowFlags = 0;
3938 SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX);
3939 LastFrameActive = -1;
3940 LastFrameJustFocused = -1;
3941 LastTimeActive = -1.0f;
3942 FontWindowScale = FontDpiScale = 1.0f;
3943 SettingsOffset = -1;
3945 DrawList = &DrawListInst;
3946 DrawList->_Data = &Ctx->DrawListSharedData;
3947 DrawList->_OwnerName = Name;
3948 NavPreferredScoringPosRel[0] = NavPreferredScoringPosRel[1] = ImVec2(FLT_MAX, FLT_MAX);
3949 IM_PLACEMENT_NEW(&WindowClass) ImGuiWindowClass();
3952ImGuiWindow::~ImGuiWindow()
3954 IM_ASSERT(DrawList == &DrawListInst);
3956 ColumnsStorage.clear_destruct();
3959static void SetCurrentWindow(ImGuiWindow* window)
3962 g.CurrentWindow = window;
3963 g.CurrentTable = window && window->DC.CurrentTableIdx != -1 ?
g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL;
3966 g.FontSize =
g.DrawListSharedData.FontSize = window->CalcFontSize();
3967 ImGui::NavUpdateCurrentWindowIsScrollPushableX();
3971void ImGui::GcCompactTransientMiscBuffers()
3974 g.ItemFlagsStack.clear();
3975 g.GroupStack.clear();
3976 TableGcCompactSettings();
3983void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window)
3985 window->MemoryCompacted =
true;
3986 window->MemoryDrawListIdxCapacity = window->DrawList->IdxBuffer.Capacity;
3987 window->MemoryDrawListVtxCapacity = window->DrawList->VtxBuffer.Capacity;
3988 window->IDStack.clear();
3989 window->DrawList->_ClearFreeMemory();
3990 window->DC.ChildWindows.clear();
3991 window->DC.ItemWidthStack.clear();
3992 window->DC.TextWrapPosStack.clear();
3995void ImGui::GcAwakeTransientWindowBuffers(ImGuiWindow* window)
3999 window->MemoryCompacted =
false;
4000 window->DrawList->IdxBuffer.reserve(window->MemoryDrawListIdxCapacity);
4001 window->DrawList->VtxBuffer.reserve(window->MemoryDrawListVtxCapacity);
4002 window->MemoryDrawListIdxCapacity = window->MemoryDrawListVtxCapacity = 0;
4005void ImGui::SetActiveID(ImGuiID
id, ImGuiWindow* window)
4010 if (
g.ActiveId != 0)
4015 if (
g.MovingWindow != NULL &&
g.ActiveId ==
g.MovingWindow->MoveId)
4017 IMGUI_DEBUG_LOG_ACTIVEID(
"SetActiveID() cancel MovingWindow\n");
4018 g.MovingWindow = NULL;
4024 if (
g.InputTextState.ID ==
g.ActiveId)
4025 InputTextDeactivateHook(
g.ActiveId);
4029 g.ActiveIdIsJustActivated = (
g.ActiveId !=
id);
4030 if (
g.ActiveIdIsJustActivated)
4032 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 :
"");
4033 g.ActiveIdTimer = 0.0f;
4034 g.ActiveIdHasBeenPressedBefore =
false;
4035 g.ActiveIdHasBeenEditedBefore =
false;
4036 g.ActiveIdMouseButton = -1;
4039 g.LastActiveId =
id;
4040 g.LastActiveIdTimer = 0.0f;
4044 g.ActiveIdAllowOverlap =
false;
4045 g.ActiveIdNoClearOnFocusLoss =
false;
4046 g.ActiveIdWindow = window;
4047 g.ActiveIdHasBeenEditedThisFrame =
false;
4048 g.ActiveIdFromShortcut =
false;
4051 g.ActiveIdIsAlive =
id;
4052 g.ActiveIdSource = (
g.NavActivateId ==
id ||
g.NavJustMovedToId ==
id) ?
g.NavInputSource : ImGuiInputSource_Mouse;
4053 IM_ASSERT(
g.ActiveIdSource != ImGuiInputSource_None);
4058 g.ActiveIdUsingNavDirMask = 0x00;
4059 g.ActiveIdUsingAllKeyboardKeys =
false;
4060#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
4061 g.ActiveIdUsingNavInputMask = 0x00;
4065void ImGui::ClearActiveID()
4067 SetActiveID(0, NULL);
4070void ImGui::SetHoveredID(ImGuiID
id)
4074 g.HoveredIdAllowOverlap =
false;
4075 if (
id != 0 &&
g.HoveredIdPreviousFrame !=
id)
4076 g.HoveredIdTimer =
g.HoveredIdNotActiveTimer = 0.0f;
4079ImGuiID ImGui::GetHoveredID()
4082 return g.HoveredId ?
g.HoveredId :
g.HoveredIdPreviousFrame;
4085void ImGui::MarkItemEdited(ImGuiID
id)
4090 if (
g.LockMarkEdited > 0)
4092 if (
g.ActiveId ==
id ||
g.ActiveId == 0)
4094 g.ActiveIdHasBeenEditedThisFrame =
true;
4095 g.ActiveIdHasBeenEditedBefore =
true;
4100 IM_ASSERT(
g.DragDropActive ||
g.ActiveId ==
id ||
g.ActiveId == 0 ||
g.ActiveIdPreviousFrame ==
id);
4103 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
4106bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
4112 if (ImGuiWindow* focused_root_window =
g.NavWindow->RootWindowDockTree)
4113 if (focused_root_window->WasActive && focused_root_window != window->RootWindowDockTree)
4117 bool want_inhibit =
false;
4118 if (focused_root_window->Flags & ImGuiWindowFlags_Modal)
4119 want_inhibit =
true;
4120 else if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup))
4121 want_inhibit =
true;
4125 if (!IsWindowWithinBeginStackOf(window->RootWindow, focused_root_window))
4130 if (window->Viewport !=
g.MouseViewport)
4131 if (
g.MovingWindow == NULL || window->RootWindowDockTree !=
g.MovingWindow->RootWindowDockTree)
4137static inline float CalcDelayFromHoveredFlags(ImGuiHoveredFlags flags)
4140 if (flags & ImGuiHoveredFlags_DelayNormal)
4141 return g.Style.HoverDelayNormal;
4142 if (flags & ImGuiHoveredFlags_DelayShort)
4143 return g.Style.HoverDelayShort;
4147static ImGuiHoveredFlags ApplyHoverFlagsForTooltip(ImGuiHoveredFlags user_flags, ImGuiHoveredFlags shared_flags)
4150 if (user_flags & (ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal))
4151 shared_flags &= ~(ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal);
4152 return user_flags | shared_flags;
4158bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
4161 ImGuiWindow* window =
g.CurrentWindow;
4162 IM_ASSERT((flags & ~ImGuiHoveredFlags_AllowedMaskForIsItemHovered) == 0 &&
"Invalid flags for IsItemHovered()!");
4164 if (
g.NavDisableMouseHover && !
g.NavDisableHighlight && !(flags & ImGuiHoveredFlags_NoNavOverride))
4166 if ((
g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
4168 if (!IsItemFocused())
4171 if (flags & ImGuiHoveredFlags_ForTooltip)
4172 flags = ApplyHoverFlagsForTooltip(flags,
g.Style.HoverFlagsForTooltipNav);
4177 ImGuiItemStatusFlags status_flags =
g.LastItemData.StatusFlags;
4178 if (!(status_flags & ImGuiItemStatusFlags_HoveredRect))
4181 if (flags & ImGuiHoveredFlags_ForTooltip)
4182 flags = ApplyHoverFlagsForTooltip(flags,
g.Style.HoverFlagsForTooltipMouse);
4184 IM_ASSERT((flags & (ImGuiHoveredFlags_AnyWindow | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy | ImGuiHoveredFlags_DockHierarchy)) == 0);
4192 if (
g.HoveredWindow != window && (status_flags & ImGuiItemStatusFlags_HoveredWindow) == 0)
4193 if ((flags & ImGuiHoveredFlags_AllowWhenOverlappedByWindow) == 0)
4197 const ImGuiID
id =
g.LastItemData.ID;
4198 if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0)
4199 if (
g.ActiveId != 0 &&
g.ActiveId !=
id && !
g.ActiveIdAllowOverlap)
4200 if (
g.ActiveId != window->MoveId &&
g.ActiveId != window->TabId)
4205 if (!IsWindowContentHoverable(window, flags) && !(
g.LastItemData.InFlags & ImGuiItemFlags_NoWindowHoverableCheck))
4209 if ((
g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
4215 if (
id == window->MoveId && window->WriteAccessed)
4219 if ((
g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap) &&
id != 0)
4220 if ((flags & ImGuiHoveredFlags_AllowWhenOverlappedByItem) == 0)
4221 if (
g.HoveredIdPreviousFrame !=
g.LastItemData.ID)
4227 const float delay = CalcDelayFromHoveredFlags(flags);
4228 if (delay > 0.0f || (flags & ImGuiHoveredFlags_Stationary))
4230 ImGuiID hover_delay_id = (
g.LastItemData.ID != 0) ?
g.LastItemData.ID : window->GetIDFromRectangle(
g.LastItemData.Rect);
4231 if ((flags & ImGuiHoveredFlags_NoSharedDelay) && (
g.HoverItemDelayIdPreviousFrame != hover_delay_id))
4232 g.HoverItemDelayTimer = 0.0f;
4233 g.HoverItemDelayId = hover_delay_id;
4238 if ((flags & ImGuiHoveredFlags_Stationary) != 0 &&
g.HoverItemUnlockedStationaryId != hover_delay_id)
4241 if (
g.HoverItemDelayTimer < delay)
4254bool ImGui::ItemHoverable(
const ImRect& bb, ImGuiID
id, ImGuiItemFlags item_flags)
4257 ImGuiWindow* window =
g.CurrentWindow;
4258 if (
g.HoveredWindow != window)
4260 if (!IsMouseHoveringRect(bb.Min, bb.Max))
4263 if (
g.HoveredId != 0 &&
g.HoveredId !=
id && !
g.HoveredIdAllowOverlap)
4265 if (
g.ActiveId != 0 &&
g.ActiveId !=
id && !
g.ActiveIdAllowOverlap)
4266 if (!
g.ActiveIdFromShortcut)
4270 if (!(item_flags & ImGuiItemFlags_NoWindowHoverableCheck) && !IsWindowContentHoverable(window, ImGuiHoveredFlags_None))
4272 g.HoveredIdDisabled =
true;
4281 if (
g.DragDropActive &&
g.DragDropPayload.SourceId ==
id && !(
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoDisableHover))
4288 if (item_flags & ImGuiItemFlags_AllowOverlap)
4290 g.HoveredIdAllowOverlap =
true;
4291 if (
g.HoveredIdPreviousFrame !=
id)
4296 if (
id ==
g.LastItemData.ID && (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasShortcut))
4297 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_DelayNormal))
4298 SetTooltip(
"%s", GetKeyChordName(
g.LastItemData.Shortcut));
4302 if (item_flags & ImGuiItemFlags_Disabled)
4305 if (
g.ActiveId ==
id &&
id != 0)
4307 g.HoveredIdDisabled =
true;
4311#ifndef IMGUI_DISABLE_DEBUG_TOOLS
4318 if (
g.DebugItemPickerActive &&
g.HoveredIdPreviousFrame ==
id)
4319 GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
4320 if (
g.DebugItemPickerBreakId ==
id)
4325 if (
g.NavDisableMouseHover)
4333bool ImGui::IsClippedEx(
const ImRect& bb, ImGuiID
id)
4336 ImGuiWindow* window =
g.CurrentWindow;
4337 if (!bb.Overlaps(window->ClipRect))
4338 if (
id == 0 || (
id !=
g.ActiveId &&
id !=
g.ActiveIdPreviousFrame &&
id !=
g.NavId &&
id !=
g.NavActivateId))
4346void ImGui::SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags item_flags,
const ImRect& item_rect)
4349 g.LastItemData.ID = item_id;
4350 g.LastItemData.InFlags = in_flags;
4351 g.LastItemData.StatusFlags = item_flags;
4352 g.LastItemData.Rect =
g.LastItemData.NavRect = item_rect;
4355float ImGui::CalcWrapWidthForPos(
const ImVec2& pos,
float wrap_pos_x)
4357 if (wrap_pos_x < 0.0f)
4361 ImGuiWindow* window =
g.CurrentWindow;
4362 if (wrap_pos_x == 0.0f)
4369 wrap_pos_x = window->WorkRect.Max.x;
4371 else if (wrap_pos_x > 0.0f)
4373 wrap_pos_x += window->Pos.x - window->Scroll.x;
4376 return ImMax(wrap_pos_x - pos.x, 1.0f);
4380void* ImGui::MemAlloc(
size_t size)
4382 void* ptr = (*GImAllocatorAllocFunc)(
size, GImAllocatorUserData);
4383#ifndef IMGUI_DISABLE_DEBUG_TOOLS
4384 if (ImGuiContext* ctx =
GImGui)
4385 DebugAllocHook(&ctx->DebugAllocInfo, ctx->FrameCount, ptr, size);
4391void ImGui::MemFree(
void* ptr)
4393#ifndef IMGUI_DISABLE_DEBUG_TOOLS
4395 if (ImGuiContext* ctx =
GImGui)
4396 DebugAllocHook(&ctx->DebugAllocInfo, ctx->FrameCount, ptr, (
size_t)-1);
4398 return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData);
4402void ImGui::DebugAllocHook(ImGuiDebugAllocInfo* info,
int frame_count,
void* ptr,
size_t size)
4404 ImGuiDebugAllocEntry* entry = &info->LastEntriesBuf[info->LastEntriesIdx];
4406 if (entry->FrameCount != frame_count)
4408 info->LastEntriesIdx = (info->LastEntriesIdx + 1) % IM_ARRAYSIZE(info->LastEntriesBuf);
4409 entry = &info->LastEntriesBuf[info->LastEntriesIdx];
4410 entry->FrameCount = frame_count;
4411 entry->AllocCount = entry->FreeCount = 0;
4413 if (size != (
size_t)-1)
4415 entry->AllocCount++;
4416 info->TotalAllocCount++;
4422 info->TotalFreeCount++;
4427const char* ImGui::GetClipboardText()
4430 return g.IO.GetClipboardTextFn ?
g.IO.GetClipboardTextFn(
g.IO.ClipboardUserData) :
"";
4433void ImGui::SetClipboardText(
const char* text)
4436 if (
g.IO.SetClipboardTextFn)
4437 g.IO.SetClipboardTextFn(
g.IO.ClipboardUserData, text);
4440const char* ImGui::GetVersion()
4442 return IMGUI_VERSION;
4445ImGuiIO& ImGui::GetIO()
4447 IM_ASSERT(
GImGui != NULL &&
"No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
4451ImGuiPlatformIO& ImGui::GetPlatformIO()
4453 IM_ASSERT(
GImGui != NULL &&
"No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
4454 return GImGui->PlatformIO;
4458ImDrawData* ImGui::GetDrawData()
4461 ImGuiViewportP* viewport =
g.Viewports[0];
4462 return viewport->DrawDataP.Valid ? &viewport->DrawDataP : NULL;
4465double ImGui::GetTime()
4470int ImGui::GetFrameCount()
4472 return GImGui->FrameCount;
4475static ImDrawList* GetViewportBgFgDrawList(ImGuiViewportP* viewport,
size_t drawlist_no,
const char* drawlist_name)
4479 IM_ASSERT(drawlist_no < IM_ARRAYSIZE(viewport->BgFgDrawLists));
4480 ImDrawList* draw_list = viewport->BgFgDrawLists[drawlist_no];
4481 if (draw_list == NULL)
4483 draw_list = IM_NEW(ImDrawList)(&
g.DrawListSharedData);
4484 draw_list->_OwnerName = drawlist_name;
4485 viewport->BgFgDrawLists[drawlist_no] = draw_list;
4489 if (viewport->BgFgDrawListsLastFrame[drawlist_no] !=
g.FrameCount)
4491 draw_list->_ResetForNewFrame();
4492 draw_list->PushTextureID(
g.IO.Fonts->TexID);
4493 draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size,
false);
4494 viewport->BgFgDrawListsLastFrame[drawlist_no] =
g.FrameCount;
4499ImDrawList* ImGui::GetBackgroundDrawList(ImGuiViewport* viewport)
4501 return GetViewportBgFgDrawList((ImGuiViewportP*)viewport, 0,
"##Background");
4504ImDrawList* ImGui::GetBackgroundDrawList()
4507 return GetBackgroundDrawList(
g.CurrentWindow->Viewport);
4510ImDrawList* ImGui::GetForegroundDrawList(ImGuiViewport* viewport)
4512 return GetViewportBgFgDrawList((ImGuiViewportP*)viewport, 1,
"##Foreground");
4515ImDrawList* ImGui::GetForegroundDrawList()
4518 return GetForegroundDrawList(
g.CurrentWindow->Viewport);
4521ImDrawListSharedData* ImGui::GetDrawListSharedData()
4523 return &
GImGui->DrawListSharedData;
4526void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
4532 FocusWindow(window);
4533 SetActiveID(window->MoveId, window);
4534 g.NavDisableHighlight =
true;
4535 g.ActiveIdClickOffset =
g.IO.MouseClickedPos[0] - window->RootWindowDockTree->Pos;
4536 g.ActiveIdNoClearOnFocusLoss =
true;
4537 SetActiveIdUsingAllKeyboardKeys();
4539 bool can_move_window =
true;
4540 if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindowDockTree->Flags & ImGuiWindowFlags_NoMove))
4541 can_move_window =
false;
4542 if (ImGuiDockNode* node = window->DockNodeAsHost)
4543 if (node->VisibleWindow && (node->VisibleWindow->Flags & ImGuiWindowFlags_NoMove))
4544 can_move_window =
false;
4545 if (can_move_window)
4546 g.MovingWindow = window;
4550void ImGui::StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* node,
bool undock)
4553 bool can_undock_node =
false;
4554 if (undock && node != NULL && node->VisibleWindow && (node->VisibleWindow->Flags & ImGuiWindowFlags_NoMove) == 0 && (node->MergedFlags & ImGuiDockNodeFlags_NoUndocking) == 0)
4559 ImGuiDockNode* root_node = DockNodeGetRootNode(node);
4560 if (root_node->OnlyNodeWithWindows != node || root_node->CentralNode != NULL)
4561 can_undock_node =
true;
4564 const bool clicked = IsMouseClicked(0);
4565 const bool dragging = IsMouseDragging(0);
4566 if (can_undock_node && dragging)
4567 DockContextQueueUndockNode(&
g, node);
4568 else if (!can_undock_node && (clicked || dragging) &&
g.MovingWindow != window)
4569 StartMouseMovingWindow(window);
4577void ImGui::UpdateMouseMovingWindowNewFrame()
4580 if (
g.MovingWindow != NULL)
4584 KeepAliveID(
g.ActiveId);
4585 IM_ASSERT(
g.MovingWindow &&
g.MovingWindow->RootWindowDockTree);
4586 ImGuiWindow* moving_window =
g.MovingWindow->RootWindowDockTree;
4589 const bool window_disappared = (!moving_window->WasActive && !moving_window->Active);
4590 if (
g.IO.MouseDown[0] && IsMousePosValid(&
g.IO.MousePos) && !window_disappared)
4592 ImVec2 pos =
g.IO.MousePos -
g.ActiveIdClickOffset;
4593 if (moving_window->Pos.x != pos.x || moving_window->Pos.y != pos.y)
4595 SetWindowPos(moving_window, pos, ImGuiCond_Always);
4596 if (moving_window->Viewport && moving_window->ViewportOwned)
4598 moving_window->Viewport->Pos = pos;
4599 moving_window->Viewport->UpdateWorkRect();
4602 FocusWindow(
g.MovingWindow);
4606 if (!window_disappared)
4610 if (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
4611 UpdateTryMergeWindowIntoHostViewport(moving_window,
g.MouseViewport);
4614 if (moving_window->Viewport && !IsDragDropPayloadBeingAccepted())
4615 g.MouseViewport = moving_window->Viewport;
4618 if (moving_window->Viewport)
4619 moving_window->Viewport->Flags &= ~ImGuiViewportFlags_NoInputs;
4622 g.MovingWindow = NULL;
4629 if (
g.ActiveIdWindow &&
g.ActiveIdWindow->MoveId ==
g.ActiveId)
4631 KeepAliveID(
g.ActiveId);
4632 if (!
g.IO.MouseDown[0])
4640void ImGui::UpdateMouseMovingWindowEndFrame()
4643 if (
g.ActiveId != 0 ||
g.HoveredId != 0)
4647 if (
g.NavWindow &&
g.NavWindow->Appearing)
4652 if (
g.IO.MouseClicked[0])
4656 ImGuiWindow* root_window =
g.HoveredWindow ?
g.HoveredWindow->RootWindow : NULL;
4657 const bool is_closed_popup = root_window && (root_window->Flags & ImGuiWindowFlags_Popup) && !IsPopupOpen(root_window->PopupId, ImGuiPopupFlags_AnyPopupLevel);
4659 if (root_window != NULL && !is_closed_popup)
4661 StartMouseMovingWindow(
g.HoveredWindow);
4664 if (
g.IO.ConfigWindowsMoveFromTitleBarOnly)
4665 if (!(root_window->Flags & ImGuiWindowFlags_NoTitleBar) || root_window->DockIsActive)
4666 if (!root_window->TitleBarRect().Contains(
g.IO.MouseClickedPos[0]))
4667 g.MovingWindow = NULL;
4670 if (
g.HoveredIdDisabled)
4671 g.MovingWindow = NULL;
4673 else if (root_window == NULL &&
g.NavWindow != NULL)
4676 FocusWindow(NULL, ImGuiFocusRequestFlags_UnlessBelowModal);
4683 if (
g.IO.MouseClicked[1])
4687 ImGuiWindow* modal = GetTopMostPopupModal();
4688 bool hovered_window_above_modal =
g.HoveredWindow && (modal == NULL || IsWindowAbove(
g.HoveredWindow, modal));
4689 ClosePopupsOverWindow(hovered_window_above_modal ?
g.HoveredWindow : modal, true);
4695static void TranslateWindow(ImGuiWindow* window,
const ImVec2& delta)
4697 window->Pos += delta;
4698 window->ClipRect.Translate(delta);
4699 window->OuterRectClipped.Translate(delta);
4700 window->InnerRect.Translate(delta);
4701 window->DC.CursorPos += delta;
4702 window->DC.CursorStartPos += delta;
4703 window->DC.CursorMaxPos += delta;
4704 window->DC.IdealMaxPos += delta;
4707static void ScaleWindow(ImGuiWindow* window,
float scale)
4709 ImVec2 origin = window->Viewport->Pos;
4710 window->Pos = ImFloor((window->Pos - origin) * scale + origin);
4711 window->Size = ImTrunc(window->Size * scale);
4712 window->SizeFull = ImTrunc(window->SizeFull * scale);
4713 window->ContentSize = ImTrunc(window->ContentSize * scale);
4716static bool IsWindowActiveAndVisible(ImGuiWindow* window)
4718 return (window->Active) && (!window->Hidden);
4722void ImGui::UpdateHoveredWindowAndCaptureFlags()
4729 g.WindowsHoverPadding = ImMax(
g.Style.TouchExtraPadding, ImVec2(WINDOWS_HOVER_PADDING, WINDOWS_HOVER_PADDING));
4735 bool clear_hovered_windows =
false;
4736 FindHoveredWindowEx(
g.IO.MousePos,
false, &
g.HoveredWindow, &
g.HoveredWindowUnderMovingWindow);
4737 IM_ASSERT(
g.HoveredWindow == NULL ||
g.HoveredWindow ==
g.MovingWindow ||
g.HoveredWindow->Viewport ==
g.MouseViewport);
4740 ImGuiWindow* modal_window = GetTopMostPopupModal();
4741 if (modal_window &&
g.HoveredWindow && !IsWindowWithinBeginStackOf(
g.HoveredWindow->RootWindow, modal_window))
4742 clear_hovered_windows =
true;
4745 if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)
4746 clear_hovered_windows =
true;
4750 const bool has_open_popup = (
g.OpenPopupStack.Size > 0);
4751 const bool has_open_modal = (modal_window != NULL);
4752 int mouse_earliest_down = -1;
4753 bool mouse_any_down =
false;
4754 for (
int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
4756 if (io.MouseClicked[i])
4758 io.MouseDownOwned[i] = (
g.HoveredWindow != NULL) || has_open_popup;
4759 io.MouseDownOwnedUnlessPopupClose[i] = (
g.HoveredWindow != NULL) || has_open_modal;
4761 mouse_any_down |= io.MouseDown[i];
4762 if (io.MouseDown[i])
4763 if (mouse_earliest_down == -1 || io.MouseClickedTime[i] < io.MouseClickedTime[mouse_earliest_down])
4764 mouse_earliest_down = i;
4766 const bool mouse_avail = (mouse_earliest_down == -1) || io.MouseDownOwned[mouse_earliest_down];
4767 const bool mouse_avail_unless_popup_close = (mouse_earliest_down == -1) || io.MouseDownOwnedUnlessPopupClose[mouse_earliest_down];
4771 const bool mouse_dragging_extern_payload =
g.DragDropActive && (
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0;
4772 if (!mouse_avail && !mouse_dragging_extern_payload)
4773 clear_hovered_windows =
true;
4775 if (clear_hovered_windows)
4776 g.HoveredWindow =
g.HoveredWindowUnderMovingWindow = NULL;
4780 if (
g.WantCaptureMouseNextFrame != -1)
4782 io.WantCaptureMouse = io.WantCaptureMouseUnlessPopupClose = (
g.WantCaptureMouseNextFrame != 0);
4786 io.WantCaptureMouse = (mouse_avail && (
g.HoveredWindow != NULL || mouse_any_down)) || has_open_popup;
4787 io.WantCaptureMouseUnlessPopupClose = (mouse_avail_unless_popup_close && (
g.HoveredWindow != NULL || mouse_any_down)) || has_open_modal;
4791 io.WantCaptureKeyboard = (
g.ActiveId != 0) || (modal_window != NULL);
4792 if (io.NavActive && (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard))
4793 io.WantCaptureKeyboard =
true;
4794 if (
g.WantCaptureKeyboardNextFrame != -1)
4795 io.WantCaptureKeyboard = (
g.WantCaptureKeyboardNextFrame != 0);
4798 io.WantTextInput = (
g.WantTextInputNextFrame != -1) ? (
g.WantTextInputNextFrame != 0) :
false;
4802static void SetupDrawListSharedData()
4805 ImRect virtual_space(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
4806 for (ImGuiViewportP* viewport :
g.Viewports)
4807 virtual_space.Add(viewport->GetMainRect());
4808 g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4();
4809 g.DrawListSharedData.CurveTessellationTol =
g.Style.CurveTessellationTol;
4810 g.DrawListSharedData.SetCircleTessellationMaxError(
g.Style.CircleTessellationMaxError);
4811 g.DrawListSharedData.InitialFlags = ImDrawListFlags_None;
4812 if (
g.Style.AntiAliasedLines)
4813 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines;
4814 if (
g.Style.AntiAliasedLinesUseTex && !(
g.IO.Fonts->Flags & ImFontAtlasFlags_NoBakedLines))
4815 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLinesUseTex;
4816 if (
g.Style.AntiAliasedFill)
4817 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill;
4818 if (
g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)
4819 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset;
4822void ImGui::NewFrame()
4824 IM_ASSERT(
GImGui != NULL &&
"No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
4829 for (
int n =
g.Hooks.Size - 1; n >= 0; n--)
4830 if (
g.Hooks[n].Type == ImGuiContextHookType_PendingRemoval_)
4831 g.Hooks.erase(&
g.Hooks[n]);
4833 CallContextHooks(&
g, ImGuiContextHookType_NewFramePre);
4836 g.ConfigFlagsLastFrame =
g.ConfigFlagsCurrFrame;
4837 ErrorCheckNewFrameSanityChecks();
4838 g.ConfigFlagsCurrFrame =
g.IO.ConfigFlags;
4843 g.Time +=
g.IO.DeltaTime;
4844 g.WithinFrameScope =
true;
4846 g.TooltipOverrideCount = 0;
4847 g.WindowsActiveCount = 0;
4848 g.MenusIdSubmittedThisFrame.resize(0);
4851 g.FramerateSecPerFrameAccum +=
g.IO.DeltaTime -
g.FramerateSecPerFrame[
g.FramerateSecPerFrameIdx];
4852 g.FramerateSecPerFrame[
g.FramerateSecPerFrameIdx] =
g.IO.DeltaTime;
4853 g.FramerateSecPerFrameIdx = (
g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(
g.FramerateSecPerFrame);
4854 g.FramerateSecPerFrameCount = ImMin(
g.FramerateSecPerFrameCount + 1, IM_ARRAYSIZE(
g.FramerateSecPerFrame));
4855 g.IO.Framerate = (
g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (
g.FramerateSecPerFrameAccum / (
float)
g.FramerateSecPerFrameCount)) : FLT_MAX;
4858 g.InputEventsTrail.resize(0);
4859 UpdateInputEvents(
g.IO.ConfigInputTrickleEventQueue);
4862 UpdateViewportsNewFrame();
4866 g.IO.Fonts->Locked =
true;
4867 SetupDrawListSharedData();
4868 SetCurrentFont(GetDefaultFont());
4869 IM_ASSERT(
g.Font->IsLoaded());
4872 for (ImGuiViewportP* viewport :
g.Viewports)
4874 viewport->DrawData = NULL;
4875 viewport->DrawDataP.Valid =
false;
4879 if (
g.DragDropActive &&
g.DragDropPayload.SourceId ==
g.ActiveId)
4880 KeepAliveID(
g.DragDropPayload.SourceId);
4883 if (!
g.HoveredIdPreviousFrame)
4884 g.HoveredIdTimer = 0.0f;
4885 if (!
g.HoveredIdPreviousFrame || (
g.HoveredId &&
g.ActiveId ==
g.HoveredId))
4886 g.HoveredIdNotActiveTimer = 0.0f;
4888 g.HoveredIdTimer +=
g.IO.DeltaTime;
4889 if (
g.HoveredId &&
g.ActiveId !=
g.HoveredId)
4890 g.HoveredIdNotActiveTimer +=
g.IO.DeltaTime;
4891 g.HoveredIdPreviousFrame =
g.HoveredId;
4893 g.HoveredIdAllowOverlap =
false;
4894 g.HoveredIdDisabled =
false;
4899 if (
g.ActiveId != 0 &&
g.ActiveIdIsAlive !=
g.ActiveId &&
g.ActiveIdPreviousFrame ==
g.ActiveId)
4901 IMGUI_DEBUG_LOG_ACTIVEID(
"NewFrame(): ClearActiveID() because it isn't marked alive anymore!\n");
4907 g.ActiveIdTimer +=
g.IO.DeltaTime;
4908 g.LastActiveIdTimer +=
g.IO.DeltaTime;
4909 g.ActiveIdPreviousFrame =
g.ActiveId;
4910 g.ActiveIdPreviousFrameWindow =
g.ActiveIdWindow;
4911 g.ActiveIdPreviousFrameHasBeenEditedBefore =
g.ActiveIdHasBeenEditedBefore;
4912 g.ActiveIdIsAlive = 0;
4913 g.ActiveIdHasBeenEditedThisFrame =
false;
4914 g.ActiveIdPreviousFrameIsAlive =
false;
4915 g.ActiveIdIsJustActivated =
false;
4916 if (
g.TempInputId != 0 &&
g.ActiveId !=
g.TempInputId)
4918 if (
g.ActiveId == 0)
4920 g.ActiveIdUsingNavDirMask = 0x00;
4921 g.ActiveIdUsingAllKeyboardKeys =
false;
4922#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
4923 g.ActiveIdUsingNavInputMask = 0x00;
4927#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
4928 if (
g.ActiveId == 0)
4929 g.ActiveIdUsingNavInputMask = 0;
4930 else if (
g.ActiveIdUsingNavInputMask != 0)
4934 if (
g.ActiveIdUsingNavInputMask & (1 << ImGuiNavInput_Cancel))
4935 SetKeyOwner(ImGuiKey_Escape,
g.ActiveId);
4936 if (
g.ActiveIdUsingNavInputMask & ~(1 << ImGuiNavInput_Cancel))
4944 if (
g.HoverItemDelayId != 0 &&
g.MouseStationaryTimer >=
g.Style.HoverStationaryDelay)
4945 g.HoverItemUnlockedStationaryId =
g.HoverItemDelayId;
4946 else if (
g.HoverItemDelayId == 0)
4947 g.HoverItemUnlockedStationaryId = 0;
4948 if (
g.HoveredWindow != NULL &&
g.MouseStationaryTimer >=
g.Style.HoverStationaryDelay)
4949 g.HoverWindowUnlockedStationaryId =
g.HoveredWindow->ID;
4950 else if (
g.HoveredWindow == NULL)
4951 g.HoverWindowUnlockedStationaryId = 0;
4954 g.HoverItemDelayIdPreviousFrame =
g.HoverItemDelayId;
4955 if (
g.HoverItemDelayId != 0)
4957 g.HoverItemDelayTimer +=
g.IO.DeltaTime;
4958 g.HoverItemDelayClearTimer = 0.0f;
4959 g.HoverItemDelayId = 0;
4961 else if (
g.HoverItemDelayTimer > 0.0f)
4965 g.HoverItemDelayClearTimer +=
g.IO.DeltaTime;
4966 if (
g.HoverItemDelayClearTimer >= ImMax(0.25f,
g.IO.DeltaTime * 2.0f))
4967 g.HoverItemDelayTimer =
g.HoverItemDelayClearTimer = 0.0f;
4971 g.DragDropAcceptIdPrev =
g.DragDropAcceptIdCurr;
4972 g.DragDropAcceptIdCurr = 0;
4973 g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
4974 g.DragDropWithinSource =
false;
4975 g.DragDropWithinTarget =
false;
4976 g.DragDropHoldJustPressedId = 0;
4983 UpdateKeyboardInputs();
4994 UpdateMouseInputs();
4998 DockContextNewFrameUpdateUndocking(&
g);
5002 UpdateHoveredWindowAndCaptureFlags();
5005 UpdateMouseMovingWindowNewFrame();
5008 if (GetTopMostPopupModal() != NULL || (
g.NavWindowingTarget != NULL &&
g.NavWindowingHighlightAlpha > 0.0f))
5009 g.DimBgRatio = ImMin(
g.DimBgRatio +
g.IO.DeltaTime * 6.0f, 1.0f);
5011 g.DimBgRatio = ImMax(
g.DimBgRatio -
g.IO.DeltaTime * 10.0f, 0.0f);
5013 g.MouseCursor = ImGuiMouseCursor_Arrow;
5014 g.WantCaptureMouseNextFrame =
g.WantCaptureKeyboardNextFrame =
g.WantTextInputNextFrame = -1;
5017 g.PlatformImeDataPrev =
g.PlatformImeData;
5018 g.PlatformImeData.WantVisible =
false;
5024 IM_ASSERT(
g.WindowsFocusOrder.Size <=
g.Windows.Size);
5025 const float memory_compact_start_time = (
g.GcCompactAll ||
g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)
g.Time -
g.IO.ConfigMemoryCompactTimer;
5026 for (ImGuiWindow* window :
g.Windows)
5028 window->WasActive = window->Active;
5029 window->Active =
false;
5030 window->WriteAccessed =
false;
5031 window->BeginCountPreviousFrame = window->BeginCount;
5032 window->BeginCount = 0;
5035 if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
5036 GcCompactTransientWindowBuffers(window);
5040 for (
int i = 0; i <
g.TablesLastTimeActive.Size; i++)
5041 if (
g.TablesLastTimeActive[i] >= 0.0f &&
g.TablesLastTimeActive[i] < memory_compact_start_time)
5042 TableGcCompactTransientBuffers(
g.Tables.GetByIndex(i));
5043 for (ImGuiTableTempData& table_temp_data :
g.TablesTempData)
5044 if (table_temp_data.LastTimeActive >= 0.0f && table_temp_data.LastTimeActive < memory_compact_start_time)
5045 TableGcCompactTransientBuffers(&table_temp_data);
5047 GcCompactTransientMiscBuffers();
5048 g.GcCompactAll =
false;
5051 if (
g.NavWindow && !
g.NavWindow->WasActive)
5052 FocusTopMostWindowUnderOne(NULL, NULL, NULL, ImGuiFocusRequestFlags_RestoreFocusedChild);
5056 g.CurrentWindowStack.resize(0);
5057 g.BeginPopupStack.resize(0);
5058 g.ItemFlagsStack.resize(0);
5059 g.ItemFlagsStack.push_back(ImGuiItemFlags_None);
5060 g.GroupStack.resize(0);
5063 DockContextNewFrameUpdateDocking(&
g);
5066#ifndef IMGUI_DISABLE_DEBUG_TOOLS
5067 UpdateDebugToolItemPicker();
5068 UpdateDebugToolStackQueries();
5069 UpdateDebugToolFlashStyleColor();
5070 if (
g.DebugLocateFrames > 0 && --
g.DebugLocateFrames == 0)
5072 g.DebugLocateId = 0;
5073 g.DebugBreakInLocateId =
false;
5075 if (
g.DebugLogAutoDisableFrames > 0 && --
g.DebugLogAutoDisableFrames == 0)
5077 DebugLog(
"(Debug Log: Auto-disabled some ImGuiDebugLogFlags after 2 frames)\n");
5078 g.DebugLogFlags &= ~g.DebugLogAutoDisableFlags;
5079 g.DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
5086 g.WithinFrameScopeWithImplicitWindow =
true;
5087 SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
5088 Begin(
"Debug##Default");
5089 IM_ASSERT(
g.CurrentWindow->IsFallbackWindow ==
true);
5093#ifndef IMGUI_DISABLE_DEBUG_TOOLS
5094 if (
g.IO.ConfigDebugBeginReturnValueLoop)
5095 g.DebugBeginReturnValueCullDepth = (
g.DebugBeginReturnValueCullDepth == -1) ? 0 : ((
g.DebugBeginReturnValueCullDepth + ((
g.FrameCount % 4) == 0 ? 1 : 0)) % 10);
5097 g.DebugBeginReturnValueCullDepth = -1;
5100 CallContextHooks(&
g, ImGuiContextHookType_NewFramePost);
5104static int IMGUI_CDECL ChildWindowComparer(
const void* lhs,
const void* rhs)
5106 const ImGuiWindow*
const a = *(
const ImGuiWindow*
const *)lhs;
5107 const ImGuiWindow*
const b = *(
const ImGuiWindow*
const *)rhs;
5108 if (
int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup))
5110 if (
int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip))
5112 return (a->BeginOrderWithinParent - b->BeginOrderWithinParent);
5115static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window)
5117 out_sorted_windows->push_back(window);
5120 int count = window->DC.ChildWindows.Size;
5121 ImQsort(window->DC.ChildWindows.Data, (
size_t)count,
sizeof(ImGuiWindow*), ChildWindowComparer);
5122 for (
int i = 0; i <
count; i++)
5124 ImGuiWindow* child = window->DC.ChildWindows[i];
5126 AddWindowToSortBuffer(out_sorted_windows, child);
5131static void AddWindowToDrawData(ImGuiWindow* window,
int layer)
5134 ImGuiViewportP* viewport = window->Viewport;
5135 IM_ASSERT(viewport != NULL);
5136 g.IO.MetricsRenderWindows++;
5137 if (window->DrawList->_Splitter._Count > 1)
5138 window->DrawList->ChannelsMerge();
5139 ImGui::AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[layer], window->DrawList);
5140 for (ImGuiWindow* child : window->DC.ChildWindows)
5141 if (IsWindowActiveAndVisible(child))
5142 AddWindowToDrawData(child, layer);
5145static inline int GetWindowDisplayLayer(ImGuiWindow* window)
5147 return (window->Flags & ImGuiWindowFlags_Tooltip) ? 1 : 0;
5151static inline void AddRootWindowToDrawData(ImGuiWindow* window)
5153 AddWindowToDrawData(window, GetWindowDisplayLayer(window));
5156static void FlattenDrawDataIntoSingleLayer(ImDrawDataBuilder* builder)
5158 int n = builder->Layers[0]->Size;
5160 for (
int i = 1; i < IM_ARRAYSIZE(builder->Layers); i++)
5161 full_size += builder->Layers[i]->Size;
5162 builder->Layers[0]->resize(full_size);
5163 for (
int layer_n = 1; layer_n < IM_ARRAYSIZE(builder->Layers); layer_n++)
5165 ImVector<ImDrawList*>* layer = builder->Layers[layer_n];
5168 memcpy(builder->Layers[0]->Data + n, layer->Data, layer->Size *
sizeof(ImDrawList*));
5174static void InitViewportDrawData(ImGuiViewportP* viewport)
5176 ImGuiIO& io = ImGui::GetIO();
5177 ImDrawData* draw_data = &viewport->DrawDataP;
5179 viewport->DrawData = draw_data;
5180 viewport->DrawDataBuilder.Layers[0] = &draw_data->CmdLists;
5181 viewport->DrawDataBuilder.Layers[1] = &viewport->DrawDataBuilder.LayerData1;
5182 viewport->DrawDataBuilder.Layers[0]->resize(0);
5183 viewport->DrawDataBuilder.Layers[1]->resize(0);
5190 const bool is_minimized = (viewport->Flags & ImGuiViewportFlags_IsMinimized) != 0;
5192 draw_data->Valid =
true;
5193 draw_data->CmdListsCount = 0;
5194 draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0;
5195 draw_data->DisplayPos = viewport->Pos;
5196 draw_data->DisplaySize = is_minimized ? ImVec2(0.0f, 0.0f) : viewport->Size;
5197 draw_data->FramebufferScale = io.DisplayFramebufferScale;
5198 draw_data->OwnerViewport = viewport;
5207void ImGui::PushClipRect(
const ImVec2& clip_rect_min,
const ImVec2& clip_rect_max,
bool intersect_with_current_clip_rect)
5209 ImGuiWindow* window = GetCurrentWindow();
5210 window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect);
5211 window->ClipRect = window->DrawList->_ClipRectStack.back();
5214void ImGui::PopClipRect()
5216 ImGuiWindow* window = GetCurrentWindow();
5217 window->DrawList->PopClipRect();
5218 window->ClipRect = window->DrawList->_ClipRectStack.back();
5221static ImGuiWindow* FindFrontMostVisibleChildWindow(ImGuiWindow* window)
5223 for (
int n = window->DC.ChildWindows.Size - 1; n >= 0; n--)
5224 if (IsWindowActiveAndVisible(window->DC.ChildWindows[n]))
5225 return FindFrontMostVisibleChildWindow(window->DC.ChildWindows[n]);
5229static void ImGui::RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col)
5231 if ((col & IM_COL32_A_MASK) == 0)
5234 ImGuiViewportP* viewport = window->Viewport;
5235 ImRect viewport_rect = viewport->GetMainRect();
5241 ImDrawList* draw_list = window->RootWindowDockTree->DrawList;
5242 draw_list->ChannelsMerge();
5243 if (draw_list->CmdBuffer.Size == 0)
5244 draw_list->AddDrawCmd();
5245 draw_list->PushClipRect(viewport_rect.Min - ImVec2(1, 1), viewport_rect.Max + ImVec2(1, 1),
false);
5246 draw_list->AddRectFilled(viewport_rect.Min, viewport_rect.Max, col);
5247 ImDrawCmd cmd = draw_list->CmdBuffer.back();
5248 IM_ASSERT(cmd.ElemCount == 6);
5249 draw_list->CmdBuffer.pop_back();
5250 draw_list->CmdBuffer.push_front(cmd);
5251 draw_list->AddDrawCmd();
5252 draw_list->PopClipRect();
5256 if (window->RootWindow->DockIsActive)
5258 ImDrawList* draw_list = FindFrontMostVisibleChildWindow(window->RootWindowDockTree)->DrawList;
5259 draw_list->ChannelsMerge();
5260 if (draw_list->CmdBuffer.Size == 0)
5261 draw_list->AddDrawCmd();
5262 draw_list->PushClipRect(viewport_rect.Min, viewport_rect.Max,
false);
5263 RenderRectFilledWithHole(draw_list, window->RootWindowDockTree->Rect(), window->RootWindow->Rect(), col, 0.0f);
5264 draw_list->PopClipRect();
5268ImGuiWindow* ImGui::FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* parent_window)
5271 ImGuiWindow* bottom_most_visible_window = parent_window;
5272 for (
int i = FindWindowDisplayIndex(parent_window); i >= 0; i--)
5274 ImGuiWindow* window =
g.Windows[i];
5275 if (window->Flags & ImGuiWindowFlags_ChildWindow)
5277 if (!IsWindowWithinBeginStackOf(window, parent_window))
5279 if (IsWindowActiveAndVisible(window) && GetWindowDisplayLayer(window) <= GetWindowDisplayLayer(parent_window))
5280 bottom_most_visible_window = window;
5282 return bottom_most_visible_window;
5287static void ImGui::RenderDimmedBackgrounds()
5290 ImGuiWindow* modal_window = GetTopMostAndVisiblePopupModal();
5291 if (
g.DimBgRatio <= 0.0f &&
g.NavWindowingHighlightAlpha <= 0.0f)
5293 const bool dim_bg_for_modal = (modal_window != NULL);
5294 const bool dim_bg_for_window_list = (
g.NavWindowingTargetAnim != NULL &&
g.NavWindowingTargetAnim->Active);
5295 if (!dim_bg_for_modal && !dim_bg_for_window_list)
5298 ImGuiViewport* viewports_already_dimmed[2] = { NULL, NULL };
5299 if (dim_bg_for_modal)
5302 ImGuiWindow* dim_behind_window = FindBottomMostVisibleWindowWithinBeginStack(modal_window);
5303 RenderDimmedBackgroundBehindWindow(dim_behind_window, GetColorU32(modal_window->DC.ModalDimBgColor,
g.DimBgRatio));
5304 viewports_already_dimmed[0] = modal_window->Viewport;
5306 else if (dim_bg_for_window_list)
5309 RenderDimmedBackgroundBehindWindow(
g.NavWindowingTargetAnim, GetColorU32(ImGuiCol_NavWindowingDimBg,
g.DimBgRatio));
5310 if (
g.NavWindowingListWindow != NULL &&
g.NavWindowingListWindow->Viewport &&
g.NavWindowingListWindow->Viewport !=
g.NavWindowingTargetAnim->Viewport)
5311 RenderDimmedBackgroundBehindWindow(
g.NavWindowingListWindow, GetColorU32(ImGuiCol_NavWindowingDimBg,
g.DimBgRatio));
5312 viewports_already_dimmed[0] =
g.NavWindowingTargetAnim->Viewport;
5313 viewports_already_dimmed[1] =
g.NavWindowingListWindow ?
g.NavWindowingListWindow->Viewport : NULL;
5316 ImGuiWindow* window =
g.NavWindowingTargetAnim;
5317 ImGuiViewport* viewport = window->Viewport;
5319 ImRect bb = window->Rect();
5320 bb.Expand(distance);
5321 if (bb.GetWidth() >= viewport->Size.x && bb.GetHeight() >= viewport->Size.y)
5322 bb.Expand(-distance - 1.0f);
5323 window->DrawList->ChannelsMerge();
5324 if (window->DrawList->CmdBuffer.Size == 0)
5325 window->DrawList->AddDrawCmd();
5326 window->DrawList->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size);
5327 window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight,
g.NavWindowingHighlightAlpha), window->WindowRounding, 0, 3.0f);
5328 window->DrawList->PopClipRect();
5332 for (ImGuiViewportP* viewport :
g.Viewports)
5334 if (viewport == viewports_already_dimmed[0] || viewport == viewports_already_dimmed[1])
5336 if (modal_window && viewport->Window && IsWindowAbove(viewport->Window, modal_window))
5338 ImDrawList* draw_list = GetForegroundDrawList(viewport);
5339 const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg,
g.DimBgRatio);
5340 draw_list->AddRectFilled(viewport->Pos, viewport->Pos + viewport->Size, dim_bg_col);
5345void ImGui::EndFrame()
5348 IM_ASSERT(
g.Initialized);
5351 if (
g.FrameCountEnded ==
g.FrameCount)
5353 IM_ASSERT(
g.WithinFrameScope &&
"Forgot to call ImGui::NewFrame()?");
5355 CallContextHooks(&
g, ImGuiContextHookType_EndFramePre);
5357 ErrorCheckEndFrameSanityChecks();
5360 ImGuiPlatformImeData* ime_data = &
g.PlatformImeData;
5361 if (
g.IO.SetPlatformImeDataFn && memcmp(ime_data, &
g.PlatformImeDataPrev,
sizeof(ImGuiPlatformImeData)) != 0)
5363 ImGuiViewport* viewport = FindViewportByID(
g.PlatformImeViewport);
5364 IMGUI_DEBUG_LOG_IO(
"[io] Calling io.SetPlatformImeDataFn(): WantVisible: %d, InputPos (%.2f,%.2f)\n", ime_data->WantVisible, ime_data->InputPos.x, ime_data->InputPos.y);
5365 if (viewport == NULL)
5366 viewport = GetMainViewport();
5367 g.IO.SetPlatformImeDataFn(viewport, ime_data);
5371 g.WithinFrameScopeWithImplicitWindow =
false;
5372 if (
g.CurrentWindow && !
g.CurrentWindow->WriteAccessed)
5373 g.CurrentWindow->Active =
false;
5380 DockContextEndFrame(&
g);
5382 SetCurrentViewport(NULL, NULL);
5385 if (
g.DragDropActive)
5387 bool is_delivered =
g.DragDropPayload.Delivery;
5388 bool is_elapsed = (
g.DragDropPayload.DataFrameCount + 1 <
g.FrameCount) && ((
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceAutoExpirePayload) || !IsMouseDown(
g.DragDropMouseButton));
5389 if (is_delivered || is_elapsed)
5394 if (
g.DragDropActive &&
g.DragDropSourceFrameCount <
g.FrameCount && !(
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
5396 g.DragDropWithinSource =
true;
5398 g.DragDropWithinSource =
false;
5402 g.WithinFrameScope =
false;
5403 g.FrameCountEnded =
g.FrameCount;
5406 UpdateMouseMovingWindowEndFrame();
5409 UpdateViewportsEndFrame();
5413 g.WindowsTempSortBuffer.resize(0);
5414 g.WindowsTempSortBuffer.reserve(
g.Windows.Size);
5415 for (ImGuiWindow* window :
g.Windows)
5417 if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow))
5419 AddWindowToSortBuffer(&
g.WindowsTempSortBuffer, window);
5423 IM_ASSERT(
g.Windows.Size ==
g.WindowsTempSortBuffer.Size);
5424 g.Windows.swap(
g.WindowsTempSortBuffer);
5425 g.IO.MetricsActiveWindows =
g.WindowsActiveCount;
5428 g.IO.Fonts->Locked =
false;
5431 g.IO.MousePosPrev =
g.IO.MousePos;
5432 g.IO.AppFocusLost =
false;
5433 g.IO.MouseWheel =
g.IO.MouseWheelH = 0.0f;
5434 g.IO.InputQueueCharacters.resize(0);
5436 CallContextHooks(&
g, ImGuiContextHookType_EndFramePost);
5445 IM_ASSERT(
g.Initialized);
5447 if (
g.FrameCountEnded !=
g.FrameCount)
5449 if (
g.FrameCountRendered ==
g.FrameCount)
5451 g.FrameCountRendered =
g.FrameCount;
5453 g.IO.MetricsRenderWindows = 0;
5454 CallContextHooks(&
g, ImGuiContextHookType_RenderPre);
5457 for (ImGuiViewportP* viewport :
g.Viewports)
5459 InitViewportDrawData(viewport);
5460 if (viewport->BgFgDrawLists[0] != NULL)
5461 AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport));
5465 RenderDimmedBackgrounds();
5468 ImGuiWindow* windows_to_render_top_most[2];
5469 windows_to_render_top_most[0] = (
g.NavWindowingTarget && !(
g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ?
g.NavWindowingTarget->RootWindowDockTree : NULL;
5470 windows_to_render_top_most[1] = (
g.NavWindowingTarget ?
g.NavWindowingListWindow : NULL);
5471 for (ImGuiWindow* window :
g.Windows)
5473 IM_MSVC_WARNING_SUPPRESS(6011);
5474 if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1])
5475 AddRootWindowToDrawData(window);
5477 for (
int n = 0; n < IM_ARRAYSIZE(windows_to_render_top_most); n++)
5478 if (windows_to_render_top_most[n] && IsWindowActiveAndVisible(windows_to_render_top_most[n]))
5479 AddRootWindowToDrawData(windows_to_render_top_most[n]);
5482 if (
g.IO.MouseDrawCursor &&
g.MouseCursor != ImGuiMouseCursor_None)
5483 RenderMouseCursor(
g.IO.MousePos,
g.Style.MouseCursorScale,
g.MouseCursor, IM_COL32_WHITE, IM_COL32_BLACK, IM_COL32(0, 0, 0, 48));
5486 g.IO.MetricsRenderVertices =
g.IO.MetricsRenderIndices = 0;
5487 for (ImGuiViewportP* viewport :
g.Viewports)
5489 FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder);
5492 if (viewport->BgFgDrawLists[1] != NULL)
5493 AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport));
5496 ImDrawData* draw_data = &viewport->DrawDataP;
5497 IM_ASSERT(draw_data->CmdLists.Size == draw_data->CmdListsCount);
5498 for (ImDrawList* draw_list : draw_data->CmdLists)
5499 draw_list->_PopUnusedDrawCmd();
5501 g.IO.MetricsRenderVertices += draw_data->TotalVtxCount;
5502 g.IO.MetricsRenderIndices += draw_data->TotalIdxCount;
5505 CallContextHooks(&
g, ImGuiContextHookType_RenderPost);
5510ImVec2
ImGui::CalcTextSize(
const char* text,
const char* text_end,
bool hide_text_after_double_hash,
float wrap_width)
5514 const char* text_display_end;
5515 if (hide_text_after_double_hash)
5516 text_display_end = FindRenderedTextEnd(text, text_end);
5518 text_display_end = text_end;
5520 ImFont* font =
g.Font;
5521 const float font_size =
g.FontSize;
5522 if (text == text_display_end)
5523 return ImVec2(0.0f, font_size);
5524 ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);
5531 text_size.x = IM_TRUNC(text_size.x + 0.99999f);
5542void ImGui::FindHoveredWindowEx(
const ImVec2& pos,
bool find_first_and_in_any_viewport, ImGuiWindow** out_hovered_window, ImGuiWindow** out_hovered_window_under_moving_window)
5545 ImGuiWindow* hovered_window = NULL;
5546 ImGuiWindow* hovered_window_under_moving_window = NULL;
5549 ImGuiViewportP* backup_moving_window_viewport = NULL;
5550 if (find_first_and_in_any_viewport ==
false &&
g.MovingWindow)
5552 backup_moving_window_viewport =
g.MovingWindow->Viewport;
5553 g.MovingWindow->Viewport =
g.MouseViewport;
5554 if (!(
g.MovingWindow->Flags & ImGuiWindowFlags_NoMouseInputs))
5555 hovered_window =
g.MovingWindow;
5558 ImVec2 padding_regular =
g.Style.TouchExtraPadding;
5559 ImVec2 padding_for_resize =
g.IO.ConfigWindowsResizeFromEdges ?
g.WindowsHoverPadding : padding_regular;
5560 for (
int i =
g.Windows.Size - 1; i >= 0; i--)
5562 ImGuiWindow* window =
g.Windows[i];
5563 IM_MSVC_WARNING_SUPPRESS(28182);
5564 if (!window->Active || window->Hidden)
5566 if (window->Flags & ImGuiWindowFlags_NoMouseInputs)
5568 IM_ASSERT(window->Viewport);
5569 if (window->Viewport !=
g.MouseViewport)
5573 ImVec2 hit_padding = (window->Flags & (ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) ? padding_regular : padding_for_resize;
5574 if (!window->OuterRectClipped.ContainsWithPad(pos, hit_padding))
5579 if (window->HitTestHoleSize.x != 0)
5581 ImVec2 hole_pos(window->Pos.x + (
float)window->HitTestHoleOffset.x, window->Pos.y + (
float)window->HitTestHoleOffset.y);
5582 ImVec2 hole_size((
float)window->HitTestHoleSize.x, (
float)window->HitTestHoleSize.y);
5583 if (ImRect(hole_pos, hole_pos + hole_size).Contains(pos))
5587 if (find_first_and_in_any_viewport)
5589 hovered_window = window;
5594 if (hovered_window == NULL)
5595 hovered_window = window;
5596 IM_MSVC_WARNING_SUPPRESS(28182);
5597 if (hovered_window_under_moving_window == NULL && (!
g.MovingWindow || window->RootWindowDockTree !=
g.MovingWindow->RootWindowDockTree))
5598 hovered_window_under_moving_window = window;
5599 if (hovered_window && hovered_window_under_moving_window)
5604 *out_hovered_window = hovered_window;
5605 if (out_hovered_window_under_moving_window != NULL)
5606 *out_hovered_window_under_moving_window = hovered_window_under_moving_window;
5607 if (find_first_and_in_any_viewport ==
false &&
g.MovingWindow)
5608 g.MovingWindow->Viewport = backup_moving_window_viewport;
5611bool ImGui::IsItemActive()
5615 return g.ActiveId ==
g.LastItemData.ID;
5619bool ImGui::IsItemActivated()
5623 if (
g.ActiveId ==
g.LastItemData.ID &&
g.ActiveIdPreviousFrame !=
g.LastItemData.ID)
5628bool ImGui::IsItemDeactivated()
5631 if (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDeactivated)
5632 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Deactivated) != 0;
5633 return (
g.ActiveIdPreviousFrame ==
g.LastItemData.ID &&
g.ActiveIdPreviousFrame != 0 &&
g.ActiveId !=
g.LastItemData.ID);
5636bool ImGui::IsItemDeactivatedAfterEdit()
5639 return IsItemDeactivated() && (
g.ActiveIdPreviousFrameHasBeenEditedBefore || (
g.ActiveId == 0 &&
g.ActiveIdHasBeenEditedBefore));
5643bool ImGui::IsItemFocused()
5646 if (
g.NavId !=
g.LastItemData.ID ||
g.NavId == 0)
5651 ImGuiWindow* window =
g.CurrentWindow;
5652 if (
g.LastItemData.ID == window->ID && window->WriteAccessed)
5660bool ImGui::IsItemClicked(ImGuiMouseButton mouse_button)
5662 return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None);
5665bool ImGui::IsItemToggledOpen()
5668 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true :
false;
5671bool ImGui::IsItemToggledSelection()
5674 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true :
false;
5680bool ImGui::IsAnyItemHovered()
5683 return g.HoveredId != 0 ||
g.HoveredIdPreviousFrame != 0;
5686bool ImGui::IsAnyItemActive()
5689 return g.ActiveId != 0;
5692bool ImGui::IsAnyItemFocused()
5695 return g.NavId != 0 && !
g.NavDisableHighlight;
5698bool ImGui::IsItemVisible()
5701 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) != 0;
5704bool ImGui::IsItemEdited()
5707 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Edited) != 0;
5713void ImGui::SetNextItemAllowOverlap()
5716 g.NextItemData.ItemFlags |= ImGuiItemFlags_AllowOverlap;
5719#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
5722void ImGui::SetItemAllowOverlap()
5725 ImGuiID
id =
g.LastItemData.ID;
5726 if (
g.HoveredId ==
id)
5727 g.HoveredIdAllowOverlap =
true;
5728 if (
g.ActiveId ==
id)
5729 g.ActiveIdAllowOverlap =
true;
5734void ImGui::SetActiveIdUsingAllKeyboardKeys()
5737 IM_ASSERT(
g.ActiveId != 0);
5738 g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_COUNT) - 1;
5739 g.ActiveIdUsingAllKeyboardKeys =
true;
5740 NavMoveRequestCancel();
5743ImGuiID ImGui::GetItemID()
5746 return g.LastItemData.ID;
5749ImVec2 ImGui::GetItemRectMin()
5752 return g.LastItemData.Rect.Min;
5755ImVec2 ImGui::GetItemRectMax()
5758 return g.LastItemData.Rect.Max;
5761ImVec2 ImGui::GetItemRectSize()
5764 return g.LastItemData.Rect.GetSize();
5769bool ImGui::BeginChild(
const char* str_id,
const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags)
5771 ImGuiID
id = GetCurrentWindow()->GetID(str_id);
5772 return BeginChildEx(str_id,
id, size_arg, child_flags, window_flags);
5775bool ImGui::BeginChild(ImGuiID
id,
const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags)
5777 return BeginChildEx(NULL,
id, size_arg, child_flags, window_flags);
5780bool ImGui::BeginChildEx(
const char* name, ImGuiID
id,
const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags)
5783 ImGuiWindow* parent_window =
g.CurrentWindow;
5787 const ImGuiChildFlags ImGuiChildFlags_SupportedMask_ = ImGuiChildFlags_Border | ImGuiChildFlags_AlwaysUseWindowPadding | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_FrameStyle;
5788 IM_UNUSED(ImGuiChildFlags_SupportedMask_);
5789 IM_ASSERT((child_flags & ~ImGuiChildFlags_SupportedMask_) == 0 &&
"Illegal ImGuiChildFlags value. Did you pass ImGuiWindowFlags values instead of ImGuiChildFlags?");
5790 IM_ASSERT((window_flags & ImGuiWindowFlags_AlwaysAutoResize) == 0 &&
"Cannot specify ImGuiWindowFlags_AlwaysAutoResize for BeginChild(). Use ImGuiChildFlags_AlwaysAutoResize!");
5791 if (child_flags & ImGuiChildFlags_AlwaysAutoResize)
5793 IM_ASSERT((child_flags & (ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY)) == 0 &&
"Cannot use ImGuiChildFlags_ResizeX or ImGuiChildFlags_ResizeY with ImGuiChildFlags_AlwaysAutoResize!");
5794 IM_ASSERT((child_flags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY)) != 0 &&
"Must use ImGuiChildFlags_AutoResizeX or ImGuiChildFlags_AutoResizeY with ImGuiChildFlags_AlwaysAutoResize!");
5796#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
5797 if (window_flags & ImGuiWindowFlags_AlwaysUseWindowPadding)
5798 child_flags |= ImGuiChildFlags_AlwaysUseWindowPadding;
5800 if (child_flags & ImGuiChildFlags_AutoResizeX)
5801 child_flags &= ~ImGuiChildFlags_ResizeX;
5802 if (child_flags & ImGuiChildFlags_AutoResizeY)
5803 child_flags &= ~ImGuiChildFlags_ResizeY;
5806 window_flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDocking;
5807 window_flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove);
5808 if (child_flags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize))
5809 window_flags |= ImGuiWindowFlags_AlwaysAutoResize;
5810 if ((child_flags & (ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY)) == 0)
5811 window_flags |= ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings;
5814 if (child_flags & ImGuiChildFlags_FrameStyle)
5816 PushStyleColor(ImGuiCol_ChildBg,
g.Style.Colors[ImGuiCol_FrameBg]);
5817 PushStyleVar(ImGuiStyleVar_ChildRounding,
g.Style.FrameRounding);
5818 PushStyleVar(ImGuiStyleVar_ChildBorderSize,
g.Style.FrameBorderSize);
5819 PushStyleVar(ImGuiStyleVar_WindowPadding,
g.Style.FramePadding);
5820 child_flags |= ImGuiChildFlags_Border | ImGuiChildFlags_AlwaysUseWindowPadding;
5821 window_flags |= ImGuiWindowFlags_NoMove;
5825 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags;
5826 g.NextWindowData.ChildFlags = child_flags;
5831 const ImVec2 size_avail = GetContentRegionAvail();
5832 const ImVec2 size_default((child_flags & ImGuiChildFlags_AutoResizeX) ? 0.0f : size_avail.x, (child_flags & ImGuiChildFlags_AutoResizeY) ? 0.0f : size_avail.y);
5833 const ImVec2
size = CalcItemSize(size_arg, size_default.x, size_default.y);
5834 SetNextWindowSize(size);
5839 const char* temp_window_name;
5849 const float backup_border_size =
g.Style.ChildBorderSize;
5850 if ((child_flags & ImGuiChildFlags_Border) == 0)
5851 g.Style.ChildBorderSize = 0.0f;
5854 const bool ret = Begin(temp_window_name, NULL, window_flags);
5857 g.Style.ChildBorderSize = backup_border_size;
5858 if (child_flags & ImGuiChildFlags_FrameStyle)
5864 ImGuiWindow* child_window =
g.CurrentWindow;
5865 child_window->ChildId =
id;
5869 if (child_window->BeginCount == 1)
5870 parent_window->DC.CursorPos = child_window->Pos;
5874 const ImGuiID temp_id_for_activation =
ImHashStr(
"##Child", 0,
id);
5875 if (
g.ActiveId == temp_id_for_activation)
5877 if (
g.NavActivateId ==
id && !(window_flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY))
5879 FocusWindow(child_window);
5880 NavInitWindow(child_window,
false);
5881 SetActiveID(temp_id_for_activation, child_window);
5882 g.ActiveIdSource =
g.NavInputSource;
5887void ImGui::EndChild()
5890 ImGuiWindow* child_window =
g.CurrentWindow;
5892 IM_ASSERT(
g.WithinEndChild ==
false);
5893 IM_ASSERT(child_window->Flags & ImGuiWindowFlags_ChildWindow);
5895 g.WithinEndChild =
true;
5896 ImVec2 child_size = child_window->Size;
5898 if (child_window->BeginCount == 1)
5900 ImGuiWindow* parent_window =
g.CurrentWindow;
5901 ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + child_size);
5902 ItemSize(child_size);
5903 if ((child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY) && !(child_window->Flags & ImGuiWindowFlags_NavFlattened))
5905 ItemAdd(bb, child_window->ChildId);
5906 RenderNavHighlight(bb, child_window->ChildId);
5909 if (child_window->DC.NavLayersActiveMask == 0 && child_window ==
g.NavWindow)
5910 RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)),
g.NavId, ImGuiNavHighlightFlags_Compact);
5917 ItemAdd(bb, child_window->ChildId, NULL, ImGuiItemFlags_NoNav);
5920 if (child_window->Flags & ImGuiWindowFlags_NavFlattened)
5921 parent_window->DC.NavLayersActiveMaskNext |= child_window->DC.NavLayersActiveMaskNext;
5923 if (
g.HoveredWindow == child_window)
5924 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
5926 g.WithinEndChild =
false;
5927 g.LogLinePosY = -FLT_MAX;
5930static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags,
bool enabled)
5932 window->SetWindowPosAllowFlags = enabled ? (window->SetWindowPosAllowFlags | flags) : (window->SetWindowPosAllowFlags & ~flags);
5933 window->SetWindowSizeAllowFlags = enabled ? (window->SetWindowSizeAllowFlags | flags) : (window->SetWindowSizeAllowFlags & ~flags);
5934 window->SetWindowCollapsedAllowFlags = enabled ? (window->SetWindowCollapsedAllowFlags | flags) : (window->SetWindowCollapsedAllowFlags & ~flags);
5935 window->SetWindowDockAllowFlags = enabled ? (window->SetWindowDockAllowFlags | flags) : (window->SetWindowDockAllowFlags & ~flags);
5938ImGuiWindow* ImGui::FindWindowByID(ImGuiID
id)
5941 return (ImGuiWindow*)
g.WindowsById.GetVoidPtr(
id);
5944ImGuiWindow* ImGui::FindWindowByName(
const char* name)
5947 return FindWindowByID(
id);
5950static void ApplyWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
5952 const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
5953 window->ViewportPos = main_viewport->Pos;
5954 if (settings->ViewportId)
5956 window->ViewportId = settings->ViewportId;
5957 window->ViewportPos = ImVec2(settings->ViewportPos.x, settings->ViewportPos.y);
5959 window->Pos = ImTrunc(ImVec2(settings->Pos.x + window->ViewportPos.x, settings->Pos.y + window->ViewportPos.y));
5960 if (settings->Size.x > 0 && settings->Size.y > 0)
5961 window->Size = window->SizeFull = ImTrunc(ImVec2(settings->Size.x, settings->Size.y));
5962 window->Collapsed = settings->Collapsed;
5963 window->DockId = settings->DockId;
5964 window->DockOrder = settings->DockOrder;
5967static void UpdateWindowInFocusOrderList(ImGuiWindow* window,
bool just_created, ImGuiWindowFlags new_flags)
5971 const bool new_is_explicit_child = (new_flags & ImGuiWindowFlags_ChildWindow) != 0 && ((new_flags & ImGuiWindowFlags_Popup) == 0 || (new_flags & ImGuiWindowFlags_ChildMenu) != 0);
5972 const bool child_flag_changed = new_is_explicit_child != window->IsExplicitChild;
5973 if ((just_created || child_flag_changed) && !new_is_explicit_child)
5975 IM_ASSERT(!
g.WindowsFocusOrder.contains(window));
5976 g.WindowsFocusOrder.push_back(window);
5977 window->FocusOrder = (short)(
g.WindowsFocusOrder.Size - 1);
5979 else if (!just_created && child_flag_changed && new_is_explicit_child)
5981 IM_ASSERT(
g.WindowsFocusOrder[window->FocusOrder] == window);
5982 for (
int n = window->FocusOrder + 1; n <
g.WindowsFocusOrder.Size; n++)
5983 g.WindowsFocusOrder[n]->FocusOrder--;
5984 g.WindowsFocusOrder.erase(
g.WindowsFocusOrder.Data + window->FocusOrder);
5985 window->FocusOrder = -1;
5987 window->IsExplicitChild = new_is_explicit_child;
5990static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
5994 const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
5995 window->Pos = main_viewport->Pos + ImVec2(60, 60);
5996 window->Size = window->SizeFull = ImVec2(0, 0);
5997 window->ViewportPos = main_viewport->Pos;
5998 window->SetWindowPosAllowFlags = window->SetWindowSizeAllowFlags = window->SetWindowCollapsedAllowFlags = window->SetWindowDockAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
6000 if (settings != NULL)
6002 SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver,
false);
6003 ApplyWindowSettings(window, settings);
6005 window->DC.CursorStartPos = window->DC.CursorMaxPos = window->DC.IdealMaxPos = window->Pos;
6007 if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
6009 window->AutoFitFramesX = window->AutoFitFramesY = 2;
6010 window->AutoFitOnlyGrows =
false;
6014 if (window->Size.x <= 0.0f)
6015 window->AutoFitFramesX = 2;
6016 if (window->Size.y <= 0.0f)
6017 window->AutoFitFramesY = 2;
6018 window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
6022static ImGuiWindow* CreateNewWindow(
const char* name, ImGuiWindowFlags flags)
6027 ImGuiWindow* window = IM_NEW(ImGuiWindow)(&
g, name);
6028 window->Flags = flags;
6029 g.WindowsById.SetVoidPtr(window->ID, window);
6031 ImGuiWindowSettings* settings = NULL;
6032 if (!(flags & ImGuiWindowFlags_NoSavedSettings))
6033 if ((settings = ImGui::FindWindowSettingsByWindow(window)) != 0)
6034 window->SettingsOffset =
g.SettingsWindows.offset_from_ptr(settings);
6036 InitOrLoadWindowSettings(window, settings);
6038 if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus)
6039 g.Windows.push_front(window);
6041 g.Windows.push_back(window);
6046static ImGuiWindow* GetWindowForTitleDisplay(ImGuiWindow* window)
6048 return window->DockNodeAsHost ? window->DockNodeAsHost->VisibleWindow : window;
6051static ImGuiWindow* GetWindowForTitleAndMenuHeight(ImGuiWindow* window)
6053 return (window->DockNodeAsHost && window->DockNodeAsHost->VisibleWindow) ? window->DockNodeAsHost->VisibleWindow : window;
6056static inline ImVec2 CalcWindowMinSize(ImGuiWindow* window)
6063 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_Popup))
6065 size_min.x = (window->ChildFlags & ImGuiChildFlags_ResizeX) ?
g.Style.WindowMinSize.x : 4.0f;
6066 size_min.y = (window->ChildFlags & ImGuiChildFlags_ResizeY) ?
g.Style.WindowMinSize.y : 4.0f;
6070 size_min.x = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ?
g.Style.WindowMinSize.x : 4.0f;
6071 size_min.y = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ?
g.Style.WindowMinSize.y : 4.0f;
6075 ImGuiWindow* window_for_height = GetWindowForTitleAndMenuHeight(window);
6076 size_min.y = ImMax(size_min.y, window_for_height->TitleBarHeight + window_for_height->MenuBarHeight + ImMax(0.0f,
g.Style.WindowRounding - 1.0f));
6080static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window,
const ImVec2& size_desired)
6083 ImVec2 new_size = size_desired;
6084 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)
6087 ImRect cr =
g.NextWindowData.SizeConstraintRect;
6088 new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x;
6089 new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y;
6090 if (
g.NextWindowData.SizeCallback)
6092 ImGuiSizeCallbackData data;
6093 data.UserData =
g.NextWindowData.SizeCallbackUserData;
6094 data.Pos = window->Pos;
6095 data.CurrentSize = window->SizeFull;
6096 data.DesiredSize = new_size;
6097 g.NextWindowData.SizeCallback(&data);
6098 new_size = data.DesiredSize;
6100 new_size.x = IM_TRUNC(new_size.x);
6101 new_size.y = IM_TRUNC(new_size.y);
6105 ImVec2 size_min = CalcWindowMinSize(window);
6106 return ImMax(new_size, size_min);
6109static void CalcWindowContentSizes(ImGuiWindow* window, ImVec2* content_size_current, ImVec2* content_size_ideal)
6111 bool preserve_old_content_sizes =
false;
6112 if (window->Collapsed && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
6113 preserve_old_content_sizes =
true;
6114 else if (window->Hidden && window->HiddenFramesCannotSkipItems == 0 && window->HiddenFramesCanSkipItems > 0)
6115 preserve_old_content_sizes =
true;
6116 if (preserve_old_content_sizes)
6118 *content_size_current = window->ContentSize;
6119 *content_size_ideal = window->ContentSizeIdeal;
6123 content_size_current->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : IM_TRUNC(window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x);
6124 content_size_current->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : IM_TRUNC(window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y);
6125 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);
6126 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);
6129static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window,
const ImVec2& size_contents)
6132 ImGuiStyle& style =
g.Style;
6133 const float decoration_w_without_scrollbars = window->DecoOuterSizeX1 + window->DecoOuterSizeX2 - window->ScrollbarSizes.x;
6134 const float decoration_h_without_scrollbars = window->DecoOuterSizeY1 + window->DecoOuterSizeY2 - window->ScrollbarSizes.y;
6135 ImVec2 size_pad = window->WindowPadding * 2.0f;
6136 ImVec2 size_desired = size_contents + size_pad + ImVec2(decoration_w_without_scrollbars, decoration_h_without_scrollbars);
6137 if (window->Flags & ImGuiWindowFlags_Tooltip)
6140 return size_desired;
6145 ImVec2 size_min = CalcWindowMinSize(window);
6146 ImVec2 size_max = (window->ViewportOwned || ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_Popup))) ? ImVec2(FLT_MAX, FLT_MAX) :
ImGui::GetMainViewport()->WorkSize - style.DisplaySafeAreaPadding * 2.0f;
6147 const int monitor_idx = window->ViewportAllowPlatformMonitorExtend;
6148 if (monitor_idx >= 0 && monitor_idx <
g.PlatformIO.Monitors.Size && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0)
6149 size_max =
g.PlatformIO.Monitors[monitor_idx].WorkSize - style.DisplaySafeAreaPadding * 2.0f;
6150 ImVec2 size_auto_fit = ImClamp(size_desired, size_min, ImMax(size_min, size_max));
6155 if ((window->ChildFlags & ImGuiChildFlags_ResizeX) && !(window->ChildFlags & ImGuiChildFlags_ResizeY))
6156 size_auto_fit.y = window->SizeFull.y;
6157 else if (!(window->ChildFlags & ImGuiChildFlags_ResizeX) && (window->ChildFlags & ImGuiChildFlags_ResizeY))
6158 size_auto_fit.x = window->SizeFull.x;
6162 ImVec2 size_auto_fit_after_constraint = CalcWindowSizeAfterConstraint(window, size_auto_fit);
6163 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);
6164 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);
6165 if (will_have_scrollbar_x)
6166 size_auto_fit.y += style.ScrollbarSize;
6167 if (will_have_scrollbar_y)
6168 size_auto_fit.x += style.ScrollbarSize;
6169 return size_auto_fit;
6173ImVec2 ImGui::CalcWindowNextAutoFitSize(ImGuiWindow* window)
6175 ImVec2 size_contents_current;
6176 ImVec2 size_contents_ideal;
6177 CalcWindowContentSizes(window, &size_contents_current, &size_contents_ideal);
6178 ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, size_contents_ideal);
6179 ImVec2 size_final = CalcWindowSizeAfterConstraint(window, size_auto_fit);
6183static ImGuiCol GetWindowBgColorIdx(ImGuiWindow* window)
6185 if (window->Flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
6186 return ImGuiCol_PopupBg;
6187 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !window->DockIsActive)
6188 return ImGuiCol_ChildBg;
6189 return ImGuiCol_WindowBg;
6192static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window,
const ImVec2& corner_target,
const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size)
6194 ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm);
6195 ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm);
6196 ImVec2 size_expected = pos_max - pos_min;
6197 ImVec2 size_constrained = CalcWindowSizeAfterConstraint(window, size_expected);
6199 if (corner_norm.x == 0.0f)
6200 out_pos->x -= (size_constrained.x - size_expected.x);
6201 if (corner_norm.y == 0.0f)
6202 out_pos->y -= (size_constrained.y - size_expected.y);
6203 *out_size = size_constrained;
6215 { ImVec2(1, 1), ImVec2(-1, -1), 0, 3 },
6216 { ImVec2(0, 1), ImVec2(+1, -1), 3, 6 },
6217 { ImVec2(0, 0), ImVec2(+1, +1), 6, 9 },
6218 { ImVec2(1, 0), ImVec2(-1, +1), 9, 12 }
6230 { ImVec2(+1, 0), ImVec2(0, 1), ImVec2(0, 0), IM_PI * 1.00f },
6231 { ImVec2(-1, 0), ImVec2(1, 0), ImVec2(1, 1), IM_PI * 0.00f },
6232 { ImVec2(0, +1), ImVec2(0, 0), ImVec2(1, 0), IM_PI * 1.50f },
6233 { ImVec2(0, -1), ImVec2(1, 1), ImVec2(0, 1), IM_PI * 0.50f }
6236static ImRect GetResizeBorderRect(ImGuiWindow* window,
int border_n,
float perp_padding,
float thickness)
6238 ImRect rect = window->Rect();
6239 if (thickness == 0.0f)
6240 rect.Max -= ImVec2(1, 1);
6241 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); }
6242 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); }
6243 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); }
6244 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); }
6250ImGuiID ImGui::GetWindowResizeCornerID(ImGuiWindow* window,
int n)
6252 IM_ASSERT(n >= 0 && n < 4);
6253 ImGuiID
id = window->DockIsActive ? window->DockNode->HostWindow->ID : window->ID;
6260ImGuiID ImGui::GetWindowResizeBorderID(ImGuiWindow* window, ImGuiDir dir)
6262 IM_ASSERT(dir >= 0 && dir < 4);
6263 int n = (int)dir + 4;
6264 ImGuiID
id = window->DockIsActive ? window->DockNode->HostWindow->ID : window->ID;
6272static 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)
6275 ImGuiWindowFlags flags = window->Flags;
6277 if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
6279 if (window->WasActive ==
false)
6282 int ret_auto_fit_mask = 0x00;
6283 const float grip_draw_size = IM_TRUNC(ImMax(
g.FontSize * 1.35f, window->WindowRounding + 1.0f +
g.FontSize * 0.2f));
6284 const float grip_hover_inner_size = (resize_grip_count > 0) ? IM_TRUNC(grip_draw_size * 0.75f) : 0.0f;
6285 const float grip_hover_outer_size =
g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_HOVER_PADDING : 0.0f;
6287 ImRect clamp_rect = visibility_rect;
6288 const bool window_move_from_title_bar =
g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar);
6289 if (window_move_from_title_bar)
6290 clamp_rect.Min.y -= window->TitleBarHeight;
6292 ImVec2 pos_target(FLT_MAX, FLT_MAX);
6293 ImVec2 size_target(FLT_MAX, FLT_MAX);
6301 const bool clip_with_viewport_rect = !(
g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport) || (
g.IO.MouseHoveredViewport != window->ViewportId) || !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration);
6302 if (clip_with_viewport_rect)
6303 window->ClipRect = window->Viewport->GetMainRect();
6306 window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
6310 for (
int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
6313 const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, def.
CornerPosN);
6317 ImRect resize_rect(corner - def.
InnerDir * grip_hover_outer_size, corner + def.
InnerDir * grip_hover_inner_size);
6318 if (resize_rect.Min.x > resize_rect.Max.x) ImSwap(resize_rect.Min.x, resize_rect.Max.x);
6319 if (resize_rect.Min.y > resize_rect.Max.y) ImSwap(resize_rect.Min.y, resize_rect.Max.y);
6320 ImGuiID resize_grip_id = window->GetID(resize_grip_n);
6321 ItemAdd(resize_rect, resize_grip_id, NULL, ImGuiItemFlags_NoNav);
6322 ButtonBehavior(resize_rect, resize_grip_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
6324 if (hovered || held)
6325 g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;
6327 if (held &&
g.IO.MouseDoubleClicked[0])
6330 size_target = CalcWindowSizeAfterConstraint(window, size_auto_fit);
6331 ret_auto_fit_mask = 0x03;
6338 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);
6339 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);
6340 ImVec2 corner_target =
g.IO.MousePos -
g.ActiveIdClickOffset + ImLerp(def.
InnerDir * grip_hover_outer_size, def.
InnerDir * -grip_hover_inner_size, def.
CornerPosN);
6341 corner_target = ImClamp(corner_target, clamp_min, clamp_max);
6342 CalcResizePosSizeFromAnyCorner(window, corner_target, def.
CornerPosN, &pos_target, &size_target);
6346 if (resize_grip_n == 0 || held || hovered)
6347 resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
6350 int resize_border_mask = 0x00;
6351 if (window->Flags & ImGuiWindowFlags_ChildWindow)
6352 resize_border_mask |= ((window->ChildFlags & ImGuiChildFlags_ResizeX) ? 0x02 : 0) | ((window->ChildFlags & ImGuiChildFlags_ResizeY) ? 0x08 : 0);
6354 resize_border_mask =
g.IO.ConfigWindowsResizeFromEdges ? 0x0F : 0x00;
6355 for (
int border_n = 0; border_n < 4; border_n++)
6357 if ((resize_border_mask & (1 << border_n)) == 0)
6360 const ImGuiAxis axis = (border_n == ImGuiDir_Left || border_n == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
6363 ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_HOVER_PADDING);
6364 ImGuiID border_id = window->GetID(border_n + 4);
6365 ItemAdd(border_rect, border_id, NULL, ImGuiItemFlags_NoNav);
6366 ButtonBehavior(border_rect, border_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
6368 if (hovered &&
g.HoveredIdTimer <= WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER)
6370 if (hovered || held)
6371 g.MouseCursor = (axis == ImGuiAxis_X) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS;
6372 if (held &&
g.IO.MouseDoubleClicked[0])
6377 if (border_n == 1 || border_n == 3)
6379 size_target[axis] = CalcWindowSizeAfterConstraint(window, size_auto_fit)[axis];
6380 ret_auto_fit_mask |= (1 << axis);
6381 hovered = held =
false;
6390 const bool just_scrolled_manually_while_resizing = (
g.WheelingWindow != NULL &&
g.WheelingWindowScrolledFrame ==
g.FrameCount && IsWindowChildOf(window,
g.WheelingWindow,
false,
true));
6391 if (
g.ActiveIdIsJustActivated || just_scrolled_manually_while_resizing)
6393 g.WindowResizeBorderExpectedRect = border_rect;
6394 g.WindowResizeRelativeMode =
false;
6396 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && memcmp(&
g.WindowResizeBorderExpectedRect, &border_rect,
sizeof(ImRect)) != 0)
6397 g.WindowResizeRelativeMode =
true;
6399 const ImVec2 border_curr = (window->Pos + ImMin(def.
SegmentN1, def.
SegmentN2) * window->Size);
6400 const float border_target_rel_mode_for_axis = border_curr[axis] +
g.IO.MouseDelta[axis];
6401 const float border_target_abs_mode_for_axis =
g.IO.MousePos[axis] -
g.ActiveIdClickOffset[axis] + WINDOWS_HOVER_PADDING;
6404 ImVec2 border_target = window->Pos;
6405 border_target[axis] = border_target_abs_mode_for_axis;
6408 bool ignore_resize =
false;
6409 if (
g.WindowResizeRelativeMode)
6412 border_target[axis] = border_target_rel_mode_for_axis;
6413 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))
6414 ignore_resize =
true;
6418 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);
6419 ImVec2 clamp_max(border_n == ImGuiDir_Left ? clamp_rect.Max.x : +FLT_MAX, border_n == ImGuiDir_Up ? clamp_rect.Max.y : +FLT_MAX);
6420 border_target = ImClamp(border_target, clamp_min, clamp_max);
6421 if (flags & ImGuiWindowFlags_ChildWindow)
6423 ImGuiWindowFlags parent_flags = window->ParentWindow->Flags;
6424 ImRect border_limit_rect = window->ParentWindow->InnerRect;
6425 border_limit_rect.Expand(ImVec2(-ImMax(window->WindowPadding.x, window->WindowBorderSize), -ImMax(window->WindowPadding.y, window->WindowBorderSize)));
6426 if ((parent_flags & (ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar)) == 0 || (parent_flags & ImGuiWindowFlags_NoScrollbar))
6427 border_target.x = ImClamp(border_target.x, border_limit_rect.Min.x, border_limit_rect.Max.x);
6428 if (parent_flags & ImGuiWindowFlags_NoScrollbar)
6429 border_target.y = ImClamp(border_target.y, border_limit_rect.Min.y, border_limit_rect.Max.y);
6432 CalcResizePosSizeFromAnyCorner(window, border_target, ImMin(def.
SegmentN1, def.
SegmentN2), &pos_target, &size_target);
6435 *border_hovered = border_n;
6437 *border_held = border_n;
6442 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
6447 if (
g.NavWindowingTarget &&
g.NavWindowingTarget->RootWindowDockTree == window)
6449 ImVec2 nav_resize_dir;
6450 if (
g.NavInputSource == ImGuiInputSource_Keyboard &&
g.IO.KeyShift)
6451 nav_resize_dir = GetKeyMagnitude2d(ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow);
6452 if (
g.NavInputSource == ImGuiInputSource_Gamepad)
6453 nav_resize_dir = GetKeyMagnitude2d(ImGuiKey_GamepadDpadLeft, ImGuiKey_GamepadDpadRight, ImGuiKey_GamepadDpadUp, ImGuiKey_GamepadDpadDown);
6454 if (nav_resize_dir.x != 0.0f || nav_resize_dir.y != 0.0f)
6456 const float NAV_RESIZE_SPEED = 600.0f;
6457 const float resize_step = NAV_RESIZE_SPEED *
g.IO.DeltaTime * ImMin(
g.IO.DisplayFramebufferScale.x,
g.IO.DisplayFramebufferScale.y);
6458 g.NavWindowingAccumDeltaSize += nav_resize_dir * resize_step;
6459 g.NavWindowingAccumDeltaSize = ImMax(
g.NavWindowingAccumDeltaSize, clamp_rect.Min - window->Pos - window->Size);
6460 g.NavWindowingToggleLayer =
false;
6461 g.NavDisableMouseHover =
true;
6462 resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive);
6463 ImVec2 accum_floored = ImTrunc(
g.NavWindowingAccumDeltaSize);
6464 if (accum_floored.x != 0.0f || accum_floored.y != 0.0f)
6467 size_target = CalcWindowSizeAfterConstraint(window, window->SizeFull + accum_floored);
6468 g.NavWindowingAccumDeltaSize -= accum_floored;
6474 const ImVec2 curr_pos = window->Pos;
6475 const ImVec2 curr_size = window->SizeFull;
6476 if (size_target.x != FLT_MAX && (window->Size.x != size_target.x || window->SizeFull.x != size_target.x))
6477 window->Size.x = window->SizeFull.x = size_target.x;
6478 if (size_target.y != FLT_MAX && (window->Size.y != size_target.y || window->SizeFull.y != size_target.y))
6479 window->Size.y = window->SizeFull.y = size_target.y;
6480 if (pos_target.x != FLT_MAX && window->Pos.x != ImTrunc(pos_target.x))
6481 window->Pos.x = ImTrunc(pos_target.x);
6482 if (pos_target.y != FLT_MAX && window->Pos.y != ImTrunc(pos_target.y))
6483 window->Pos.y = ImTrunc(pos_target.y);
6484 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)
6485 MarkIniSettingsDirty(window);
6488 if (*border_held != -1)
6489 g.WindowResizeBorderExpectedRect = GetResizeBorderRect(window, *border_held, grip_hover_inner_size, WINDOWS_HOVER_PADDING);
6491 return ret_auto_fit_mask;
6494static inline void ClampWindowPos(ImGuiWindow* window,
const ImRect& visibility_rect)
6497 ImVec2 size_for_clamping = window->Size;
6498 if (
g.IO.ConfigWindowsMoveFromTitleBarOnly && window->DockNodeAsHost)
6499 size_for_clamping.y = ImGui::GetFrameHeight();
6500 else if (
g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
6501 size_for_clamping.y = window->TitleBarHeight;
6502 window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max);
6505static void RenderWindowOuterSingleBorder(ImGuiWindow* window,
int border_n, ImU32 border_col,
float border_size)
6508 const float rounding = window->WindowRounding;
6509 const ImRect border_r = GetResizeBorderRect(window, border_n, rounding, 0.0f);
6510 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);
6511 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);
6512 window->DrawList->PathStroke(border_col, ImDrawFlags_None, border_size);
6515static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
6518 const float border_size = window->WindowBorderSize;
6519 const ImU32 border_col = GetColorU32(ImGuiCol_Border);
6520 if (border_size > 0.0f && (window->Flags & ImGuiWindowFlags_NoBackground) == 0)
6521 window->DrawList->AddRect(window->Pos, window->Pos + window->Size, border_col, window->WindowRounding, 0, window->WindowBorderSize);
6522 else if (border_size > 0.0f)
6524 if (window->ChildFlags & ImGuiChildFlags_ResizeX)
6525 RenderWindowOuterSingleBorder(window, 1, border_col, border_size);
6526 if (window->ChildFlags & ImGuiChildFlags_ResizeY)
6527 RenderWindowOuterSingleBorder(window, 3, border_col, border_size);
6529 if (window->ResizeBorderHovered != -1 || window->ResizeBorderHeld != -1)
6531 const int border_n = (window->ResizeBorderHeld != -1) ? window->ResizeBorderHeld : window->ResizeBorderHovered;
6532 const ImU32 border_col_resizing = GetColorU32((window->ResizeBorderHeld != -1) ? ImGuiCol_SeparatorActive : ImGuiCol_SeparatorHovered);
6533 RenderWindowOuterSingleBorder(window, border_n, border_col_resizing, ImMax(2.0f, window->WindowBorderSize));
6535 if (
g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
6537 float y = window->Pos.y + window->TitleBarHeight - 1;
6538 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);
6544void 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)
6547 ImGuiStyle& style =
g.Style;
6548 ImGuiWindowFlags flags = window->Flags;
6551 IM_ASSERT(window->BeginCount == 0);
6552 window->SkipItems =
false;
6556 const float window_rounding = window->WindowRounding;
6557 const float window_border_size = window->WindowBorderSize;
6558 if (window->Collapsed)
6561 const float backup_border_size = style.FrameBorderSize;
6562 g.Style.FrameBorderSize = window->WindowBorderSize;
6563 ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !
g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed);
6564 if (window->ViewportOwned)
6565 title_bar_col |= IM_COL32_A_MASK;
6566 RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col,
true, window_rounding);
6567 g.Style.FrameBorderSize = backup_border_size;
6572 if (!(flags & ImGuiWindowFlags_NoBackground))
6574 bool is_docking_transparent_payload =
false;
6575 if (
g.DragDropActive && (
g.FrameCount -
g.DragDropAcceptFrameCount) <= 1 &&
g.IO.ConfigDockingTransparentPayload)
6576 if (
g.DragDropPayload.IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) && *(ImGuiWindow**)
g.DragDropPayload.Data == window)
6577 is_docking_transparent_payload =
true;
6579 ImU32 bg_col = GetColorU32(GetWindowBgColorIdx(window));
6580 if (window->ViewportOwned)
6582 bg_col |= IM_COL32_A_MASK;
6583 if (is_docking_transparent_payload)
6584 window->Viewport->Alpha *= DOCKING_TRANSPARENT_PAYLOAD_ALPHA;
6589 bool override_alpha =
false;
6591 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasBgAlpha)
6593 alpha =
g.NextWindowData.BgAlphaVal;
6594 override_alpha =
true;
6596 if (is_docking_transparent_payload)
6598 alpha *= DOCKING_TRANSPARENT_PAYLOAD_ALPHA;
6599 override_alpha =
true;
6602 bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT);
6606 if (window->DockIsActive)
6607 window->DockNode->LastBgColor = bg_col;
6608 ImDrawList* bg_draw_list = window->DockIsActive ? window->DockNode->HostWindow->DrawList : window->DrawList;
6609 if (window->DockIsActive || (flags & ImGuiWindowFlags_DockNodeHost))
6610 bg_draw_list->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
6611 bg_draw_list->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
6612 if (window->DockIsActive || (flags & ImGuiWindowFlags_DockNodeHost))
6613 bg_draw_list->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_FG);
6615 if (window->DockIsActive)
6616 window->DockNode->IsBgDrawnThisFrame =
true;
6621 if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
6623 ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
6624 if (window->ViewportOwned)
6625 title_bar_col |= IM_COL32_A_MASK;
6626 window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawFlags_RoundCornersTop);
6630 if (flags & ImGuiWindowFlags_MenuBar)
6632 ImRect menu_bar_rect = window->MenuBarRect();
6633 menu_bar_rect.ClipWith(window->Rect());
6634 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);
6635 if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
6636 window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
6640 ImGuiDockNode* node = window->DockNode;
6641 if (window->DockIsActive && node->IsHiddenTabBar() && !node->IsNoTabBar())
6643 float unhide_sz_draw = ImTrunc(
g.FontSize * 0.70f);
6644 float unhide_sz_hit = ImTrunc(
g.FontSize * 0.55f);
6645 ImVec2 p = node->Pos;
6646 ImRect r(p, p + ImVec2(unhide_sz_hit, unhide_sz_hit));
6647 ImGuiID unhide_id = window->GetID(
"#UNHIDE");
6648 KeepAliveID(unhide_id);
6650 if (ButtonBehavior(r, unhide_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren))
6651 node->WantHiddenTabBarToggle =
true;
6652 else if (held && IsMouseDragging(0))
6653 StartMouseMovingWindowOrNode(window, node,
true);
6656 ImU32 col = GetColorU32(((held && hovered) || (node->IsFocused && !hovered)) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
6657 window->DrawList->AddTriangleFilled(p, p + ImVec2(unhide_sz_draw, 0.0f), p + ImVec2(0.0f, unhide_sz_draw), col);
6661 if (window->ScrollbarX)
6662 Scrollbar(ImGuiAxis_X);
6663 if (window->ScrollbarY)
6664 Scrollbar(ImGuiAxis_Y);
6667 if (handle_borders_and_resize_grips && !(flags & ImGuiWindowFlags_NoResize))
6669 for (
int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
6671 const ImU32 col = resize_grip_col[resize_grip_n];
6672 if ((col & IM_COL32_A_MASK) == 0)
6675 const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.
CornerPosN);
6676 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)));
6677 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)));
6678 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);
6679 window->DrawList->PathFillConvex(col);
6684 if (handle_borders_and_resize_grips && !window->DockNodeAsHost)
6685 RenderWindowOuterBorders(window);
6691void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window,
const ImRect& title_bar_rect,
const char* name,
bool* p_open)
6694 ImGuiStyle& style =
g.Style;
6695 ImGuiWindowFlags flags = window->Flags;
6697 const bool has_close_button = (p_open != NULL);
6698 const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None);
6702 const ImGuiItemFlags item_flags_backup =
g.CurrentItemFlags;
6703 g.CurrentItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
6704 window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
6708 float pad_l = style.FramePadding.x;
6709 float pad_r = style.FramePadding.x;
6710 float button_sz =
g.FontSize;
6711 ImVec2 close_button_pos;
6712 ImVec2 collapse_button_pos;
6713 if (has_close_button)
6715 close_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - button_sz, title_bar_rect.Min.y + style.FramePadding.y);
6716 pad_r += button_sz + style.ItemInnerSpacing.x;
6718 if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Right)
6720 collapse_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - button_sz, title_bar_rect.Min.y + style.FramePadding.y);
6721 pad_r += button_sz + style.ItemInnerSpacing.x;
6723 if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Left)
6725 collapse_button_pos = ImVec2(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y + style.FramePadding.y);
6726 pad_l += button_sz + style.ItemInnerSpacing.x;
6730 if (has_collapse_button)
6731 if (CollapseButton(window->GetID(
"#COLLAPSE"), collapse_button_pos, NULL))
6732 window->WantCollapseToggle =
true;
6735 if (has_close_button)
6736 if (CloseButton(window->GetID(
"#CLOSE"), close_button_pos))
6739 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
6740 g.CurrentItemFlags = item_flags_backup;
6744 const float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? button_sz * 0.80f : 0.0f;
6745 const ImVec2 text_size =
CalcTextSize(name, NULL,
true) + ImVec2(marker_size_x, 0.0f);
6749 if (pad_l > style.FramePadding.x)
6750 pad_l +=
g.Style.ItemInnerSpacing.x;
6751 if (pad_r > style.FramePadding.x)
6752 pad_r +=
g.Style.ItemInnerSpacing.x;
6753 if (style.WindowTitleAlign.x > 0.0f && style.WindowTitleAlign.x < 1.0f)
6755 float centerness = ImSaturate(1.0f - ImFabs(style.WindowTitleAlign.x - 0.5f) * 2.0f);
6756 float pad_extend = ImMin(ImMax(pad_l, pad_r), title_bar_rect.GetWidth() - pad_l - pad_r - text_size.x);
6757 pad_l = ImMax(pad_l, pad_extend * centerness);
6758 pad_r = ImMax(pad_r, pad_extend * centerness);
6761 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);
6762 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);
6763 if (flags & ImGuiWindowFlags_UnsavedDocument)
6766 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);
6767 marker_pos.y = (layout_r.Min.y + layout_r.Max.y) * 0.5f;
6768 if (marker_pos.x > layout_r.Min.x)
6770 RenderBullet(window->DrawList, marker_pos, GetColorU32(ImGuiCol_Text));
6771 clip_r.Max.x = ImMin(clip_r.Max.x, marker_pos.x - (
int)(marker_size_x * 0.5f));
6776 RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r);
6779void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window)
6781 window->ParentWindow = parent_window;
6782 window->RootWindow = window->RootWindowPopupTree = window->RootWindowDockTree = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window;
6783 if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
6785 window->RootWindowDockTree = parent_window->RootWindowDockTree;
6786 if (!window->DockIsActive && !(parent_window->Flags & ImGuiWindowFlags_DockNodeHost))
6787 window->RootWindow = parent_window->RootWindow;
6789 if (parent_window && (flags & ImGuiWindowFlags_Popup))
6790 window->RootWindowPopupTree = parent_window->RootWindowPopupTree;
6791 if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)))
6792 window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight;
6793 while (window->RootWindowForNav->Flags & ImGuiWindowFlags_NavFlattened)
6795 IM_ASSERT(window->RootWindowForNav->ParentWindow != NULL);
6796 window->RootWindowForNav = window->RootWindowForNav->ParentWindow;
6802void ImGui::UpdateWindowSkipRefresh(ImGuiWindow* window)
6805 window->SkipRefresh =
false;
6806 if ((
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasRefreshPolicy) == 0)
6808 if (
g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_TryToAvoidRefresh)
6811 if (window->Appearing)
6815 if ((
g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_RefreshOnHover) &&
g.HoveredWindow && window->RootWindow ==
g.HoveredWindow->RootWindow)
6817 if ((
g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_RefreshOnFocus) &&
g.NavWindow && window->RootWindow ==
g.NavWindow->RootWindow)
6819 window->DrawList = NULL;
6820 window->SkipRefresh =
true;
6837ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
6840 if (
g.OpenPopupStack.Size <= 0)
6844 for (ImGuiPopupData& popup_data :
g.OpenPopupStack)
6846 ImGuiWindow* popup_window = popup_data.Window;
6847 if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal))
6849 if (!popup_window->Active && !popup_window->WasActive)
6852 return popup_window;
6853 if (IsWindowWithinBeginStackOf(window, popup_window))
6855 return popup_window;
6867bool ImGui::Begin(
const char* name,
bool* p_open, ImGuiWindowFlags flags)
6870 const ImGuiStyle& style =
g.Style;
6871 IM_ASSERT(name != NULL && name[0] !=
'\0');
6872 IM_ASSERT(
g.WithinFrameScope);
6873 IM_ASSERT(
g.FrameCountEnded !=
g.FrameCount);
6876 ImGuiWindow* window = FindWindowByName(name);
6877 const bool window_just_created = (window == NULL);
6878 if (window_just_created)
6879 window = CreateNewWindow(name, flags);
6882 if (
g.DebugBreakInWindow == window->ID)
6886 if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs)
6887 flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
6889 if (flags & ImGuiWindowFlags_NavFlattened)
6890 IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow);
6892 const int current_frame =
g.FrameCount;
6893 const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame);
6894 window->IsFallbackWindow = (
g.CurrentWindowStack.Size == 0 &&
g.WithinFrameScopeWithImplicitWindow);
6897 bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1);
6898 if (flags & ImGuiWindowFlags_Popup)
6900 ImGuiPopupData& popup_ref =
g.OpenPopupStack[
g.BeginPopupStack.Size];
6901 window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId);
6902 window_just_activated_by_user |= (window != popup_ref.Window);
6906 const bool window_was_appearing = window->Appearing;
6907 if (first_begin_of_the_frame)
6909 UpdateWindowInFocusOrderList(window, window_just_created, flags);
6910 window->Appearing = window_just_activated_by_user;
6911 if (window->Appearing)
6912 SetWindowConditionAllowFlags(window, ImGuiCond_Appearing,
true);
6913 window->FlagsPreviousFrame = window->Flags;
6914 window->Flags = (ImGuiWindowFlags)flags;
6915 window->ChildFlags = (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasChildFlags) ?
g.NextWindowData.ChildFlags : 0;
6916 window->LastFrameActive = current_frame;
6917 window->LastTimeActive = (float)
g.Time;
6918 window->BeginOrderWithinParent = 0;
6919 window->BeginOrderWithinContext = (short)(
g.WindowsActiveCount++);
6923 flags = window->Flags;
6928 IM_ASSERT(window->DockNode == NULL || window->DockNodeAsHost == NULL);
6929 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasDock)
6930 SetWindowDock(window,
g.NextWindowData.DockId,
g.NextWindowData.DockCond);
6931 if (first_begin_of_the_frame)
6933 bool has_dock_node = (window->DockId != 0 || window->DockNode != NULL);
6934 bool new_auto_dock_node = !has_dock_node && GetWindowAlwaysWantOwnTabBar(window);
6935 bool dock_node_was_visible = window->DockNodeIsVisible;
6936 bool dock_tab_was_visible = window->DockTabIsVisible;
6937 if (has_dock_node || new_auto_dock_node)
6939 BeginDocked(window, p_open);
6940 flags = window->Flags;
6941 if (window->DockIsActive)
6943 IM_ASSERT(window->DockNode != NULL);
6944 g.NextWindowData.Flags &= ~ImGuiNextWindowDataFlags_HasSizeConstraint;
6948 if (window->DockTabIsVisible && !dock_tab_was_visible && dock_node_was_visible && !window->Appearing && !window_was_appearing)
6950 window->Appearing =
true;
6951 SetWindowConditionAllowFlags(window, ImGuiCond_Appearing,
true);
6956 window->DockIsActive = window->DockNodeIsVisible = window->DockTabIsVisible =
false;
6961 ImGuiWindow* parent_window_in_stack = (window->DockIsActive && window->DockNode->HostWindow) ? window->DockNode->HostWindow :
g.CurrentWindowStack.empty() ? NULL :
g.CurrentWindowStack.back().
Window;
6962 ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow;
6963 IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
6966 if (window->IDStack.Size == 0)
6967 window->IDStack.push_back(window->ID);
6970 g.CurrentWindow = window;
6971 ImGuiWindowStackData window_stack_data;
6972 window_stack_data.Window = window;
6973 window_stack_data.ParentLastItemDataBackup =
g.LastItemData;
6974 window_stack_data.StackSizesOnBegin.SetToContextState(&
g);
6975 g.CurrentWindowStack.push_back(window_stack_data);
6976 if (flags & ImGuiWindowFlags_ChildMenu)
6980 if (first_begin_of_the_frame)
6982 UpdateWindowParentAndRootLinks(window, flags, parent_window);
6983 window->ParentWindowInBeginStack = parent_window_in_stack;
6988 window->ParentWindowForFocusRoute = (window->RootWindow != window) ? parent_window_in_stack : NULL;
6989 if (window->ParentWindowForFocusRoute == NULL && window->DockNode != NULL)
6990 if (window->DockNode->MergedFlags & ImGuiDockNodeFlags_DockedWindowsInFocusRoute)
6991 window->ParentWindowForFocusRoute = window->DockNode->HostWindow;
6994 if (window->WindowClass.FocusRouteParentWindowId != 0)
6996 window->ParentWindowForFocusRoute = FindWindowByID(window->WindowClass.FocusRouteParentWindowId);
6997 IM_ASSERT(window->ParentWindowForFocusRoute != 0);
7002 PushFocusScope((flags & ImGuiWindowFlags_NavFlattened) ?
g.CurrentFocusScopeId : window->
ID);
7003 window->NavRootFocusScopeId =
g.CurrentFocusScopeId;
7006 if (flags & ImGuiWindowFlags_Popup)
7008 ImGuiPopupData& popup_ref =
g.OpenPopupStack[
g.BeginPopupStack.Size];
7009 popup_ref.Window = window;
7010 popup_ref.ParentNavLayer = parent_window_in_stack->DC.NavLayerCurrent;
7011 g.BeginPopupStack.push_back(popup_ref);
7012 window->PopupId = popup_ref.PopupId;
7017 bool window_pos_set_by_api =
false;
7018 bool window_size_x_set_by_api =
false, window_size_y_set_by_api =
false;
7019 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos)
7021 window_pos_set_by_api = (window->SetWindowPosAllowFlags &
g.NextWindowData.PosCond) != 0;
7022 if (window_pos_set_by_api && ImLengthSqr(
g.NextWindowData.PosPivotVal) > 0.00001f)
7026 window->SetWindowPosVal =
g.NextWindowData.PosVal;
7027 window->SetWindowPosPivot =
g.NextWindowData.PosPivotVal;
7028 window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
7032 SetWindowPos(window,
g.NextWindowData.PosVal,
g.NextWindowData.PosCond);
7035 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize)
7037 window_size_x_set_by_api = (window->SetWindowSizeAllowFlags &
g.NextWindowData.SizeCond) != 0 && (
g.NextWindowData.SizeVal.x > 0.0f);
7038 window_size_y_set_by_api = (window->SetWindowSizeAllowFlags &
g.NextWindowData.SizeCond) != 0 && (
g.NextWindowData.SizeVal.y > 0.0f);
7039 if ((window->ChildFlags & ImGuiChildFlags_ResizeX) && (window->SetWindowSizeAllowFlags & ImGuiCond_FirstUseEver) == 0)
7040 g.NextWindowData.SizeVal.x = window->SizeFull.x;
7041 if ((window->ChildFlags & ImGuiChildFlags_ResizeY) && (window->SetWindowSizeAllowFlags & ImGuiCond_FirstUseEver) == 0)
7042 g.NextWindowData.SizeVal.y = window->SizeFull.y;
7043 SetWindowSize(window,
g.NextWindowData.SizeVal,
g.NextWindowData.SizeCond);
7045 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasScroll)
7047 if (
g.NextWindowData.ScrollVal.x >= 0.0f)
7049 window->ScrollTarget.x =
g.NextWindowData.ScrollVal.x;
7050 window->ScrollTargetCenterRatio.x = 0.0f;
7052 if (
g.NextWindowData.ScrollVal.y >= 0.0f)
7054 window->ScrollTarget.y =
g.NextWindowData.ScrollVal.y;
7055 window->ScrollTargetCenterRatio.y = 0.0f;
7058 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasContentSize)
7059 window->ContentSizeExplicit =
g.NextWindowData.ContentSizeVal;
7060 else if (first_begin_of_the_frame)
7061 window->ContentSizeExplicit = ImVec2(0.0f, 0.0f);
7062 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasWindowClass)
7063 window->WindowClass =
g.NextWindowData.WindowClass;
7064 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasCollapsed)
7065 SetWindowCollapsed(window,
g.NextWindowData.CollapsedVal,
g.NextWindowData.CollapsedCond);
7066 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasFocus)
7067 FocusWindow(window);
7068 if (window->Appearing)
7069 SetWindowConditionAllowFlags(window, ImGuiCond_Appearing,
false);
7072 UpdateWindowSkipRefresh(window);
7075 g.CurrentWindow = NULL;
7078 if (first_begin_of_the_frame && !window->SkipRefresh)
7081 const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip);
7082 const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesCannotSkipItems > 0);
7083 window->Active =
true;
7084 window->HasCloseButton = (p_open != NULL);
7085 window->ClipRect = ImVec4(-FLT_MAX, -FLT_MAX, +FLT_MAX, +FLT_MAX);
7086 window->IDStack.resize(1);
7087 window->DrawList->_ResetForNewFrame();
7088 window->DC.CurrentTableIdx = -1;
7089 if (flags & ImGuiWindowFlags_DockNodeHost)
7091 window->DrawList->ChannelsSplit(2);
7092 window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_FG);
7096 if (window->MemoryCompacted)
7097 GcAwakeTransientWindowBuffers(window);
7101 bool window_title_visible_elsewhere =
false;
7102 if ((window->Viewport && window->Viewport->Window == window) || (window->DockIsActive))
7103 window_title_visible_elsewhere =
true;
7104 else if (
g.NavWindowingListWindow != NULL && (window->Flags & ImGuiWindowFlags_NoNavFocus) == 0)
7105 window_title_visible_elsewhere =
true;
7106 if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0)
7108 size_t buf_len = (size_t)window->NameBufLen;
7109 window->Name =
ImStrdupcpy(window->Name, &buf_len, name);
7110 window->NameBufLen = (int)buf_len;
7116 CalcWindowContentSizes(window, &window->ContentSize, &window->ContentSizeIdeal);
7121 if (window->HiddenFramesCanSkipItems > 0)
7122 window->HiddenFramesCanSkipItems--;
7123 if (window->HiddenFramesCannotSkipItems > 0)
7124 window->HiddenFramesCannotSkipItems--;
7125 if (window->HiddenFramesForRenderOnly > 0)
7126 window->HiddenFramesForRenderOnly--;
7129 if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api))
7130 window->HiddenFramesCannotSkipItems = 1;
7134 if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0)
7136 window->HiddenFramesCannotSkipItems = 1;
7137 if (flags & ImGuiWindowFlags_AlwaysAutoResize)
7139 if (!window_size_x_set_by_api)
7140 window->Size.x = window->SizeFull.x = 0.f;
7141 if (!window_size_y_set_by_api)
7142 window->Size.y = window->SizeFull.y = 0.f;
7143 window->ContentSize = window->ContentSizeIdeal = ImVec2(0.f, 0.f);
7150 WindowSelectViewport(window);
7151 SetCurrentViewport(window, window->Viewport);
7152 window->FontDpiScale = (
g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleFonts) ? window->Viewport->DpiScale : 1.0f;
7153 SetCurrentWindow(window);
7154 flags = window->Flags;
7159 if (!window->DockIsActive && (flags & ImGuiWindowFlags_ChildWindow))
7160 window->WindowBorderSize = style.ChildBorderSize;
7162 window->WindowBorderSize = ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize;
7163 window->WindowPadding = style.WindowPadding;
7164 if (!window->DockIsActive && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !(window->ChildFlags & ImGuiChildFlags_AlwaysUseWindowPadding) && window->WindowBorderSize == 0.0f)
7165 window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
7168 window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x),
g.NextWindowData.MenuBarOffsetMinVal.x);
7169 window->DC.MenuBarOffset.y =
g.NextWindowData.MenuBarOffsetMinVal.y;
7170 window->TitleBarHeight = (flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f :
g.FontSize +
g.Style.FramePadding.y * 2.0f;
7171 window->MenuBarHeight = (flags & ImGuiWindowFlags_MenuBar) ? window->DC.MenuBarOffset.y +
g.FontSize +
g.Style.FramePadding.y * 2.0f : 0.0f;
7175 bool use_current_size_for_scrollbar_x = window_just_created;
7176 bool use_current_size_for_scrollbar_y = window_just_created;
7177 if (window_size_x_set_by_api && window->ContentSizeExplicit.x != 0.0f)
7178 use_current_size_for_scrollbar_x =
true;
7179 if (window_size_y_set_by_api && window->ContentSizeExplicit.y != 0.0f)
7180 use_current_size_for_scrollbar_y =
true;
7184 if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse) && !window->DockIsActive)
7187 ImRect title_bar_rect = window->TitleBarRect();
7188 if (
g.HoveredWindow == window &&
g.HoveredId == 0 &&
g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max))
7189 if (
g.IO.MouseClickedCount[0] == 2 && GetKeyOwner(ImGuiKey_MouseLeft) == ImGuiKeyOwner_NoOwner)
7190 window->WantCollapseToggle =
true;
7191 if (window->WantCollapseToggle)
7193 window->Collapsed = !window->Collapsed;
7194 if (!window->Collapsed)
7195 use_current_size_for_scrollbar_y =
true;
7196 MarkIniSettingsDirty(window);
7201 window->Collapsed =
false;
7203 window->WantCollapseToggle =
false;
7209 const ImVec2 scrollbar_sizes_from_last_frame = window->ScrollbarSizes;
7210 window->DecoOuterSizeX1 = 0.0f;
7211 window->DecoOuterSizeX2 = 0.0f;
7212 window->DecoOuterSizeY1 = window->TitleBarHeight + window->MenuBarHeight;
7213 window->DecoOuterSizeY2 = 0.0f;
7214 window->ScrollbarSizes = ImVec2(0.0f, 0.0f);
7217 const ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, window->ContentSizeIdeal);
7218 if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed)
7221 if (!window_size_x_set_by_api)
7223 window->SizeFull.x = size_auto_fit.x;
7224 use_current_size_for_scrollbar_x =
true;
7226 if (!window_size_y_set_by_api)
7228 window->SizeFull.y = size_auto_fit.y;
7229 use_current_size_for_scrollbar_y =
true;
7232 else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
7236 if (!window_size_x_set_by_api && window->AutoFitFramesX > 0)
7238 window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
7239 use_current_size_for_scrollbar_x =
true;
7241 if (!window_size_y_set_by_api && window->AutoFitFramesY > 0)
7243 window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
7244 use_current_size_for_scrollbar_y =
true;
7246 if (!window->Collapsed)
7247 MarkIniSettingsDirty(window);
7251 window->SizeFull = CalcWindowSizeAfterConstraint(window, window->SizeFull);
7252 window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull;
7257 if (window_just_activated_by_user)
7259 window->AutoPosLastDirection = ImGuiDir_None;
7260 if ((flags & ImGuiWindowFlags_Popup) != 0 && !(flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api)
7261 window->Pos =
g.BeginPopupStack.back().OpenPopupPos;
7265 if (flags & ImGuiWindowFlags_ChildWindow)
7267 IM_ASSERT(parent_window && parent_window->Active);
7268 window->BeginOrderWithinParent = (short)parent_window->DC.ChildWindows.Size;
7269 parent_window->DC.ChildWindows.push_back(window);
7270 if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api && !window_is_child_tooltip)
7271 window->Pos = parent_window->DC.CursorPos;
7274 const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesCannotSkipItems == 0);
7275 if (window_pos_with_pivot)
7276 SetWindowPos(window, window->SetWindowPosVal - window->Size * window->SetWindowPosPivot, 0);
7277 else if ((flags & ImGuiWindowFlags_ChildMenu) != 0)
7278 window->Pos = FindBestWindowPosForPopup(window);
7279 else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize)
7280 window->Pos = FindBestWindowPosForPopup(window);
7281 else if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip)
7282 window->Pos = FindBestWindowPosForPopup(window);
7285 if (window->ViewportAllowPlatformMonitorExtend >= 0 && !window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_IsMinimized))
7286 if (!window->Viewport->GetMainRect().Contains(window->Rect()))
7290 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoFocusOnAppearing);
7294 SetCurrentViewport(window, window->Viewport);
7295 window->FontDpiScale = (
g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleFonts) ? window->Viewport->DpiScale : 1.0f;
7296 SetCurrentWindow(window);
7299 if (window->ViewportOwned)
7300 WindowSyncOwnedViewport(window, parent_window_in_stack);
7304 ImRect viewport_rect(window->Viewport->GetMainRect());
7305 ImRect viewport_work_rect(window->Viewport->GetWorkRect());
7306 ImVec2 visibility_padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
7307 ImRect visibility_rect(viewport_work_rect.Min + visibility_padding, viewport_work_rect.Max - visibility_padding);
7312 if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow))
7314 if (!window->ViewportOwned && viewport_rect.GetWidth() > 0 && viewport_rect.GetHeight() > 0.0f)
7316 ClampWindowPos(window, visibility_rect);
7318 else if (window->ViewportOwned &&
g.PlatformIO.Monitors.Size > 0)
7320 if (
g.MovingWindow != NULL && window->RootWindowDockTree ==
g.MovingWindow->RootWindowDockTree)
7323 visibility_rect =
g.PlatformMonitorsFullWorkRect;
7329 const ImGuiPlatformMonitor* monitor = GetViewportPlatformMonitor(window->Viewport);
7330 visibility_rect = ImRect(monitor->WorkPos, monitor->WorkPos + monitor->WorkSize);
7332 visibility_rect.Expand(-visibility_padding);
7333 ClampWindowPos(window, visibility_rect);
7336 window->Pos = ImTrunc(window->Pos);
7340 if (window->ViewportOwned || window->DockIsActive)
7341 window->WindowRounding = 0.0f;
7343 window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
7350 bool want_focus =
false;
7351 if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing))
7353 if (flags & ImGuiWindowFlags_Popup)
7355 else if ((window->DockIsActive || (flags & ImGuiWindowFlags_ChildWindow) == 0) && !(flags & ImGuiWindowFlags_Tooltip))
7360#ifdef IMGUI_ENABLE_TEST_ENGINE
7361 if (
g.TestEngineHookItems)
7363 IM_ASSERT(window->IDStack.Size == 1);
7364 window->IDStack.Size = 0;
7365 IMGUI_TEST_ENGINE_ITEM_ADD(window->ID, window->Rect(), NULL);
7366 IMGUI_TEST_ENGINE_ITEM_INFO(window->ID, window->Name, (
g.HoveredWindow == window) ? ImGuiItemStatusFlags_HoveredRect : 0);
7367 window->IDStack.Size = 1;
7372 const bool handle_borders_and_resize_grips = (window->DockNodeAsHost || !window->DockIsActive);
7375 int border_hovered = -1, border_held = -1;
7376 ImU32 resize_grip_col[4] = {};
7377 const int resize_grip_count = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) ? 0 :
g.IO.ConfigWindowsResizeFromEdges ? 2 : 1;
7378 const float resize_grip_draw_size = IM_TRUNC(ImMax(
g.FontSize * 1.10f, window->WindowRounding + 1.0f +
g.FontSize * 0.2f));
7379 if (handle_borders_and_resize_grips && !window->Collapsed)
7380 if (
int auto_fit_mask = UpdateWindowManualResize(window, size_auto_fit, &border_hovered, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect))
7382 if (auto_fit_mask & (1 << ImGuiAxis_X))
7383 use_current_size_for_scrollbar_x =
true;
7384 if (auto_fit_mask & (1 << ImGuiAxis_Y))
7385 use_current_size_for_scrollbar_y =
true;
7387 window->ResizeBorderHovered = (
signed char)border_hovered;
7388 window->ResizeBorderHeld = (
signed char)border_held;
7391 if (window->ViewportOwned)
7393 if (!window->Viewport->PlatformRequestMove)
7394 window->Viewport->Pos = window->Pos;
7395 if (!window->Viewport->PlatformRequestResize)
7396 window->Viewport->Size = window->Size;
7397 window->Viewport->UpdateWorkRect();
7398 viewport_rect = window->Viewport->GetMainRect();
7402 window->ViewportPos = window->Viewport->Pos;
7407 if (!window->Collapsed)
7412 ImVec2 avail_size_from_current_frame = ImVec2(window->SizeFull.x, window->SizeFull.y - (window->DecoOuterSizeY1 + window->DecoOuterSizeY2));
7413 ImVec2 avail_size_from_last_frame = window->InnerRect.GetSize() + scrollbar_sizes_from_last_frame;
7414 ImVec2 needed_size_from_last_frame = window_just_created ? ImVec2(0, 0) : window->ContentSize + window->WindowPadding * 2.0f;
7415 float size_x_for_scrollbars = use_current_size_for_scrollbar_x ? avail_size_from_current_frame.x : avail_size_from_last_frame.x;
7416 float size_y_for_scrollbars = use_current_size_for_scrollbar_y ? avail_size_from_current_frame.y : avail_size_from_last_frame.y;
7418 window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
7419 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));
7420 if (window->ScrollbarX && !window->ScrollbarY)
7421 window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar);
7422 window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
7425 window->DecoOuterSizeX2 += window->ScrollbarSizes.x;
7426 window->DecoOuterSizeY2 += window->ScrollbarSizes.y;
7438 const ImRect host_rect = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) ? parent_window->ClipRect : viewport_rect;
7439 const ImRect outer_rect = window->Rect();
7440 const ImRect title_bar_rect = window->TitleBarRect();
7441 window->OuterRectClipped = outer_rect;
7442 if (window->DockIsActive)
7443 window->OuterRectClipped.Min.y += window->TitleBarHeight;
7444 window->OuterRectClipped.ClipWith(host_rect);
7452 window->InnerRect.Min.x = window->Pos.x + window->DecoOuterSizeX1;
7453 window->InnerRect.Min.y = window->Pos.y + window->DecoOuterSizeY1;
7454 window->InnerRect.Max.x = window->Pos.x + window->Size.x - window->DecoOuterSizeX2;
7455 window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->DecoOuterSizeY2;
7466 float top_border_size = (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
7467 window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + window->WindowBorderSize);
7468 window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + top_border_size);
7469 window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - window->WindowBorderSize);
7470 window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y - window->WindowBorderSize);
7471 window->InnerClipRect.ClipWithFull(host_rect);
7474 if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))
7475 window->ItemWidthDefault = ImTrunc(window->Size.x * 0.65f);
7477 window->ItemWidthDefault = ImTrunc(
g.FontSize * 16.0f);
7484 window->ScrollMax.x = ImMax(0.0f, window->ContentSize.x + window->WindowPadding.x * 2.0f - window->InnerRect.GetWidth());
7485 window->ScrollMax.y = ImMax(0.0f, window->ContentSize.y + window->WindowPadding.y * 2.0f - window->InnerRect.GetHeight());
7488 window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window);
7489 window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
7490 window->DecoInnerSizeX1 = window->DecoInnerSizeY1 = 0.0f;
7495 IM_ASSERT(window->DrawList->CmdBuffer.Size == 1 && window->DrawList->CmdBuffer[0].ElemCount == 0);
7496 window->DrawList->PushTextureID(
g.Font->ContainerAtlas->TexID);
7497 PushClipRect(host_rect.Min, host_rect.Max,
false);
7502 const bool is_undocked_or_docked_visible = !window->DockIsActive || window->DockTabIsVisible;
7503 if (is_undocked_or_docked_visible)
7505 bool render_decorations_in_parent =
false;
7506 if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip)
7510 ImGuiWindow* previous_child = parent_window->DC.ChildWindows.Size >= 2 ? parent_window->DC.ChildWindows[parent_window->DC.ChildWindows.Size - 2] : NULL;
7511 bool previous_child_overlapping = previous_child ? previous_child->Rect().Overlaps(window->Rect()) :
false;
7512 bool parent_is_empty = (parent_window->DrawList->VtxBuffer.Size == 0);
7513 if (window->DrawList->CmdBuffer.back().ElemCount == 0 && !parent_is_empty && !previous_child_overlapping)
7514 render_decorations_in_parent =
true;
7516 if (render_decorations_in_parent)
7517 window->DrawList = parent_window->DrawList;
7520 const ImGuiWindow* window_to_highlight =
g.NavWindowingTarget ?
g.NavWindowingTarget :
g.NavWindow;
7521 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)));
7522 RenderWindowDecorations(window, title_bar_rect, title_bar_is_highlight, handle_borders_and_resize_grips, resize_grip_count, resize_grip_col, resize_grip_draw_size);
7524 if (render_decorations_in_parent)
7525 window->DrawList = &window->DrawListInst;
7535 const bool allow_scrollbar_x = !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar);
7536 const bool allow_scrollbar_y = !(flags & ImGuiWindowFlags_NoScrollbar);
7537 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)));
7538 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)));
7539 window->WorkRect.Min.x = ImTrunc(window->InnerRect.Min.x - window->Scroll.x + ImMax(window->WindowPadding.x, window->WindowBorderSize));
7540 window->WorkRect.Min.y = ImTrunc(window->InnerRect.Min.y - window->Scroll.y + ImMax(window->WindowPadding.y, window->WindowBorderSize));
7541 window->WorkRect.Max.x = window->WorkRect.Min.x + work_rect_size_x;
7542 window->WorkRect.Max.y = window->WorkRect.Min.y + work_rect_size_y;
7543 window->ParentWorkRect = window->WorkRect;
7550 window->ContentRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x + window->DecoOuterSizeX1;
7551 window->ContentRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->DecoOuterSizeY1;
7552 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)));
7553 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)));
7557 window->DC.Indent.x = window->DecoOuterSizeX1 + window->WindowPadding.x - window->Scroll.x;
7558 window->DC.GroupOffset.x = 0.0f;
7559 window->DC.ColumnsOffset.x = 0.0f;
7563 double start_pos_highp_x = (double)window->Pos.x + window->WindowPadding.x - (
double)window->Scroll.x + window->DecoOuterSizeX1 + window->DC.ColumnsOffset.x;
7564 double start_pos_highp_y = (double)window->Pos.y + window->WindowPadding.y - (
double)window->Scroll.y + window->DecoOuterSizeY1;
7565 window->DC.CursorStartPos = ImVec2((
float)start_pos_highp_x, (
float)start_pos_highp_y);
7566 window->DC.CursorStartPosLossyness = ImVec2((
float)(start_pos_highp_x - window->DC.CursorStartPos.x), (
float)(start_pos_highp_y - window->DC.CursorStartPos.y));
7567 window->DC.CursorPos = window->DC.CursorStartPos;
7568 window->DC.CursorPosPrevLine = window->DC.CursorPos;
7569 window->DC.CursorMaxPos = window->DC.CursorStartPos;
7570 window->DC.IdealMaxPos = window->DC.CursorStartPos;
7571 window->DC.CurrLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f);
7572 window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
7573 window->DC.IsSameLine = window->DC.IsSetPos =
false;
7575 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
7576 window->DC.NavLayersActiveMask = window->DC.NavLayersActiveMaskNext;
7577 window->DC.NavLayersActiveMaskNext = 0x00;
7578 window->DC.NavIsScrollPushableX =
true;
7579 window->DC.NavHideHighlightOneFrame =
false;
7580 window->DC.NavWindowHasScrollY = (window->ScrollMax.y > 0.0f);
7582 window->DC.MenuBarAppending =
false;
7583 window->DC.MenuColumns.Update(style.ItemSpacing.x, window_just_activated_by_user);
7584 window->DC.TreeDepth = 0;
7585 window->DC.TreeJumpToParentOnPopMask = 0x00;
7586 window->DC.ChildWindows.resize(0);
7587 window->DC.StateStorage = &window->StateStorage;
7588 window->DC.CurrentColumns = NULL;
7589 window->DC.LayoutType = ImGuiLayoutType_Vertical;
7590 window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
7592 window->DC.ItemWidth = window->ItemWidthDefault;
7593 window->DC.TextWrapPos = -1.0f;
7594 window->DC.ItemWidthStack.resize(0);
7595 window->DC.TextWrapPosStack.resize(0);
7596 if (flags & ImGuiWindowFlags_Modal)
7597 window->DC.ModalDimBgColor = ColorConvertFloat4ToU32(GetStyleColorVec4(ImGuiCol_ModalWindowDimBg));
7599 if (window->AutoFitFramesX > 0)
7600 window->AutoFitFramesX--;
7601 if (window->AutoFitFramesY > 0)
7602 window->AutoFitFramesY--;
7605 g.NextWindowData.ClearFlags();
7612 FocusWindow(window, ImGuiFocusRequestFlags_UnlessBelowModal);
7613 if (want_focus && window ==
g.NavWindow)
7614 NavInitWindow(window,
false);
7617 if (p_open != NULL && window->Viewport->PlatformRequestClose && window->Viewport != GetMainViewport())
7619 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Window '%s' closed by PlatformRequestClose\n", window->Name);
7621 g.NavWindowingToggleLayer =
false;
7625 if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
7626 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);
7629 window->HitTestHoleSize.x = window->HitTestHoleSize.y = 0;
7641 if (
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable)
7645 if (
g.MovingWindow == window && (window->RootWindowDockTree->Flags & ImGuiWindowFlags_NoDocking) == 0)
7646 BeginDockableDragDropSource(window);
7649 if (
g.DragDropActive && !(flags & ImGuiWindowFlags_NoDocking))
7650 if (
g.MovingWindow == NULL ||
g.MovingWindow->RootWindowDockTree != window)
7651 if ((window == window->RootWindowDockTree) && !(window->Flags & ImGuiWindowFlags_DockNodeHost))
7652 BeginDockableDragDropTarget(window);
7657 SetLastItemDataForWindow(window, title_bar_rect);
7660#ifndef IMGUI_DISABLE_DEBUG_TOOLS
7661 if (
g.DebugLocateId != 0 && (window->ID ==
g.DebugLocateId || window->MoveId ==
g.DebugLocateId))
7662 DebugLocateItemResolveWithLastItem();
7666#ifdef IMGUI_ENABLE_TEST_ENGINE
7667 if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
7668 IMGUI_TEST_ENGINE_ITEM_ADD(
g.LastItemData.ID,
g.LastItemData.Rect, &
g.LastItemData);
7674 if (window->SkipRefresh)
7675 window->Active =
true;
7678 SetCurrentViewport(window, window->Viewport);
7679 SetCurrentWindow(window);
7680 g.NextWindowData.ClearFlags();
7681 SetLastItemDataForWindow(window, window->TitleBarRect());
7684 if (!(flags & ImGuiWindowFlags_DockNodeHost) && !window->SkipRefresh)
7685 PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max,
true);
7688 window->WriteAccessed =
false;
7689 window->BeginCount++;
7692 if (first_begin_of_the_frame && !window->SkipRefresh)
7698 if (window->DockIsActive && !window->DockTabIsVisible)
7700 if (window->LastFrameJustFocused ==
g.FrameCount)
7701 window->HiddenFramesCannotSkipItems = 1;
7703 window->HiddenFramesCanSkipItems = 1;
7706 if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ChildMenu))
7710 IM_ASSERT((flags& ImGuiWindowFlags_NoTitleBar) != 0 || window->DockIsActive);
7711 const bool nav_request = (flags & ImGuiWindowFlags_NavFlattened) && (
g.NavAnyRequest &&
g.NavWindow &&
g.NavWindow->RootWindowForNav == window->RootWindowForNav);
7712 if (!
g.LogEnabled && !nav_request)
7713 if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y)
7715 if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
7716 window->HiddenFramesCannotSkipItems = 1;
7718 window->HiddenFramesCanSkipItems = 1;
7722 if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCanSkipItems > 0))
7723 window->HiddenFramesCanSkipItems = 1;
7724 if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCannotSkipItems > 0))
7725 window->HiddenFramesCannotSkipItems = 1;
7729 if (style.Alpha <= 0.0f)
7730 window->HiddenFramesCanSkipItems = 1;
7733 bool hidden_regular = (window->HiddenFramesCanSkipItems > 0) || (window->HiddenFramesCannotSkipItems > 0);
7734 window->Hidden = hidden_regular || (window->HiddenFramesForRenderOnly > 0);
7737 if (window->DisableInputsFrames > 0)
7739 window->DisableInputsFrames--;
7740 window->Flags |= ImGuiWindowFlags_NoInputs;
7744 bool skip_items =
false;
7745 if (window->Collapsed || !window->Active || hidden_regular)
7746 if (window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesCannotSkipItems <= 0)
7748 window->SkipItems = skip_items;
7751 if (window->SkipItems)
7752 window->DC.NavLayersActiveMaskNext = window->DC.NavLayersActiveMask;
7757 if (window->SkipItems && !window->Appearing)
7758 IM_ASSERT(window->Appearing ==
false);
7760 else if (first_begin_of_the_frame)
7763 window->SkipItems =
true;
7768#ifndef IMGUI_DISABLE_DEBUG_TOOLS
7769 if (!window->IsFallbackWindow)
7770 if ((
g.IO.ConfigDebugBeginReturnValueOnce && window_just_created) || (
g.IO.ConfigDebugBeginReturnValueLoop &&
g.DebugBeginReturnValueCullDepth ==
g.CurrentWindowStack.Size))
7772 if (window->AutoFitFramesX > 0) { window->AutoFitFramesX++; }
7773 if (window->AutoFitFramesY > 0) { window->AutoFitFramesY++; }
7778 return !window->SkipItems;
7781static void ImGui::SetLastItemDataForWindow(ImGuiWindow* window,
const ImRect& rect)
7784 if (window->DockIsActive)
7785 SetLastItemData(window->MoveId,
g.CurrentItemFlags, window->DockTabItemStatusFlags, window->DockTabItemRect);
7787 SetLastItemData(window->MoveId,
g.CurrentItemFlags, IsMouseHoveringRect(rect.Min, rect.Max,
false) ? ImGuiItemStatusFlags_HoveredRect : 0, rect);
7793 ImGuiWindow* window =
g.CurrentWindow;
7796 if (
g.CurrentWindowStack.Size <= 1 &&
g.WithinFrameScopeWithImplicitWindow)
7798 IM_ASSERT_USER_ERROR(
g.CurrentWindowStack.Size > 1,
"Calling End() too many times!");
7801 IM_ASSERT(
g.CurrentWindowStack.Size > 0);
7804 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_DockNodeHost) && !window->DockIsActive)
7805 IM_ASSERT_USER_ERROR(
g.WithinEndChild,
"Must call EndChild() and not End()!");
7808 if (window->DC.CurrentColumns)
7810 if (!(window->Flags & ImGuiWindowFlags_DockNodeHost) && !window->SkipRefresh)
7814 if (window->SkipRefresh)
7816 IM_ASSERT(window->DrawList == NULL);
7817 window->DrawList = &window->DrawListInst;
7821 if (!(window->Flags & ImGuiWindowFlags_ChildWindow))
7824 if (window->DC.IsSetPos)
7825 ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
7828 if (window->DockNode && window->DockTabIsVisible)
7829 if (ImGuiWindow* host_window = window->DockNode->HostWindow)
7830 host_window->DC.CursorMaxPos = window->DC.CursorMaxPos + window->WindowPadding - host_window->WindowPadding;
7833 g.LastItemData =
g.CurrentWindowStack.back().ParentLastItemDataBackup;
7834 if (window->Flags & ImGuiWindowFlags_ChildMenu)
7836 if (window->Flags & ImGuiWindowFlags_Popup)
7837 g.BeginPopupStack.pop_back();
7838 g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithContextState(&
g);
7839 g.CurrentWindowStack.pop_back();
7840 SetCurrentWindow(
g.CurrentWindowStack.Size == 0 ? NULL :
g.CurrentWindowStack.back().
Window);
7841 if (
g.CurrentWindow)
7842 SetCurrentViewport(
g.CurrentWindow,
g.CurrentWindow->Viewport);
7845void ImGui::BringWindowToFocusFront(ImGuiWindow* window)
7848 IM_ASSERT(window == window->RootWindow);
7850 const int cur_order = window->FocusOrder;
7851 IM_ASSERT(
g.WindowsFocusOrder[cur_order] == window);
7852 if (
g.WindowsFocusOrder.back() == window)
7855 const int new_order =
g.WindowsFocusOrder.Size - 1;
7856 for (
int n = cur_order; n < new_order; n++)
7858 g.WindowsFocusOrder[n] =
g.WindowsFocusOrder[n + 1];
7859 g.WindowsFocusOrder[n]->FocusOrder--;
7860 IM_ASSERT(
g.WindowsFocusOrder[n]->FocusOrder == n);
7862 g.WindowsFocusOrder[new_order] = window;
7863 window->FocusOrder = (short)new_order;
7866void ImGui::BringWindowToDisplayFront(ImGuiWindow* window)
7869 ImGuiWindow* current_front_window =
g.Windows.back();
7870 if (current_front_window == window || current_front_window->RootWindowDockTree == window)
7872 for (
int i =
g.Windows.Size - 2; i >= 0; i--)
7873 if (
g.Windows[i] == window)
7875 memmove(&
g.Windows[i], &
g.Windows[i + 1], (
size_t)(
g.Windows.Size - i - 1) *
sizeof(ImGuiWindow*));
7876 g.Windows[
g.Windows.Size - 1] = window;
7881void ImGui::BringWindowToDisplayBack(ImGuiWindow* window)
7884 if (
g.Windows[0] == window)
7886 for (
int i = 0; i <
g.Windows.Size; i++)
7887 if (
g.Windows[i] == window)
7889 memmove(&
g.Windows[1], &
g.Windows[0], (
size_t)i *
sizeof(ImGuiWindow*));
7890 g.Windows[0] = window;
7895void ImGui::BringWindowToDisplayBehind(ImGuiWindow* window, ImGuiWindow* behind_window)
7897 IM_ASSERT(window != NULL && behind_window != NULL);
7899 window = window->RootWindow;
7900 behind_window = behind_window->RootWindow;
7901 int pos_wnd = FindWindowDisplayIndex(window);
7902 int pos_beh = FindWindowDisplayIndex(behind_window);
7903 if (pos_wnd < pos_beh)
7905 size_t copy_bytes = (pos_beh - pos_wnd - 1) *
sizeof(ImGuiWindow*);
7906 memmove(&
g.Windows.Data[pos_wnd], &
g.Windows.Data[pos_wnd + 1], copy_bytes);
7907 g.Windows[pos_beh - 1] = window;
7911 size_t copy_bytes = (pos_wnd - pos_beh) *
sizeof(ImGuiWindow*);
7912 memmove(&
g.Windows.Data[pos_beh + 1], &
g.Windows.Data[pos_beh], copy_bytes);
7913 g.Windows[pos_beh] = window;
7917int ImGui::FindWindowDisplayIndex(ImGuiWindow* window)
7920 return g.Windows.index_from_ptr(
g.Windows.find(window));
7924void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags)
7929 if ((flags & ImGuiFocusRequestFlags_UnlessBelowModal) && (
g.NavWindow != window))
7930 if (ImGuiWindow* blocking_modal = FindBlockingModal(window))
7932 IMGUI_DEBUG_LOG_FOCUS(
"[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n", window ? window->Name :
"<NULL>", blocking_modal->Name);
7933 if (window && window == window->RootWindow && (window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
7934 BringWindowToDisplayBehind(window, blocking_modal);
7939 if ((flags & ImGuiFocusRequestFlags_RestoreFocusedChild) && window != NULL)
7940 window = NavRestoreLastChildNavWindow(window);
7943 if (
g.NavWindow != window)
7945 SetNavWindow(window);
7946 if (window &&
g.NavDisableMouseHover)
7947 g.NavMousePosDirty =
true;
7948 g.NavId = window ? window->NavLastIds[0] : 0;
7949 g.NavLayer = ImGuiNavLayer_Main;
7950 SetNavFocusScope(window ? window->NavRootFocusScopeId : 0);
7951 g.NavIdIsAlive =
false;
7952 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
7955 ClosePopupsOverWindow(window,
false);
7959 IM_ASSERT(window == NULL || window->RootWindowDockTree != NULL);
7960 ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL;
7961 ImGuiWindow* display_front_window = window ? window->RootWindowDockTree : NULL;
7962 ImGuiDockNode* dock_node = window ? window->DockNode : NULL;
7963 bool active_id_window_is_dock_node_host = (
g.ActiveIdWindow && dock_node && dock_node->HostWindow ==
g.ActiveIdWindow);
7969 if (
g.ActiveId != 0 &&
g.ActiveIdWindow &&
g.ActiveIdWindow->RootWindow != focus_front_window)
7970 if (!
g.ActiveIdNoClearOnFocusLoss && !active_id_window_is_dock_node_host)
7976 window->LastFrameJustFocused =
g.FrameCount;
7984 BringWindowToFocusFront(focus_front_window);
7985 if (((window->Flags | focus_front_window->Flags | display_front_window->Flags) & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
7986 BringWindowToDisplayFront(display_front_window);
7989void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport, ImGuiFocusRequestFlags flags)
7992 int start_idx =
g.WindowsFocusOrder.Size - 1;
7993 if (under_this_window != NULL)
7997 while (under_this_window->Flags & ImGuiWindowFlags_ChildWindow)
7999 under_this_window = under_this_window->ParentWindow;
8002 start_idx = FindWindowFocusIndex(under_this_window) + offset;
8004 for (
int i = start_idx; i >= 0; i--)
8007 ImGuiWindow* window =
g.WindowsFocusOrder[i];
8008 if (window == ignore_window || !window->WasActive)
8010 if (filter_viewport != NULL && window->Viewport != filter_viewport)
8012 if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
8019 FocusWindow(window, flags);
8023 FocusWindow(NULL, flags);
8027void ImGui::SetCurrentFont(ImFont* font)
8030 IM_ASSERT(font && font->IsLoaded());
8031 IM_ASSERT(font->Scale > 0.0f);
8033 g.FontBaseSize = ImMax(1.0f,
g.IO.FontGlobalScale *
g.Font->FontSize *
g.Font->Scale);
8034 g.FontSize =
g.CurrentWindow ?
g.CurrentWindow->CalcFontSize() : 0.0f;
8036 ImFontAtlas* atlas =
g.Font->ContainerAtlas;
8037 g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel;
8038 g.DrawListSharedData.TexUvLines = atlas->TexUvLines;
8039 g.DrawListSharedData.Font =
g.Font;
8040 g.DrawListSharedData.FontSize =
g.FontSize;
8043void ImGui::PushFont(ImFont* font)
8047 font = GetDefaultFont();
8048 SetCurrentFont(font);
8049 g.FontStack.push_back(font);
8050 g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID);
8053void ImGui::PopFont()
8056 g.CurrentWindow->DrawList->PopTextureID();
8057 g.FontStack.pop_back();
8058 SetCurrentFont(
g.FontStack.empty() ? GetDefaultFont() :
g.FontStack.back());
8061void ImGui::PushItemFlag(ImGuiItemFlags option,
bool enabled)
8064 ImGuiItemFlags item_flags =
g.CurrentItemFlags;
8065 IM_ASSERT(item_flags ==
g.ItemFlagsStack.back());
8067 item_flags |= option;
8069 item_flags &= ~option;
8070 g.CurrentItemFlags = item_flags;
8071 g.ItemFlagsStack.push_back(item_flags);
8074void ImGui::PopItemFlag()
8077 IM_ASSERT(
g.ItemFlagsStack.Size > 1);
8078 g.ItemFlagsStack.pop_back();
8079 g.CurrentItemFlags =
g.ItemFlagsStack.back();
8088void ImGui::BeginDisabled(
bool disabled)
8091 bool was_disabled = (
g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
8092 if (!was_disabled && disabled)
8094 g.DisabledAlphaBackup =
g.Style.Alpha;
8095 g.Style.Alpha *=
g.Style.DisabledAlpha;
8097 if (was_disabled || disabled)
8098 g.CurrentItemFlags |= ImGuiItemFlags_Disabled;
8099 g.ItemFlagsStack.push_back(
g.CurrentItemFlags);
8100 g.DisabledStackSize++;
8103void ImGui::EndDisabled()
8106 IM_ASSERT(
g.DisabledStackSize > 0);
8107 g.DisabledStackSize--;
8108 bool was_disabled = (
g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
8110 g.ItemFlagsStack.pop_back();
8111 g.CurrentItemFlags =
g.ItemFlagsStack.back();
8112 if (was_disabled && (
g.CurrentItemFlags & ImGuiItemFlags_Disabled) == 0)
8113 g.Style.Alpha =
g.DisabledAlphaBackup;
8116void ImGui::PushTabStop(
bool tab_stop)
8118 PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop);
8121void ImGui::PopTabStop()
8126void ImGui::PushButtonRepeat(
bool repeat)
8128 PushItemFlag(ImGuiItemFlags_ButtonRepeat,
repeat);
8131void ImGui::PopButtonRepeat()
8136void ImGui::PushTextWrapPos(
float wrap_pos_x)
8138 ImGuiWindow* window = GetCurrentWindow();
8139 window->DC.TextWrapPosStack.push_back(window->DC.TextWrapPos);
8140 window->DC.TextWrapPos = wrap_pos_x;
8143void ImGui::PopTextWrapPos()
8145 ImGuiWindow* window = GetCurrentWindow();
8146 window->DC.TextWrapPos = window->DC.TextWrapPosStack.back();
8147 window->DC.TextWrapPosStack.pop_back();
8150static ImGuiWindow* GetCombinedRootWindow(ImGuiWindow* window,
bool popup_hierarchy,
bool dock_hierarchy)
8152 ImGuiWindow* last_window = NULL;
8153 while (last_window != window)
8155 last_window = window;
8156 window = window->RootWindow;
8157 if (popup_hierarchy)
8158 window = window->RootWindowPopupTree;
8160 window = window->RootWindowDockTree;
8165bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent,
bool popup_hierarchy,
bool dock_hierarchy)
8167 ImGuiWindow* window_root = GetCombinedRootWindow(window, popup_hierarchy, dock_hierarchy);
8168 if (window_root == potential_parent)
8170 while (window != NULL)
8172 if (window == potential_parent)
8174 if (window == window_root)
8176 window = window->ParentWindow;
8181bool ImGui::IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent)
8183 if (window->RootWindow == potential_parent)
8185 while (window != NULL)
8187 if (window == potential_parent)
8189 window = window->ParentWindowInBeginStack;
8194bool ImGui::IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below)
8199 const int display_layer_delta = GetWindowDisplayLayer(potential_above) - GetWindowDisplayLayer(potential_below);
8200 if (display_layer_delta != 0)
8201 return display_layer_delta > 0;
8203 for (
int i =
g.Windows.Size - 1; i >= 0; i--)
8205 ImGuiWindow* candidate_window =
g.Windows[i];
8206 if (candidate_window == potential_above)
8208 if (candidate_window == potential_below)
8218bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
8220 IM_ASSERT((flags & ~ImGuiHoveredFlags_AllowedMaskForIsWindowHovered) == 0 &&
"Invalid flags for IsWindowHovered()!");
8223 ImGuiWindow* ref_window =
g.HoveredWindow;
8224 ImGuiWindow* cur_window =
g.CurrentWindow;
8225 if (ref_window == NULL)
8228 if ((flags & ImGuiHoveredFlags_AnyWindow) == 0)
8230 IM_ASSERT(cur_window);
8231 const bool popup_hierarchy = (flags & ImGuiHoveredFlags_NoPopupHierarchy) == 0;
8232 const bool dock_hierarchy = (flags & ImGuiHoveredFlags_DockHierarchy) != 0;
8233 if (flags & ImGuiHoveredFlags_RootWindow)
8234 cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy, dock_hierarchy);
8237 if (flags & ImGuiHoveredFlags_ChildWindows)
8238 result = IsWindowChildOf(ref_window, cur_window, popup_hierarchy, dock_hierarchy);
8240 result = (ref_window == cur_window);
8245 if (!IsWindowContentHoverable(ref_window, flags))
8247 if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
8248 if (
g.ActiveId != 0 && !
g.ActiveIdAllowOverlap &&
g.ActiveId != ref_window->MoveId)
8256 if (flags & ImGuiHoveredFlags_ForTooltip)
8257 flags = ApplyHoverFlagsForTooltip(flags,
g.Style.HoverFlagsForTooltipMouse);
8258 if ((flags & ImGuiHoveredFlags_Stationary) != 0 &&
g.HoverWindowUnlockedStationaryId != ref_window->ID)
8264bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags)
8267 ImGuiWindow* ref_window =
g.NavWindow;
8268 ImGuiWindow* cur_window =
g.CurrentWindow;
8270 if (ref_window == NULL)
8272 if (flags & ImGuiFocusedFlags_AnyWindow)
8275 IM_ASSERT(cur_window);
8276 const bool popup_hierarchy = (flags & ImGuiFocusedFlags_NoPopupHierarchy) == 0;
8277 const bool dock_hierarchy = (flags & ImGuiFocusedFlags_DockHierarchy) != 0;
8278 if (flags & ImGuiHoveredFlags_RootWindow)
8279 cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy, dock_hierarchy);
8281 if (flags & ImGuiHoveredFlags_ChildWindows)
8282 return IsWindowChildOf(ref_window, cur_window, popup_hierarchy, dock_hierarchy);
8284 return (ref_window == cur_window);
8287ImGuiID ImGui::GetWindowDockID()
8290 return g.CurrentWindow->DockId;
8293bool ImGui::IsWindowDocked()
8296 return g.CurrentWindow->DockIsActive;
8302bool ImGui::IsWindowNavFocusable(ImGuiWindow* window)
8304 return window->WasActive && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
8307float ImGui::GetWindowWidth()
8309 ImGuiWindow* window =
GImGui->CurrentWindow;
8310 return window->Size.x;
8313float ImGui::GetWindowHeight()
8315 ImGuiWindow* window =
GImGui->CurrentWindow;
8316 return window->Size.y;
8319ImVec2 ImGui::GetWindowPos()
8322 ImGuiWindow* window =
g.CurrentWindow;
8326void ImGui::SetWindowPos(ImGuiWindow* window,
const ImVec2& pos, ImGuiCond cond)
8329 if (cond && (window->SetWindowPosAllowFlags & cond) == 0)
8332 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
8333 window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
8334 window->SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX);
8337 const ImVec2 old_pos = window->Pos;
8338 window->Pos = ImTrunc(pos);
8339 ImVec2 offset = window->Pos - old_pos;
8340 if (offset.x == 0.0f && offset.y == 0.0f)
8342 MarkIniSettingsDirty(window);
8344 window->DC.CursorPos += offset;
8345 window->DC.CursorMaxPos += offset;
8346 window->DC.IdealMaxPos += offset;
8347 window->DC.CursorStartPos += offset;
8350void ImGui::SetWindowPos(
const ImVec2& pos, ImGuiCond cond)
8352 ImGuiWindow* window = GetCurrentWindowRead();
8353 SetWindowPos(window, pos, cond);
8356void ImGui::SetWindowPos(
const char* name,
const ImVec2& pos, ImGuiCond cond)
8358 if (ImGuiWindow* window = FindWindowByName(name))
8359 SetWindowPos(window, pos, cond);
8362ImVec2 ImGui::GetWindowSize()
8364 ImGuiWindow* window = GetCurrentWindowRead();
8365 return window->Size;
8368void ImGui::SetWindowSize(ImGuiWindow* window,
const ImVec2& size, ImGuiCond cond)
8371 if (cond && (window->SetWindowSizeAllowFlags & cond) == 0)
8374 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
8375 window->SetWindowSizeAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
8378 if ((window->Flags & ImGuiWindowFlags_ChildWindow) == 0 || window->Appearing || (window->ChildFlags & ImGuiChildFlags_AlwaysAutoResize) != 0)
8379 window->AutoFitFramesX = (
size.x <= 0.0f) ? 2 : 0;
8380 if ((window->Flags & ImGuiWindowFlags_ChildWindow) == 0 || window->Appearing || (window->ChildFlags & ImGuiChildFlags_AlwaysAutoResize) != 0)
8381 window->AutoFitFramesY = (
size.y <= 0.0f) ? 2 : 0;
8384 ImVec2 old_size = window->SizeFull;
8386 window->AutoFitOnlyGrows =
false;
8388 window->SizeFull.x = IM_TRUNC(
size.x);
8390 window->AutoFitOnlyGrows =
false;
8392 window->SizeFull.y = IM_TRUNC(
size.y);
8393 if (old_size.x != window->SizeFull.x || old_size.y != window->SizeFull.y)
8394 MarkIniSettingsDirty(window);
8397void ImGui::SetWindowSize(
const ImVec2& size, ImGuiCond cond)
8399 SetWindowSize(
GImGui->CurrentWindow, size, cond);
8402void ImGui::SetWindowSize(
const char* name,
const ImVec2& size, ImGuiCond cond)
8404 if (ImGuiWindow* window = FindWindowByName(name))
8405 SetWindowSize(window, size, cond);
8408void ImGui::SetWindowCollapsed(ImGuiWindow* window,
bool collapsed, ImGuiCond cond)
8411 if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0)
8413 window->SetWindowCollapsedAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
8416 window->Collapsed = collapsed;
8419void ImGui::SetWindowHitTestHole(ImGuiWindow* window,
const ImVec2& pos,
const ImVec2& size)
8421 IM_ASSERT(window->HitTestHoleSize.x == 0);
8422 window->HitTestHoleSize = ImVec2ih(size);
8423 window->HitTestHoleOffset = ImVec2ih(pos - window->Pos);
8426void ImGui::SetWindowHiddenAndSkipItemsForCurrentFrame(ImGuiWindow* window)
8428 window->Hidden = window->SkipItems =
true;
8429 window->HiddenFramesCanSkipItems = 1;
8432void ImGui::SetWindowCollapsed(
bool collapsed, ImGuiCond cond)
8434 SetWindowCollapsed(
GImGui->CurrentWindow, collapsed, cond);
8437bool ImGui::IsWindowCollapsed()
8439 ImGuiWindow* window = GetCurrentWindowRead();
8440 return window->Collapsed;
8443bool ImGui::IsWindowAppearing()
8445 ImGuiWindow* window = GetCurrentWindowRead();
8446 return window->Appearing;
8449void ImGui::SetWindowCollapsed(
const char* name,
bool collapsed, ImGuiCond cond)
8451 if (ImGuiWindow* window = FindWindowByName(name))
8452 SetWindowCollapsed(window, collapsed, cond);
8455void ImGui::SetWindowFocus()
8457 FocusWindow(
GImGui->CurrentWindow);
8460void ImGui::SetWindowFocus(
const char* name)
8464 if (ImGuiWindow* window = FindWindowByName(name))
8465 FocusWindow(window);
8473void ImGui::SetNextWindowPos(
const ImVec2& pos, ImGuiCond cond,
const ImVec2& pivot)
8476 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
8477 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasPos;
8478 g.NextWindowData.PosVal = pos;
8479 g.NextWindowData.PosPivotVal = pivot;
8480 g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always;
8481 g.NextWindowData.PosUndock =
true;
8484void ImGui::SetNextWindowSize(
const ImVec2& size, ImGuiCond cond)
8487 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
8488 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSize;
8489 g.NextWindowData.SizeVal =
size;
8490 g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always;
8497void ImGui::SetNextWindowSizeConstraints(
const ImVec2& size_min,
const ImVec2& size_max, ImGuiSizeCallback custom_callback,
void* custom_callback_user_data)
8500 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint;
8501 g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max);
8502 g.NextWindowData.SizeCallback = custom_callback;
8503 g.NextWindowData.SizeCallbackUserData = custom_callback_user_data;
8508void ImGui::SetNextWindowContentSize(
const ImVec2& size)
8511 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasContentSize;
8512 g.NextWindowData.ContentSizeVal = ImTrunc(size);
8515void ImGui::SetNextWindowScroll(
const ImVec2& scroll)
8518 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasScroll;
8519 g.NextWindowData.ScrollVal = scroll;
8522void ImGui::SetNextWindowCollapsed(
bool collapsed, ImGuiCond cond)
8525 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
8526 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasCollapsed;
8527 g.NextWindowData.CollapsedVal = collapsed;
8528 g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always;
8531void ImGui::SetNextWindowFocus()
8534 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus;
8537void ImGui::SetNextWindowBgAlpha(
float alpha)
8540 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasBgAlpha;
8541 g.NextWindowData.BgAlphaVal = alpha;
8544void ImGui::SetNextWindowViewport(ImGuiID
id)
8547 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasViewport;
8548 g.NextWindowData.ViewportId =
id;
8551void ImGui::SetNextWindowDockID(ImGuiID
id, ImGuiCond cond)
8554 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasDock;
8555 g.NextWindowData.DockCond = cond ? cond : ImGuiCond_Always;
8556 g.NextWindowData.DockId =
id;
8559void ImGui::SetNextWindowClass(
const ImGuiWindowClass* window_class)
8562 IM_ASSERT((window_class->ViewportFlagsOverrideSet & window_class->ViewportFlagsOverrideClear) == 0);
8563 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasWindowClass;
8564 g.NextWindowData.WindowClass = *window_class;
8568void ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags)
8571 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasRefreshPolicy;
8572 g.NextWindowData.RefreshFlagsVal = flags;
8575ImDrawList* ImGui::GetWindowDrawList()
8577 ImGuiWindow* window = GetCurrentWindow();
8578 return window->DrawList;
8581float ImGui::GetWindowDpiScale()
8584 return g.CurrentDpiScale;
8587ImGuiViewport* ImGui::GetWindowViewport()
8590 IM_ASSERT(
g.CurrentViewport != NULL &&
g.CurrentViewport ==
g.CurrentWindow->Viewport);
8591 return g.CurrentViewport;
8594ImFont* ImGui::GetFont()
8599float ImGui::GetFontSize()
8604ImVec2 ImGui::GetFontTexUvWhitePixel()
8606 return GImGui->DrawListSharedData.TexUvWhitePixel;
8609void ImGui::SetWindowFontScale(
float scale)
8611 IM_ASSERT(scale > 0.0f);
8613 ImGuiWindow* window = GetCurrentWindow();
8614 window->FontWindowScale =
scale;
8615 g.FontSize =
g.DrawListSharedData.FontSize = window->CalcFontSize();
8618void ImGui::PushFocusScope(ImGuiID
id)
8621 ImGuiFocusScopeData data;
8623 data.WindowID =
g.CurrentWindow->ID;
8624 g.FocusScopeStack.push_back(data);
8625 g.CurrentFocusScopeId =
id;
8628void ImGui::PopFocusScope()
8631 if (
g.FocusScopeStack.Size == 0)
8633 IM_ASSERT_USER_ERROR(
g.FocusScopeStack.Size > 0,
"Calling PopFocusScope() too many times!");
8636 g.FocusScopeStack.pop_back();
8637 g.CurrentFocusScopeId =
g.FocusScopeStack.Size ?
g.FocusScopeStack.back().ID : 0;
8640void ImGui::SetNavFocusScope(ImGuiID focus_scope_id)
8643 g.NavFocusScopeId = focus_scope_id;
8644 g.NavFocusRoute.resize(0);
8645 if (focus_scope_id == 0)
8647 IM_ASSERT(
g.NavWindow != NULL);
8650 if (focus_scope_id ==
g.CurrentFocusScopeId)
8653 for (
int n =
g.FocusScopeStack.Size - 1; n >= 0 &&
g.FocusScopeStack.Data[n].WindowID ==
g.CurrentWindow->ID; n--)
8654 g.NavFocusRoute.push_back(
g.FocusScopeStack.Data[n]);
8656 else if (focus_scope_id ==
g.NavWindow->NavRootFocusScopeId)
8657 g.NavFocusRoute.push_back({ focus_scope_id,
g.NavWindow->ID });
8662 for (ImGuiWindow* window =
g.NavWindow->ParentWindowForFocusRoute; window != NULL; window = window->ParentWindowForFocusRoute)
8663 g.NavFocusRoute.push_back({ window->NavRootFocusScopeId, window->ID });
8664 IM_ASSERT(
g.NavFocusRoute.Size < 100);
8668void ImGui::FocusItem()
8671 ImGuiWindow* window =
g.CurrentWindow;
8672 IMGUI_DEBUG_LOG_FOCUS(
"FocusItem(0x%08x) in window \"%s\"\n",
g.LastItemData.ID, window->Name);
8673 if (
g.DragDropActive ||
g.MovingWindow != NULL)
8675 IMGUI_DEBUG_LOG_FOCUS(
"FocusItem() ignored while DragDropActive!\n");
8679 ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavHighlight | ImGuiNavMoveFlags_NoSelect;
8680 ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
8681 SetNavWindow(window);
8682 NavMoveRequestSubmit(ImGuiDir_None, ImGuiDir_Up, move_flags, scroll_flags);
8683 NavMoveRequestResolveWithLastItem(&
g.NavMoveResultLocal);
8686void ImGui::ActivateItemByID(ImGuiID
id)
8689 g.NavNextActivateId =
id;
8690 g.NavNextActivateFlags = ImGuiActivateFlags_None;
8695void ImGui::SetKeyboardFocusHere(
int offset)
8698 ImGuiWindow* window =
g.CurrentWindow;
8699 IM_ASSERT(offset >= -1);
8700 IMGUI_DEBUG_LOG_FOCUS(
"SetKeyboardFocusHere(%d) in window \"%s\"\n", offset, window->Name);
8706 if (
g.DragDropActive ||
g.MovingWindow != NULL)
8708 IMGUI_DEBUG_LOG_FOCUS(
"SetKeyboardFocusHere() ignored while DragDropActive!\n");
8712 SetNavWindow(window);
8714 ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavHighlight;
8715 ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
8716 NavMoveRequestSubmit(ImGuiDir_None, offset < 0 ? ImGuiDir_Up : ImGuiDir_Down, move_flags, scroll_flags);
8719 NavMoveRequestResolveWithLastItem(&
g.NavMoveResultLocal);
8723 g.NavTabbingDir = 1;
8724 g.NavTabbingCounter = offset + 1;
8728void ImGui::SetItemDefaultFocus()
8731 ImGuiWindow* window =
g.CurrentWindow;
8732 if (!window->Appearing)
8734 if (
g.NavWindow != window->RootWindowForNav || (!
g.NavInitRequest &&
g.NavInitResult.ID == 0) ||
g.NavLayer != window->DC.NavLayerCurrent)
8737 g.NavInitRequest =
false;
8738 NavApplyItemToResult(&
g.NavInitResult);
8739 NavUpdateAnyRequestFlag();
8742 if (!window->ClipRect.Contains(
g.LastItemData.Rect))
8743 ScrollToRectEx(window,
g.LastItemData.Rect, ImGuiScrollFlags_None);
8746void ImGui::SetStateStorage(ImGuiStorage* tree)
8748 ImGuiWindow* window =
GImGui->CurrentWindow;
8749 window->DC.StateStorage = tree ? tree : &window->StateStorage;
8752ImGuiStorage* ImGui::GetStateStorage()
8754 ImGuiWindow* window =
GImGui->CurrentWindow;
8755 return window->DC.StateStorage;
8758bool ImGui::IsRectVisible(
const ImVec2& size)
8760 ImGuiWindow* window =
GImGui->CurrentWindow;
8761 return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size));
8764bool ImGui::IsRectVisible(
const ImVec2& rect_min,
const ImVec2& rect_max)
8766 ImGuiWindow* window =
GImGui->CurrentWindow;
8767 return window->ClipRect.Overlaps(ImRect(rect_min, rect_max));
8776ImGuiID ImGuiWindow::GetID(
const char* str,
const char* str_end)
8778 ImGuiID seed = IDStack.back();
8779 ImGuiID
id =
ImHashStr(str, str_end ? (str_end - str) : 0, seed);
8780#ifndef IMGUI_DISABLE_DEBUG_TOOLS
8781 ImGuiContext&
g = *Ctx;
8782 if (
g.DebugHookIdInfo ==
id)
8783 ImGui::DebugHookIdInfo(
id, ImGuiDataType_String, str, str_end);
8788ImGuiID ImGuiWindow::GetID(
const void* ptr)
8790 ImGuiID seed = IDStack.back();
8791 ImGuiID
id =
ImHashData(&ptr,
sizeof(
void*), seed);
8792#ifndef IMGUI_DISABLE_DEBUG_TOOLS
8793 ImGuiContext&
g = *Ctx;
8794 if (
g.DebugHookIdInfo ==
id)
8795 ImGui::DebugHookIdInfo(
id, ImGuiDataType_Pointer, ptr, NULL);
8800ImGuiID ImGuiWindow::GetID(
int n)
8802 ImGuiID seed = IDStack.back();
8803 ImGuiID
id =
ImHashData(&n,
sizeof(n), seed);
8804#ifndef IMGUI_DISABLE_DEBUG_TOOLS
8805 ImGuiContext&
g = *Ctx;
8806 if (
g.DebugHookIdInfo ==
id)
8807 ImGui::DebugHookIdInfo(
id, ImGuiDataType_S32, (
void*)(intptr_t)n, NULL);
8813ImGuiID ImGuiWindow::GetIDFromRectangle(
const ImRect& r_abs)
8815 ImGuiID seed = IDStack.back();
8816 ImRect r_rel = ImGui::WindowRectAbsToRel(
this, r_abs);
8817 ImGuiID
id =
ImHashData(&r_rel,
sizeof(r_rel), seed);
8821void ImGui::PushID(
const char* str_id)
8824 ImGuiWindow* window =
g.CurrentWindow;
8825 ImGuiID
id = window->GetID(str_id);
8826 window->IDStack.push_back(
id);
8829void ImGui::PushID(
const char* str_id_begin,
const char* str_id_end)
8832 ImGuiWindow* window =
g.CurrentWindow;
8833 ImGuiID
id = window->GetID(str_id_begin, str_id_end);
8834 window->IDStack.push_back(
id);
8837void ImGui::PushID(
const void* ptr_id)
8840 ImGuiWindow* window =
g.CurrentWindow;
8841 ImGuiID
id = window->GetID(ptr_id);
8842 window->IDStack.push_back(
id);
8845void ImGui::PushID(
int int_id)
8848 ImGuiWindow* window =
g.CurrentWindow;
8849 ImGuiID
id = window->GetID(int_id);
8850 window->IDStack.push_back(
id);
8854void ImGui::PushOverrideID(ImGuiID
id)
8857 ImGuiWindow* window =
g.CurrentWindow;
8858#ifndef IMGUI_DISABLE_DEBUG_TOOLS
8859 if (
g.DebugHookIdInfo ==
id)
8860 DebugHookIdInfo(
id, ImGuiDataType_ID, NULL, NULL);
8862 window->IDStack.push_back(
id);
8868ImGuiID ImGui::GetIDWithSeed(
const char* str,
const char* str_end, ImGuiID seed)
8870 ImGuiID
id =
ImHashStr(str, str_end ? (str_end - str) : 0, seed);
8871#ifndef IMGUI_DISABLE_DEBUG_TOOLS
8873 if (
g.DebugHookIdInfo ==
id)
8874 DebugHookIdInfo(
id, ImGuiDataType_String, str, str_end);
8879ImGuiID ImGui::GetIDWithSeed(
int n, ImGuiID seed)
8881 ImGuiID
id =
ImHashData(&n,
sizeof(n), seed);
8882#ifndef IMGUI_DISABLE_DEBUG_TOOLS
8884 if (
g.DebugHookIdInfo ==
id)
8885 DebugHookIdInfo(
id, ImGuiDataType_S32, (
void*)(intptr_t)n, NULL);
8892 ImGuiWindow* window =
GImGui->CurrentWindow;
8893 IM_ASSERT(window->IDStack.Size > 1);
8894 window->IDStack.pop_back();
8897ImGuiID ImGui::GetID(
const char* str_id)
8899 ImGuiWindow* window =
GImGui->CurrentWindow;
8900 return window->GetID(str_id);
8903ImGuiID ImGui::GetID(
const char* str_id_begin,
const char* str_id_end)
8905 ImGuiWindow* window =
GImGui->CurrentWindow;
8906 return window->GetID(str_id_begin, str_id_end);
8909ImGuiID ImGui::GetID(
const void* ptr_id)
8911 ImGuiWindow* window =
GImGui->CurrentWindow;
8912 return window->GetID(ptr_id);
8981static ImGuiKeyChord GetModForModKey(ImGuiKey key)
8983 if (key == ImGuiKey_LeftCtrl || key == ImGuiKey_RightCtrl)
8984 return ImGuiMod_Ctrl;
8985 if (key == ImGuiKey_LeftShift || key == ImGuiKey_RightShift)
8986 return ImGuiMod_Shift;
8987 if (key == ImGuiKey_LeftAlt || key == ImGuiKey_RightAlt)
8988 return ImGuiMod_Alt;
8989 if (key == ImGuiKey_LeftSuper || key == ImGuiKey_RightSuper)
8990 return ImGuiMod_Super;
8991 return ImGuiMod_None;
8994ImGuiKeyChord ImGui::FixupKeyChord(ImGuiKeyChord key_chord)
8997 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
8999 key_chord |= GetModForModKey(key);
9003ImGuiKeyData* ImGui::GetKeyData(ImGuiContext* ctx, ImGuiKey key)
9005 ImGuiContext&
g = *ctx;
9008 if (key & ImGuiMod_Mask_)
9009 key = ConvertSingleModFlagToKey(key);
9011#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
9012 IM_ASSERT(key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_NamedKey_END);
9013 if (IsLegacyKey(key) &&
g.IO.KeyMap[key] != -1)
9014 key = (ImGuiKey)
g.IO.KeyMap[key];
9016 IM_ASSERT(IsNamedKey(key) &&
"Support for user key indices was dropped in favor of ImGuiKey. Please update backend & user code.");
9018 return &
g.IO.KeysData[key - ImGuiKey_KeysData_OFFSET];
9021#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
9023ImGuiKey ImGui::GetKeyIndex(ImGuiKey key)
9026 IM_ASSERT(IsNamedKey(key));
9027 const ImGuiKeyData* key_data = GetKeyData(key);
9028 return (ImGuiKey)(key_data -
g.IO.KeysData);
9033static const char*
const GKeyNames[] =
9035 "Tab",
"LeftArrow",
"RightArrow",
"UpArrow",
"DownArrow",
"PageUp",
"PageDown",
9036 "Home",
"End",
"Insert",
"Delete",
"Backspace",
"Space",
"Enter",
"Escape",
9037 "LeftCtrl",
"LeftShift",
"LeftAlt",
"LeftSuper",
"RightCtrl",
"RightShift",
"RightAlt",
"RightSuper",
"Menu",
9038 "0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
9039 "I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
9040 "F1",
"F2",
"F3",
"F4",
"F5",
"F6",
"F7",
"F8",
"F9",
"F10",
"F11",
"F12",
9041 "F13",
"F14",
"F15",
"F16",
"F17",
"F18",
"F19",
"F20",
"F21",
"F22",
"F23",
"F24",
9042 "Apostrophe",
"Comma",
"Minus",
"Period",
"Slash",
"Semicolon",
"Equal",
"LeftBracket",
9043 "Backslash",
"RightBracket",
"GraveAccent",
"CapsLock",
"ScrollLock",
"NumLock",
"PrintScreen",
9044 "Pause",
"Keypad0",
"Keypad1",
"Keypad2",
"Keypad3",
"Keypad4",
"Keypad5",
"Keypad6",
9045 "Keypad7",
"Keypad8",
"Keypad9",
"KeypadDecimal",
"KeypadDivide",
"KeypadMultiply",
9046 "KeypadSubtract",
"KeypadAdd",
"KeypadEnter",
"KeypadEqual",
9047 "AppBack",
"AppForward",
9048 "GamepadStart",
"GamepadBack",
9049 "GamepadFaceLeft",
"GamepadFaceRight",
"GamepadFaceUp",
"GamepadFaceDown",
9050 "GamepadDpadLeft",
"GamepadDpadRight",
"GamepadDpadUp",
"GamepadDpadDown",
9051 "GamepadL1",
"GamepadR1",
"GamepadL2",
"GamepadR2",
"GamepadL3",
"GamepadR3",
9052 "GamepadLStickLeft",
"GamepadLStickRight",
"GamepadLStickUp",
"GamepadLStickDown",
9053 "GamepadRStickLeft",
"GamepadRStickRight",
"GamepadRStickUp",
"GamepadRStickDown",
9054 "MouseLeft",
"MouseRight",
"MouseMiddle",
"MouseX1",
"MouseX2",
"MouseWheelX",
"MouseWheelY",
9055 "ModCtrl",
"ModShift",
"ModAlt",
"ModSuper",
9059const char* ImGui::GetKeyName(ImGuiKey key)
9061 if (key == ImGuiKey_None)
9063#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
9064 IM_ASSERT(IsNamedKeyOrMod(key) &&
"Support for user key indices was dropped in favor of ImGuiKey. Please update backend and user code.");
9067 if (IsLegacyKey(key))
9069 if (
g.IO.KeyMap[key] == -1)
9071 IM_ASSERT(IsNamedKey((ImGuiKey)
g.IO.KeyMap[key]));
9072 key = (ImGuiKey)
g.IO.KeyMap[key];
9075 if (key & ImGuiMod_Mask_)
9076 key = ConvertSingleModFlagToKey(key);
9077 if (!IsNamedKey(key))
9080 return GKeyNames[key - ImGuiKey_NamedKey_BEGIN];
9085const char* ImGui::GetKeyChordName(ImGuiKeyChord key_chord)
9089 const ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
9091 key_chord &= ~GetModForModKey(key);
9092 ImFormatString(
g.TempKeychordName, IM_ARRAYSIZE(
g.TempKeychordName),
"%s%s%s%s%s",
9093 (key_chord & ImGuiMod_Ctrl) ?
"Ctrl+" :
"",
9094 (key_chord & ImGuiMod_Shift) ?
"Shift+" :
"",
9095 (key_chord & ImGuiMod_Alt) ?
"Alt+" :
"",
9096 (key_chord & ImGuiMod_Super) ?
"Super+" :
"",
9097 (key != ImGuiKey_None || key_chord == ImGuiKey_None) ? GetKeyName(key) :
"");
9099 if (key == ImGuiKey_None && key_chord != 0)
9100 if ((len = strlen(
g.TempKeychordName)) != 0)
9101 g.TempKeychordName[len - 1] = 0;
9102 return g.TempKeychordName;
9109int ImGui::CalcTypematicRepeatAmount(
float t0,
float t1,
float repeat_delay,
float repeat_rate)
9115 if (repeat_rate <= 0.0f)
9116 return (t0 < repeat_delay) && (t1 >= repeat_delay);
9117 const int count_t0 = (t0 < repeat_delay) ? -1 : (int)((t0 - repeat_delay) / repeat_rate);
9118 const int count_t1 = (t1 < repeat_delay) ? -1 : (int)((t1 - repeat_delay) / repeat_rate);
9119 const int count = count_t1 - count_t0;
9123void ImGui::GetTypematicRepeatRate(ImGuiInputFlags flags,
float* repeat_delay,
float* repeat_rate)
9126 switch (flags & ImGuiInputFlags_RepeatRateMask_)
9128 case ImGuiInputFlags_RepeatRateNavMove: *repeat_delay =
g.IO.KeyRepeatDelay * 0.72f; *repeat_rate =
g.IO.KeyRepeatRate * 0.80f;
return;
9129 case ImGuiInputFlags_RepeatRateNavTweak: *repeat_delay =
g.IO.KeyRepeatDelay * 0.72f; *repeat_rate =
g.IO.KeyRepeatRate * 0.30f;
return;
9130 case ImGuiInputFlags_RepeatRateDefault:
default: *repeat_delay =
g.IO.KeyRepeatDelay * 1.00f; *repeat_rate =
g.IO.KeyRepeatRate * 1.00f;
return;
9136int ImGui::GetKeyPressedAmount(ImGuiKey key,
float repeat_delay,
float repeat_rate)
9139 const ImGuiKeyData* key_data = GetKeyData(key);
9140 if (!key_data->Down)
9142 const float t = key_data->DownDuration;
9143 return CalcTypematicRepeatAmount(
t -
g.IO.DeltaTime,
t, repeat_delay, repeat_rate);
9147ImVec2 ImGui::GetKeyMagnitude2d(ImGuiKey key_left, ImGuiKey key_right, ImGuiKey key_up, ImGuiKey key_down)
9150 GetKeyData(key_right)->AnalogValue - GetKeyData(key_left)->AnalogValue,
9151 GetKeyData(key_down)->AnalogValue - GetKeyData(key_up)->AnalogValue);
9158static void ImGui::UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt)
9161 rt->EntriesNext.resize(0);
9162 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
9164 const int new_routing_start_idx = rt->EntriesNext.Size;
9165 ImGuiKeyRoutingData* routing_entry;
9166 for (
int old_routing_idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; old_routing_idx != -1; old_routing_idx = routing_entry->NextEntryIndex)
9168 routing_entry = &rt->Entries[old_routing_idx];
9169 routing_entry->RoutingCurrScore = routing_entry->RoutingNextScore;
9170 routing_entry->RoutingCurr = routing_entry->RoutingNext;
9171 routing_entry->RoutingNext = ImGuiKeyOwner_NoOwner;
9172 routing_entry->RoutingNextScore = 255;
9173 if (routing_entry->RoutingCurr == ImGuiKeyOwner_NoOwner)
9175 rt->EntriesNext.push_back(*routing_entry);
9179 if (routing_entry->Mods ==
g.IO.KeyMods)
9181 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
9182 if (owner_data->OwnerCurr == ImGuiKeyOwner_NoOwner)
9184 owner_data->OwnerCurr = routing_entry->RoutingCurr;
9191 rt->Index[key - ImGuiKey_NamedKey_BEGIN] = (ImGuiKeyRoutingIndex)(new_routing_start_idx < rt->EntriesNext.Size ? new_routing_start_idx : -1);
9192 for (
int n = new_routing_start_idx; n < rt->EntriesNext.Size; n++)
9193 rt->EntriesNext[n].NextEntryIndex = (ImGuiKeyRoutingIndex)((n + 1 < rt->EntriesNext.Size) ? n + 1 : -1);
9195 rt->Entries.swap(rt->EntriesNext);
9199static inline ImGuiID GetRoutingIdFromOwnerId(ImGuiID owner_id)
9202 return (owner_id != ImGuiKeyOwner_NoOwner && owner_id != ImGuiKeyOwner_Any) ? owner_id :
g.CurrentFocusScopeId;
9205ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord)
9214 ImGuiKeyRoutingTable* rt = &
g.KeysRoutingTable;
9215 ImGuiKeyRoutingData* routing_data;
9216 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
9217 ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
9218 if (key == ImGuiKey_None)
9219 key = ConvertSingleModFlagToKey(mods);
9220 IM_ASSERT(IsNamedKey(key));
9224 for (ImGuiKeyRoutingIndex idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; idx != -1; idx = routing_data->NextEntryIndex)
9226 routing_data = &rt->Entries[idx];
9227 if (routing_data->Mods == mods)
9228 return routing_data;
9232 ImGuiKeyRoutingIndex routing_data_idx = (ImGuiKeyRoutingIndex)rt->Entries.Size;
9233 rt->Entries.push_back(ImGuiKeyRoutingData());
9234 routing_data = &rt->Entries[routing_data_idx];
9235 routing_data->Mods = (ImU16)mods;
9236 routing_data->NextEntryIndex = rt->Index[key - ImGuiKey_NamedKey_BEGIN];
9237 rt->Index[key - ImGuiKey_NamedKey_BEGIN] = routing_data_idx;
9238 return routing_data;
9249static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInputFlags flags)
9252 if (flags & ImGuiInputFlags_RouteFocused)
9256 if (owner_id != 0 &&
g.ActiveId == owner_id)
9266 if (focus_scope_id == 0)
9268 for (
int index_in_focus_path = 0; index_in_focus_path <
g.NavFocusRoute.Size; index_in_focus_path++)
9269 if (
g.NavFocusRoute.Data[index_in_focus_path].ID == focus_scope_id)
9270 return 3 + index_in_focus_path;
9273 else if (flags & ImGuiInputFlags_RouteActive)
9275 if (owner_id != 0 &&
g.ActiveId == owner_id)
9279 else if (flags & ImGuiInputFlags_RouteGlobal)
9281 if (flags & ImGuiInputFlags_RouteOverActive)
9283 if (flags & ImGuiInputFlags_RouteOverFocused)
9293static bool IsKeyChordPotentiallyCharInput(ImGuiKeyChord key_chord)
9299 ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
9300 const bool ignore_char_inputs = ((mods & ImGuiMod_Ctrl) && !(mods & ImGuiMod_Alt)) || (
g.IO.ConfigMacOSXBehaviors && (mods & ImGuiMod_Ctrl));
9301 if (ignore_char_inputs)
9305 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
9306 return g.KeysMayBeCharInput.TestBit(key);
9314bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id)
9317 if ((flags & ImGuiInputFlags_RouteTypeMask_) == 0)
9318 flags |= ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive;
9320 IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteTypeMask_));
9321 IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_NoOwner);
9322 if (flags & (ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused))
9323 IM_ASSERT(flags & ImGuiInputFlags_RouteGlobal);
9326 key_chord = FixupKeyChord(key_chord);
9329 if (
g.DebugBreakInShortcutRouting == key_chord)
9332 if (flags & ImGuiInputFlags_RouteUnlessBgFocused)
9333 if (
g.NavWindow == NULL)
9337 if (flags & ImGuiInputFlags_RouteAlways)
9339 IMGUI_DEBUG_LOG_INPUTROUTING(
"SetShortcutRouting(%s, flags=%04X, owner_id=0x%08X) -> always, no register\n", GetKeyChordName(key_chord), flags, owner_id);
9344 if (
g.ActiveId != 0 &&
g.ActiveId != owner_id)
9346 if (flags & ImGuiInputFlags_RouteActive)
9354 if (
g.IO.WantTextInput && IsKeyChordPotentiallyCharInput(key_chord))
9356 IMGUI_DEBUG_LOG_INPUTROUTING(
"SetShortcutRouting(%s, flags=%04X, owner_id=0x%08X) -> filtered as potential char input\n", GetKeyChordName(key_chord), flags, owner_id);
9361 if ((flags & ImGuiInputFlags_RouteOverActive) == 0 &&
g.ActiveIdUsingAllKeyboardKeys)
9363 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
9364 if (key == ImGuiKey_None)
9365 key = ConvertSingleModFlagToKey((ImGuiKey)(key_chord & ImGuiMod_Mask_));
9366 if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END)
9372 ImGuiID focus_scope_id =
g.CurrentFocusScopeId;
9373 if (flags & ImGuiInputFlags_RouteFromRootWindow)
9374 focus_scope_id =
g.CurrentWindow->RootWindow->ID;
9376 const int score = CalcRoutingScore(focus_scope_id, owner_id, flags);
9377 IMGUI_DEBUG_LOG_INPUTROUTING(
"SetShortcutRouting(%s, flags=%04X, owner_id=0x%08X) -> score %d\n", GetKeyChordName(key_chord), flags, owner_id, score);
9383 ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord);
9385 if (score < routing_data->RoutingNextScore)
9387 routing_data->RoutingNext = owner_id;
9388 routing_data->RoutingNextScore = (ImU8)score;
9392 if (routing_data->RoutingCurr == owner_id)
9393 IMGUI_DEBUG_LOG_INPUTROUTING(
"--> granting current route\n");
9394 return routing_data->RoutingCurr == owner_id;
9399bool ImGui::TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id)
9401 const ImGuiID routing_id = GetRoutingIdFromOwnerId(owner_id);
9402 key_chord = FixupKeyChord(key_chord);
9403 ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord);
9404 return routing_data->RoutingCurr == routing_id;
9409bool ImGui::IsKeyDown(ImGuiKey key)
9411 return IsKeyDown(key, ImGuiKeyOwner_Any);
9414bool ImGui::IsKeyDown(ImGuiKey key, ImGuiID owner_id)
9416 const ImGuiKeyData* key_data = GetKeyData(key);
9417 if (!key_data->Down)
9419 if (!TestKeyOwner(key, owner_id))
9424bool ImGui::IsKeyPressed(ImGuiKey key,
bool repeat)
9426 return IsKeyPressed(key,
repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None, ImGuiKeyOwner_Any);
9430bool ImGui::IsKeyPressed(ImGuiKey key, ImGuiInputFlags flags, ImGuiID owner_id)
9432 const ImGuiKeyData* key_data = GetKeyData(key);
9433 if (!key_data->Down)
9435 const float t = key_data->DownDuration;
9438 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsKeyPressed) == 0);
9439 if (flags & (ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_))
9440 flags |= ImGuiInputFlags_Repeat;
9442 bool pressed = (
t == 0.0f);
9443 if (!pressed && (flags & ImGuiInputFlags_Repeat) != 0)
9445 float repeat_delay, repeat_rate;
9446 GetTypematicRepeatRate(flags, &repeat_delay, &repeat_rate);
9447 pressed = (
t > repeat_delay) && GetKeyPressedAmount(key, repeat_delay, repeat_rate) > 0;
9448 if (pressed && (flags & ImGuiInputFlags_RepeatUntilMask_))
9453 double key_pressed_time =
g.Time -
t + 0.00001f;
9454 if ((flags & ImGuiInputFlags_RepeatUntilKeyModsChange) && (
g.LastKeyModsChangeTime > key_pressed_time))
9456 if ((flags & ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone) && (
g.LastKeyModsChangeFromNoneTime > key_pressed_time))
9458 if ((flags & ImGuiInputFlags_RepeatUntilOtherKeyPress) && (
g.LastKeyboardKeyPressTime > key_pressed_time))
9464 if (!TestKeyOwner(key, owner_id))
9469bool ImGui::IsKeyReleased(ImGuiKey key)
9471 return IsKeyReleased(key, ImGuiKeyOwner_Any);
9474bool ImGui::IsKeyReleased(ImGuiKey key, ImGuiID owner_id)
9476 const ImGuiKeyData* key_data = GetKeyData(key);
9477 if (key_data->DownDurationPrev < 0.0f || key_data->Down)
9479 if (!TestKeyOwner(key, owner_id))
9484bool ImGui::IsMouseDown(ImGuiMouseButton button)
9487 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9488 return g.IO.MouseDown[button] && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any);
9491bool ImGui::IsMouseDown(ImGuiMouseButton button, ImGuiID owner_id)
9494 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9495 return g.IO.MouseDown[button] && TestKeyOwner(MouseButtonToKey(button), owner_id);
9498bool ImGui::IsMouseClicked(ImGuiMouseButton button,
bool repeat)
9500 return IsMouseClicked(button, ImGuiKeyOwner_Any,
repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None);
9503bool ImGui::IsMouseClicked(ImGuiMouseButton button, ImGuiInputFlags flags, ImGuiID owner_id)
9506 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9507 if (!
g.IO.MouseDown[button])
9509 const float t =
g.IO.MouseDownDuration[button];
9512 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsMouseClicked) == 0);
9514 const bool repeat = (flags & ImGuiInputFlags_Repeat) != 0;
9515 const bool pressed = (
t == 0.0f) || (
repeat &&
t >
g.IO.KeyRepeatDelay && CalcTypematicRepeatAmount(
t -
g.IO.DeltaTime,
t,
g.IO.KeyRepeatDelay,
g.IO.KeyRepeatRate) > 0);
9519 if (!TestKeyOwner(MouseButtonToKey(button), owner_id))
9525bool ImGui::IsMouseReleased(ImGuiMouseButton button)
9528 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9529 return g.IO.MouseReleased[button] && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any);
9532bool ImGui::IsMouseReleased(ImGuiMouseButton button, ImGuiID owner_id)
9535 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9536 return g.IO.MouseReleased[button] && TestKeyOwner(MouseButtonToKey(button), owner_id);
9539bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button)
9542 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9543 return g.IO.MouseClickedCount[button] == 2 && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any);
9546bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button, ImGuiID owner_id)
9549 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9550 return g.IO.MouseClickedCount[button] == 2 && TestKeyOwner(MouseButtonToKey(button), owner_id);
9553int ImGui::GetMouseClickedCount(ImGuiMouseButton button)
9556 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9557 return g.IO.MouseClickedCount[button];
9563bool ImGui::IsMouseHoveringRect(
const ImVec2& r_min,
const ImVec2& r_max,
bool clip)
9568 ImRect rect_clipped(r_min, r_max);
9570 rect_clipped.ClipWith(
g.CurrentWindow->ClipRect);
9573 if (!rect_clipped.ContainsWithPad(
g.IO.MousePos,
g.Style.TouchExtraPadding))
9575 if (!
g.MouseViewport->GetMainRect().Overlaps(rect_clipped))
9582bool ImGui::IsMouseDragPastThreshold(ImGuiMouseButton button,
float lock_threshold)
9585 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9586 if (lock_threshold < 0.0f)
9587 lock_threshold =
g.IO.MouseDragThreshold;
9588 return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;
9591bool ImGui::IsMouseDragging(ImGuiMouseButton button,
float lock_threshold)
9594 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9595 if (!
g.IO.MouseDown[button])
9597 return IsMouseDragPastThreshold(button, lock_threshold);
9600ImVec2 ImGui::GetMousePos()
9603 return g.IO.MousePos;
9608void ImGui::TeleportMousePos(
const ImVec2& pos)
9611 g.IO.MousePos =
g.IO.MousePosPrev = pos;
9612 g.IO.MouseDelta = ImVec2(0.0f, 0.0f);
9613 g.IO.WantSetMousePos =
true;
9618ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
9621 if (
g.BeginPopupStack.Size > 0)
9622 return g.OpenPopupStack[
g.BeginPopupStack.Size - 1].OpenMousePos;
9623 return g.IO.MousePos;
9627bool ImGui::IsMousePosValid(
const ImVec2* mouse_pos)
9631 IM_ASSERT(
GImGui != NULL);
9632 const float MOUSE_INVALID = -256000.0f;
9633 ImVec2 p = mouse_pos ? *mouse_pos :
GImGui->IO.MousePos;
9634 return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID;
9638bool ImGui::IsAnyMouseDown()
9641 for (
int n = 0; n < IM_ARRAYSIZE(
g.IO.MouseDown); n++)
9642 if (
g.IO.MouseDown[n])
9650ImVec2 ImGui::GetMouseDragDelta(ImGuiMouseButton button,
float lock_threshold)
9653 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9654 if (lock_threshold < 0.0f)
9655 lock_threshold =
g.IO.MouseDragThreshold;
9656 if (
g.IO.MouseDown[button] ||
g.IO.MouseReleased[button])
9657 if (
g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold)
9658 if (IsMousePosValid(&
g.IO.MousePos) && IsMousePosValid(&
g.IO.MouseClickedPos[button]))
9659 return g.IO.MousePos -
g.IO.MouseClickedPos[button];
9660 return ImVec2(0.0f, 0.0f);
9663void ImGui::ResetMouseDragDelta(ImGuiMouseButton button)
9666 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9668 g.IO.MouseClickedPos[button] =
g.IO.MousePos;
9675ImGuiMouseCursor ImGui::GetMouseCursor()
9678 return g.MouseCursor;
9681void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)
9684 g.MouseCursor = cursor_type;
9687static void UpdateAliasKey(ImGuiKey key,
bool v,
float analog_value)
9689 IM_ASSERT(ImGui::IsAliasKey(key));
9690 ImGuiKeyData* key_data = ImGui::GetKeyData(key);
9692 key_data->AnalogValue = analog_value;
9696static ImGuiKeyChord GetMergedModsFromKeys()
9698 ImGuiKeyChord mods = 0;
9699 if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) { mods |= ImGuiMod_Ctrl; }
9700 if (ImGui::IsKeyDown(ImGuiMod_Shift)) { mods |= ImGuiMod_Shift; }
9701 if (ImGui::IsKeyDown(ImGuiMod_Alt)) { mods |= ImGuiMod_Alt; }
9702 if (ImGui::IsKeyDown(ImGuiMod_Super)) { mods |= ImGuiMod_Super; }
9706static void ImGui::UpdateKeyboardInputs()
9712#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
9713 if (io.BackendUsingLegacyKeyArrays == 0)
9716 for (
int n = 0; n < ImGuiKey_LegacyNativeKey_END; n++)
9717 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!");
9721 if (
g.FrameCount == 0)
9722 for (
int n = ImGuiKey_LegacyNativeKey_BEGIN; n < ImGuiKey_LegacyNativeKey_END; n++)
9723 IM_ASSERT(
g.IO.KeyMap[n] == -1 &&
"Backend is not allowed to write to io.KeyMap[0..511]!");
9726 for (
int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++)
9727 if (io.KeyMap[n] != -1)
9729 IM_ASSERT(IsLegacyKey((ImGuiKey)io.KeyMap[n]));
9730 io.KeyMap[io.KeyMap[n]] = n;
9734 for (
int n = ImGuiKey_LegacyNativeKey_BEGIN; n < ImGuiKey_LegacyNativeKey_END; n++)
9735 if (io.KeysDown[n] || io.BackendUsingLegacyKeyArrays == 1)
9737 const ImGuiKey key = (ImGuiKey)(io.KeyMap[n] != -1 ? io.KeyMap[n] : n);
9738 IM_ASSERT(io.KeyMap[n] == -1 || IsNamedKey(key));
9739 io.KeysData[key].Down = io.KeysDown[n];
9741 io.KeysDown[key] = io.KeysDown[n];
9742 io.BackendUsingLegacyKeyArrays = 1;
9744 if (io.BackendUsingLegacyKeyArrays == 1)
9746 GetKeyData(ImGuiMod_Ctrl)->Down = io.KeyCtrl;
9747 GetKeyData(ImGuiMod_Shift)->Down = io.KeyShift;
9748 GetKeyData(ImGuiMod_Alt)->Down = io.KeyAlt;
9749 GetKeyData(ImGuiMod_Super)->Down = io.KeySuper;
9755#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
9756 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
9757 if (io.BackendUsingLegacyNavInputArray && nav_gamepad_active)
9759 #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)
9760 #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)
9761 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceDown, ImGuiNavInput_Activate);
9762 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceRight, ImGuiNavInput_Cancel);
9763 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceLeft, ImGuiNavInput_Menu);
9764 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceUp, ImGuiNavInput_Input);
9765 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadLeft, ImGuiNavInput_DpadLeft);
9766 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadRight, ImGuiNavInput_DpadRight);
9767 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadUp, ImGuiNavInput_DpadUp);
9768 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadDown, ImGuiNavInput_DpadDown);
9769 MAP_LEGACY_NAV_INPUT_TO_KEY2(ImGuiKey_GamepadL1, ImGuiNavInput_FocusPrev, ImGuiNavInput_TweakSlow);
9770 MAP_LEGACY_NAV_INPUT_TO_KEY2(ImGuiKey_GamepadR1, ImGuiNavInput_FocusNext, ImGuiNavInput_TweakFast);
9771 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickLeft, ImGuiNavInput_LStickLeft);
9772 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickRight, ImGuiNavInput_LStickRight);
9773 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickUp, ImGuiNavInput_LStickUp);
9774 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickDown, ImGuiNavInput_LStickDown);
9780 for (
int n = 0; n < ImGuiMouseButton_COUNT; n++)
9781 UpdateAliasKey(MouseButtonToKey(n), io.MouseDown[n], io.MouseDown[n] ? 1.0f : 0.0f);
9782 UpdateAliasKey(ImGuiKey_MouseWheelX, io.MouseWheelH != 0.0f, io.MouseWheelH);
9783 UpdateAliasKey(ImGuiKey_MouseWheelY, io.MouseWheel != 0.0f, io.MouseWheel);
9789 const ImGuiKeyChord prev_key_mods = io.KeyMods;
9790 io.KeyMods = GetMergedModsFromKeys();
9791 io.KeyCtrl = (io.KeyMods & ImGuiMod_Ctrl) != 0;
9792 io.KeyShift = (io.KeyMods & ImGuiMod_Shift) != 0;
9793 io.KeyAlt = (io.KeyMods & ImGuiMod_Alt) != 0;
9794 io.KeySuper = (io.KeyMods & ImGuiMod_Super) != 0;
9795 if (prev_key_mods != io.KeyMods)
9796 g.LastKeyModsChangeTime =
g.Time;
9797 if (prev_key_mods != io.KeyMods && prev_key_mods == 0)
9798 g.LastKeyModsChangeFromNoneTime =
g.Time;
9801 if ((io.BackendFlags & ImGuiBackendFlags_HasGamepad) == 0)
9802 for (
int i = ImGuiKey_Gamepad_BEGIN; i < ImGuiKey_Gamepad_END; i++)
9804 io.KeysData[i - ImGuiKey_KeysData_OFFSET].Down =
false;
9805 io.KeysData[i - ImGuiKey_KeysData_OFFSET].AnalogValue = 0.0f;
9809 for (
int i = 0; i < ImGuiKey_KeysData_SIZE; i++)
9811 ImGuiKeyData* key_data = &io.KeysData[i];
9812 key_data->DownDurationPrev = key_data->DownDuration;
9813 key_data->DownDuration = key_data->Down ? (key_data->DownDuration < 0.0f ? 0.0f : key_data->DownDuration + io.DeltaTime) : -1.0f;
9814 if (key_data->DownDuration == 0.0f)
9816 ImGuiKey key = (ImGuiKey)(ImGuiKey_KeysData_OFFSET + i);
9817 if (IsKeyboardKey(key))
9818 g.LastKeyboardKeyPressTime =
g.Time;
9819 else if (key == ImGuiKey_ReservedForModCtrl || key == ImGuiKey_ReservedForModShift || key == ImGuiKey_ReservedForModAlt || key == ImGuiKey_ReservedForModSuper)
9820 g.LastKeyboardKeyPressTime =
g.Time;
9825 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
9827 ImGuiKeyData* key_data = &io.KeysData[key - ImGuiKey_KeysData_OFFSET];
9828 ImGuiKeyOwnerData* owner_data = &
g.KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN];
9829 owner_data->OwnerCurr = owner_data->OwnerNext;
9830 if (!key_data->Down)
9831 owner_data->OwnerNext = ImGuiKeyOwner_NoOwner;
9832 owner_data->LockThisFrame = owner_data->LockUntilRelease = owner_data->LockUntilRelease && key_data->Down;
9836 UpdateKeyRoutingTable(&
g.KeysRoutingTable);
9839static void ImGui::UpdateMouseInputs()
9849 io.MouseWheelRequestAxisSwap = io.KeyShift && !io.ConfigMacOSXBehaviors;
9852 if (IsMousePosValid(&io.MousePos))
9853 io.MousePos =
g.MouseLastValidPos = ImFloor(io.MousePos);
9856 if (IsMousePosValid(&io.MousePos) && IsMousePosValid(&io.MousePosPrev))
9857 io.MouseDelta = io.MousePos - io.MousePosPrev;
9859 io.MouseDelta = ImVec2(0.0f, 0.0f);
9863 const float mouse_stationary_threshold = (io.MouseSource == ImGuiMouseSource_Mouse) ? 2.0f : 3.0f;
9864 const bool mouse_stationary = (ImLengthSqr(io.MouseDelta) <= mouse_stationary_threshold * mouse_stationary_threshold);
9865 g.MouseStationaryTimer = mouse_stationary ? (
g.MouseStationaryTimer + io.DeltaTime) : 0.0f;
9869 if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)
9870 g.NavDisableMouseHover =
false;
9872 for (
int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
9874 io.MouseClicked[i] = io.MouseDown[i] && io.MouseDownDuration[i] < 0.0f;
9875 io.MouseClickedCount[i] = 0;
9876 io.MouseReleased[i] = !io.MouseDown[i] && io.MouseDownDuration[i] >= 0.0f;
9877 io.MouseDownDurationPrev[i] = io.MouseDownDuration[i];
9878 io.MouseDownDuration[i] = io.MouseDown[i] ? (io.MouseDownDuration[i] < 0.0f ? 0.0f : io.MouseDownDuration[i] + io.DeltaTime) : -1.0f;
9879 if (io.MouseClicked[i])
9881 bool is_repeated_click =
false;
9882 if ((
float)(
g.Time - io.MouseClickedTime[i]) < io.MouseDoubleClickTime)
9884 ImVec2 delta_from_click_pos = IsMousePosValid(&io.MousePos) ? (io.MousePos - io.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
9885 if (ImLengthSqr(delta_from_click_pos) < io.MouseDoubleClickMaxDist * io.MouseDoubleClickMaxDist)
9886 is_repeated_click =
true;
9888 if (is_repeated_click)
9889 io.MouseClickedLastCount[i]++;
9891 io.MouseClickedLastCount[i] = 1;
9892 io.MouseClickedTime[i] =
g.Time;
9893 io.MouseClickedPos[i] = io.MousePos;
9894 io.MouseClickedCount[i] = io.MouseClickedLastCount[i];
9895 io.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f);
9896 io.MouseDragMaxDistanceSqr[i] = 0.0f;
9898 else if (io.MouseDown[i])
9901 ImVec2 delta_from_click_pos = IsMousePosValid(&io.MousePos) ? (io.MousePos - io.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
9902 io.MouseDragMaxDistanceSqr[i] = ImMax(io.MouseDragMaxDistanceSqr[i], ImLengthSqr(delta_from_click_pos));
9903 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);
9904 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);
9908 io.MouseDoubleClicked[i] = (io.MouseClickedCount[i] == 2);
9911 if (io.MouseClicked[i])
9912 g.NavDisableMouseHover =
false;
9916static void LockWheelingWindow(ImGuiWindow* window,
float wheel_amount)
9920 g.WheelingWindowReleaseTimer = ImMin(
g.WheelingWindowReleaseTimer + ImAbs(wheel_amount) * WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER, WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER);
9922 g.WheelingWindowReleaseTimer = 0.0f;
9923 if (
g.WheelingWindow == window)
9925 IMGUI_DEBUG_LOG_IO(
"[io] LockWheelingWindow() \"%s\"\n", window ? window->Name :
"NULL");
9926 g.WheelingWindow = window;
9927 g.WheelingWindowRefMousePos =
g.IO.MousePos;
9930 g.WheelingWindowStartFrame = -1;
9931 g.WheelingAxisAvg = ImVec2(0.0f, 0.0f);
9935static ImGuiWindow* FindBestWheelingWindow(
const ImVec2& wheel)
9939 ImGuiWindow* windows[2] = { NULL, NULL };
9940 for (
int axis = 0; axis < 2; axis++)
9941 if (wheel[axis] != 0.0f)
9942 for (ImGuiWindow* window = windows[axis] =
g.HoveredWindow; window->Flags & ImGuiWindowFlags_ChildWindow; window = windows[axis] = window->ParentWindow)
9948 const bool has_scrolling = (window->ScrollMax[axis] != 0.0f);
9949 const bool inputs_disabled = (window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs);
9951 if (has_scrolling && !inputs_disabled)
9954 if (windows[0] == NULL && windows[1] == NULL)
9958 if (windows[0] == windows[1] || windows[0] == NULL || windows[1] == NULL)
9959 return windows[1] ? windows[1] : windows[0];
9964 if (
g.WheelingWindowStartFrame == -1)
9965 g.WheelingWindowStartFrame =
g.FrameCount;
9966 if ((
g.WheelingWindowStartFrame ==
g.FrameCount && wheel.x != 0.0f && wheel.y != 0.0f) || (
g.WheelingAxisAvg.x ==
g.WheelingAxisAvg.y))
9968 g.WheelingWindowWheelRemainder = wheel;
9971 return (
g.WheelingAxisAvg.x >
g.WheelingAxisAvg.y) ? windows[0] : windows[1];
9975void ImGui::UpdateMouseWheel()
9980 if (
g.WheelingWindow != NULL)
9982 g.WheelingWindowReleaseTimer -=
g.IO.DeltaTime;
9983 if (IsMousePosValid() && ImLengthSqr(
g.IO.MousePos -
g.WheelingWindowRefMousePos) >
g.IO.MouseDragThreshold *
g.IO.MouseDragThreshold)
9984 g.WheelingWindowReleaseTimer = 0.0f;
9985 if (
g.WheelingWindowReleaseTimer <= 0.0f)
9986 LockWheelingWindow(NULL, 0.0f);
9990 wheel.x = TestKeyOwner(ImGuiKey_MouseWheelX, ImGuiKeyOwner_NoOwner) ?
g.IO.MouseWheelH : 0.0f;
9991 wheel.y = TestKeyOwner(ImGuiKey_MouseWheelY, ImGuiKeyOwner_NoOwner) ?
g.IO.MouseWheel : 0.0f;
9994 ImGuiWindow* mouse_window =
g.WheelingWindow ?
g.WheelingWindow :
g.HoveredWindow;
9995 if (!mouse_window || mouse_window->Collapsed)
10000 if (wheel.y != 0.0f &&
g.IO.KeyCtrl &&
g.IO.FontAllowUserScaling)
10002 LockWheelingWindow(mouse_window, wheel.y);
10003 ImGuiWindow* window = mouse_window;
10004 const float new_font_scale = ImClamp(window->FontWindowScale +
g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
10005 const float scale = new_font_scale / window->FontWindowScale;
10006 window->FontWindowScale = new_font_scale;
10007 if (window == window->RootWindow)
10009 const ImVec2 offset = window->Size * (1.0f -
scale) * (
g.IO.MousePos - window->Pos) / window->Size;
10010 SetWindowPos(window, window->Pos + offset, 0);
10011 window->Size = ImTrunc(window->Size * scale);
10012 window->SizeFull = ImTrunc(window->SizeFull * scale);
10021 if (
g.IO.MouseWheelRequestAxisSwap)
10022 wheel = ImVec2(wheel.y, 0.0f);
10026 g.WheelingAxisAvg.x = ImExponentialMovingAverage(
g.WheelingAxisAvg.x, ImAbs(wheel.x), 30);
10027 g.WheelingAxisAvg.y = ImExponentialMovingAverage(
g.WheelingAxisAvg.y, ImAbs(wheel.y), 30);
10030 wheel +=
g.WheelingWindowWheelRemainder;
10031 g.WheelingWindowWheelRemainder = ImVec2(0.0f, 0.0f);
10032 if (wheel.x == 0.0f && wheel.y == 0.0f)
10038 if (ImGuiWindow* window = (
g.WheelingWindow ?
g.WheelingWindow : FindBestWheelingWindow(wheel)))
10039 if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))
10041 bool do_scroll[2] = { wheel.x != 0.0f && window->ScrollMax.x != 0.0f, wheel.y != 0.0f && window->ScrollMax.y != 0.0f };
10042 if (do_scroll[ImGuiAxis_X] && do_scroll[ImGuiAxis_Y])
10043 do_scroll[(
g.WheelingAxisAvg.x >
g.WheelingAxisAvg.y) ? ImGuiAxis_Y : ImGuiAxis_X] = false;
10044 if (do_scroll[ImGuiAxis_X])
10046 LockWheelingWindow(window, wheel.x);
10047 float max_step = window->InnerRect.GetWidth() * 0.67f;
10048 float scroll_step = ImTrunc(ImMin(2 * window->CalcFontSize(), max_step));
10049 SetScrollX(window, window->Scroll.x - wheel.x * scroll_step);
10050 g.WheelingWindowScrolledFrame =
g.FrameCount;
10052 if (do_scroll[ImGuiAxis_Y])
10054 LockWheelingWindow(window, wheel.y);
10055 float max_step = window->InnerRect.GetHeight() * 0.67f;
10056 float scroll_step = ImTrunc(ImMin(5 * window->CalcFontSize(), max_step));
10057 SetScrollY(window, window->Scroll.y - wheel.y * scroll_step);
10058 g.WheelingWindowScrolledFrame =
g.FrameCount;
10063void ImGui::SetNextFrameWantCaptureKeyboard(
bool want_capture_keyboard)
10066 g.WantCaptureKeyboardNextFrame = want_capture_keyboard ? 1 : 0;
10069void ImGui::SetNextFrameWantCaptureMouse(
bool want_capture_mouse)
10072 g.WantCaptureMouseNextFrame = want_capture_mouse ? 1 : 0;
10075#ifndef IMGUI_DISABLE_DEBUG_TOOLS
10076static const char* GetInputSourceName(ImGuiInputSource source)
10078 const char* input_source_names[] = {
"None",
"Mouse",
"Keyboard",
"Gamepad" };
10079 IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT && source >= 0 && source < ImGuiInputSource_COUNT);
10080 return input_source_names[source];
10082static const char* GetMouseSourceName(ImGuiMouseSource source)
10084 const char* mouse_source_names[] = {
"Mouse",
"TouchScreen",
"Pen" };
10085 IM_ASSERT(IM_ARRAYSIZE(mouse_source_names) == ImGuiMouseSource_COUNT && source >= 0 && source < ImGuiMouseSource_COUNT);
10086 return mouse_source_names[source];
10088static void DebugPrintInputEvent(
const char* prefix,
const ImGuiInputEvent* e)
10091 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; }
10092 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; }
10093 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; }
10094 if (
e->Type == ImGuiInputEventType_MouseViewport){IMGUI_DEBUG_LOG_IO(
"[io] %s: MouseViewport (0x%08X)\n", prefix,
e->MouseViewport.HoveredViewportID);
return; }
10095 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; }
10096 if (
e->Type == ImGuiInputEventType_Text) { IMGUI_DEBUG_LOG_IO(
"[io] %s: Text: %c (U+%08X)\n", prefix,
e->Text.Char,
e->Text.Char);
return; }
10097 if (
e->Type == ImGuiInputEventType_Focus) { IMGUI_DEBUG_LOG_IO(
"[io] %s: AppFocused %d\n", prefix,
e->AppFocused.Focused);
return; }
10105void ImGui::UpdateInputEvents(
bool trickle_fast_inputs)
10108 ImGuiIO& io =
g.IO;
10113 const bool trickle_interleaved_keys_and_text = (trickle_fast_inputs &&
g.WantTextInputNextFrame == 1);
10115 bool mouse_moved =
false, mouse_wheeled =
false, key_changed =
false, text_inputted =
false;
10116 int mouse_button_changed = 0x00;
10117 ImBitArray<ImGuiKey_KeysData_SIZE> key_changed_mask;
10120 for (; event_n <
g.InputEventsQueue.Size; event_n++)
10122 ImGuiInputEvent*
e = &
g.InputEventsQueue[event_n];
10123 if (
e->Type == ImGuiInputEventType_MousePos)
10125 if (
g.IO.WantSetMousePos)
10128 ImVec2 event_pos(
e->MousePos.PosX,
e->MousePos.PosY);
10129 if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || text_inputted))
10131 io.MousePos = event_pos;
10132 io.MouseSource =
e->MousePos.MouseSource;
10133 mouse_moved =
true;
10135 else if (
e->Type == ImGuiInputEventType_MouseButton)
10138 const ImGuiMouseButton button =
e->MouseButton.Button;
10139 IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT);
10140 if (trickle_fast_inputs && ((mouse_button_changed & (1 << button)) || mouse_wheeled))
10142 if (trickle_fast_inputs &&
e->MouseButton.MouseSource == ImGuiMouseSource_TouchScreen && mouse_moved)
10144 io.MouseDown[button] =
e->MouseButton.Down;
10145 io.MouseSource =
e->MouseButton.MouseSource;
10146 mouse_button_changed |= (1 << button);
10148 else if (
e->Type == ImGuiInputEventType_MouseWheel)
10151 if (trickle_fast_inputs && (mouse_moved || mouse_button_changed != 0))
10153 io.MouseWheelH +=
e->MouseWheel.WheelX;
10154 io.MouseWheel +=
e->MouseWheel.WheelY;
10155 io.MouseSource =
e->MouseWheel.MouseSource;
10156 mouse_wheeled =
true;
10158 else if (
e->Type == ImGuiInputEventType_MouseViewport)
10160 io.MouseHoveredViewport =
e->MouseViewport.HoveredViewportID;
10162 else if (
e->Type == ImGuiInputEventType_Key)
10165 ImGuiKey key =
e->Key.Key;
10166 IM_ASSERT(key != ImGuiKey_None);
10167 ImGuiKeyData* key_data = GetKeyData(key);
10168 const int key_data_index = (int)(key_data -
g.IO.KeysData);
10169 if (trickle_fast_inputs && key_data->Down !=
e->Key.Down && (key_changed_mask.TestBit(key_data_index) || text_inputted || mouse_button_changed != 0))
10171 key_data->Down =
e->Key.Down;
10172 key_data->AnalogValue =
e->Key.AnalogValue;
10173 key_changed =
true;
10174 key_changed_mask.SetBit(key_data_index);
10177#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
10178 io.KeysDown[key_data_index] = key_data->Down;
10179 if (io.KeyMap[key_data_index] != -1)
10180 io.KeysDown[io.KeyMap[key_data_index]] = key_data->Down;
10183 else if (
e->Type == ImGuiInputEventType_Text)
10186 if (trickle_fast_inputs && ((key_changed && trickle_interleaved_keys_and_text) || mouse_button_changed != 0 || mouse_moved || mouse_wheeled))
10188 unsigned int c =
e->Text.Char;
10189 io.InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID);
10190 if (trickle_interleaved_keys_and_text)
10191 text_inputted =
true;
10193 else if (
e->Type == ImGuiInputEventType_Focus)
10197 const bool focus_lost = !
e->AppFocused.Focused;
10198 io.AppFocusLost = focus_lost;
10202 IM_ASSERT(0 &&
"Unknown event!");
10208 for (
int n = 0; n < event_n; n++)
10209 g.InputEventsTrail.push_back(
g.InputEventsQueue[n]);
10212#ifndef IMGUI_DISABLE_DEBUG_TOOLS
10213 if (event_n != 0 && (
g.DebugLogFlags & ImGuiDebugLogFlags_EventIO))
10214 for (
int n = 0; n <
g.InputEventsQueue.Size; n++)
10215 DebugPrintInputEvent(n < event_n ?
"Processed" :
"Remaining", &
g.InputEventsQueue[n]);
10219 if (event_n ==
g.InputEventsQueue.Size)
10220 g.InputEventsQueue.resize(0);
10222 g.InputEventsQueue.erase(
g.InputEventsQueue.Data,
g.InputEventsQueue.Data + event_n);
10228 if (
g.IO.AppFocusLost)
10229 g.IO.ClearInputKeys();
10232ImGuiID ImGui::GetKeyOwner(ImGuiKey key)
10234 if (!IsNamedKeyOrMod(key))
10235 return ImGuiKeyOwner_NoOwner;
10238 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
10239 ImGuiID owner_id = owner_data->OwnerCurr;
10241 if (
g.ActiveIdUsingAllKeyboardKeys && owner_id !=
g.ActiveId && owner_id != ImGuiKeyOwner_Any)
10242 if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END)
10243 return ImGuiKeyOwner_NoOwner;
10252bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id)
10254 if (!IsNamedKeyOrMod(key))
10258 if (
g.ActiveIdUsingAllKeyboardKeys && owner_id !=
g.ActiveId && owner_id != ImGuiKeyOwner_Any)
10259 if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END)
10262 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
10263 if (owner_id == ImGuiKeyOwner_Any)
10264 return (owner_data->LockThisFrame ==
false);
10269 if (owner_data->OwnerCurr != owner_id)
10271 if (owner_data->LockThisFrame)
10273 if (owner_data->OwnerCurr != ImGuiKeyOwner_NoOwner)
10285void ImGui::SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags)
10288 IM_ASSERT(IsNamedKeyOrMod(key) && (owner_id != ImGuiKeyOwner_Any || (flags & (ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease))));
10289 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetKeyOwner) == 0);
10292 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
10293 owner_data->OwnerCurr = owner_data->OwnerNext = owner_id;
10297 owner_data->LockUntilRelease = (flags & ImGuiInputFlags_LockUntilRelease) != 0;
10298 owner_data->LockThisFrame = (flags & ImGuiInputFlags_LockThisFrame) != 0 || (owner_data->LockUntilRelease);
10302void ImGui::SetKeyOwnersForKeyChord(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
10304 if (key_chord & ImGuiMod_Ctrl) { SetKeyOwner(ImGuiMod_Ctrl, owner_id, flags); }
10305 if (key_chord & ImGuiMod_Shift) { SetKeyOwner(ImGuiMod_Shift, owner_id, flags); }
10306 if (key_chord & ImGuiMod_Alt) { SetKeyOwner(ImGuiMod_Alt, owner_id, flags); }
10307 if (key_chord & ImGuiMod_Super) { SetKeyOwner(ImGuiMod_Super, owner_id, flags); }
10308 if (key_chord & ~ImGuiMod_Mask_) { SetKeyOwner((ImGuiKey)(key_chord & ~ImGuiMod_Mask_), owner_id, flags); }
10317void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
10320 ImGuiID
id =
g.LastItemData.ID;
10321 if (
id == 0 || (
g.HoveredId !=
id &&
g.ActiveId !=
id))
10323 if ((flags & ImGuiInputFlags_CondMask_) == 0)
10324 flags |= ImGuiInputFlags_CondDefault_;
10325 if ((
g.HoveredId ==
id && (flags & ImGuiInputFlags_CondHovered)) || (
g.ActiveId ==
id && (flags & ImGuiInputFlags_CondActive)))
10327 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetItemKeyOwner) == 0);
10328 SetKeyOwner(key,
id, flags & ~ImGuiInputFlags_CondMask_);
10333bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord)
10335 return IsKeyChordPressed(key_chord, 0, ImGuiInputFlags_None);
10339bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id)
10342 key_chord = FixupKeyChord(key_chord);
10343 ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
10344 if (
g.IO.KeyMods != mods)
10348 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
10349 if (key == ImGuiKey_None)
10350 key = ConvertSingleModFlagToKey(mods);
10351 if (!IsKeyPressed(key, (flags & ImGuiInputFlags_RepeatMask_), owner_id))
10356void ImGui::SetNextItemShortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags)
10359 g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasShortcut;
10360 g.NextItemData.Shortcut = key_chord;
10361 g.NextItemData.ShortcutFlags = flags;
10364void ImGui::ItemHandleShortcut(ImGuiID
id)
10367 ImGuiInputFlags flags =
g.NextItemData.ShortcutFlags;
10368 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetNextItemShortcut) == 0);
10370 if (flags & ImGuiInputFlags_Tooltip)
10372 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasShortcut;
10373 g.LastItemData.Shortcut =
g.NextItemData.Shortcut;
10375 if (!Shortcut(
g.NextItemData.Shortcut, flags & ImGuiInputFlags_SupportedByShortcut,
id) ||
g.NavActivateId != 0)
10379 g.NavActivateId =
id;
10380 g.NavActivateFlags = ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_FromShortcut;
10382 g.NavActivateDownId =
g.NavActivatePressedId =
id;
10383 NavHighlightActivated(
id);
10386bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags)
10388 return Shortcut(key_chord, flags, ImGuiKeyOwner_Any);
10391bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id)
10397 if ((flags & ImGuiInputFlags_RouteTypeMask_) == 0)
10398 flags |= ImGuiInputFlags_RouteFocused;
10402 if (owner_id == ImGuiKeyOwner_Any || owner_id == ImGuiKeyOwner_NoOwner)
10403 owner_id = GetRoutingIdFromOwnerId(owner_id);
10406 if (!SetShortcutRouting(key_chord, flags, owner_id))
10411 if ((flags & ImGuiInputFlags_Repeat) != 0 && (flags & ImGuiInputFlags_RepeatUntilMask_) == 0)
10412 flags |= ImGuiInputFlags_RepeatUntilKeyModsChange;
10414 if (!IsKeyChordPressed(key_chord, flags, owner_id))
10418 SetKeyOwnersForKeyChord(key_chord & ImGuiMod_Mask_, owner_id);
10420 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByShortcut) == 0);
10439bool 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)
10441 bool error =
false;
10442 if (strcmp(version, IMGUI_VERSION) != 0) { error =
true; IM_ASSERT(strcmp(version, IMGUI_VERSION) == 0 &&
"Mismatched version string!"); }
10443 if (sz_io !=
sizeof(ImGuiIO)) { error =
true; IM_ASSERT(sz_io ==
sizeof(ImGuiIO) &&
"Mismatched struct layout!"); }
10444 if (sz_style !=
sizeof(ImGuiStyle)) { error =
true; IM_ASSERT(sz_style ==
sizeof(ImGuiStyle) &&
"Mismatched struct layout!"); }
10445 if (sz_vec2 !=
sizeof(ImVec2)) { error =
true; IM_ASSERT(sz_vec2 ==
sizeof(ImVec2) &&
"Mismatched struct layout!"); }
10446 if (sz_vec4 !=
sizeof(ImVec4)) { error =
true; IM_ASSERT(sz_vec4 ==
sizeof(ImVec4) &&
"Mismatched struct layout!"); }
10447 if (sz_vert !=
sizeof(ImDrawVert)) { error =
true; IM_ASSERT(sz_vert ==
sizeof(ImDrawVert) &&
"Mismatched struct layout!"); }
10448 if (sz_idx !=
sizeof(ImDrawIdx)) { error =
true; IM_ASSERT(sz_idx ==
sizeof(ImDrawIdx) &&
"Mismatched struct layout!"); }
10467void ImGui::ErrorCheckUsingSetCursorPosToExtendParentBoundaries()
10470 ImGuiWindow* window =
g.CurrentWindow;
10471 IM_ASSERT(window->DC.IsSetPos);
10472 window->DC.IsSetPos =
false;
10473#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
10474 if (window->DC.CursorPos.x <= window->DC.CursorMaxPos.x && window->DC.CursorPos.y <= window->DC.CursorMaxPos.y)
10476 if (window->SkipItems)
10478 IM_ASSERT(0 &&
"Code uses SetCursorPos()/SetCursorScreenPos() to extend window/parent boundaries. Please submit an item e.g. Dummy() to validate extent.");
10480 window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
10484static void ImGui::ErrorCheckNewFrameSanityChecks()
10494 if (
true) IM_ASSERT(1);
else IM_ASSERT(0);
10498#ifdef __EMSCRIPTEN__
10499 if (
g.IO.DeltaTime <= 0.0f &&
g.FrameCount > 0)
10500 g.IO.DeltaTime = 0.00001f;
10505 IM_ASSERT(
g.Initialized);
10506 IM_ASSERT((
g.IO.DeltaTime > 0.0f ||
g.FrameCount == 0) &&
"Need a positive DeltaTime!");
10507 IM_ASSERT((
g.FrameCount == 0 ||
g.FrameCountEnded ==
g.FrameCount) &&
"Forgot to call Render() or EndFrame() at the end of the previous frame?");
10508 IM_ASSERT(
g.IO.DisplaySize.x >= 0.0f &&
g.IO.DisplaySize.y >= 0.0f &&
"Invalid DisplaySize value!");
10509 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()");
10510 IM_ASSERT(
g.Style.CurveTessellationTol > 0.0f &&
"Invalid style setting!");
10511 IM_ASSERT(
g.Style.CircleTessellationMaxError > 0.0f &&
"Invalid style setting!");
10512 IM_ASSERT(
g.Style.Alpha >= 0.0f &&
g.Style.Alpha <= 1.0f &&
"Invalid style setting!");
10513 IM_ASSERT(
g.Style.WindowMinSize.x >= 1.0f &&
g.Style.WindowMinSize.y >= 1.0f &&
"Invalid style setting.");
10514 IM_ASSERT(
g.Style.WindowMenuButtonPosition == ImGuiDir_None ||
g.Style.WindowMenuButtonPosition == ImGuiDir_Left ||
g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
10515 IM_ASSERT(
g.Style.ColorButtonPosition == ImGuiDir_Left ||
g.Style.ColorButtonPosition == ImGuiDir_Right);
10516#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
10517 for (
int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_COUNT; n++)
10518 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)");
10521 if ((
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) &&
g.IO.BackendUsingLegacyKeyArrays == 1)
10522 IM_ASSERT(
g.IO.KeyMap[ImGuiKey_Space] != -1 &&
"ImGuiKey_Space is not mapped, required for keyboard navigation.");
10526 if (
g.IO.ConfigWindowsResizeFromEdges && !(
g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors))
10527 g.IO.ConfigWindowsResizeFromEdges =
false;
10530 if (
g.FrameCount == 1 && (
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable) && (
g.ConfigFlagsLastFrame & ImGuiConfigFlags_DockingEnable) == 0)
10531 IM_ASSERT(0 &&
"Please set DockingEnable before the first call to NewFrame()! Otherwise you will lose your .ini settings!");
10532 if (
g.FrameCount == 1 && (
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) && (
g.ConfigFlagsLastFrame & ImGuiConfigFlags_ViewportsEnable) == 0)
10533 IM_ASSERT(0 &&
"Please set ViewportsEnable before the first call to NewFrame()! Otherwise you will lose your .ini settings!");
10536 if (
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
10538 if ((
g.IO.BackendFlags & ImGuiBackendFlags_PlatformHasViewports) && (
g.IO.BackendFlags & ImGuiBackendFlags_RendererHasViewports))
10540 IM_ASSERT((
g.FrameCount == 0 ||
g.FrameCount ==
g.FrameCountPlatformEnded) &&
"Forgot to call UpdatePlatformWindows() in main loop after EndFrame()? Check examples/ applications for reference.");
10541 IM_ASSERT(
g.PlatformIO.Platform_CreateWindow != NULL &&
"Platform init didn't install handlers?");
10542 IM_ASSERT(
g.PlatformIO.Platform_DestroyWindow != NULL &&
"Platform init didn't install handlers?");
10543 IM_ASSERT(
g.PlatformIO.Platform_GetWindowPos != NULL &&
"Platform init didn't install handlers?");
10544 IM_ASSERT(
g.PlatformIO.Platform_SetWindowPos != NULL &&
"Platform init didn't install handlers?");
10545 IM_ASSERT(
g.PlatformIO.Platform_GetWindowSize != NULL &&
"Platform init didn't install handlers?");
10546 IM_ASSERT(
g.PlatformIO.Platform_SetWindowSize != NULL &&
"Platform init didn't install handlers?");
10547 IM_ASSERT(
g.PlatformIO.Monitors.Size > 0 &&
"Platform init didn't setup Monitors list?");
10548 IM_ASSERT((
g.Viewports[0]->PlatformUserData != NULL ||
g.Viewports[0]->PlatformHandle != NULL) &&
"Platform init didn't setup main viewport.");
10549 if (
g.IO.ConfigDockingTransparentPayload && (
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
10550 IM_ASSERT(
g.PlatformIO.Platform_SetWindowAlpha != NULL &&
"Platform_SetWindowAlpha handler is required to use io.ConfigDockingTransparent!");
10555 g.IO.ConfigFlags &= ~ImGuiConfigFlags_ViewportsEnable;
10559 for (ImGuiPlatformMonitor& mon :
g.PlatformIO.Monitors)
10562 IM_ASSERT(mon.MainSize.x > 0.0f && mon.MainSize.y > 0.0f &&
"Monitor main bounds not setup properly.");
10563 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.");
10564 IM_ASSERT(mon.DpiScale != 0.0f);
10569static void ImGui::ErrorCheckEndFrameSanityChecks()
10579 const ImGuiKeyChord key_mods = GetMergedModsFromKeys();
10580 IM_ASSERT((key_mods == 0 ||
g.IO.KeyMods == key_mods) &&
"Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
10581 IM_UNUSED(key_mods);
10588 if (
g.CurrentWindowStack.Size != 1)
10590 if (
g.CurrentWindowStack.Size > 1)
10592 ImGuiWindow* window =
g.CurrentWindowStack.back().Window;
10593 IM_ASSERT_USER_ERROR(
g.CurrentWindowStack.Size == 1,
"Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?");
10595 while (
g.CurrentWindowStack.Size > 1)
10600 IM_ASSERT_USER_ERROR(
g.CurrentWindowStack.Size == 1,
"Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?");
10604 IM_ASSERT_USER_ERROR(
g.GroupStack.Size == 0,
"Missing EndGroup call!");
10612void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback,
void* user_data)
10616 while (
g.CurrentWindowStack.Size > 0)
10618 ErrorCheckEndWindowRecover(log_callback, user_data);
10619 ImGuiWindow* window =
g.CurrentWindow;
10620 if (
g.CurrentWindowStack.Size == 1)
10622 IM_ASSERT(window->IsFallbackWindow);
10625 if (window->Flags & ImGuiWindowFlags_ChildWindow)
10627 if (log_callback) log_callback(user_data,
"Recovered from missing EndChild() for '%s'", window->Name);
10632 if (log_callback) log_callback(user_data,
"Recovered from missing End() for '%s'", window->Name);
10639void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback,
void* user_data)
10642 while (
g.CurrentTable && (
g.CurrentTable->OuterWindow ==
g.CurrentWindow ||
g.CurrentTable->InnerWindow ==
g.CurrentWindow))
10644 if (log_callback) log_callback(user_data,
"Recovered from missing EndTable() in '%s'",
g.CurrentTable->OuterWindow->Name);
10648 ImGuiWindow* window =
g.CurrentWindow;
10649 ImGuiStackSizes* stack_sizes = &
g.CurrentWindowStack.back().StackSizesOnBegin;
10650 IM_ASSERT(window != NULL);
10651 while (
g.CurrentTabBar != NULL)
10653 if (log_callback) log_callback(user_data,
"Recovered from missing EndTabBar() in '%s'", window->Name);
10656 while (window->DC.TreeDepth > 0)
10658 if (log_callback) log_callback(user_data,
"Recovered from missing TreePop() in '%s'", window->Name);
10661 while (
g.GroupStack.Size > stack_sizes->SizeOfGroupStack)
10663 if (log_callback) log_callback(user_data,
"Recovered from missing EndGroup() in '%s'", window->Name);
10666 while (window->IDStack.Size > 1)
10668 if (log_callback) log_callback(user_data,
"Recovered from missing PopID() in '%s'", window->Name);
10671 while (
g.DisabledStackSize > stack_sizes->SizeOfDisabledStack)
10673 if (log_callback) log_callback(user_data,
"Recovered from missing EndDisabled() in '%s'", window->Name);
10676 while (
g.ColorStack.Size > stack_sizes->SizeOfColorStack)
10678 if (log_callback) log_callback(user_data,
"Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s", window->Name, GetStyleColorName(
g.ColorStack.back().Col));
10681 while (
g.ItemFlagsStack.Size > stack_sizes->SizeOfItemFlagsStack)
10683 if (log_callback) log_callback(user_data,
"Recovered from missing PopItemFlag() in '%s'", window->Name);
10686 while (
g.StyleVarStack.Size > stack_sizes->SizeOfStyleVarStack)
10688 if (log_callback) log_callback(user_data,
"Recovered from missing PopStyleVar() in '%s'", window->Name);
10691 while (
g.FontStack.Size > stack_sizes->SizeOfFontStack)
10693 if (log_callback) log_callback(user_data,
"Recovered from missing PopFont() in '%s'", window->Name);
10696 while (
g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack + 1)
10698 if (log_callback) log_callback(user_data,
"Recovered from missing PopFocusScope() in '%s'", window->Name);
10704void ImGuiStackSizes::SetToContextState(ImGuiContext* ctx)
10706 ImGuiContext&
g = *ctx;
10707 ImGuiWindow* window =
g.CurrentWindow;
10708 SizeOfIDStack = (short)window->IDStack.Size;
10709 SizeOfColorStack = (short)
g.ColorStack.Size;
10710 SizeOfStyleVarStack = (short)
g.StyleVarStack.Size;
10711 SizeOfFontStack = (short)
g.FontStack.Size;
10712 SizeOfFocusScopeStack = (short)
g.FocusScopeStack.Size;
10713 SizeOfGroupStack = (short)
g.GroupStack.Size;
10714 SizeOfItemFlagsStack = (short)
g.ItemFlagsStack.Size;
10715 SizeOfBeginPopupStack = (short)
g.BeginPopupStack.Size;
10716 SizeOfDisabledStack = (short)
g.DisabledStackSize;
10720void ImGuiStackSizes::CompareWithContextState(ImGuiContext* ctx)
10722 ImGuiContext&
g = *ctx;
10723 ImGuiWindow* window =
g.CurrentWindow;
10728 IM_ASSERT(SizeOfIDStack == window->IDStack.Size &&
"PushID/PopID or TreeNode/TreePop Mismatch!");
10732 IM_ASSERT(SizeOfGroupStack ==
g.GroupStack.Size &&
"BeginGroup/EndGroup Mismatch!");
10733 IM_ASSERT(SizeOfBeginPopupStack ==
g.BeginPopupStack.Size &&
"BeginPopup/EndPopup or BeginMenu/EndMenu Mismatch!");
10734 IM_ASSERT(SizeOfDisabledStack ==
g.DisabledStackSize &&
"BeginDisabled/EndDisabled Mismatch!");
10735 IM_ASSERT(SizeOfItemFlagsStack >=
g.ItemFlagsStack.Size &&
"PushItemFlag/PopItemFlag Mismatch!");
10736 IM_ASSERT(SizeOfColorStack >=
g.ColorStack.Size &&
"PushStyleColor/PopStyleColor Mismatch!");
10737 IM_ASSERT(SizeOfStyleVarStack >=
g.StyleVarStack.Size &&
"PushStyleVar/PopStyleVar Mismatch!");
10738 IM_ASSERT(SizeOfFontStack >=
g.FontStack.Size &&
"PushFont/PopFont Mismatch!");
10739 IM_ASSERT(SizeOfFocusScopeStack ==
g.FocusScopeStack.Size &&
"PushFocusScope/PopFocusScope Mismatch!");
10750void ImGui::KeepAliveID(ImGuiID
id)
10753 if (
g.ActiveId ==
id)
10754 g.ActiveIdIsAlive =
id;
10755 if (
g.ActiveIdPreviousFrame ==
id)
10756 g.ActiveIdPreviousFrameIsAlive =
true;
10763bool ImGui::ItemAdd(
const ImRect& bb, ImGuiID
id,
const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags)
10766 ImGuiWindow* window =
g.CurrentWindow;
10770 g.LastItemData.ID =
id;
10771 g.LastItemData.Rect = bb;
10772 g.LastItemData.NavRect = nav_bb_arg ? *nav_bb_arg : bb;
10773 g.LastItemData.InFlags =
g.CurrentItemFlags |
g.NextItemData.ItemFlags | extra_flags;
10774 g.LastItemData.StatusFlags = ImGuiItemStatusFlags_None;
10791 if (!(
g.LastItemData.InFlags & ImGuiItemFlags_NoNav))
10794 window->DC.NavLayersActiveMaskNext |= (1 << window->DC.NavLayerCurrent);
10795 if (
g.NavId ==
id ||
g.NavAnyRequest)
10796 if (
g.NavWindow->RootWindowForNav == window->RootWindowForNav)
10797 if (window ==
g.NavWindow || ((window->Flags |
g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened))
10801 if (
g.NextItemData.Flags & ImGuiNextItemDataFlags_HasShortcut)
10802 ItemHandleShortcut(
id);
10806 g.NextItemData.Flags = ImGuiNextItemDataFlags_None;
10807 g.NextItemData.ItemFlags = ImGuiItemFlags_None;
10809#ifdef IMGUI_ENABLE_TEST_ENGINE
10811 IMGUI_TEST_ENGINE_ITEM_ADD(
id,
g.LastItemData.NavRect, &
g.LastItemData);
10820 const bool is_rect_visible = bb.Overlaps(window->ClipRect);
10821 if (!is_rect_visible)
10822 if (
id == 0 || (
id !=
g.ActiveId &&
id !=
g.ActiveIdPreviousFrame &&
id !=
g.NavId &&
id !=
g.NavActivateId))
10827#ifndef IMGUI_DISABLE_DEBUG_TOOLS
10830 if (
id ==
g.DebugLocateId)
10831 DebugLocateItemResolveWithLastItem();
10836 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!");
10844 if (is_rect_visible)
10845 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Visible;
10846 if (IsMouseHoveringRect(bb.Min, bb.Max))
10847 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect;
10887void ImGui::ItemSize(
const ImVec2& size,
float text_baseline_y)
10890 ImGuiWindow* window =
g.CurrentWindow;
10891 if (window->SkipItems)
10897 const float offset_to_match_baseline_y = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f;
10899 const float line_y1 = window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y;
10900 const float line_height = ImMax(window->DC.CurrLineSize.y, window->DC.CursorPos.y - line_y1 +
size.y + offset_to_match_baseline_y);
10904 window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x +
size.x;
10905 window->DC.CursorPosPrevLine.y = line_y1;
10906 window->DC.CursorPos.x = IM_TRUNC(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
10907 window->DC.CursorPos.y = IM_TRUNC(line_y1 + line_height +
g.Style.ItemSpacing.y);
10908 window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
10909 window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y -
g.Style.ItemSpacing.y);
10912 window->DC.PrevLineSize.y = line_height;
10913 window->DC.CurrLineSize.y = 0.0f;
10914 window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y);
10915 window->DC.CurrLineTextBaseOffset = 0.0f;
10916 window->DC.IsSameLine = window->DC.IsSetPos =
false;
10919 if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
10928void ImGui::SameLine(
float offset_from_start_x,
float spacing_w)
10931 ImGuiWindow* window =
g.CurrentWindow;
10932 if (window->SkipItems)
10935 if (offset_from_start_x != 0.0f)
10937 if (spacing_w < 0.0f)
10939 window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + offset_from_start_x + spacing_w + window->DC.GroupOffset.x + window->DC.ColumnsOffset.x;
10940 window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
10944 if (spacing_w < 0.0f)
10945 spacing_w =
g.Style.ItemSpacing.x;
10946 window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w;
10947 window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
10949 window->DC.CurrLineSize = window->DC.PrevLineSize;
10950 window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
10951 window->DC.IsSameLine =
true;
10954ImVec2 ImGui::GetCursorScreenPos()
10956 ImGuiWindow* window = GetCurrentWindowRead();
10957 return window->DC.CursorPos;
10960void ImGui::SetCursorScreenPos(
const ImVec2& pos)
10962 ImGuiWindow* window = GetCurrentWindow();
10963 window->DC.CursorPos = pos;
10965 window->DC.IsSetPos =
true;
10970ImVec2 ImGui::GetCursorPos()
10972 ImGuiWindow* window = GetCurrentWindowRead();
10973 return window->DC.CursorPos - window->Pos + window->Scroll;
10976float ImGui::GetCursorPosX()
10978 ImGuiWindow* window = GetCurrentWindowRead();
10979 return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x;
10982float ImGui::GetCursorPosY()
10984 ImGuiWindow* window = GetCurrentWindowRead();
10985 return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y;
10988void ImGui::SetCursorPos(
const ImVec2& local_pos)
10990 ImGuiWindow* window = GetCurrentWindow();
10991 window->DC.CursorPos = window->Pos - window->Scroll + local_pos;
10993 window->DC.IsSetPos =
true;
10996void ImGui::SetCursorPosX(
float x)
10998 ImGuiWindow* window = GetCurrentWindow();
10999 window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x;
11001 window->DC.IsSetPos =
true;
11004void ImGui::SetCursorPosY(
float y)
11006 ImGuiWindow* window = GetCurrentWindow();
11007 window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y;
11009 window->DC.IsSetPos =
true;
11012ImVec2 ImGui::GetCursorStartPos()
11014 ImGuiWindow* window = GetCurrentWindowRead();
11015 return window->DC.CursorStartPos - window->Pos;
11018void ImGui::Indent(
float indent_w)
11021 ImGuiWindow* window = GetCurrentWindow();
11022 window->DC.Indent.x += (indent_w != 0.0f) ? indent_w :
g.Style.IndentSpacing;
11023 window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
11026void ImGui::Unindent(
float indent_w)
11029 ImGuiWindow* window = GetCurrentWindow();
11030 window->DC.Indent.x -= (indent_w != 0.0f) ? indent_w :
g.Style.IndentSpacing;
11031 window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
11035void ImGui::SetNextItemWidth(
float item_width)
11038 g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasWidth;
11039 g.NextItemData.Width = item_width;
11043void ImGui::PushItemWidth(
float item_width)
11046 ImGuiWindow* window =
g.CurrentWindow;
11047 window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);
11048 window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);
11049 g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
11052void ImGui::PushMultiItemsWidths(
int components,
float w_full)
11055 ImGuiWindow* window =
g.CurrentWindow;
11056 IM_ASSERT(components > 0);
11057 const ImGuiStyle& style =
g.Style;
11058 window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);
11059 float w_items = w_full - style.ItemInnerSpacing.x * (components - 1);
11060 float prev_split = w_items;
11061 for (
int i = components - 1; i > 0; i--)
11063 float next_split = IM_TRUNC(w_items * i / components);
11064 window->DC.ItemWidthStack.push_back(ImMax(prev_split - next_split, 1.0f));
11065 prev_split = next_split;
11067 window->DC.ItemWidth = ImMax(prev_split, 1.0f);
11068 g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
11071void ImGui::PopItemWidth()
11073 ImGuiWindow* window = GetCurrentWindow();
11074 window->DC.ItemWidth = window->DC.ItemWidthStack.back();
11075 window->DC.ItemWidthStack.pop_back();
11080float ImGui::CalcItemWidth()
11083 ImGuiWindow* window =
g.CurrentWindow;
11085 if (
g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth)
11086 w =
g.NextItemData.Width;
11088 w = window->DC.ItemWidth;
11091 float region_max_x = GetContentRegionMaxAbs().x;
11092 w = ImMax(1.0f, region_max_x - window->DC.CursorPos.x + w);
11102ImVec2 ImGui::CalcItemSize(ImVec2 size,
float default_w,
float default_h)
11105 ImGuiWindow* window =
g.CurrentWindow;
11108 if (
size.x < 0.0f ||
size.y < 0.0f)
11109 region_max = GetContentRegionMaxAbs();
11111 if (
size.x == 0.0f)
11112 size.x = default_w;
11113 else if (
size.x < 0.0f)
11114 size.x = ImMax(4.0f, region_max.x - window->DC.CursorPos.x +
size.x);
11116 if (
size.y == 0.0f)
11117 size.y = default_h;
11118 else if (
size.y < 0.0f)
11119 size.y = ImMax(4.0f, region_max.y - window->DC.CursorPos.y +
size.y);
11124float ImGui::GetTextLineHeight()
11130float ImGui::GetTextLineHeightWithSpacing()
11133 return g.FontSize +
g.Style.ItemSpacing.y;
11136float ImGui::GetFrameHeight()
11139 return g.FontSize +
g.Style.FramePadding.y * 2.0f;
11142float ImGui::GetFrameHeightWithSpacing()
11145 return g.FontSize +
g.Style.FramePadding.y * 2.0f +
g.Style.ItemSpacing.y;
11151ImVec2 ImGui::GetContentRegionMax()
11154 ImGuiWindow* window =
g.CurrentWindow;
11155 ImVec2 mx = (window->DC.CurrentColumns ||
g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max;
11156 return mx - window->Pos;
11160ImVec2 ImGui::GetContentRegionMaxAbs()
11163 ImGuiWindow* window =
g.CurrentWindow;
11164 ImVec2 mx = (window->DC.CurrentColumns ||
g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max;
11168ImVec2 ImGui::GetContentRegionAvail()
11170 ImGuiWindow* window =
GImGui->CurrentWindow;
11171 return GetContentRegionMaxAbs() - window->DC.CursorPos;
11175ImVec2 ImGui::GetWindowContentRegionMin()
11177 ImGuiWindow* window =
GImGui->CurrentWindow;
11178 return window->ContentRegionRect.Min - window->Pos;
11181ImVec2 ImGui::GetWindowContentRegionMax()
11183 ImGuiWindow* window =
GImGui->CurrentWindow;
11184 return window->ContentRegionRect.Max - window->Pos;
11190void ImGui::BeginGroup()
11193 ImGuiWindow* window =
g.CurrentWindow;
11195 g.GroupStack.resize(
g.GroupStack.Size + 1);
11196 ImGuiGroupData& group_data =
g.GroupStack.back();
11197 group_data.WindowID = window->ID;
11198 group_data.BackupCursorPos = window->DC.CursorPos;
11199 group_data.BackupCursorPosPrevLine = window->DC.CursorPosPrevLine;
11200 group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
11201 group_data.BackupIndent = window->DC.Indent;
11202 group_data.BackupGroupOffset = window->DC.GroupOffset;
11203 group_data.BackupCurrLineSize = window->DC.CurrLineSize;
11204 group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset;
11205 group_data.BackupActiveIdIsAlive =
g.ActiveIdIsAlive;
11206 group_data.BackupHoveredIdIsAlive =
g.HoveredId != 0;
11207 group_data.BackupIsSameLine = window->DC.IsSameLine;
11208 group_data.BackupActiveIdPreviousFrameIsAlive =
g.ActiveIdPreviousFrameIsAlive;
11209 group_data.EmitItem =
true;
11211 window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
11212 window->DC.Indent = window->DC.GroupOffset;
11213 window->DC.CursorMaxPos = window->DC.CursorPos;
11214 window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
11216 g.LogLinePosY = -FLT_MAX;
11219void ImGui::EndGroup()
11222 ImGuiWindow* window =
g.CurrentWindow;
11223 IM_ASSERT(
g.GroupStack.Size > 0);
11225 ImGuiGroupData& group_data =
g.GroupStack.back();
11226 IM_ASSERT(group_data.WindowID == window->ID);
11228 if (window->DC.IsSetPos)
11229 ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
11231 ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos));
11233 window->DC.CursorPos = group_data.BackupCursorPos;
11234 window->DC.CursorPosPrevLine = group_data.BackupCursorPosPrevLine;
11235 window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos);
11236 window->DC.Indent = group_data.BackupIndent;
11237 window->DC.GroupOffset = group_data.BackupGroupOffset;
11238 window->DC.CurrLineSize = group_data.BackupCurrLineSize;
11239 window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset;
11240 window->DC.IsSameLine = group_data.BackupIsSameLine;
11242 g.LogLinePosY = -FLT_MAX;
11244 if (!group_data.EmitItem)
11246 g.GroupStack.pop_back();
11250 window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset);
11251 ItemSize(group_bb.GetSize());
11252 ItemAdd(group_bb, 0, NULL, ImGuiItemFlags_NoTabStop);
11258 const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive !=
g.ActiveId) && (
g.ActiveIdIsAlive ==
g.ActiveId) &&
g.ActiveId;
11259 const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive ==
false) && (
g.ActiveIdPreviousFrameIsAlive ==
true);
11260 if (group_contains_curr_active_id)
11261 g.LastItemData.ID =
g.ActiveId;
11262 else if (group_contains_prev_active_id)
11263 g.LastItemData.ID =
g.ActiveIdPreviousFrame;
11264 g.LastItemData.Rect = group_bb;
11267 const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive ==
false) &&
g.HoveredId != 0;
11268 if (group_contains_curr_hovered_id)
11269 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
11272 if (group_contains_curr_active_id &&
g.ActiveIdHasBeenEditedThisFrame)
11273 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
11276 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated;
11277 if (group_contains_prev_active_id &&
g.ActiveId !=
g.ActiveIdPreviousFrame)
11278 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated;
11280 g.GroupStack.pop_back();
11281 if (
g.DebugShowGroupRects)
11282 window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255));
11294static float CalcScrollEdgeSnap(
float target,
float snap_min,
float snap_max,
float snap_threshold,
float center_ratio)
11296 if (target <= snap_min + snap_threshold)
11297 return ImLerp(snap_min, target, center_ratio);
11298 if (target >= snap_max - snap_threshold)
11299 return ImLerp(target, snap_max, center_ratio);
11303static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window)
11305 ImVec2 scroll = window->Scroll;
11306 ImVec2 decoration_size(window->DecoOuterSizeX1 + window->DecoInnerSizeX1 + window->DecoOuterSizeX2, window->DecoOuterSizeY1 + window->DecoInnerSizeY1 + window->DecoOuterSizeY2);
11307 for (
int axis = 0; axis < 2; axis++)
11309 if (window->ScrollTarget[axis] < FLT_MAX)
11311 float center_ratio = window->ScrollTargetCenterRatio[axis];
11312 float scroll_target = window->ScrollTarget[axis];
11313 if (window->ScrollTargetEdgeSnapDist[axis] > 0.0f)
11315 float snap_min = 0.0f;
11316 float snap_max = window->ScrollMax[axis] + window->SizeFull[axis] - decoration_size[axis];
11317 scroll_target = CalcScrollEdgeSnap(scroll_target, snap_min, snap_max, window->ScrollTargetEdgeSnapDist[axis], center_ratio);
11319 scroll[axis] = scroll_target - center_ratio * (window->SizeFull[axis] - decoration_size[axis]);
11321 scroll[axis] = IM_ROUND(ImMax(scroll[axis], 0.0f));
11322 if (!window->Collapsed && !window->SkipItems)
11323 scroll[axis] = ImMin(scroll[axis], window->ScrollMax[axis]);
11328void ImGui::ScrollToItem(ImGuiScrollFlags flags)
11331 ImGuiWindow* window =
g.CurrentWindow;
11332 ScrollToRectEx(window,
g.LastItemData.NavRect, flags);
11335void ImGui::ScrollToRect(ImGuiWindow* window,
const ImRect& item_rect, ImGuiScrollFlags flags)
11337 ScrollToRectEx(window, item_rect, flags);
11341ImVec2 ImGui::ScrollToRectEx(ImGuiWindow* window,
const ImRect& item_rect, ImGuiScrollFlags flags)
11344 ImRect scroll_rect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1));
11345 scroll_rect.Min.x = ImMin(scroll_rect.Min.x + window->DecoInnerSizeX1, scroll_rect.Max.x);
11346 scroll_rect.Min.y = ImMin(scroll_rect.Min.y + window->DecoInnerSizeY1, scroll_rect.Max.y);
11351 IM_ASSERT((flags & ImGuiScrollFlags_MaskX_) == 0 || ImIsPowerOfTwo(flags & ImGuiScrollFlags_MaskX_));
11352 IM_ASSERT((flags & ImGuiScrollFlags_MaskY_) == 0 || ImIsPowerOfTwo(flags & ImGuiScrollFlags_MaskY_));
11355 ImGuiScrollFlags in_flags = flags;
11356 if ((flags & ImGuiScrollFlags_MaskX_) == 0 && window->ScrollbarX)
11357 flags |= ImGuiScrollFlags_KeepVisibleEdgeX;
11358 if ((flags & ImGuiScrollFlags_MaskY_) == 0)
11359 flags |= window->Appearing ? ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeY;
11361 const bool fully_visible_x = item_rect.Min.x >= scroll_rect.Min.x && item_rect.Max.x <= scroll_rect.Max.x;
11362 const bool fully_visible_y = item_rect.Min.y >= scroll_rect.Min.y && item_rect.Max.y <= scroll_rect.Max.y;
11363 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;
11364 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;
11366 if ((flags & ImGuiScrollFlags_KeepVisibleEdgeX) && !fully_visible_x)
11368 if (item_rect.Min.x < scroll_rect.Min.x || !can_be_fully_visible_x)
11369 SetScrollFromPosX(window, item_rect.Min.x -
g.Style.ItemSpacing.x - window->Pos.x, 0.0f);
11370 else if (item_rect.Max.x >= scroll_rect.Max.x)
11371 SetScrollFromPosX(window, item_rect.Max.x +
g.Style.ItemSpacing.x - window->Pos.x, 1.0f);
11373 else if (((flags & ImGuiScrollFlags_KeepVisibleCenterX) && !fully_visible_x) || (flags & ImGuiScrollFlags_AlwaysCenterX))
11375 if (can_be_fully_visible_x)
11376 SetScrollFromPosX(window, ImTrunc((item_rect.Min.x + item_rect.Max.x) * 0.5f) - window->Pos.x, 0.5f);
11378 SetScrollFromPosX(window, item_rect.Min.x - window->Pos.x, 0.0f);
11381 if ((flags & ImGuiScrollFlags_KeepVisibleEdgeY) && !fully_visible_y)
11383 if (item_rect.Min.y < scroll_rect.Min.y || !can_be_fully_visible_y)
11384 SetScrollFromPosY(window, item_rect.Min.y -
g.Style.ItemSpacing.y - window->Pos.y, 0.0f);
11385 else if (item_rect.Max.y >= scroll_rect.Max.y)
11386 SetScrollFromPosY(window, item_rect.Max.y +
g.Style.ItemSpacing.y - window->Pos.y, 1.0f);
11388 else if (((flags & ImGuiScrollFlags_KeepVisibleCenterY) && !fully_visible_y) || (flags & ImGuiScrollFlags_AlwaysCenterY))
11390 if (can_be_fully_visible_y)
11391 SetScrollFromPosY(window, ImTrunc((item_rect.Min.y + item_rect.Max.y) * 0.5f) - window->Pos.y, 0.5f);
11393 SetScrollFromPosY(window, item_rect.Min.y - window->Pos.y, 0.0f);
11396 ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
11397 ImVec2 delta_scroll = next_scroll - window->Scroll;
11400 if (!(flags & ImGuiScrollFlags_NoScrollParent) && (window->Flags & ImGuiWindowFlags_ChildWindow))
11403 if ((in_flags & (ImGuiScrollFlags_AlwaysCenterX | ImGuiScrollFlags_KeepVisibleCenterX)) != 0)
11404 in_flags = (in_flags & ~ImGuiScrollFlags_MaskX_) | ImGuiScrollFlags_KeepVisibleEdgeX;
11405 if ((in_flags & (ImGuiScrollFlags_AlwaysCenterY | ImGuiScrollFlags_KeepVisibleCenterY)) != 0)
11406 in_flags = (in_flags & ~ImGuiScrollFlags_MaskY_) | ImGuiScrollFlags_KeepVisibleEdgeY;
11407 delta_scroll += ScrollToRectEx(window->ParentWindow, ImRect(item_rect.Min - delta_scroll, item_rect.Max - delta_scroll), in_flags);
11410 return delta_scroll;
11413float ImGui::GetScrollX()
11415 ImGuiWindow* window =
GImGui->CurrentWindow;
11416 return window->Scroll.x;
11419float ImGui::GetScrollY()
11421 ImGuiWindow* window =
GImGui->CurrentWindow;
11422 return window->Scroll.y;
11425float ImGui::GetScrollMaxX()
11427 ImGuiWindow* window =
GImGui->CurrentWindow;
11428 return window->ScrollMax.x;
11431float ImGui::GetScrollMaxY()
11433 ImGuiWindow* window =
GImGui->CurrentWindow;
11434 return window->ScrollMax.y;
11437void ImGui::SetScrollX(ImGuiWindow* window,
float scroll_x)
11439 window->ScrollTarget.x = scroll_x;
11440 window->ScrollTargetCenterRatio.x = 0.0f;
11441 window->ScrollTargetEdgeSnapDist.x = 0.0f;
11444void ImGui::SetScrollY(ImGuiWindow* window,
float scroll_y)
11446 window->ScrollTarget.y = scroll_y;
11447 window->ScrollTargetCenterRatio.y = 0.0f;
11448 window->ScrollTargetEdgeSnapDist.y = 0.0f;
11451void ImGui::SetScrollX(
float scroll_x)
11454 SetScrollX(
g.CurrentWindow, scroll_x);
11457void ImGui::SetScrollY(
float scroll_y)
11460 SetScrollY(
g.CurrentWindow, scroll_y);
11473void ImGui::SetScrollFromPosX(ImGuiWindow* window,
float local_x,
float center_x_ratio)
11475 IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f);
11476 window->ScrollTarget.x = IM_TRUNC(local_x - window->DecoOuterSizeX1 - window->DecoInnerSizeX1 + window->Scroll.x);
11477 window->ScrollTargetCenterRatio.x = center_x_ratio;
11478 window->ScrollTargetEdgeSnapDist.x = 0.0f;
11481void ImGui::SetScrollFromPosY(ImGuiWindow* window,
float local_y,
float center_y_ratio)
11483 IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f);
11484 window->ScrollTarget.y = IM_TRUNC(local_y - window->DecoOuterSizeY1 - window->DecoInnerSizeY1 + window->Scroll.y);
11485 window->ScrollTargetCenterRatio.y = center_y_ratio;
11486 window->ScrollTargetEdgeSnapDist.y = 0.0f;
11489void ImGui::SetScrollFromPosX(
float local_x,
float center_x_ratio)
11492 SetScrollFromPosX(
g.CurrentWindow, local_x, center_x_ratio);
11495void ImGui::SetScrollFromPosY(
float local_y,
float center_y_ratio)
11498 SetScrollFromPosY(
g.CurrentWindow, local_y, center_y_ratio);
11502void ImGui::SetScrollHereX(
float center_x_ratio)
11505 ImGuiWindow* window =
g.CurrentWindow;
11506 float spacing_x = ImMax(window->WindowPadding.x,
g.Style.ItemSpacing.x);
11507 float target_pos_x = ImLerp(
g.LastItemData.Rect.Min.x - spacing_x,
g.LastItemData.Rect.Max.x + spacing_x, center_x_ratio);
11508 SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio);
11511 window->ScrollTargetEdgeSnapDist.x = ImMax(0.0f, window->WindowPadding.x - spacing_x);
11515void ImGui::SetScrollHereY(
float center_y_ratio)
11518 ImGuiWindow* window =
g.CurrentWindow;
11519 float spacing_y = ImMax(window->WindowPadding.y,
g.Style.ItemSpacing.y);
11520 float target_pos_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y, window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y, center_y_ratio);
11521 SetScrollFromPosY(window, target_pos_y - window->Pos.y, center_y_ratio);
11524 window->ScrollTargetEdgeSnapDist.y = ImMax(0.0f, window->WindowPadding.y - spacing_y);
11531bool ImGui::BeginTooltip()
11533 return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None);
11536bool ImGui::BeginItemTooltip()
11538 if (!IsItemHovered(ImGuiHoveredFlags_ForTooltip))
11540 return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None);
11543bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags)
11547 if (
g.DragDropWithinSource ||
g.DragDropWithinTarget)
11555 ImVec2 tooltip_pos =
g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET *
g.Style.MouseCursorScale;
11556 SetNextWindowPos(tooltip_pos);
11557 SetNextWindowBgAlpha(
g.Style.Colors[ImGuiCol_PopupBg].w * 0.60f);
11559 tooltip_flags |= ImGuiTooltipFlags_OverridePrevious;
11562 char window_name[16];
11563 ImFormatString(window_name, IM_ARRAYSIZE(window_name),
"##Tooltip_%02d",
g.TooltipOverrideCount);
11564 if (tooltip_flags & ImGuiTooltipFlags_OverridePrevious)
11565 if (ImGuiWindow* window = FindWindowByName(window_name))
11566 if (window->Active)
11569 SetWindowHiddenAndSkipItemsForCurrentFrame(window);
11570 ImFormatString(window_name, IM_ARRAYSIZE(window_name),
"##Tooltip_%02d", ++
g.TooltipOverrideCount);
11572 ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDocking;
11573 Begin(window_name, NULL, flags | extra_window_flags);
11582void ImGui::EndTooltip()
11584 IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip);
11588void ImGui::SetTooltip(
const char* fmt, ...)
11591 va_start(args, fmt);
11592 SetTooltipV(fmt, args);
11596void ImGui::SetTooltipV(
const char* fmt, va_list args)
11598 if (!BeginTooltipEx(ImGuiTooltipFlags_OverridePrevious, ImGuiWindowFlags_None))
11606void ImGui::SetItemTooltip(
const char* fmt, ...)
11609 va_start(args, fmt);
11610 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip))
11611 SetTooltipV(fmt, args);
11615void ImGui::SetItemTooltipV(
const char* fmt, va_list args)
11617 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip))
11618 SetTooltipV(fmt, args);
11627bool ImGui::IsPopupOpen(ImGuiID
id, ImGuiPopupFlags popup_flags)
11630 if (popup_flags & ImGuiPopupFlags_AnyPopupId)
11634 IM_ASSERT(
id == 0);
11635 if (popup_flags & ImGuiPopupFlags_AnyPopupLevel)
11636 return g.OpenPopupStack.Size > 0;
11638 return g.OpenPopupStack.Size >
g.BeginPopupStack.Size;
11642 if (popup_flags & ImGuiPopupFlags_AnyPopupLevel)
11645 for (ImGuiPopupData& popup_data :
g.OpenPopupStack)
11646 if (popup_data.PopupId ==
id)
11653 return g.OpenPopupStack.Size >
g.BeginPopupStack.Size &&
g.OpenPopupStack[
g.BeginPopupStack.Size].PopupId ==
id;
11658bool ImGui::IsPopupOpen(
const char* str_id, ImGuiPopupFlags popup_flags)
11661 ImGuiID
id = (popup_flags & ImGuiPopupFlags_AnyPopupId) ? 0 :
g.CurrentWindow->GetID(str_id);
11662 if ((popup_flags & ImGuiPopupFlags_AnyPopupLevel) &&
id != 0)
11663 IM_ASSERT(0 &&
"Cannot use IsPopupOpen() with a string id and ImGuiPopupFlags_AnyPopupLevel.");
11664 return IsPopupOpen(
id, popup_flags);
11668ImGuiWindow* ImGui::GetTopMostPopupModal()
11671 for (
int n =
g.OpenPopupStack.Size - 1; n >= 0; n--)
11672 if (ImGuiWindow* popup =
g.OpenPopupStack.Data[n].Window)
11673 if (popup->Flags & ImGuiWindowFlags_Modal)
11679ImGuiWindow* ImGui::GetTopMostAndVisiblePopupModal()
11682 for (
int n =
g.OpenPopupStack.Size - 1; n >= 0; n--)
11683 if (ImGuiWindow* popup =
g.OpenPopupStack.Data[n].Window)
11684 if ((popup->Flags & ImGuiWindowFlags_Modal) && IsWindowActiveAndVisible(popup))
11689void ImGui::OpenPopup(
const char* str_id, ImGuiPopupFlags popup_flags)
11692 ImGuiID
id =
g.CurrentWindow->GetID(str_id);
11693 IMGUI_DEBUG_LOG_POPUP(
"[popup] OpenPopup(\"%s\" -> 0x%08X)\n", str_id,
id);
11694 OpenPopupEx(
id, popup_flags);
11697void ImGui::OpenPopup(ImGuiID
id, ImGuiPopupFlags popup_flags)
11699 OpenPopupEx(
id, popup_flags);
11706void ImGui::OpenPopupEx(ImGuiID
id, ImGuiPopupFlags popup_flags)
11709 ImGuiWindow* parent_window =
g.CurrentWindow;
11710 const int current_stack_size =
g.BeginPopupStack.Size;
11712 if (popup_flags & ImGuiPopupFlags_NoOpenOverExistingPopup)
11713 if (IsPopupOpen((ImGuiID)0, ImGuiPopupFlags_AnyPopupId))
11716 ImGuiPopupData popup_ref;
11717 popup_ref.PopupId =
id;
11718 popup_ref.Window = NULL;
11719 popup_ref.RestoreNavWindow =
g.NavWindow;
11720 popup_ref.OpenFrameCount =
g.FrameCount;
11721 popup_ref.OpenParentId = parent_window->IDStack.back();
11722 popup_ref.OpenPopupPos = NavCalcPreferredRefPos();
11723 popup_ref.OpenMousePos = IsMousePosValid(&
g.IO.MousePos) ?
g.IO.MousePos : popup_ref.OpenPopupPos;
11725 IMGUI_DEBUG_LOG_POPUP(
"[popup] OpenPopupEx(0x%08X)\n",
id);
11726 if (
g.OpenPopupStack.Size < current_stack_size + 1)
11728 g.OpenPopupStack.push_back(popup_ref);
11736 bool keep_existing =
false;
11737 if (
g.OpenPopupStack[current_stack_size].PopupId ==
id)
11738 if ((
g.OpenPopupStack[current_stack_size].OpenFrameCount ==
g.FrameCount - 1) || (popup_flags & ImGuiPopupFlags_NoReopen))
11739 keep_existing =
true;
11743 g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount;
11748 ClosePopupToLevel(current_stack_size,
true);
11749 g.OpenPopupStack.push_back(popup_ref);
11761void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window,
bool restore_focus_to_window_under_popup)
11764 if (
g.OpenPopupStack.Size == 0)
11769 int popup_count_to_keep = 0;
11773 for (; popup_count_to_keep <
g.OpenPopupStack.Size; popup_count_to_keep++)
11775 ImGuiPopupData& popup =
g.OpenPopupStack[popup_count_to_keep];
11778 IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0);
11788 bool ref_window_is_descendent_of_popup =
false;
11789 for (
int n = popup_count_to_keep; n <
g.OpenPopupStack.Size; n++)
11790 if (ImGuiWindow* popup_window =
g.OpenPopupStack[n].Window)
11792 if (IsWindowWithinBeginStackOf(ref_window, popup_window))
11794 ref_window_is_descendent_of_popup =
true;
11797 if (!ref_window_is_descendent_of_popup)
11801 if (popup_count_to_keep <
g.OpenPopupStack.Size)
11803 IMGUI_DEBUG_LOG_POPUP(
"[popup] ClosePopupsOverWindow(\"%s\")\n", ref_window ? ref_window->Name :
"<NULL>");
11804 ClosePopupToLevel(popup_count_to_keep, restore_focus_to_window_under_popup);
11808void ImGui::ClosePopupsExceptModals()
11812 int popup_count_to_keep;
11813 for (popup_count_to_keep =
g.OpenPopupStack.Size; popup_count_to_keep > 0; popup_count_to_keep--)
11815 ImGuiWindow* window =
g.OpenPopupStack[popup_count_to_keep - 1].Window;
11816 if (!window || (window->Flags & ImGuiWindowFlags_Modal))
11819 if (popup_count_to_keep <
g.OpenPopupStack.Size)
11820 ClosePopupToLevel(popup_count_to_keep,
true);
11823void ImGui::ClosePopupToLevel(
int remaining,
bool restore_focus_to_window_under_popup)
11826 IMGUI_DEBUG_LOG_POPUP(
"[popup] ClosePopupToLevel(%d), restore_under=%d\n", remaining, restore_focus_to_window_under_popup);
11827 IM_ASSERT(remaining >= 0 && remaining <
g.OpenPopupStack.Size);
11830 ImGuiPopupData prev_popup =
g.OpenPopupStack[remaining];
11831 g.OpenPopupStack.resize(remaining);
11834 if (restore_focus_to_window_under_popup && prev_popup.Window)
11836 ImGuiWindow* popup_window = prev_popup.Window;
11837 ImGuiWindow* focus_window = (popup_window->Flags & ImGuiWindowFlags_ChildMenu) ? popup_window->ParentWindow : prev_popup.RestoreNavWindow;
11838 if (focus_window && !focus_window->WasActive)
11839 FocusTopMostWindowUnderOne(popup_window, NULL, NULL, ImGuiFocusRequestFlags_RestoreFocusedChild);
11841 FocusWindow(focus_window, (
g.NavLayer == ImGuiNavLayer_Main) ? ImGuiFocusRequestFlags_RestoreFocusedChild : ImGuiFocusRequestFlags_None);
11846void ImGui::CloseCurrentPopup()
11849 int popup_idx =
g.BeginPopupStack.Size - 1;
11850 if (popup_idx < 0 || popup_idx >=
g.OpenPopupStack.Size ||
g.BeginPopupStack[popup_idx].PopupId !=
g.OpenPopupStack[popup_idx].PopupId)
11854 while (popup_idx > 0)
11856 ImGuiWindow* popup_window =
g.OpenPopupStack[popup_idx].Window;
11857 ImGuiWindow* parent_popup_window =
g.OpenPopupStack[popup_idx - 1].Window;
11858 bool close_parent =
false;
11859 if (popup_window && (popup_window->Flags & ImGuiWindowFlags_ChildMenu))
11860 if (parent_popup_window && !(parent_popup_window->Flags & ImGuiWindowFlags_MenuBar))
11861 close_parent =
true;
11866 IMGUI_DEBUG_LOG_POPUP(
"[popup] CloseCurrentPopup %d -> %d\n",
g.BeginPopupStack.Size - 1, popup_idx);
11867 ClosePopupToLevel(popup_idx,
true);
11872 if (ImGuiWindow* window =
g.NavWindow)
11873 window->DC.NavHideHighlightOneFrame =
true;
11877bool ImGui::BeginPopupEx(ImGuiID
id, ImGuiWindowFlags flags)
11880 if (!IsPopupOpen(
id, ImGuiPopupFlags_None))
11882 g.NextWindowData.ClearFlags();
11887 if (flags & ImGuiWindowFlags_ChildMenu)
11888 ImFormatString(name, IM_ARRAYSIZE(name),
"##Menu_%02d",
g.BeginMenuDepth);
11892 flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoDocking;
11893 bool is_open = Begin(name, NULL, flags);
11902bool ImGui::BeginPopup(
const char* str_id, ImGuiWindowFlags flags)
11905 if (
g.OpenPopupStack.Size <=
g.BeginPopupStack.Size)
11907 g.NextWindowData.ClearFlags();
11910 flags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings;
11911 ImGuiID
id =
g.CurrentWindow->GetID(str_id);
11912 return BeginPopupEx(
id, flags);
11919bool ImGui::BeginPopupModal(
const char* name,
bool* p_open, ImGuiWindowFlags flags)
11922 ImGuiWindow* window =
g.CurrentWindow;
11923 const ImGuiID
id = window->GetID(name);
11924 if (!IsPopupOpen(
id, ImGuiPopupFlags_None))
11926 g.NextWindowData.ClearFlags();
11927 if (p_open && *p_open)
11935 if ((
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0)
11937 const ImGuiViewport* viewport = window->WasActive ? window->Viewport : GetMainViewport();
11938 SetNextWindowPos(viewport->GetCenter(), ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f));
11941 flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDocking;
11942 const bool is_open = Begin(name, p_open, flags);
11943 if (!is_open || (p_open && !*p_open))
11947 ClosePopupToLevel(
g.BeginPopupStack.Size,
true);
11953void ImGui::EndPopup()
11956 ImGuiWindow* window =
g.CurrentWindow;
11957 IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup);
11958 IM_ASSERT(
g.BeginPopupStack.Size > 0);
11961 if (
g.NavWindow == window)
11962 NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY);
11965 IM_ASSERT(
g.WithinEndChild ==
false);
11966 if (window->Flags & ImGuiWindowFlags_ChildWindow)
11967 g.WithinEndChild =
true;
11969 g.WithinEndChild =
false;
11974void ImGui::OpenPopupOnItemClick(
const char* str_id, ImGuiPopupFlags popup_flags)
11977 ImGuiWindow* window =
g.CurrentWindow;
11978 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
11979 if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
11981 ImGuiID
id = str_id ? window->GetID(str_id) :
g.LastItemData.ID;
11982 IM_ASSERT(
id != 0);
11983 OpenPopupEx(
id, popup_flags);
12003bool ImGui::BeginPopupContextItem(
const char* str_id, ImGuiPopupFlags popup_flags)
12006 ImGuiWindow* window =
g.CurrentWindow;
12007 if (window->SkipItems)
12009 ImGuiID
id = str_id ? window->GetID(str_id) :
g.LastItemData.ID;
12010 IM_ASSERT(
id != 0);
12011 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
12012 if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
12013 OpenPopupEx(
id, popup_flags);
12014 return BeginPopupEx(
id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
12017bool ImGui::BeginPopupContextWindow(
const char* str_id, ImGuiPopupFlags popup_flags)
12020 ImGuiWindow* window =
g.CurrentWindow;
12022 str_id =
"window_context";
12023 ImGuiID
id = window->GetID(str_id);
12024 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
12025 if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
12026 if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
12027 OpenPopupEx(
id, popup_flags);
12028 return BeginPopupEx(
id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
12031bool ImGui::BeginPopupContextVoid(
const char* str_id, ImGuiPopupFlags popup_flags)
12034 ImGuiWindow* window =
g.CurrentWindow;
12036 str_id =
"void_context";
12037 ImGuiID
id = window->GetID(str_id);
12038 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
12039 if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
12040 if (GetTopMostPopupModal() == NULL)
12041 OpenPopupEx(
id, popup_flags);
12042 return BeginPopupEx(
id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
12050ImVec2 ImGui::FindBestWindowPosForPopupEx(
const ImVec2& ref_pos,
const ImVec2& size, ImGuiDir* last_dir,
const ImRect& r_outer,
const ImRect& r_avoid, ImGuiPopupPositionPolicy policy)
12052 ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size);
12057 if (policy == ImGuiPopupPositionPolicy_ComboBox)
12059 const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Down, ImGuiDir_Right, ImGuiDir_Left, ImGuiDir_Up };
12060 for (
int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
12062 const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
12063 if (n != -1 && dir == *last_dir)
12066 if (dir == ImGuiDir_Down) pos = ImVec2(r_avoid.Min.x, r_avoid.Max.y);
12067 if (dir == ImGuiDir_Right) pos = ImVec2(r_avoid.Min.x, r_avoid.Min.y -
size.y);
12068 if (dir == ImGuiDir_Left) pos = ImVec2(r_avoid.Max.x -
size.x, r_avoid.Max.y);
12069 if (dir == ImGuiDir_Up) pos = ImVec2(r_avoid.Max.x -
size.x, r_avoid.Min.y -
size.y);
12070 if (!r_outer.Contains(ImRect(pos, pos + size)))
12079 if (policy == ImGuiPopupPositionPolicy_Tooltip || policy == ImGuiPopupPositionPolicy_Default)
12081 const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left };
12082 for (
int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
12084 const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
12085 if (n != -1 && dir == *last_dir)
12088 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);
12089 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);
12092 if (avail_w <
size.x && (dir == ImGuiDir_Left || dir == ImGuiDir_Right))
12094 if (avail_h <
size.y && (dir == ImGuiDir_Up || dir == ImGuiDir_Down))
12098 pos.x = (dir == ImGuiDir_Left) ? r_avoid.Min.x -
size.x : (dir == ImGuiDir_Right) ? r_avoid.Max.x : base_pos_clamped.x;
12099 pos.y = (dir == ImGuiDir_Up) ? r_avoid.Min.y -
size.y : (dir == ImGuiDir_Down) ? r_avoid.Max.y : base_pos_clamped.y;
12102 pos.x = ImMax(pos.x, r_outer.Min.x);
12103 pos.y = ImMax(pos.y, r_outer.Min.y);
12111 *last_dir = ImGuiDir_None;
12114 if (policy == ImGuiPopupPositionPolicy_Tooltip)
12115 return ref_pos + ImVec2(2, 2);
12118 ImVec2 pos = ref_pos;
12119 pos.x = ImMax(ImMin(pos.x +
size.x, r_outer.Max.x) -
size.x, r_outer.Min.x);
12120 pos.y = ImMax(ImMin(pos.y +
size.y, r_outer.Max.y) -
size.y, r_outer.Min.y);
12125ImRect ImGui::GetPopupAllowedExtentRect(ImGuiWindow* window)
12129 if (window->ViewportAllowPlatformMonitorExtend >= 0)
12132 const ImGuiPlatformMonitor& monitor =
g.PlatformIO.Monitors[window->ViewportAllowPlatformMonitorExtend];
12133 r_screen.Min = monitor.WorkPos;
12134 r_screen.Max = monitor.WorkPos + monitor.WorkSize;
12139 r_screen = window->Viewport->GetMainRect();
12141 ImVec2 padding =
g.Style.DisplaySafeAreaPadding;
12142 r_screen.Expand(ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f, (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f));
12146ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
12150 ImRect r_outer = GetPopupAllowedExtentRect(window);
12151 if (window->Flags & ImGuiWindowFlags_ChildMenu)
12155 ImGuiWindow* parent_window = window->ParentWindow;
12156 float horizontal_overlap =
g.Style.ItemInnerSpacing.x;
12158 if (parent_window->DC.MenuBarAppending)
12159 r_avoid = ImRect(-FLT_MAX, parent_window->ClipRect.Min.y, FLT_MAX, parent_window->ClipRect.Max.y);
12161 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);
12162 return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Default);
12164 if (window->Flags & ImGuiWindowFlags_Popup)
12166 return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, ImRect(window->Pos, window->Pos), ImGuiPopupPositionPolicy_Default);
12168 if (window->Flags & ImGuiWindowFlags_Tooltip)
12173 IM_ASSERT(
g.CurrentWindow == window);
12174 const float scale =
g.Style.MouseCursorScale;
12175 const ImVec2 ref_pos = NavCalcPreferredRefPos();
12176 const ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET *
scale;
12178 if (!
g.NavDisableHighlight &&
g.NavDisableMouseHover && !(
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos))
12179 r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
12181 r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * scale, ref_pos.y + 24 * scale);
12183 return FindBestWindowPosForPopupEx(tooltip_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Tooltip);
12186 return window->Pos;
12197void ImGui::SetNavWindow(ImGuiWindow* window)
12200 if (
g.NavWindow != window)
12202 IMGUI_DEBUG_LOG_FOCUS(
"[focus] SetNavWindow(\"%s\")\n", window ? window->Name :
"<NULL>");
12203 g.NavWindow = window;
12204 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
12206 g.NavInitRequest =
g.NavMoveSubmitted =
g.NavMoveScoringItems =
false;
12207 NavUpdateAnyRequestFlag();
12210void ImGui::NavHighlightActivated(ImGuiID
id)
12213 g.NavHighlightActivatedId =
id;
12214 g.NavHighlightActivatedTimer = NAV_ACTIVATE_HIGHLIGHT_TIMER;
12217void ImGui::NavClearPreferredPosForAxis(ImGuiAxis axis)
12220 g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[
g.NavLayer][axis] = FLT_MAX;
12223void ImGui::SetNavID(ImGuiID
id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id,
const ImRect& rect_rel)
12226 IM_ASSERT(
g.NavWindow != NULL);
12227 IM_ASSERT(nav_layer == ImGuiNavLayer_Main || nav_layer == ImGuiNavLayer_Menu);
12229 g.NavLayer = nav_layer;
12230 SetNavFocusScope(focus_scope_id);
12231 g.NavWindow->NavLastIds[nav_layer] =
id;
12232 g.NavWindow->NavRectRel[nav_layer] = rect_rel;
12235 NavClearPreferredPosForAxis(ImGuiAxis_X);
12236 NavClearPreferredPosForAxis(ImGuiAxis_Y);
12239void ImGui::SetFocusID(ImGuiID
id, ImGuiWindow* window)
12242 IM_ASSERT(
id != 0);
12244 if (
g.NavWindow != window)
12245 SetNavWindow(window);
12249 const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent;
12251 g.NavLayer = nav_layer;
12252 SetNavFocusScope(
g.CurrentFocusScopeId);
12253 window->NavLastIds[nav_layer] =
id;
12254 if (
g.LastItemData.ID ==
id)
12255 window->NavRectRel[nav_layer] = WindowRectAbsToRel(window,
g.LastItemData.NavRect);
12257 if (
g.ActiveIdSource == ImGuiInputSource_Keyboard ||
g.ActiveIdSource == ImGuiInputSource_Gamepad)
12258 g.NavDisableMouseHover =
true;
12260 g.NavDisableHighlight =
true;
12263 NavClearPreferredPosForAxis(ImGuiAxis_X);
12264 NavClearPreferredPosForAxis(ImGuiAxis_Y);
12267static ImGuiDir ImGetDirQuadrantFromDelta(
float dx,
float dy)
12269 if (ImFabs(dx) > ImFabs(dy))
12270 return (dx > 0.0f) ? ImGuiDir_Right : ImGuiDir_Left;
12271 return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up;
12274static float inline NavScoreItemDistInterval(
float cand_min,
float cand_max,
float curr_min,
float curr_max)
12276 if (cand_max < curr_min)
12277 return cand_max - curr_min;
12278 if (curr_max < cand_min)
12279 return cand_min - curr_max;
12284static bool ImGui::NavScoreItem(ImGuiNavItemData* result)
12287 ImGuiWindow* window =
g.CurrentWindow;
12288 if (
g.NavLayer != window->DC.NavLayerCurrent)
12292 ImRect cand =
g.LastItemData.NavRect;
12293 const ImRect curr =
g.NavScoringRect;
12294 g.NavScoringDebugCount++;
12297 if (window->ParentWindow ==
g.NavWindow)
12299 IM_ASSERT((window->Flags |
g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened);
12300 if (!window->ClipRect.Overlaps(cand))
12302 cand.ClipWithFull(window->ClipRect);
12307 float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x);
12308 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));
12309 if (dby != 0.0f && dbx != 0.0f)
12310 dbx = (dbx / 1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f);
12311 float dist_box = ImFabs(dbx) + ImFabs(dby);
12314 float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x);
12315 float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y);
12316 float dist_center = ImFabs(dcx) + ImFabs(dcy);
12320 float dax = 0.0f, day = 0.0f, dist_axial = 0.0f;
12321 if (dbx != 0.0f || dby != 0.0f)
12326 dist_axial = dist_box;
12327 quadrant = ImGetDirQuadrantFromDelta(dbx, dby);
12329 else if (dcx != 0.0f || dcy != 0.0f)
12334 dist_axial = dist_center;
12335 quadrant = ImGetDirQuadrantFromDelta(dcx, dcy);
12340 quadrant = (
g.LastItemData.ID <
g.NavId) ? ImGuiDir_Left : ImGuiDir_Right;
12343 const ImGuiDir move_dir =
g.NavMoveDir;
12344#if IMGUI_DEBUG_NAV_SCORING
12348 if (quadrant == move_dir)
12350 ImFormatString(buf, IM_ARRAYSIZE(buf),
"%.0f/%.0f", dist_box, dist_center);
12351 ImDrawList* draw_list = GetForegroundDrawList(window);
12352 draw_list->AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 80));
12353 draw_list->AddRectFilled(cand.Min, cand.Min +
CalcTextSize(buf), IM_COL32(255, 0, 0, 200));
12354 draw_list->AddText(cand.Min, IM_COL32(255, 255, 255, 255), buf);
12357 const bool debug_hovering = IsMouseHoveringRect(cand.Min, cand.Max);
12358 const bool debug_tty = (
g.IO.KeyCtrl && IsKeyPressed(ImGuiKey_Space));
12359 if (debug_hovering || debug_tty)
12362 "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",
12363 dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial,
"-WENS"[move_dir+1],
"-WENS"[quadrant+1]);
12364 if (debug_hovering)
12366 ImDrawList* draw_list = GetForegroundDrawList(window);
12367 draw_list->AddRect(curr.Min, curr.Max, IM_COL32(255, 200, 0, 100));
12368 draw_list->AddRect(cand.Min, cand.Max, IM_COL32(255, 255, 0, 200));
12369 draw_list->AddRectFilled(cand.Max - ImVec2(4, 4), cand.Max +
CalcTextSize(buf) + ImVec2(4, 4), IM_COL32(40, 0, 0, 200));
12370 draw_list->AddText(cand.Max, ~0U, buf);
12372 if (debug_tty) { IMGUI_DEBUG_LOG_NAV(
"id 0x%08X\n%s\n",
g.LastItemData.ID, buf); }
12377 bool new_best =
false;
12378 if (quadrant == move_dir)
12381 if (dist_box < result->DistBox)
12383 result->DistBox = dist_box;
12384 result->DistCenter = dist_center;
12387 if (dist_box == result->DistBox)
12390 if (dist_center < result->DistCenter)
12392 result->DistCenter = dist_center;
12395 else if (dist_center == result->DistCenter)
12400 if (((move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) ? dby : dbx) < 0.0f)
12411 if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial)
12412 if (
g.NavLayer == ImGuiNavLayer_Menu && !(
g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
12413 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))
12415 result->DistAxial = dist_axial;
12422static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result)
12425 ImGuiWindow* window =
g.CurrentWindow;
12426 result->Window = window;
12427 result->ID =
g.LastItemData.ID;
12428 result->FocusScopeId =
g.CurrentFocusScopeId;
12429 result->InFlags =
g.LastItemData.InFlags;
12430 result->RectRel = WindowRectAbsToRel(window,
g.LastItemData.NavRect);
12431 if (result->InFlags & ImGuiItemFlags_HasSelectionUserData)
12433 IM_ASSERT(
g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
12434 result->SelectionUserData =
g.NextItemData.SelectionUserData;
12440void ImGui::NavUpdateCurrentWindowIsScrollPushableX()
12443 ImGuiWindow* window =
g.CurrentWindow;
12444 window->DC.NavIsScrollPushableX = (
g.CurrentTable == NULL && window->DC.CurrentColumns == NULL);
12449static void ImGui::NavProcessItem()
12452 ImGuiWindow* window =
g.CurrentWindow;
12453 const ImGuiID
id =
g.LastItemData.ID;
12454 const ImGuiItemFlags item_flags =
g.LastItemData.InFlags;
12457 if (window->DC.NavIsScrollPushableX ==
false)
12459 g.LastItemData.NavRect.Min.x = ImClamp(
g.LastItemData.NavRect.Min.x, window->ClipRect.Min.x, window->ClipRect.Max.x);
12460 g.LastItemData.NavRect.Max.x = ImClamp(
g.LastItemData.NavRect.Max.x, window->ClipRect.Min.x, window->ClipRect.Max.x);
12462 const ImRect nav_bb =
g.LastItemData.NavRect;
12465 if (
g.NavInitRequest &&
g.NavLayer == window->DC.NavLayerCurrent && (item_flags & ImGuiItemFlags_Disabled) == 0)
12468 const bool candidate_for_nav_default_focus = (item_flags & ImGuiItemFlags_NoNavDefaultFocus) == 0;
12469 if (candidate_for_nav_default_focus ||
g.NavInitResult.ID == 0)
12471 NavApplyItemToResult(&
g.NavInitResult);
12473 if (candidate_for_nav_default_focus)
12475 g.NavInitRequest =
false;
12476 NavUpdateAnyRequestFlag();
12482 if (
g.NavMoveScoringItems && (item_flags & ImGuiItemFlags_Disabled) == 0)
12484 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_FocusApi) || (window->Flags & ImGuiWindowFlags_NoNavInputs) == 0)
12486 const bool is_tabbing = (
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0;
12489 NavProcessItemForTabbingRequest(
id, item_flags,
g.NavMoveFlags);
12491 else if (
g.NavId !=
id || (
g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId))
12493 ImGuiNavItemData* result = (window ==
g.NavWindow) ? &
g.NavMoveResultLocal : &
g.NavMoveResultOther;
12494 if (NavScoreItem(result))
12495 NavApplyItemToResult(result);
12498 const float VISIBLE_RATIO = 0.70f;
12499 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb))
12500 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)
12501 if (NavScoreItem(&
g.NavMoveResultLocalVisible))
12502 NavApplyItemToResult(&
g.NavMoveResultLocalVisible);
12510 if (
g.NavWindow != window)
12511 SetNavWindow(window);
12512 g.NavLayer = window->DC.NavLayerCurrent;
12513 SetNavFocusScope(
g.CurrentFocusScopeId);
12514 g.NavFocusScopeId =
g.CurrentFocusScopeId;
12515 g.NavIdIsAlive =
true;
12516 if (
g.LastItemData.InFlags & ImGuiItemFlags_HasSelectionUserData)
12518 IM_ASSERT(
g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
12519 g.NavLastValidSelectionUserData =
g.NextItemData.SelectionUserData;
12521 window->NavRectRel[window->DC.NavLayerCurrent] = WindowRectAbsToRel(window, nav_bb);
12532void ImGui::NavProcessItemForTabbingRequest(ImGuiID
id, ImGuiItemFlags item_flags, ImGuiNavMoveFlags move_flags)
12536 if ((move_flags & ImGuiNavMoveFlags_FocusApi) == 0)
12538 if (
g.NavLayer !=
g.CurrentWindow->DC.NavLayerCurrent)
12540 if (
g.NavFocusScopeId !=
g.CurrentFocusScopeId)
12548 if (move_flags & ImGuiNavMoveFlags_FocusApi)
12551 can_stop = (item_flags & ImGuiItemFlags_NoTabStop) == 0 && ((
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) || (item_flags & ImGuiItemFlags_Inputable));
12554 ImGuiNavItemData* result = &
g.NavMoveResultLocal;
12555 if (
g.NavTabbingDir == +1)
12558 if (can_stop &&
g.NavTabbingResultFirst.ID == 0)
12559 NavApplyItemToResult(&
g.NavTabbingResultFirst);
12560 if (can_stop &&
g.NavTabbingCounter > 0 && --
g.NavTabbingCounter == 0)
12561 NavMoveRequestResolveWithLastItem(result);
12562 else if (
g.NavId ==
id)
12563 g.NavTabbingCounter = 1;
12565 else if (
g.NavTabbingDir == -1)
12572 g.NavMoveScoringItems =
false;
12573 NavUpdateAnyRequestFlag();
12579 NavApplyItemToResult(result);
12582 else if (
g.NavTabbingDir == 0)
12584 if (can_stop &&
g.NavId ==
id)
12585 NavMoveRequestResolveWithLastItem(result);
12586 if (can_stop &&
g.NavTabbingResultFirst.ID == 0)
12587 NavApplyItemToResult(&
g.NavTabbingResultFirst);
12591bool ImGui::NavMoveRequestButNoResultYet()
12594 return g.NavMoveScoringItems &&
g.NavMoveResultLocal.ID == 0 &&
g.NavMoveResultOther.ID == 0;
12598void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags)
12601 IM_ASSERT(
g.NavWindow != NULL);
12603 if (move_flags & ImGuiNavMoveFlags_IsTabbing)
12604 move_flags |= ImGuiNavMoveFlags_AllowCurrentNavId;
12606 g.NavMoveSubmitted =
g.NavMoveScoringItems =
true;
12607 g.NavMoveDir = move_dir;
12608 g.NavMoveDirForDebug = move_dir;
12609 g.NavMoveClipDir = clip_dir;
12610 g.NavMoveFlags = move_flags;
12611 g.NavMoveScrollFlags = scroll_flags;
12612 g.NavMoveForwardToNextFrame =
false;
12613 g.NavMoveKeyMods = (move_flags & ImGuiNavMoveFlags_FocusApi) ? 0 :
g.IO.KeyMods;
12614 g.NavMoveResultLocal.Clear();
12615 g.NavMoveResultLocalVisible.Clear();
12616 g.NavMoveResultOther.Clear();
12617 g.NavTabbingCounter = 0;
12618 g.NavTabbingResultFirst.Clear();
12619 NavUpdateAnyRequestFlag();
12622void ImGui::NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result)
12625 g.NavMoveScoringItems =
false;
12626 NavApplyItemToResult(result);
12627 NavUpdateAnyRequestFlag();
12631void ImGui::NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiNavTreeNodeData* tree_node_data)
12634 g.NavMoveScoringItems =
false;
12635 g.LastItemData.ID = tree_node_data->ID;
12636 g.LastItemData.InFlags = tree_node_data->InFlags & ~ImGuiItemFlags_HasSelectionUserData;
12637 g.LastItemData.NavRect = tree_node_data->NavRect;
12638 NavApplyItemToResult(result);
12639 NavClearPreferredPosForAxis(ImGuiAxis_Y);
12640 NavUpdateAnyRequestFlag();
12643void ImGui::NavMoveRequestCancel()
12646 g.NavMoveSubmitted =
g.NavMoveScoringItems =
false;
12647 NavUpdateAnyRequestFlag();
12651void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags)
12654 IM_ASSERT(
g.NavMoveForwardToNextFrame ==
false);
12655 NavMoveRequestCancel();
12656 g.NavMoveForwardToNextFrame =
true;
12657 g.NavMoveDir = move_dir;
12658 g.NavMoveClipDir = clip_dir;
12659 g.NavMoveFlags = move_flags | ImGuiNavMoveFlags_Forwarded;
12660 g.NavMoveScrollFlags = scroll_flags;
12665void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags wrap_flags)
12668 IM_ASSERT((wrap_flags & ImGuiNavMoveFlags_WrapMask_ ) != 0 && (wrap_flags & ~ImGuiNavMoveFlags_WrapMask_) == 0);
12672 if (
g.NavWindow == window &&
g.NavMoveScoringItems &&
g.NavLayer == ImGuiNavLayer_Main)
12673 g.NavMoveFlags = (
g.NavMoveFlags & ~ImGuiNavMoveFlags_WrapMask_) | wrap_flags;
12678static void ImGui::NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window)
12680 ImGuiWindow* parent = nav_window;
12681 while (parent && parent->RootWindow != parent && (parent->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
12682 parent = parent->ParentWindow;
12683 if (parent && parent != nav_window)
12684 parent->NavLastChildNavWindow = nav_window;
12689static ImGuiWindow* ImGui::NavRestoreLastChildNavWindow(ImGuiWindow* window)
12691 if (window->NavLastChildNavWindow && window->NavLastChildNavWindow->WasActive)
12692 return window->NavLastChildNavWindow;
12693 if (window->DockNodeAsHost && window->DockNodeAsHost->TabBar)
12694 if (ImGuiTabItem* tab = TabBarFindMostRecentlySelectedTabForActiveWindow(window->DockNodeAsHost->TabBar))
12695 return tab->Window;
12699void ImGui::NavRestoreLayer(ImGuiNavLayer layer)
12702 if (layer == ImGuiNavLayer_Main)
12704 ImGuiWindow* prev_nav_window =
g.NavWindow;
12705 g.NavWindow = NavRestoreLastChildNavWindow(
g.NavWindow);
12706 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
12707 if (prev_nav_window)
12708 IMGUI_DEBUG_LOG_FOCUS(
"[focus] NavRestoreLayer: from \"%s\" to SetNavWindow(\"%s\")\n", prev_nav_window->Name,
g.NavWindow->Name);
12710 ImGuiWindow* window =
g.NavWindow;
12711 if (window->NavLastIds[layer] != 0)
12713 SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
12717 g.NavLayer = layer;
12718 NavInitWindow(window,
true);
12722void ImGui::NavRestoreHighlightAfterMove()
12725 g.NavDisableHighlight =
false;
12726 g.NavDisableMouseHover =
g.NavMousePosDirty =
true;
12729static inline void ImGui::NavUpdateAnyRequestFlag()
12733 if (
g.NavAnyRequest)
12734 IM_ASSERT(
g.NavWindow != NULL);
12738void ImGui::NavInitWindow(ImGuiWindow* window,
bool force_reinit)
12742 IM_ASSERT(window ==
g.NavWindow);
12744 if (window->Flags & ImGuiWindowFlags_NoNavInputs)
12747 SetNavFocusScope(window->NavRootFocusScopeId);
12751 bool init_for_nav =
false;
12752 if (window == window->RootWindow || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
12753 init_for_nav =
true;
12754 IMGUI_DEBUG_LOG_NAV(
"[nav] NavInitRequest: from NavInitWindow(), init_for_nav=%d, window=\"%s\", layer=%d\n", init_for_nav, window->Name,
g.NavLayer);
12757 SetNavID(0,
g.NavLayer, window->NavRootFocusScopeId, ImRect());
12758 g.NavInitRequest =
true;
12759 g.NavInitRequestFromMove =
false;
12760 g.NavInitResult.ID = 0;
12761 NavUpdateAnyRequestFlag();
12765 g.NavId = window->NavLastIds[0];
12766 SetNavFocusScope(window->NavRootFocusScopeId);
12770static ImVec2 ImGui::NavCalcPreferredRefPos()
12773 ImGuiWindow* window =
g.NavWindow;
12774 const bool activated_shortcut =
g.ActiveId != 0 &&
g.ActiveIdFromShortcut &&
g.ActiveId ==
g.LastItemData.ID;
12777 if ((
g.NavDisableHighlight || !
g.NavDisableMouseHover || !window) && !activated_shortcut)
12782 ImVec2 p = IsMousePosValid(&
g.IO.MousePos) ?
g.IO.MousePos :
g.MouseLastValidPos;
12783 return ImVec2(p.x + 1.0f, p.y);
12789 if (activated_shortcut)
12790 ref_rect =
g.LastItemData.NavRect;
12792 ref_rect = WindowRectRelToAbs(window, window->NavRectRel[
g.NavLayer]);
12795 if (window->LastFrameActive !=
g.FrameCount && (window->ScrollTarget.x != FLT_MAX || window->ScrollTarget.y != FLT_MAX))
12797 ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
12798 ref_rect.Translate(window->Scroll - next_scroll);
12800 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()));
12801 ImGuiViewport* viewport = window->Viewport;
12802 return ImTrunc(ImClamp(pos, viewport->Pos, viewport->Pos + viewport->Size));
12806float ImGui::GetNavTweakPressedAmount(ImGuiAxis axis)
12809 float repeat_delay, repeat_rate;
12810 GetTypematicRepeatRate(ImGuiInputFlags_RepeatRateNavTweak, &repeat_delay, &repeat_rate);
12812 ImGuiKey key_less, key_more;
12813 if (
g.NavInputSource == ImGuiInputSource_Gamepad)
12815 key_less = (axis == ImGuiAxis_X) ? ImGuiKey_GamepadDpadLeft : ImGuiKey_GamepadDpadUp;
12816 key_more = (axis == ImGuiAxis_X) ? ImGuiKey_GamepadDpadRight : ImGuiKey_GamepadDpadDown;
12820 key_less = (axis == ImGuiAxis_X) ? ImGuiKey_LeftArrow : ImGuiKey_UpArrow;
12821 key_more = (axis == ImGuiAxis_X) ? ImGuiKey_RightArrow : ImGuiKey_DownArrow;
12823 float amount = (float)GetKeyPressedAmount(key_more, repeat_delay, repeat_rate) - (float)GetKeyPressedAmount(key_less, repeat_delay, repeat_rate);
12824 if (amount != 0.0f && IsKeyDown(key_less) && IsKeyDown(key_more))
12829static void ImGui::NavUpdate()
12832 ImGuiIO& io =
g.IO;
12834 io.WantSetMousePos =
false;
12839 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
12840 const ImGuiKey nav_gamepad_keys_to_change_source[] = { ImGuiKey_GamepadFaceRight, ImGuiKey_GamepadFaceLeft, ImGuiKey_GamepadFaceUp, ImGuiKey_GamepadFaceDown, ImGuiKey_GamepadDpadRight, ImGuiKey_GamepadDpadLeft, ImGuiKey_GamepadDpadUp, ImGuiKey_GamepadDpadDown };
12841 if (nav_gamepad_active)
12842 for (ImGuiKey key : nav_gamepad_keys_to_change_source)
12843 if (IsKeyDown(key))
12844 g.NavInputSource = ImGuiInputSource_Gamepad;
12845 const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
12846 const ImGuiKey nav_keyboard_keys_to_change_source[] = { ImGuiKey_Space, ImGuiKey_Enter, ImGuiKey_Escape, ImGuiKey_RightArrow, ImGuiKey_LeftArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow };
12847 if (nav_keyboard_active)
12848 for (ImGuiKey key : nav_keyboard_keys_to_change_source)
12849 if (IsKeyDown(key))
12850 g.NavInputSource = ImGuiInputSource_Keyboard;
12853 g.NavJustMovedToId = 0;
12854 if (
g.NavInitResult.ID != 0)
12855 NavInitRequestApplyResult();
12856 g.NavInitRequest =
false;
12857 g.NavInitRequestFromMove =
false;
12858 g.NavInitResult.ID = 0;
12861 if (
g.NavMoveSubmitted)
12862 NavMoveRequestApplyResult();
12863 g.NavTabbingCounter = 0;
12864 g.NavMoveSubmitted =
g.NavMoveScoringItems =
false;
12867 bool set_mouse_pos =
false;
12868 if (
g.NavMousePosDirty &&
g.NavIdIsAlive)
12869 if (!
g.NavDisableHighlight &&
g.NavDisableMouseHover &&
g.NavWindow)
12870 set_mouse_pos =
true;
12871 g.NavMousePosDirty =
false;
12872 IM_ASSERT(
g.NavLayer == ImGuiNavLayer_Main ||
g.NavLayer == ImGuiNavLayer_Menu);
12876 NavSaveLastChildNavWindowIntoParent(
g.NavWindow);
12877 if (
g.NavWindow &&
g.NavWindow->NavLastChildNavWindow != NULL &&
g.NavLayer == ImGuiNavLayer_Main)
12878 g.NavWindow->NavLastChildNavWindow = NULL;
12881 NavUpdateWindowing();
12884 io.NavActive = (nav_keyboard_active || nav_gamepad_active) &&
g.NavWindow && !(
g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs);
12885 io.NavVisible = (io.NavActive &&
g.NavId != 0 && !
g.NavDisableHighlight) || (
g.NavWindowingTarget != NULL);
12888 NavUpdateCancelRequest();
12891 g.NavActivateId =
g.NavActivateDownId =
g.NavActivatePressedId = 0;
12892 g.NavActivateFlags = ImGuiActivateFlags_None;
12893 if (
g.NavId != 0 && !
g.NavDisableHighlight && !
g.NavWindowingTarget &&
g.NavWindow && !(
g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
12895 const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space, ImGuiKeyOwner_NoOwner)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_NoOwner));
12896 const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, 0, ImGuiKeyOwner_NoOwner)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, 0, ImGuiKeyOwner_NoOwner)));
12897 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));
12898 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)));
12899 if (
g.ActiveId == 0 && activate_pressed)
12901 g.NavActivateId =
g.NavId;
12902 g.NavActivateFlags = ImGuiActivateFlags_PreferTweak;
12904 if ((
g.ActiveId == 0 ||
g.ActiveId ==
g.NavId) && input_pressed)
12906 g.NavActivateId =
g.NavId;
12907 g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
12909 if ((
g.ActiveId == 0 ||
g.ActiveId ==
g.NavId) && (activate_down || input_down))
12910 g.NavActivateDownId =
g.NavId;
12911 if ((
g.ActiveId == 0 ||
g.ActiveId ==
g.NavId) && (activate_pressed || input_pressed))
12913 g.NavActivatePressedId =
g.NavId;
12914 NavHighlightActivated(
g.NavId);
12917 if (
g.NavWindow && (
g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
12918 g.NavDisableHighlight =
true;
12919 if (
g.NavActivateId != 0)
12920 IM_ASSERT(
g.NavActivateDownId ==
g.NavActivateId);
12923 if (
g.NavHighlightActivatedTimer > 0.0f)
12924 g.NavHighlightActivatedTimer = ImMax(0.0f,
g.NavHighlightActivatedTimer - io.DeltaTime);
12925 if (
g.NavHighlightActivatedTimer == 0.0f)
12926 g.NavHighlightActivatedId = 0;
12930 if (
g.NavNextActivateId != 0)
12932 g.NavActivateId =
g.NavActivateDownId =
g.NavActivatePressedId =
g.NavNextActivateId;
12933 g.NavActivateFlags =
g.NavNextActivateFlags;
12935 g.NavNextActivateId = 0;
12938 NavUpdateCreateMoveRequest();
12939 if (
g.NavMoveDir == ImGuiDir_None)
12940 NavUpdateCreateTabbingRequest();
12941 NavUpdateAnyRequestFlag();
12942 g.NavIdIsAlive =
false;
12945 if (
g.NavWindow && !(
g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !
g.NavWindowingTarget)
12948 ImGuiWindow* window =
g.NavWindow;
12949 const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * io.DeltaTime);
12950 const ImGuiDir move_dir =
g.NavMoveDir;
12951 if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavWindowHasScrollY && move_dir != ImGuiDir_None)
12953 if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right)
12954 SetScrollX(window, ImTrunc(window->Scroll.x + ((move_dir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
12955 if (move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down)
12956 SetScrollY(window, ImTrunc(window->Scroll.y + ((move_dir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed));
12961 if (nav_gamepad_active)
12963 const ImVec2 scroll_dir = GetKeyMagnitude2d(ImGuiKey_GamepadLStickLeft, ImGuiKey_GamepadLStickRight, ImGuiKey_GamepadLStickUp, ImGuiKey_GamepadLStickDown);
12964 const float tweak_factor = IsKeyDown(ImGuiKey_NavGamepadTweakSlow) ? 1.0f / 10.0f : IsKeyDown(ImGuiKey_NavGamepadTweakFast) ? 10.0f : 1.0f;
12965 if (scroll_dir.x != 0.0f && window->ScrollbarX)
12966 SetScrollX(window, ImTrunc(window->Scroll.x + scroll_dir.x * scroll_speed * tweak_factor));
12967 if (scroll_dir.y != 0.0f)
12968 SetScrollY(window, ImTrunc(window->Scroll.y + scroll_dir.y * scroll_speed * tweak_factor));
12973 if (!nav_keyboard_active && !nav_gamepad_active)
12975 g.NavDisableHighlight =
true;
12976 g.NavDisableMouseHover = set_mouse_pos =
false;
12981 if (set_mouse_pos && (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
12982 TeleportMousePos(NavCalcPreferredRefPos());
12985 g.NavScoringDebugCount = 0;
12986#if IMGUI_DEBUG_NAV_RECTS
12987 if (ImGuiWindow* debug_window =
g.NavWindow)
12989 ImDrawList* draw_list = GetForegroundDrawList(debug_window);
12990 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)); }
12996void ImGui::NavInitRequestApplyResult()
13003 ImGuiNavItemData* result = &
g.NavInitResult;
13004 if (
g.NavId != result->ID)
13006 g.NavJustMovedToId = result->ID;
13007 g.NavJustMovedToFocusScopeId = result->FocusScopeId;
13008 g.NavJustMovedToKeyMods = 0;
13013 IMGUI_DEBUG_LOG_NAV(
"[nav] NavInitRequest: ApplyResult: NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID,
g.NavLayer,
g.NavWindow->Name);
13014 SetNavID(result->ID,
g.NavLayer, result->FocusScopeId, result->RectRel);
13015 g.NavIdIsAlive =
true;
13016 if (result->SelectionUserData != ImGuiSelectionUserData_Invalid)
13017 g.NavLastValidSelectionUserData = result->SelectionUserData;
13018 if (
g.NavInitRequestFromMove)
13019 NavRestoreHighlightAfterMove();
13023static void NavBiasScoringRect(ImRect& r, ImVec2& preferred_pos_rel, ImGuiDir move_dir, ImGuiNavMoveFlags move_flags)
13027 const ImVec2 rel_to_abs_offset =
g.NavWindow->DC.CursorStartPos;
13032 if ((move_flags & ImGuiNavMoveFlags_Forwarded) == 0)
13034 if (preferred_pos_rel.x == FLT_MAX)
13035 preferred_pos_rel.x = ImMin(r.Min.x + 1.0f, r.Max.x) - rel_to_abs_offset.x;
13036 if (preferred_pos_rel.y == FLT_MAX)
13037 preferred_pos_rel.y = r.GetCenter().y - rel_to_abs_offset.y;
13041 if ((move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) && preferred_pos_rel.x != FLT_MAX)
13042 r.Min.x = r.Max.x = preferred_pos_rel.x + rel_to_abs_offset.x;
13043 else if ((move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right) && preferred_pos_rel.y != FLT_MAX)
13044 r.Min.y = r.Max.y = preferred_pos_rel.y + rel_to_abs_offset.y;
13047void ImGui::NavUpdateCreateMoveRequest()
13050 ImGuiIO& io =
g.IO;
13051 ImGuiWindow* window =
g.NavWindow;
13052 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
13053 const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
13055 if (
g.NavMoveForwardToNextFrame && window != NULL)
13059 IM_ASSERT(
g.NavMoveDir != ImGuiDir_None &&
g.NavMoveClipDir != ImGuiDir_None);
13060 IM_ASSERT(
g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded);
13061 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveRequestForward %d\n",
g.NavMoveDir);
13066 g.NavMoveDir = ImGuiDir_None;
13067 g.NavMoveFlags = ImGuiNavMoveFlags_None;
13068 g.NavMoveScrollFlags = ImGuiScrollFlags_None;
13069 if (window && !
g.NavWindowingTarget && !(window->Flags & ImGuiWindowFlags_NoNavInputs))
13071 const ImGuiInputFlags repeat_mode = ImGuiInputFlags_Repeat | (ImGuiInputFlags)ImGuiInputFlags_RepeatRateNavMove;
13072 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; }
13073 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; }
13074 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; }
13075 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; }
13077 g.NavMoveClipDir =
g.NavMoveDir;
13078 g.NavScoringNoClipRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
13083 float scoring_rect_offset_y = 0.0f;
13084 if (window &&
g.NavMoveDir == ImGuiDir_None && nav_keyboard_active)
13085 scoring_rect_offset_y = NavUpdatePageUpPageDown();
13086 if (scoring_rect_offset_y != 0.0f)
13088 g.NavScoringNoClipRect = window->InnerRect;
13089 g.NavScoringNoClipRect.TranslateY(scoring_rect_offset_y);
13093#if IMGUI_DEBUG_NAV_SCORING
13098 if (
g.NavMoveDir == ImGuiDir_None)
13099 g.NavMoveDir =
g.NavMoveDirForDebug;
13100 g.NavMoveClipDir =
g.NavMoveDir;
13101 g.NavMoveFlags |= ImGuiNavMoveFlags_DebugNoResult;
13106 g.NavMoveForwardToNextFrame =
false;
13107 if (
g.NavMoveDir != ImGuiDir_None)
13108 NavMoveRequestSubmit(
g.NavMoveDir,
g.NavMoveClipDir,
g.NavMoveFlags,
g.NavMoveScrollFlags);
13111 if (
g.NavMoveSubmitted &&
g.NavId == 0)
13113 IMGUI_DEBUG_LOG_NAV(
"[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", window ? window->Name :
"<NULL>",
g.NavLayer);
13114 g.NavInitRequest =
g.NavInitRequestFromMove =
true;
13115 g.NavInitResult.ID = 0;
13116 g.NavDisableHighlight =
false;
13122 if (
g.NavMoveSubmitted &&
g.NavInputSource == ImGuiInputSource_Gamepad &&
g.NavLayer == ImGuiNavLayer_Main && window != NULL)
13124 bool clamp_x = (
g.NavMoveFlags & (ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_WrapX)) == 0;
13125 bool clamp_y = (
g.NavMoveFlags & (ImGuiNavMoveFlags_LoopY | ImGuiNavMoveFlags_WrapY)) == 0;
13126 ImRect inner_rect_rel = WindowRectAbsToRel(window, ImRect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1)));
13130 inner_rect_rel.Translate(CalcNextScrollFromScrollTargetAndClamp(window) - window->Scroll);
13132 if ((clamp_x || clamp_y) && !inner_rect_rel.Contains(window->NavRectRel[
g.NavLayer]))
13134 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveRequest: clamp NavRectRel for gamepad move\n");
13135 float pad_x = ImMin(inner_rect_rel.GetWidth(), window->CalcFontSize() * 0.5f);
13136 float pad_y = ImMin(inner_rect_rel.GetHeight(), window->CalcFontSize() * 0.5f);
13137 inner_rect_rel.Min.x = clamp_x ? (inner_rect_rel.Min.x + pad_x) : -FLT_MAX;
13138 inner_rect_rel.Max.x = clamp_x ? (inner_rect_rel.Max.x - pad_x) : +FLT_MAX;
13139 inner_rect_rel.Min.y = clamp_y ? (inner_rect_rel.Min.y + pad_y) : -FLT_MAX;
13140 inner_rect_rel.Max.y = clamp_y ? (inner_rect_rel.Max.y - pad_y) : +FLT_MAX;
13141 window->NavRectRel[
g.NavLayer].ClipWithFull(inner_rect_rel);
13147 ImRect scoring_rect;
13148 if (window != NULL)
13150 ImRect nav_rect_rel = !window->NavRectRel[
g.NavLayer].IsInverted() ? window->NavRectRel[
g.NavLayer] : ImRect(0, 0, 0, 0);
13151 scoring_rect = WindowRectRelToAbs(window, nav_rect_rel);
13152 scoring_rect.TranslateY(scoring_rect_offset_y);
13153 if (
g.NavMoveSubmitted)
13154 NavBiasScoringRect(scoring_rect, window->RootWindowForNav->NavPreferredScoringPosRel[
g.NavLayer],
g.NavMoveDir,
g.NavMoveFlags);
13155 IM_ASSERT(!scoring_rect.IsInverted());
13159 g.NavScoringRect = scoring_rect;
13160 g.NavScoringNoClipRect.Add(scoring_rect);
13163void ImGui::NavUpdateCreateTabbingRequest()
13166 ImGuiWindow* window =
g.NavWindow;
13167 IM_ASSERT(
g.NavMoveDir == ImGuiDir_None);
13168 if (window == NULL ||
g.NavWindowingTarget != NULL || (window->Flags & ImGuiWindowFlags_NoNavInputs))
13171 const bool tab_pressed = IsKeyPressed(ImGuiKey_Tab, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner) && !
g.IO.KeyCtrl && !
g.IO.KeyAlt;
13178 const bool nav_keyboard_active = (
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
13179 if (nav_keyboard_active)
13180 g.NavTabbingDir =
g.IO.KeyShift ? -1 : (
g.NavDisableHighlight ==
true &&
g.ActiveId == 0) ? 0 : +1;
13182 g.NavTabbingDir =
g.IO.KeyShift ? -1 : (
g.ActiveId == 0) ? 0 : +1;
13183 ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate;
13184 ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
13185 ImGuiDir clip_dir = (
g.NavTabbingDir < 0) ? ImGuiDir_Up : ImGuiDir_Down;
13186 NavMoveRequestSubmit(ImGuiDir_None, clip_dir, move_flags, scroll_flags);
13187 g.NavTabbingCounter = -1;
13191void ImGui::NavMoveRequestApplyResult()
13194#if IMGUI_DEBUG_NAV_SCORING
13195 if (
g.NavMoveFlags & ImGuiNavMoveFlags_DebugNoResult)
13200 ImGuiNavItemData* result = (
g.NavMoveResultLocal.ID != 0) ? &
g.NavMoveResultLocal : (
g.NavMoveResultOther.
ID != 0) ? &
g.NavMoveResultOther : NULL;
13203 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && result == NULL)
13204 if ((
g.NavTabbingCounter == 1 ||
g.NavTabbingDir == 0) &&
g.NavTabbingResultFirst.ID)
13205 result = &
g.NavTabbingResultFirst;
13208 const ImGuiAxis axis = (
g.NavMoveDir == ImGuiDir_Up ||
g.NavMoveDir == ImGuiDir_Down) ? ImGuiAxis_Y : ImGuiAxis_X;
13209 if (result == NULL)
13211 if (
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing)
13212 g.NavMoveFlags |= ImGuiNavMoveFlags_NoSetNavHighlight;
13213 if (
g.NavId != 0 && (
g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavHighlight) == 0)
13214 NavRestoreHighlightAfterMove();
13215 NavClearPreferredPosForAxis(axis);
13216 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveSubmitted but not led to a result!\n");
13221 if (
g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet)
13222 if (
g.NavMoveResultLocalVisible.ID != 0 &&
g.NavMoveResultLocalVisible.ID !=
g.NavId)
13223 result = &
g.NavMoveResultLocalVisible;
13226 if (result != &
g.NavMoveResultOther &&
g.NavMoveResultOther.ID != 0 &&
g.NavMoveResultOther.Window->ParentWindow ==
g.NavWindow)
13227 if ((
g.NavMoveResultOther.DistBox < result->DistBox) || (
g.NavMoveResultOther.DistBox == result->DistBox &&
g.NavMoveResultOther.DistCenter < result->DistCenter))
13228 result = &
g.NavMoveResultOther;
13229 IM_ASSERT(
g.NavWindow && result->Window);
13232 if (
g.NavLayer == ImGuiNavLayer_Main)
13234 ImRect rect_abs = WindowRectRelToAbs(result->Window, result->RectRel);
13235 ScrollToRectEx(result->Window, rect_abs,
g.NavMoveScrollFlags);
13237 if (
g.NavMoveFlags & ImGuiNavMoveFlags_ScrollToEdgeY)
13240 float scroll_target = (
g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f;
13241 SetScrollY(result->Window, scroll_target);
13245 if (
g.NavWindow != result->Window)
13247 IMGUI_DEBUG_LOG_FOCUS(
"[focus] NavMoveRequest: SetNavWindow(\"%s\")\n", result->Window->Name);
13248 g.NavWindow = result->Window;
13249 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
13255 if (
g.ActiveId != result->ID && (
g.NavMoveFlags & ImGuiNavMoveFlags_NoClearActiveId) == 0)
13260 if ((
g.NavId != result->ID || (
g.NavMoveFlags & ImGuiNavMoveFlags_IsPageMove)) && (
g.NavMoveFlags & ImGuiNavMoveFlags_NoSelect) == 0)
13262 g.NavJustMovedToId = result->ID;
13263 g.NavJustMovedToFocusScopeId = result->FocusScopeId;
13264 g.NavJustMovedToKeyMods =
g.NavMoveKeyMods;
13268 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID,
g.NavLayer,
g.NavWindow->Name);
13269 ImVec2 preferred_scoring_pos_rel =
g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[
g.NavLayer];
13270 SetNavID(result->ID,
g.NavLayer, result->FocusScopeId, result->RectRel);
13271 if (result->SelectionUserData != ImGuiSelectionUserData_Invalid)
13272 g.NavLastValidSelectionUserData = result->SelectionUserData;
13276 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) == 0)
13278 preferred_scoring_pos_rel[axis] = result->RectRel.GetCenter()[axis];
13279 g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[
g.NavLayer] = preferred_scoring_pos_rel;
13283 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && (result->InFlags & ImGuiItemFlags_Inputable) == 0)
13284 g.NavMoveFlags &= ~ImGuiNavMoveFlags_Activate;
13287 if (
g.NavMoveFlags & ImGuiNavMoveFlags_Activate)
13289 g.NavNextActivateId = result->ID;
13290 g.NavNextActivateFlags = ImGuiActivateFlags_None;
13291 if (
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing)
13292 g.NavNextActivateFlags |= ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState | ImGuiActivateFlags_FromTabbing;
13296 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavHighlight) == 0)
13297 NavRestoreHighlightAfterMove();
13304static void ImGui::NavUpdateCancelRequest()
13307 const bool nav_gamepad_active = (
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (
g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
13308 const bool nav_keyboard_active = (
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
13309 if (!(nav_keyboard_active && IsKeyPressed(ImGuiKey_Escape, 0, ImGuiKeyOwner_NoOwner)) && !(nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadCancel, 0, ImGuiKeyOwner_NoOwner)))
13312 IMGUI_DEBUG_LOG_NAV(
"[nav] NavUpdateCancelRequest()\n");
13313 if (
g.ActiveId != 0)
13317 else if (
g.NavLayer != ImGuiNavLayer_Main)
13320 NavRestoreLayer(ImGuiNavLayer_Main);
13321 NavRestoreHighlightAfterMove();
13323 else if (
g.NavWindow &&
g.NavWindow !=
g.NavWindow->RootWindow && !(
g.NavWindow->RootWindowForNav->Flags & ImGuiWindowFlags_Popup) &&
g.NavWindow->RootWindowForNav->ParentWindow)
13326 ImGuiWindow* child_window =
g.NavWindow->RootWindowForNav;
13327 ImGuiWindow* parent_window = child_window->ParentWindow;
13328 IM_ASSERT(child_window->ChildId != 0);
13329 FocusWindow(parent_window);
13330 SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, WindowRectAbsToRel(parent_window, child_window->Rect()));
13331 NavRestoreHighlightAfterMove();
13333 else if (
g.OpenPopupStack.Size > 0 &&
g.OpenPopupStack.back().Window != NULL && !(
g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal))
13336 ClosePopupToLevel(
g.OpenPopupStack.Size - 1,
true);
13341 if (
g.NavWindow && ((
g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(
g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow)))
13342 g.NavWindow->NavLastIds[0] = 0;
13351static float ImGui::NavUpdatePageUpPageDown()
13354 ImGuiWindow* window =
g.NavWindow;
13355 if ((window->Flags & ImGuiWindowFlags_NoNavInputs) ||
g.NavWindowingTarget != NULL)
13358 const bool page_up_held = IsKeyDown(ImGuiKey_PageUp, ImGuiKeyOwner_NoOwner);
13359 const bool page_down_held = IsKeyDown(ImGuiKey_PageDown, ImGuiKeyOwner_NoOwner);
13360 const bool home_pressed = IsKeyPressed(ImGuiKey_Home, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner);
13361 const bool end_pressed = IsKeyPressed(ImGuiKey_End, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner);
13362 if (page_up_held == page_down_held && home_pressed == end_pressed)
13365 if (
g.NavLayer != ImGuiNavLayer_Main)
13366 NavRestoreLayer(ImGuiNavLayer_Main);
13368 if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavWindowHasScrollY)
13371 if (IsKeyPressed(ImGuiKey_PageUp, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner))
13372 SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight());
13373 else if (IsKeyPressed(ImGuiKey_PageDown, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner))
13374 SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight());
13375 else if (home_pressed)
13376 SetScrollY(window, 0.0f);
13377 else if (end_pressed)
13378 SetScrollY(window, window->ScrollMax.y);
13382 ImRect& nav_rect_rel = window->NavRectRel[
g.NavLayer];
13383 const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
13384 float nav_scoring_rect_offset_y = 0.0f;
13385 if (IsKeyPressed(ImGuiKey_PageUp,
true))
13387 nav_scoring_rect_offset_y = -page_offset_y;
13388 g.NavMoveDir = ImGuiDir_Down;
13389 g.NavMoveClipDir = ImGuiDir_Up;
13390 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet | ImGuiNavMoveFlags_IsPageMove;
13392 else if (IsKeyPressed(ImGuiKey_PageDown,
true))
13394 nav_scoring_rect_offset_y = +page_offset_y;
13395 g.NavMoveDir = ImGuiDir_Up;
13396 g.NavMoveClipDir = ImGuiDir_Down;
13397 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet | ImGuiNavMoveFlags_IsPageMove;
13399 else if (home_pressed)
13404 nav_rect_rel.Min.y = nav_rect_rel.Max.y = 0.0f;
13405 if (nav_rect_rel.IsInverted())
13406 nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
13407 g.NavMoveDir = ImGuiDir_Down;
13408 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdgeY;
13411 else if (end_pressed)
13413 nav_rect_rel.Min.y = nav_rect_rel.Max.y = window->ContentSize.y;
13414 if (nav_rect_rel.IsInverted())
13415 nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
13416 g.NavMoveDir = ImGuiDir_Up;
13417 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdgeY;
13420 return nav_scoring_rect_offset_y;
13425static void ImGui::NavEndFrame()
13430 if (
g.NavWindowingTarget != NULL)
13431 NavUpdateWindowingOverlay();
13436 if (
g.NavWindow && NavMoveRequestButNoResultYet() && (
g.NavMoveFlags & ImGuiNavMoveFlags_WrapMask_) && (
g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0)
13437 NavUpdateCreateWrappingRequest();
13440static void ImGui::NavUpdateCreateWrappingRequest()
13443 ImGuiWindow* window =
g.NavWindow;
13445 bool do_forward =
false;
13446 ImRect bb_rel = window->NavRectRel[
g.NavLayer];
13447 ImGuiDir clip_dir =
g.NavMoveDir;
13449 const ImGuiNavMoveFlags move_flags =
g.NavMoveFlags;
13451 if (
g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
13453 bb_rel.Min.x = bb_rel.Max.x = window->ContentSize.x + window->WindowPadding.x;
13454 if (move_flags & ImGuiNavMoveFlags_WrapX)
13456 bb_rel.TranslateY(-bb_rel.GetHeight());
13457 clip_dir = ImGuiDir_Up;
13461 if (
g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
13463 bb_rel.Min.x = bb_rel.Max.x = -window->WindowPadding.x;
13464 if (move_flags & ImGuiNavMoveFlags_WrapX)
13466 bb_rel.TranslateY(+bb_rel.GetHeight());
13467 clip_dir = ImGuiDir_Down;
13471 if (
g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
13473 bb_rel.Min.y = bb_rel.Max.y = window->ContentSize.y + window->WindowPadding.y;
13474 if (move_flags & ImGuiNavMoveFlags_WrapY)
13476 bb_rel.TranslateX(-bb_rel.GetWidth());
13477 clip_dir = ImGuiDir_Left;
13481 if (
g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
13483 bb_rel.Min.y = bb_rel.Max.y = -window->WindowPadding.y;
13484 if (move_flags & ImGuiNavMoveFlags_WrapY)
13486 bb_rel.TranslateX(+bb_rel.GetWidth());
13487 clip_dir = ImGuiDir_Right;
13493 window->NavRectRel[
g.NavLayer] = bb_rel;
13494 NavClearPreferredPosForAxis(ImGuiAxis_X);
13495 NavClearPreferredPosForAxis(ImGuiAxis_Y);
13496 NavMoveRequestForward(
g.NavMoveDir, clip_dir, move_flags,
g.NavMoveScrollFlags);
13499static int ImGui::FindWindowFocusIndex(ImGuiWindow* window)
13503 int order = window->FocusOrder;
13504 IM_ASSERT(window->RootWindow == window);
13505 IM_ASSERT(
g.WindowsFocusOrder[order] == window);
13509static ImGuiWindow* FindWindowNavFocusable(
int i_start,
int i_stop,
int dir)
13512 for (
int i = i_start; i >= 0 && i <
g.WindowsFocusOrder.Size && i != i_stop; i += dir)
13513 if (ImGui::IsWindowNavFocusable(
g.WindowsFocusOrder[i]))
13514 return g.WindowsFocusOrder[i];
13518static void NavUpdateWindowingHighlightWindow(
int focus_change_dir)
13521 IM_ASSERT(
g.NavWindowingTarget);
13522 if (
g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)
13525 const int i_current = ImGui::FindWindowFocusIndex(
g.NavWindowingTarget);
13526 ImGuiWindow* window_target = FindWindowNavFocusable(i_current + focus_change_dir, -INT_MAX, focus_change_dir);
13527 if (!window_target)
13528 window_target = FindWindowNavFocusable((focus_change_dir < 0) ? (
g.WindowsFocusOrder.Size - 1) : 0, i_current, focus_change_dir);
13531 g.NavWindowingTarget =
g.NavWindowingTargetAnim = window_target;
13532 g.NavWindowingAccumDeltaPos =
g.NavWindowingAccumDeltaSize = ImVec2(0.0f, 0.0f);
13534 g.NavWindowingToggleLayer =
false;
13540static void ImGui::NavUpdateWindowing()
13543 ImGuiIO& io =
g.IO;
13545 ImGuiWindow* apply_focus_window = NULL;
13546 bool apply_toggle_layer =
false;
13548 ImGuiWindow* modal_window = GetTopMostPopupModal();
13549 bool allow_windowing = (modal_window == NULL);
13550 if (!allow_windowing)
13551 g.NavWindowingTarget = NULL;
13554 if (
g.NavWindowingTargetAnim &&
g.NavWindowingTarget == NULL)
13556 g.NavWindowingHighlightAlpha = ImMax(
g.NavWindowingHighlightAlpha - io.DeltaTime * 10.0f, 0.0f);
13557 if (
g.DimBgRatio <= 0.0f &&
g.NavWindowingHighlightAlpha <= 0.0f)
13558 g.NavWindowingTargetAnim = NULL;
13563 const ImGuiID owner_id =
ImHashStr(
"###NavUpdateWindowing");
13564 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
13565 const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
13566 const bool keyboard_next_window = allow_windowing &&
g.ConfigNavWindowingKeyNext && Shortcut(
g.ConfigNavWindowingKeyNext, ImGuiInputFlags_Repeat | ImGuiInputFlags_RouteAlways, owner_id);
13567 const bool keyboard_prev_window = allow_windowing &&
g.ConfigNavWindowingKeyPrev && Shortcut(
g.ConfigNavWindowingKeyPrev, ImGuiInputFlags_Repeat | ImGuiInputFlags_RouteAlways, owner_id);
13568 const bool start_windowing_with_gamepad = allow_windowing && nav_gamepad_active && !
g.NavWindowingTarget && IsKeyPressed(ImGuiKey_NavGamepadMenu, ImGuiInputFlags_None);
13569 const bool start_windowing_with_keyboard = allow_windowing && !
g.NavWindowingTarget && (keyboard_next_window || keyboard_prev_window);
13570 if (start_windowing_with_gamepad || start_windowing_with_keyboard)
13571 if (ImGuiWindow* window =
g.NavWindow ?
g.NavWindow : FindWindowNavFocusable(
g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
13573 g.NavWindowingTarget =
g.NavWindowingTargetAnim = window->RootWindow;
13574 g.NavWindowingTimer =
g.NavWindowingHighlightAlpha = 0.0f;
13575 g.NavWindowingAccumDeltaPos =
g.NavWindowingAccumDeltaSize = ImVec2(0.0f, 0.0f);
13576 g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true :
false;
13577 g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad;
13580 if (keyboard_next_window || keyboard_prev_window)
13581 SetKeyOwnersForKeyChord((
g.ConfigNavWindowingKeyNext |
g.ConfigNavWindowingKeyPrev) & ImGuiMod_Mask_, owner_id);
13585 g.NavWindowingTimer += io.DeltaTime;
13586 if (
g.NavWindowingTarget &&
g.NavInputSource == ImGuiInputSource_Gamepad)
13589 g.NavWindowingHighlightAlpha = ImMax(
g.NavWindowingHighlightAlpha, ImSaturate((
g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
13592 const int focus_change_dir = (int)IsKeyPressed(ImGuiKey_GamepadL1) - (int)IsKeyPressed(ImGuiKey_GamepadR1);
13593 if (focus_change_dir != 0)
13595 NavUpdateWindowingHighlightWindow(focus_change_dir);
13596 g.NavWindowingHighlightAlpha = 1.0f;
13600 if (!IsKeyDown(ImGuiKey_NavGamepadMenu))
13602 g.NavWindowingToggleLayer &= (
g.NavWindowingHighlightAlpha < 1.0f);
13603 if (
g.NavWindowingToggleLayer &&
g.NavWindow)
13604 apply_toggle_layer =
true;
13605 else if (!
g.NavWindowingToggleLayer)
13606 apply_focus_window =
g.NavWindowingTarget;
13607 g.NavWindowingTarget = NULL;
13612 if (
g.NavWindowingTarget &&
g.NavInputSource == ImGuiInputSource_Keyboard)
13615 ImGuiKeyChord shared_mods = ((
g.ConfigNavWindowingKeyNext ?
g.ConfigNavWindowingKeyNext : ImGuiMod_Mask_) & (
g.ConfigNavWindowingKeyPrev ?
g.ConfigNavWindowingKeyPrev : ImGuiMod_Mask_)) & ImGuiMod_Mask_;
13616 IM_ASSERT(shared_mods != 0);
13617 g.NavWindowingHighlightAlpha = ImMax(
g.NavWindowingHighlightAlpha, ImSaturate((
g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
13618 if (keyboard_next_window || keyboard_prev_window)
13619 NavUpdateWindowingHighlightWindow(keyboard_next_window ? -1 : +1);
13620 else if ((io.KeyMods & shared_mods) != shared_mods)
13621 apply_focus_window =
g.NavWindowingTarget;
13625 const ImGuiKey windowing_toggle_keys[] = { ImGuiKey_LeftAlt, ImGuiKey_RightAlt };
13626 for (ImGuiKey windowing_toggle_key : windowing_toggle_keys)
13627 if (nav_keyboard_active && IsKeyPressed(windowing_toggle_key, 0, ImGuiKeyOwner_NoOwner))
13629 g.NavWindowingToggleLayer =
true;
13630 g.NavWindowingToggleKey = windowing_toggle_key;
13631 g.NavInputSource = ImGuiInputSource_Keyboard;
13634 if (
g.NavWindowingToggleLayer &&
g.NavInputSource == ImGuiInputSource_Keyboard)
13640 if (io.InputQueueCharacters.Size > 0 || io.KeyCtrl || io.KeyShift || io.KeySuper)
13641 g.NavWindowingToggleLayer =
false;
13642 if (TestKeyOwner(
g.NavWindowingToggleKey, ImGuiKeyOwner_NoOwner) ==
false || TestKeyOwner(ImGuiMod_Alt, ImGuiKeyOwner_NoOwner) ==
false)
13643 g.NavWindowingToggleLayer =
false;
13647 if (IsKeyReleased(
g.NavWindowingToggleKey) &&
g.NavWindowingToggleLayer)
13648 if (
g.ActiveId == 0 ||
g.ActiveIdAllowOverlap)
13649 if (IsMousePosValid(&io.MousePos) == IsMousePosValid(&io.MousePosPrev))
13650 apply_toggle_layer =
true;
13651 if (!IsKeyDown(
g.NavWindowingToggleKey))
13652 g.NavWindowingToggleLayer =
false;
13656 if (
g.NavWindowingTarget && !(
g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove))
13658 ImVec2 nav_move_dir;
13659 if (
g.NavInputSource == ImGuiInputSource_Keyboard && !io.KeyShift)
13660 nav_move_dir = GetKeyMagnitude2d(ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow);
13661 if (
g.NavInputSource == ImGuiInputSource_Gamepad)
13662 nav_move_dir = GetKeyMagnitude2d(ImGuiKey_GamepadLStickLeft, ImGuiKey_GamepadLStickRight, ImGuiKey_GamepadLStickUp, ImGuiKey_GamepadLStickDown);
13663 if (nav_move_dir.x != 0.0f || nav_move_dir.y != 0.0f)
13665 const float NAV_MOVE_SPEED = 800.0f;
13666 const float move_step = NAV_MOVE_SPEED * io.DeltaTime * ImMin(io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
13667 g.NavWindowingAccumDeltaPos += nav_move_dir * move_step;
13668 g.NavDisableMouseHover =
true;
13669 ImVec2 accum_floored = ImTrunc(
g.NavWindowingAccumDeltaPos);
13670 if (accum_floored.x != 0.0f || accum_floored.y != 0.0f)
13672 ImGuiWindow* moving_window =
g.NavWindowingTarget->RootWindowDockTree;
13673 SetWindowPos(moving_window, moving_window->Pos + accum_floored, ImGuiCond_Always);
13674 g.NavWindowingAccumDeltaPos -= accum_floored;
13680 if (apply_focus_window && (
g.NavWindow == NULL || apply_focus_window !=
g.NavWindow->RootWindow))
13684 ImGuiViewport* previous_viewport =
g.NavWindow ?
g.NavWindow->Viewport : NULL;
13686 NavRestoreHighlightAfterMove();
13687 ClosePopupsOverWindow(apply_focus_window,
false);
13688 FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild);
13689 apply_focus_window =
g.NavWindow;
13690 if (apply_focus_window->NavLastIds[0] == 0)
13691 NavInitWindow(apply_focus_window,
false);
13700 if (apply_focus_window->DC.NavLayersActiveMaskNext == (1 << ImGuiNavLayer_Menu))
13701 g.NavLayer = ImGuiNavLayer_Menu;
13704 if (apply_focus_window->Viewport != previous_viewport &&
g.PlatformIO.Platform_SetWindowFocus)
13705 g.PlatformIO.Platform_SetWindowFocus(apply_focus_window->Viewport);
13707 if (apply_focus_window)
13708 g.NavWindowingTarget = NULL;
13711 if (apply_toggle_layer &&
g.NavWindow)
13716 ImGuiWindow* new_nav_window =
g.NavWindow;
13717 while (new_nav_window->ParentWindow
13718 && (new_nav_window->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) == 0
13719 && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0
13720 && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
13721 new_nav_window = new_nav_window->ParentWindow;
13722 if (new_nav_window !=
g.NavWindow)
13724 ImGuiWindow* old_nav_window =
g.NavWindow;
13725 FocusWindow(new_nav_window);
13726 new_nav_window->NavLastChildNavWindow = old_nav_window;
13730 const ImGuiNavLayer new_nav_layer = (
g.NavWindow->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((
int)
g.NavLayer ^ 1) : ImGuiNavLayer_Main;
13731 if (new_nav_layer !=
g.NavLayer)
13734 const bool preserve_layer_1_nav_id = (new_nav_window->DockNodeAsHost != NULL);
13735 if (new_nav_layer == ImGuiNavLayer_Menu && !preserve_layer_1_nav_id)
13736 g.NavWindow->NavLastIds[new_nav_layer] = 0;
13737 NavRestoreLayer(new_nav_layer);
13738 NavRestoreHighlightAfterMove();
13744static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window)
13746 if (window->Flags & ImGuiWindowFlags_Popup)
13747 return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingPopup);
13748 if ((window->Flags & ImGuiWindowFlags_MenuBar) && strcmp(window->Name,
"##MainMenuBar") == 0)
13749 return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingMainMenuBar);
13750 if (window->DockNodeAsHost)
13751 return "(Dock node)";
13752 return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingUntitled);
13756void ImGui::NavUpdateWindowingOverlay()
13759 IM_ASSERT(
g.NavWindowingTarget != NULL);
13761 if (
g.NavWindowingTimer < NAV_WINDOWING_LIST_APPEAR_DELAY)
13764 if (
g.NavWindowingListWindow == NULL)
13765 g.NavWindowingListWindow = FindWindowByName(
"###NavWindowingList");
13766 const ImGuiViewport* viewport = GetMainViewport();
13767 SetNextWindowSizeConstraints(ImVec2(viewport->Size.x * 0.20f, viewport->Size.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX));
13768 SetNextWindowPos(viewport->GetCenter(), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
13769 PushStyleVar(ImGuiStyleVar_WindowPadding,
g.Style.WindowPadding * 2.0f);
13770 Begin(
"###NavWindowingList", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings);
13771 for (
int n =
g.WindowsFocusOrder.Size - 1; n >= 0; n--)
13773 ImGuiWindow* window =
g.WindowsFocusOrder[n];
13774 IM_ASSERT(window != NULL);
13775 if (!IsWindowNavFocusable(window))
13777 const char* label = window->Name;
13778 if (label == FindRenderedTextEnd(label))
13779 label = GetFallbackWindowNameForWindowingList(window);
13780 Selectable(label,
g.NavWindowingTarget == window);
13791bool ImGui::IsDragDropActive()
13794 return g.DragDropActive;
13797void ImGui::ClearDragDrop()
13800 g.DragDropActive =
false;
13801 g.DragDropPayload.Clear();
13802 g.DragDropAcceptFlags = ImGuiDragDropFlags_None;
13803 g.DragDropAcceptIdCurr =
g.DragDropAcceptIdPrev = 0;
13804 g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
13805 g.DragDropAcceptFrameCount = -1;
13807 g.DragDropPayloadBufHeap.clear();
13808 memset(&
g.DragDropPayloadBufLocal, 0,
sizeof(
g.DragDropPayloadBufLocal));
13811bool ImGui::BeginTooltipHidden()
13814 bool ret = Begin(
"##Tooltip_Hidden", NULL, ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize);
13815 SetWindowHiddenAndSkipItemsForCurrentFrame(
g.CurrentWindow);
13826bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
13829 ImGuiWindow* window =
g.CurrentWindow;
13833 ImGuiMouseButton mouse_button = ImGuiMouseButton_Left;
13835 bool source_drag_active =
false;
13836 ImGuiID source_id = 0;
13837 ImGuiID source_parent_id = 0;
13838 if (!(flags & ImGuiDragDropFlags_SourceExtern))
13840 source_id =
g.LastItemData.ID;
13841 if (source_id != 0)
13844 if (
g.ActiveId != source_id)
13846 if (
g.ActiveIdMouseButton != -1)
13847 mouse_button =
g.ActiveIdMouseButton;
13848 if (
g.IO.MouseDown[mouse_button] ==
false || window->SkipItems)
13850 g.ActiveIdAllowOverlap =
false;
13855 if (
g.IO.MouseDown[mouse_button] ==
false || window->SkipItems)
13857 if ((
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) == 0 && (
g.ActiveId == 0 ||
g.ActiveIdWindow != window))
13862 if (!(flags & ImGuiDragDropFlags_SourceAllowNullID))
13873 source_id =
g.LastItemData.ID = window->GetIDFromRectangle(
g.LastItemData.Rect);
13874 KeepAliveID(source_id);
13875 bool is_hovered = ItemHoverable(
g.LastItemData.Rect, source_id,
g.LastItemData.InFlags);
13876 if (is_hovered &&
g.IO.MouseClicked[mouse_button])
13878 SetActiveID(source_id, window);
13879 FocusWindow(window);
13881 if (
g.ActiveId == source_id)
13882 g.ActiveIdAllowOverlap = is_hovered;
13884 if (
g.ActiveId != source_id)
13886 source_parent_id = window->IDStack.back();
13887 source_drag_active = IsMouseDragging(mouse_button);
13890 SetActiveIdUsingAllKeyboardKeys();
13895 source_id =
ImHashStr(
"#SourceExtern");
13896 source_drag_active =
true;
13899 IM_ASSERT(
g.DragDropWithinTarget ==
false);
13900 if (source_drag_active)
13902 if (!
g.DragDropActive)
13904 IM_ASSERT(source_id != 0);
13906 ImGuiPayload& payload =
g.DragDropPayload;
13907 payload.SourceId = source_id;
13908 payload.SourceParentId = source_parent_id;
13909 g.DragDropActive =
true;
13910 g.DragDropSourceFlags = flags;
13911 g.DragDropMouseButton = mouse_button;
13912 if (payload.SourceId ==
g.ActiveId)
13913 g.ActiveIdNoClearOnFocusLoss =
true;
13915 g.DragDropSourceFrameCount =
g.FrameCount;
13916 g.DragDropWithinSource =
true;
13918 if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
13923 if (
g.DragDropAcceptIdPrev && (
g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
13924 ret = BeginTooltipHidden();
13926 ret = BeginTooltip();
13931 if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
13932 g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
13939void ImGui::EndDragDropSource()
13942 IM_ASSERT(
g.DragDropActive);
13943 IM_ASSERT(
g.DragDropWithinSource &&
"Not after a BeginDragDropSource()?");
13945 if (!(
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
13949 if (
g.DragDropPayload.DataFrameCount == -1)
13951 g.DragDropWithinSource =
false;
13955bool ImGui::SetDragDropPayload(
const char* type,
const void* data,
size_t data_size, ImGuiCond cond)
13958 ImGuiPayload& payload =
g.DragDropPayload;
13960 cond = ImGuiCond_Always;
13962 IM_ASSERT(type != NULL);
13963 IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType) &&
"Payload type can be at most 32 characters long");
13964 IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0));
13965 IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once);
13966 IM_ASSERT(payload.SourceId != 0);
13968 if (cond == ImGuiCond_Always || payload.DataFrameCount == -1)
13971 ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType));
13972 g.DragDropPayloadBufHeap.resize(0);
13973 if (data_size >
sizeof(
g.DragDropPayloadBufLocal))
13976 g.DragDropPayloadBufHeap.resize((
int)data_size);
13977 payload.Data =
g.DragDropPayloadBufHeap.Data;
13978 memcpy(payload.Data, data, data_size);
13980 else if (data_size > 0)
13983 memset(&
g.DragDropPayloadBufLocal, 0,
sizeof(
g.DragDropPayloadBufLocal));
13984 payload.Data =
g.DragDropPayloadBufLocal;
13985 memcpy(payload.Data, data, data_size);
13989 payload.Data = NULL;
13991 payload.DataSize = (int)data_size;
13993 payload.DataFrameCount =
g.FrameCount;
13996 return (
g.DragDropAcceptFrameCount ==
g.FrameCount) || (
g.DragDropAcceptFrameCount ==
g.FrameCount - 1);
13999bool ImGui::BeginDragDropTargetCustom(
const ImRect& bb, ImGuiID
id)
14002 if (!
g.DragDropActive)
14005 ImGuiWindow* window =
g.CurrentWindow;
14006 ImGuiWindow* hovered_window =
g.HoveredWindowUnderMovingWindow;
14007 if (hovered_window == NULL || window->RootWindowDockTree != hovered_window->RootWindowDockTree)
14009 IM_ASSERT(
id != 0);
14010 if (!IsMouseHoveringRect(bb.Min, bb.Max) || (
id ==
g.DragDropPayload.SourceId))
14012 if (window->SkipItems)
14015 IM_ASSERT(
g.DragDropWithinTarget ==
false &&
g.DragDropWithinSource ==
false);
14016 g.DragDropTargetRect = bb;
14017 g.DragDropTargetClipRect = window->ClipRect;
14018 g.DragDropTargetId =
id;
14019 g.DragDropWithinTarget =
true;
14027bool ImGui::BeginDragDropTarget()
14030 if (!
g.DragDropActive)
14033 ImGuiWindow* window =
g.CurrentWindow;
14034 if (!(
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect))
14036 ImGuiWindow* hovered_window =
g.HoveredWindowUnderMovingWindow;
14037 if (hovered_window == NULL || window->RootWindowDockTree != hovered_window->RootWindowDockTree || window->SkipItems)
14040 const ImRect& display_rect = (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ?
g.LastItemData.DisplayRect :
g.LastItemData.Rect;
14041 ImGuiID
id =
g.LastItemData.ID;
14044 id = window->GetIDFromRectangle(display_rect);
14047 if (
g.DragDropPayload.SourceId ==
id)
14050 IM_ASSERT(
g.DragDropWithinTarget ==
false &&
g.DragDropWithinSource ==
false);
14051 g.DragDropTargetRect = display_rect;
14052 g.DragDropTargetClipRect = (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasClipRect) ?
g.LastItemData.ClipRect : window->ClipRect;
14053 g.DragDropTargetId =
id;
14054 g.DragDropWithinTarget =
true;
14058bool ImGui::IsDragDropPayloadBeingAccepted()
14061 return g.DragDropActive &&
g.DragDropAcceptIdPrev != 0;
14064const ImGuiPayload* ImGui::AcceptDragDropPayload(
const char* type, ImGuiDragDropFlags flags)
14067 ImGuiPayload& payload =
g.DragDropPayload;
14068 IM_ASSERT(
g.DragDropActive);
14069 IM_ASSERT(payload.DataFrameCount != -1);
14070 if (type != NULL && !payload.IsDataType(type))
14075 const bool was_accepted_previously = (
g.DragDropAcceptIdPrev ==
g.DragDropTargetId);
14076 ImRect r =
g.DragDropTargetRect;
14077 float r_surface = r.GetWidth() * r.GetHeight();
14078 if (r_surface >
g.DragDropAcceptIdCurrRectSurface)
14081 g.DragDropAcceptFlags = flags;
14082 g.DragDropAcceptIdCurr =
g.DragDropTargetId;
14083 g.DragDropAcceptIdCurrRectSurface = r_surface;
14087 payload.Preview = was_accepted_previously;
14088 flags |= (
g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect);
14089 if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview)
14090 RenderDragDropTargetRect(r,
g.DragDropTargetClipRect);
14092 g.DragDropAcceptFrameCount =
g.FrameCount;
14093 payload.Delivery = was_accepted_previously && !IsMouseDown(
g.DragDropMouseButton);
14094 if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery))
14102void ImGui::RenderDragDropTargetRect(
const ImRect& bb,
const ImRect& item_clip_rect)
14105 ImGuiWindow* window =
g.CurrentWindow;
14106 ImRect bb_display = bb;
14107 bb_display.ClipWith(item_clip_rect);
14108 bb_display.Expand(3.5f);
14109 bool push_clip_rect = !window->ClipRect.Contains(bb_display);
14110 if (push_clip_rect)
14111 window->DrawList->PushClipRectFullScreen();
14112 window->DrawList->AddRect(bb_display.Min, bb_display.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f);
14113 if (push_clip_rect)
14114 window->DrawList->PopClipRect();
14117const ImGuiPayload* ImGui::GetDragDropPayload()
14120 return (
g.DragDropActive &&
g.DragDropPayload.DataFrameCount != -1) ? &
g.DragDropPayload : NULL;
14123void ImGui::EndDragDropTarget()
14126 IM_ASSERT(
g.DragDropActive);
14127 IM_ASSERT(
g.DragDropWithinTarget);
14128 g.DragDropWithinTarget =
false;
14131 if (
g.DragDropPayload.Delivery)
14143static inline void LogTextV(ImGuiContext&
g,
const char* fmt, va_list args)
14147 g.LogBuffer.Buf.resize(0);
14148 g.LogBuffer.appendfv(fmt, args);
14149 ImFileWrite(
g.LogBuffer.c_str(),
sizeof(
char), (ImU64)
g.LogBuffer.size(),
g.LogFile);
14153 g.LogBuffer.appendfv(fmt, args);
14157void ImGui::LogText(
const char* fmt, ...)
14164 va_start(args, fmt);
14165 LogTextV(
g, fmt, args);
14169void ImGui::LogTextV(
const char* fmt, va_list args)
14175 LogTextV(
g, fmt, args);
14181void ImGui::LogRenderedText(
const ImVec2* ref_pos,
const char* text,
const char* text_end)
14184 ImGuiWindow* window =
g.CurrentWindow;
14186 const char* prefix =
g.LogNextPrefix;
14187 const char* suffix =
g.LogNextSuffix;
14188 g.LogNextPrefix =
g.LogNextSuffix = NULL;
14191 text_end = FindRenderedTextEnd(text, text_end);
14193 const bool log_new_line = ref_pos && (ref_pos->y >
g.LogLinePosY +
g.Style.FramePadding.y + 1);
14195 g.LogLinePosY = ref_pos->y;
14199 g.LogLineFirstItem =
true;
14203 LogRenderedText(ref_pos, prefix, prefix + strlen(prefix));
14206 if (
g.LogDepthRef > window->DC.TreeDepth)
14207 g.LogDepthRef = window->DC.TreeDepth;
14208 const int tree_depth = (window->DC.TreeDepth -
g.LogDepthRef);
14210 const char* text_remaining = text;
14215 const char* line_start = text_remaining;
14216 const char* line_end =
ImStreolRange(line_start, text_end);
14217 const bool is_last_line = (line_end == text_end);
14218 if (line_start != line_end || !is_last_line)
14220 const int line_length = (int)(line_end - line_start);
14221 const int indentation =
g.LogLineFirstItem ? tree_depth * 4 : 1;
14222 LogText(
"%*s%.*s", indentation,
"", line_length, line_start);
14223 g.LogLineFirstItem =
false;
14224 if (*line_end ==
'\n')
14227 g.LogLineFirstItem =
true;
14232 text_remaining = line_end + 1;
14236 LogRenderedText(ref_pos, suffix, suffix + strlen(suffix));
14240void ImGui::LogBegin(ImGuiLogType type,
int auto_open_depth)
14243 ImGuiWindow* window =
g.CurrentWindow;
14244 IM_ASSERT(
g.LogEnabled ==
false);
14245 IM_ASSERT(
g.LogFile == NULL);
14246 IM_ASSERT(
g.LogBuffer.empty());
14247 g.LogEnabled =
true;
14249 g.LogNextPrefix =
g.LogNextSuffix = NULL;
14250 g.LogDepthRef = window->DC.TreeDepth;
14251 g.LogDepthToExpand = ((auto_open_depth >= 0) ? auto_open_depth :
g.LogDepthToExpandDefault);
14252 g.LogLinePosY = FLT_MAX;
14253 g.LogLineFirstItem =
true;
14257void ImGui::LogSetNextTextDecoration(
const char* prefix,
const char* suffix)
14260 g.LogNextPrefix = prefix;
14261 g.LogNextSuffix = suffix;
14264void ImGui::LogToTTY(
int auto_open_depth)
14269 IM_UNUSED(auto_open_depth);
14270#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
14271 LogBegin(ImGuiLogType_TTY, auto_open_depth);
14272 g.LogFile = stdout;
14277void ImGui::LogToFile(
int auto_open_depth,
const char* filename)
14287 filename =
g.IO.LogFilename;
14288 if (!filename || !filename[0])
14290 ImFileHandle f =
ImFileOpen(filename,
"ab");
14297 LogBegin(ImGuiLogType_File, auto_open_depth);
14302void ImGui::LogToClipboard(
int auto_open_depth)
14307 LogBegin(ImGuiLogType_Clipboard, auto_open_depth);
14310void ImGui::LogToBuffer(
int auto_open_depth)
14315 LogBegin(ImGuiLogType_Buffer, auto_open_depth);
14318void ImGui::LogFinish()
14327 case ImGuiLogType_TTY:
14328#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
14332 case ImGuiLogType_File:
14335 case ImGuiLogType_Buffer:
14337 case ImGuiLogType_Clipboard:
14338 if (!
g.LogBuffer.empty())
14339 SetClipboardText(
g.LogBuffer.begin());
14341 case ImGuiLogType_None:
14346 g.LogEnabled =
false;
14347 g.LogType = ImGuiLogType_None;
14349 g.LogBuffer.clear();
14354void ImGui::LogButtons()
14358 PushID(
"LogButtons");
14359#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
14360 const bool log_to_tty = Button(
"Log To TTY"); SameLine();
14362 const bool log_to_tty =
false;
14364 const bool log_to_file = Button(
"Log To File"); SameLine();
14365 const bool log_to_clipboard = Button(
"Log To Clipboard"); SameLine();
14366 PushTabStop(
false);
14367 SetNextItemWidth(80.0f);
14368 SliderInt(
"Default Depth", &
g.LogDepthToExpandDefault, 0, 9, NULL);
14377 if (log_to_clipboard)
14402void ImGui::UpdateSettings()
14406 if (!
g.SettingsLoaded)
14408 IM_ASSERT(
g.SettingsWindows.empty());
14409 if (
g.IO.IniFilename)
14410 LoadIniSettingsFromDisk(
g.IO.IniFilename);
14411 g.SettingsLoaded =
true;
14415 if (
g.SettingsDirtyTimer > 0.0f)
14417 g.SettingsDirtyTimer -=
g.IO.DeltaTime;
14418 if (
g.SettingsDirtyTimer <= 0.0f)
14420 if (
g.IO.IniFilename != NULL)
14421 SaveIniSettingsToDisk(
g.IO.IniFilename);
14423 g.IO.WantSaveIniSettings =
true;
14424 g.SettingsDirtyTimer = 0.0f;
14429void ImGui::MarkIniSettingsDirty()
14432 if (
g.SettingsDirtyTimer <= 0.0f)
14433 g.SettingsDirtyTimer =
g.IO.IniSavingRate;
14436void ImGui::MarkIniSettingsDirty(ImGuiWindow* window)
14439 if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
14440 if (
g.SettingsDirtyTimer <= 0.0f)
14441 g.SettingsDirtyTimer =
g.IO.IniSavingRate;
14444void ImGui::AddSettingsHandler(
const ImGuiSettingsHandler* handler)
14447 IM_ASSERT(FindSettingsHandler(handler->TypeName) == NULL);
14448 g.SettingsHandlers.push_back(*handler);
14451void ImGui::RemoveSettingsHandler(
const char* type_name)
14454 if (ImGuiSettingsHandler* handler = FindSettingsHandler(type_name))
14455 g.SettingsHandlers.erase(handler);
14458ImGuiSettingsHandler* ImGui::FindSettingsHandler(
const char* type_name)
14461 const ImGuiID type_hash =
ImHashStr(type_name);
14462 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
14463 if (handler.TypeHash == type_hash)
14469void ImGui::ClearIniSettings()
14472 g.SettingsIniData.clear();
14473 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
14474 if (handler.ClearAllFn != NULL)
14475 handler.ClearAllFn(&
g, &handler);
14478void ImGui::LoadIniSettingsFromDisk(
const char* ini_filename)
14480 size_t file_data_size = 0;
14484 if (file_data_size > 0)
14485 LoadIniSettingsFromMemory(file_data, (
size_t)file_data_size);
14486 IM_FREE(file_data);
14491void ImGui::LoadIniSettingsFromMemory(
const char* ini_data,
size_t ini_size)
14494 IM_ASSERT(
g.Initialized);
14501 ini_size = strlen(ini_data);
14502 g.SettingsIniData.Buf.resize((
int)ini_size + 1);
14503 char*
const buf =
g.SettingsIniData.Buf.Data;
14504 char*
const buf_end = buf + ini_size;
14505 memcpy(buf, ini_data, ini_size);
14510 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
14511 if (handler.ReadInitFn != NULL)
14512 handler.ReadInitFn(&
g, &handler);
14514 void* entry_data = NULL;
14515 ImGuiSettingsHandler* entry_handler = NULL;
14517 char* line_end = NULL;
14518 for (
char* line = buf; line < buf_end; line = line_end + 1)
14521 while (*line ==
'\n' || *line ==
'\r')
14524 while (line_end < buf_end && *line_end !=
'\n' && *line_end !=
'\r')
14527 if (line[0] ==
';')
14529 if (line[0] ==
'[' && line_end > line && line_end[-1] ==
']')
14533 const char* name_end = line_end - 1;
14534 const char* type_start = line + 1;
14535 char* type_end = (
char*)(
void*)
ImStrchrRange(type_start, name_end,
']');
14536 const char* name_start = type_end ?
ImStrchrRange(type_end + 1, name_end,
'[') : NULL;
14537 if (!type_end || !name_start)
14541 entry_handler = FindSettingsHandler(type_start);
14542 entry_data = entry_handler ? entry_handler->ReadOpenFn(&
g, entry_handler, name_start) : NULL;
14544 else if (entry_handler != NULL && entry_data != NULL)
14547 entry_handler->ReadLineFn(&
g, entry_handler, entry_data, line);
14550 g.SettingsLoaded =
true;
14553 memcpy(buf, ini_data, ini_size);
14556 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
14557 if (handler.ApplyAllFn != NULL)
14558 handler.ApplyAllFn(&
g, &handler);
14561void ImGui::SaveIniSettingsToDisk(
const char* ini_filename)
14564 g.SettingsDirtyTimer = 0.0f;
14568 size_t ini_data_size = 0;
14569 const char* ini_data = SaveIniSettingsToMemory(&ini_data_size);
14570 ImFileHandle f =
ImFileOpen(ini_filename,
"wt");
14573 ImFileWrite(ini_data,
sizeof(
char), ini_data_size, f);
14578const char* ImGui::SaveIniSettingsToMemory(
size_t* out_size)
14581 g.SettingsDirtyTimer = 0.0f;
14582 g.SettingsIniData.Buf.resize(0);
14583 g.SettingsIniData.Buf.push_back(0);
14584 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
14585 handler.WriteAllFn(&
g, &handler, &
g.SettingsIniData);
14587 *out_size = (size_t)
g.SettingsIniData.size();
14588 return g.SettingsIniData.c_str();
14591ImGuiWindowSettings* ImGui::CreateNewWindowSettings(
const char* name)
14595 if (
g.IO.ConfigDebugIniSettings ==
false)
14599 if (
const char* p = strstr(name,
"###"))
14602 const size_t name_len = strlen(name);
14605 const size_t chunk_size =
sizeof(ImGuiWindowSettings) + name_len + 1;
14606 ImGuiWindowSettings* settings =
g.SettingsWindows.alloc_chunk(chunk_size);
14607 IM_PLACEMENT_NEW(settings) ImGuiWindowSettings();
14608 settings->ID =
ImHashStr(name, name_len);
14609 memcpy(settings->GetName(), name, name_len + 1);
14616ImGuiWindowSettings* ImGui::FindWindowSettingsByID(ImGuiID
id)
14619 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
14620 if (settings->ID ==
id && !settings->WantDelete)
14626ImGuiWindowSettings* ImGui::FindWindowSettingsByWindow(ImGuiWindow* window)
14629 if (window->SettingsOffset != -1)
14630 return g.SettingsWindows.ptr_from_offset(window->SettingsOffset);
14631 return FindWindowSettingsByID(window->ID);
14635void ImGui::ClearWindowSettings(
const char* name)
14639 ImGuiWindow* window = FindWindowByName(name);
14640 if (window != NULL)
14642 window->Flags |= ImGuiWindowFlags_NoSavedSettings;
14643 InitOrLoadWindowSettings(window, NULL);
14644 if (window->DockId != 0)
14645 DockContextProcessUndockWindow(&
g, window,
true);
14647 if (ImGuiWindowSettings* settings = window ? FindWindowSettingsByWindow(window) : FindWindowSettingsByID(
ImHashStr(name)))
14648 settings->WantDelete = true;
14651static void WindowSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
14653 ImGuiContext&
g = *ctx;
14654 for (ImGuiWindow* window :
g.Windows)
14655 window->SettingsOffset = -1;
14656 g.SettingsWindows.clear();
14659static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*,
const char* name)
14662 ImGuiWindowSettings* settings = ImGui::FindWindowSettingsByID(
id);
14664 *settings = ImGuiWindowSettings();
14666 settings = ImGui::CreateNewWindowSettings(name);
14668 settings->WantApply =
true;
14669 return (
void*)settings;
14672static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
void* entry,
const char* line)
14674 ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry;
14678 if (sscanf(line,
"Pos=%i,%i", &x, &y) == 2) { settings->Pos = ImVec2ih((
short)x, (
short)y); }
14679 else if (sscanf(line,
"Size=%i,%i", &x, &y) == 2) { settings->Size = ImVec2ih((
short)x, (
short)y); }
14680 else if (sscanf(line,
"ViewportId=0x%08X", &u1) == 1) { settings->ViewportId = u1; }
14681 else if (sscanf(line,
"ViewportPos=%i,%i", &x, &y) == 2){ settings->ViewportPos = ImVec2ih((
short)x, (
short)y); }
14682 else if (sscanf(line,
"Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); }
14683 else if (sscanf(line,
"IsChild=%d", &i) == 1) { settings->IsChild = (i != 0); }
14684 else if (sscanf(line,
"DockId=0x%X,%d", &u1, &i) == 2) { settings->DockId = u1; settings->DockOrder = (short)i; }
14685 else if (sscanf(line,
"DockId=0x%X", &u1) == 1) { settings->DockId = u1; settings->DockOrder = -1; }
14686 else if (sscanf(line,
"ClassId=0x%X", &u1) == 1) { settings->ClassId = u1; }
14690static void WindowSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
14692 ImGuiContext&
g = *ctx;
14693 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
14694 if (settings->WantApply)
14696 if (ImGuiWindow* window = ImGui::FindWindowByID(settings->ID))
14697 ApplyWindowSettings(window, settings);
14698 settings->WantApply =
false;
14702static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
14706 ImGuiContext&
g = *ctx;
14707 for (ImGuiWindow* window :
g.Windows)
14709 if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
14712 ImGuiWindowSettings* settings = ImGui::FindWindowSettingsByWindow(window);
14715 settings = ImGui::CreateNewWindowSettings(window->Name);
14716 window->SettingsOffset =
g.SettingsWindows.offset_from_ptr(settings);
14718 IM_ASSERT(settings->ID == window->ID);
14719 settings->Pos = ImVec2ih(window->Pos - window->ViewportPos);
14720 settings->Size = ImVec2ih(window->SizeFull);
14721 settings->ViewportId = window->ViewportId;
14722 settings->ViewportPos = ImVec2ih(window->ViewportPos);
14723 IM_ASSERT(window->DockNode == NULL || window->DockNode->ID == window->DockId);
14724 settings->DockId = window->DockId;
14725 settings->ClassId = window->WindowClass.ClassId;
14726 settings->DockOrder = window->DockOrder;
14727 settings->Collapsed = window->Collapsed;
14728 settings->IsChild = (window->RootWindow != window);
14729 settings->WantDelete =
false;
14733 buf->reserve(buf->size() +
g.SettingsWindows.size() * 6);
14734 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
14736 if (settings->WantDelete)
14738 const char* settings_name = settings->GetName();
14739 buf->appendf(
"[%s][%s]\n", handler->TypeName, settings_name);
14740 if (settings->IsChild)
14742 buf->appendf(
"IsChild=1\n");
14743 buf->appendf(
"Size=%d,%d\n", settings->Size.x, settings->Size.y);
14749 buf->appendf(
"ViewportPos=%d,%d\n", settings->ViewportPos.x, settings->ViewportPos.y);
14750 buf->appendf(
"ViewportId=0x%08X\n", settings->ViewportId);
14753 buf->appendf(
"Pos=%d,%d\n", settings->Pos.x, settings->Pos.y);
14754 if (settings->Size.x != 0 || settings->Size.y != 0)
14755 buf->appendf(
"Size=%d,%d\n", settings->Size.x, settings->Size.y);
14756 buf->appendf(
"Collapsed=%d\n", settings->Collapsed);
14757 if (settings->DockId != 0)
14760 if (settings->DockOrder == -1)
14761 buf->appendf(
"DockId=0x%08X\n", settings->DockId);
14763 buf->appendf(
"DockId=0x%08X,%d\n", settings->DockId, settings->DockOrder);
14764 if (settings->ClassId != 0)
14765 buf->appendf(
"ClassId=0x%08X\n", settings->ClassId);
14777void ImGui::LocalizeRegisterEntries(
const ImGuiLocEntry* entries,
int count)
14780 for (
int n = 0; n <
count; n++)
14781 g.LocalizationTable[entries[n].Key] = entries[n].Text;
14813ImGuiViewport* ImGui::GetMainViewport()
14816 return g.Viewports[0];
14820ImGuiViewport* ImGui::FindViewportByID(ImGuiID
id)
14823 for (ImGuiViewportP* viewport :
g.Viewports)
14824 if (viewport->
ID ==
id)
14829ImGuiViewport* ImGui::FindViewportByPlatformHandle(
void* platform_handle)
14832 for (ImGuiViewportP* viewport :
g.Viewports)
14833 if (viewport->PlatformHandle == platform_handle)
14838void ImGui::SetCurrentViewport(ImGuiWindow* current_window, ImGuiViewportP* viewport)
14841 (void)current_window;
14844 viewport->LastFrameActive =
g.FrameCount;
14845 if (
g.CurrentViewport == viewport)
14847 g.CurrentDpiScale = viewport ? viewport->DpiScale : 1.0f;
14848 g.CurrentViewport = viewport;
14853 if (
g.CurrentViewport &&
g.PlatformIO.Platform_OnChangedViewport)
14854 g.PlatformIO.Platform_OnChangedViewport(
g.CurrentViewport);
14857void ImGui::SetWindowViewport(ImGuiWindow* window, ImGuiViewportP* viewport)
14860 if (window->ViewportOwned && window->Viewport->Window == window)
14861 window->Viewport->Size = ImVec2(0.0f, 0.0f);
14863 window->Viewport = viewport;
14864 window->ViewportId = viewport->ID;
14865 window->ViewportOwned = (viewport->Window == window);
14868static bool ImGui::GetWindowAlwaysWantOwnViewport(ImGuiWindow* window)
14872 if (
g.IO.ConfigViewportsNoAutoMerge || (window->WindowClass.ViewportFlagsOverrideSet & ImGuiViewportFlags_NoAutoMerge))
14873 if (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
14874 if (!window->DockIsActive)
14875 if ((window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip)) == 0)
14876 if ((window->Flags & ImGuiWindowFlags_Popup) == 0 || (window->Flags & ImGuiWindowFlags_Modal) != 0)
14881static bool ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* viewport)
14884 if (window->Viewport == viewport)
14886 if ((viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) == 0)
14888 if ((viewport->Flags & ImGuiViewportFlags_IsMinimized) != 0)
14890 if (!viewport->GetMainRect().Contains(window->Rect()))
14892 if (GetWindowAlwaysWantOwnViewport(window))
14896 for (ImGuiWindow* window_behind :
g.Windows)
14898 if (window_behind == window)
14900 if (window_behind->WasActive && window_behind->ViewportOwned && !(window_behind->Flags & ImGuiWindowFlags_ChildWindow))
14901 if (window_behind->Viewport->GetMainRect().Overlaps(window->Rect()))
14906 ImGuiViewportP* old_viewport = window->Viewport;
14907 if (window->ViewportOwned)
14908 for (
int n = 0; n <
g.Windows.Size; n++)
14909 if (
g.Windows[n]->Viewport == old_viewport)
14910 SetWindowViewport(
g.Windows[n], viewport);
14911 SetWindowViewport(window, viewport);
14912 BringWindowToDisplayFront(window);
14918static bool ImGui::UpdateTryMergeWindowIntoHostViewports(ImGuiWindow* window)
14921 return UpdateTryMergeWindowIntoHostViewport(window,
g.Viewports[0]);
14926void ImGui::TranslateWindowsInViewport(ImGuiViewportP* viewport,
const ImVec2& old_pos,
const ImVec2& new_pos)
14929 IM_ASSERT(viewport->Window == NULL && (viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows));
14936 const bool translate_all_windows = (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable) != (
g.ConfigFlagsLastFrame & ImGuiConfigFlags_ViewportsEnable);
14937 ImRect test_still_fit_rect(old_pos, old_pos + viewport->Size);
14938 ImVec2 delta_pos = new_pos - old_pos;
14939 for (ImGuiWindow* window :
g.Windows)
14940 if (translate_all_windows || (window->Viewport == viewport && test_still_fit_rect.Contains(window->Rect())))
14941 TranslateWindow(window, delta_pos);
14945void ImGui::ScaleWindowsInViewport(ImGuiViewportP* viewport,
float scale)
14948 if (viewport->Window)
14950 ScaleWindow(viewport->Window, scale);
14954 for (ImGuiWindow* window :
g.Windows)
14955 if (window->Viewport == viewport)
14956 ScaleWindow(window,
scale);
14963ImGuiViewportP* ImGui::FindHoveredViewportFromPlatformWindowStack(
const ImVec2& mouse_platform_pos)
14966 ImGuiViewportP* best_candidate = NULL;
14967 for (ImGuiViewportP* viewport :
g.Viewports)
14968 if (!(viewport->Flags & (ImGuiViewportFlags_NoInputs | ImGuiViewportFlags_IsMinimized)) && viewport->GetMainRect().Contains(mouse_platform_pos))
14969 if (best_candidate == NULL || best_candidate->LastFocusedStampCount < viewport->LastFocusedStampCount)
14970 best_candidate = viewport;
14971 return best_candidate;
14976static void ImGui::UpdateViewportsNewFrame()
14979 IM_ASSERT(
g.PlatformIO.Viewports.Size <=
g.Viewports.Size);
14983 const bool viewports_enabled = (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable) != 0;
14984 if (viewports_enabled)
14986 ImGuiViewportP* focused_viewport = NULL;
14987 for (ImGuiViewportP* viewport :
g.Viewports)
14989 const bool platform_funcs_available = viewport->PlatformWindowCreated;
14990 if (
g.PlatformIO.Platform_GetWindowMinimized && platform_funcs_available)
14992 bool is_minimized =
g.PlatformIO.Platform_GetWindowMinimized(viewport);
14994 viewport->Flags |= ImGuiViewportFlags_IsMinimized;
14996 viewport->Flags &= ~ImGuiViewportFlags_IsMinimized;
15001 if (
g.PlatformIO.Platform_GetWindowFocus && platform_funcs_available)
15003 bool is_focused =
g.PlatformIO.Platform_GetWindowFocus(viewport);
15005 viewport->Flags |= ImGuiViewportFlags_IsFocused;
15007 viewport->Flags &= ~ImGuiViewportFlags_IsFocused;
15009 focused_viewport = viewport;
15014 if (focused_viewport &&
g.PlatformLastFocusedViewportId != focused_viewport->ID)
15016 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Focused viewport changed %08X -> %08X, attempting to apply our focus.\n",
g.PlatformLastFocusedViewportId, focused_viewport->ID);
15017 const ImGuiViewport* prev_focused_viewport = FindViewportByID(
g.PlatformLastFocusedViewportId);
15018 const bool prev_focused_has_been_destroyed = (prev_focused_viewport == NULL) || (prev_focused_viewport->PlatformWindowCreated ==
false);
15023 if (focused_viewport->LastFocusedStampCount !=
g.ViewportFocusedStampCount)
15024 focused_viewport->LastFocusedStampCount = ++
g.ViewportFocusedStampCount;
15025 g.PlatformLastFocusedViewportId = focused_viewport->ID;
15031 const bool apply_imgui_focus_on_focused_viewport = !IsAnyMouseDown() && !prev_focused_has_been_destroyed;
15032 if (apply_imgui_focus_on_focused_viewport)
15034 focused_viewport->LastFocusedHadNavWindow |= (
g.NavWindow != NULL) && (
g.NavWindow->Viewport == focused_viewport);
15035 ImGuiFocusRequestFlags focus_request_flags = ImGuiFocusRequestFlags_UnlessBelowModal | ImGuiFocusRequestFlags_RestoreFocusedChild;
15036 if (focused_viewport->Window != NULL)
15037 FocusWindow(focused_viewport->Window, focus_request_flags);
15038 else if (focused_viewport->LastFocusedHadNavWindow)
15039 FocusTopMostWindowUnderOne(NULL, NULL, focused_viewport, focus_request_flags);
15041 FocusWindow(NULL, focus_request_flags);
15044 if (focused_viewport)
15045 focused_viewport->LastFocusedHadNavWindow = (
g.NavWindow != NULL) && (
g.NavWindow->Viewport == focused_viewport);
15050 ImGuiViewportP* main_viewport =
g.Viewports[0];
15051 IM_ASSERT(main_viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID);
15052 IM_ASSERT(main_viewport->Window == NULL);
15053 ImVec2 main_viewport_pos = viewports_enabled ?
g.PlatformIO.Platform_GetWindowPos(main_viewport) : ImVec2(0.0f, 0.0f);
15054 ImVec2 main_viewport_size =
g.IO.DisplaySize;
15055 if (viewports_enabled && (main_viewport->Flags & ImGuiViewportFlags_IsMinimized))
15057 main_viewport_pos = main_viewport->Pos;
15058 main_viewport_size = main_viewport->Size;
15060 AddUpdateViewport(NULL, IMGUI_VIEWPORT_DEFAULT_ID, main_viewport_pos, main_viewport_size, ImGuiViewportFlags_OwnedByApp | ImGuiViewportFlags_CanHostOtherWindows);
15062 g.CurrentDpiScale = 0.0f;
15063 g.CurrentViewport = NULL;
15064 g.MouseViewport = NULL;
15065 for (
int n = 0; n <
g.Viewports.Size; n++)
15067 ImGuiViewportP* viewport =
g.Viewports[n];
15071 if (n > 0 && viewport->LastFrameActive <
g.FrameCount - 2)
15073 DestroyViewport(viewport);
15078 const bool platform_funcs_available = viewport->PlatformWindowCreated;
15079 if (viewports_enabled)
15083 if (!(viewport->Flags & ImGuiViewportFlags_IsMinimized) && platform_funcs_available)
15086 if (viewport->PlatformRequestMove)
15087 viewport->Pos = viewport->LastPlatformPos =
g.PlatformIO.Platform_GetWindowPos(viewport);
15088 if (viewport->PlatformRequestResize)
15089 viewport->Size = viewport->LastPlatformSize =
g.PlatformIO.Platform_GetWindowSize(viewport);
15094 UpdateViewportPlatformMonitor(viewport);
15097 viewport->WorkOffsetMin = viewport->BuildWorkOffsetMin;
15098 viewport->WorkOffsetMax = viewport->BuildWorkOffsetMax;
15099 viewport->BuildWorkOffsetMin = viewport->BuildWorkOffsetMax = ImVec2(0.0f, 0.0f);
15100 viewport->UpdateWorkRect();
15103 viewport->Alpha = 1.0f;
15107 const ImVec2 viewport_delta_pos = viewport->Pos - viewport->LastPos;
15108 if ((viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) && (viewport_delta_pos.x != 0.0f || viewport_delta_pos.y != 0.0f))
15109 TranslateWindowsInViewport(viewport, viewport->LastPos, viewport->Pos);
15112 float new_dpi_scale;
15113 if (
g.PlatformIO.Platform_GetWindowDpiScale && platform_funcs_available)
15114 new_dpi_scale =
g.PlatformIO.Platform_GetWindowDpiScale(viewport);
15115 else if (viewport->PlatformMonitor != -1)
15116 new_dpi_scale =
g.PlatformIO.Monitors[viewport->PlatformMonitor].DpiScale;
15118 new_dpi_scale = (viewport->DpiScale != 0.0f) ? viewport->DpiScale : 1.0f;
15119 if (viewport->DpiScale != 0.0f && new_dpi_scale != viewport->DpiScale)
15121 float scale_factor = new_dpi_scale / viewport->DpiScale;
15122 if (
g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports)
15123 ScaleWindowsInViewport(viewport, scale_factor);
15133 viewport->DpiScale = new_dpi_scale;
15137 g.PlatformMonitorsFullWorkRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
15138 if (
g.PlatformIO.Monitors.Size == 0)
15140 ImGuiPlatformMonitor* monitor = &
g.FallbackMonitor;
15141 monitor->MainPos = main_viewport->Pos;
15142 monitor->MainSize = main_viewport->Size;
15143 monitor->WorkPos = main_viewport->WorkPos;
15144 monitor->WorkSize = main_viewport->WorkSize;
15145 monitor->DpiScale = main_viewport->DpiScale;
15146 g.PlatformMonitorsFullWorkRect.Add(monitor->WorkPos);
15147 g.PlatformMonitorsFullWorkRect.Add(monitor->WorkPos + monitor->WorkSize);
15149 for (ImGuiPlatformMonitor& monitor :
g.PlatformIO.Monitors)
15151 g.PlatformMonitorsFullWorkRect.Add(monitor.WorkPos);
15152 g.PlatformMonitorsFullWorkRect.Add(monitor.WorkPos + monitor.WorkSize);
15155 if (!viewports_enabled)
15157 g.MouseViewport = main_viewport;
15163 ImGuiViewportP* viewport_hovered = NULL;
15164 if (
g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport)
15166 viewport_hovered =
g.IO.MouseHoveredViewport ? (ImGuiViewportP*)FindViewportByID(
g.IO.MouseHoveredViewport) : NULL;
15167 if (viewport_hovered && (viewport_hovered->Flags & ImGuiViewportFlags_NoInputs))
15168 viewport_hovered = FindHoveredViewportFromPlatformWindowStack(
g.IO.MousePos);
15176 viewport_hovered = FindHoveredViewportFromPlatformWindowStack(
g.IO.MousePos);
15178 if (viewport_hovered != NULL)
15179 g.MouseLastHoveredViewport = viewport_hovered;
15180 else if (
g.MouseLastHoveredViewport == NULL)
15181 g.MouseLastHoveredViewport =
g.Viewports[0];
15186 if (
g.MovingWindow &&
g.MovingWindow->Viewport)
15187 g.MouseViewport =
g.MovingWindow->Viewport;
15189 g.MouseViewport =
g.MouseLastHoveredViewport;
15196 const bool is_mouse_dragging_with_an_expected_destination =
g.DragDropActive;
15197 if (is_mouse_dragging_with_an_expected_destination && viewport_hovered == NULL)
15198 viewport_hovered =
g.MouseLastHoveredViewport;
15199 if (is_mouse_dragging_with_an_expected_destination ||
g.ActiveId == 0 || !IsAnyMouseDown())
15200 if (viewport_hovered != NULL && viewport_hovered !=
g.MouseViewport && !(viewport_hovered->Flags & ImGuiViewportFlags_NoInputs))
15201 g.MouseViewport = viewport_hovered;
15203 IM_ASSERT(
g.MouseViewport != NULL);
15207static void ImGui::UpdateViewportsEndFrame()
15210 g.PlatformIO.Viewports.resize(0);
15211 for (
int i = 0; i <
g.Viewports.Size; i++)
15213 ImGuiViewportP* viewport =
g.Viewports[i];
15214 viewport->LastPos = viewport->Pos;
15215 if (viewport->LastFrameActive <
g.FrameCount || viewport->Size.x <= 0.0f || viewport->Size.y <= 0.0f)
15218 if (viewport->Window && !IsWindowActiveAndVisible(viewport->Window))
15221 IM_ASSERT(viewport->Window != NULL);
15222 g.PlatformIO.Viewports.push_back(viewport);
15224 g.Viewports[0]->ClearRequestFlags();
15228ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID
id,
const ImVec2& pos,
const ImVec2& size, ImGuiViewportFlags flags)
15231 IM_ASSERT(
id != 0);
15233 flags |= ImGuiViewportFlags_IsPlatformWindow;
15234 if (window != NULL)
15236 if (
g.MovingWindow &&
g.MovingWindow->RootWindowDockTree == window)
15237 flags |= ImGuiViewportFlags_NoInputs | ImGuiViewportFlags_NoFocusOnAppearing;
15238 if ((window->Flags & ImGuiWindowFlags_NoMouseInputs) && (window->Flags & ImGuiWindowFlags_NoNavInputs))
15239 flags |= ImGuiViewportFlags_NoInputs;
15240 if (window->Flags & ImGuiWindowFlags_NoFocusOnAppearing)
15241 flags |= ImGuiViewportFlags_NoFocusOnAppearing;
15244 ImGuiViewportP* viewport = (ImGuiViewportP*)FindViewportByID(
id);
15248 if (!viewport->PlatformRequestMove || viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID)
15249 viewport->Pos = pos;
15250 if (!viewport->PlatformRequestResize || viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID)
15251 viewport->Size =
size;
15252 viewport->Flags = flags | (viewport->Flags & (ImGuiViewportFlags_IsMinimized | ImGuiViewportFlags_IsFocused));
15257 viewport = IM_NEW(ImGuiViewportP)();
15259 viewport->Idx =
g.Viewports.Size;
15260 viewport->Pos = viewport->LastPos = pos;
15261 viewport->Size =
size;
15262 viewport->Flags = flags;
15263 UpdateViewportPlatformMonitor(viewport);
15264 g.Viewports.push_back(viewport);
15265 g.ViewportCreatedCount++;
15266 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Add Viewport %08X '%s'\n",
id, window ? window->Name :
"<NULL>");
15270 g.DrawListSharedData.ClipRectFullscreen.x = ImMin(
g.DrawListSharedData.ClipRectFullscreen.x, viewport->Pos.x);
15271 g.DrawListSharedData.ClipRectFullscreen.y = ImMin(
g.DrawListSharedData.ClipRectFullscreen.y, viewport->Pos.y);
15272 g.DrawListSharedData.ClipRectFullscreen.z = ImMax(
g.DrawListSharedData.ClipRectFullscreen.z, viewport->Pos.x + viewport->Size.x);
15273 g.DrawListSharedData.ClipRectFullscreen.w = ImMax(
g.DrawListSharedData.ClipRectFullscreen.w, viewport->Pos.y + viewport->Size.y);
15277 if (viewport->PlatformMonitor != -1)
15278 viewport->DpiScale =
g.PlatformIO.Monitors[viewport->PlatformMonitor].DpiScale;
15281 viewport->Window = window;
15282 viewport->LastFrameActive =
g.FrameCount;
15283 viewport->UpdateWorkRect();
15284 IM_ASSERT(window == NULL || viewport->ID == window->ID);
15286 if (window != NULL)
15287 window->ViewportOwned =
true;
15292static void ImGui::DestroyViewport(ImGuiViewportP* viewport)
15296 for (ImGuiWindow* window :
g.Windows)
15298 if (window->Viewport != viewport)
15300 window->Viewport = NULL;
15301 window->ViewportOwned =
false;
15303 if (viewport ==
g.MouseLastHoveredViewport)
15304 g.MouseLastHoveredViewport = NULL;
15307 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Delete Viewport %08X '%s'\n", viewport->ID, viewport->Window ? viewport->Window->Name :
"n/a");
15308 DestroyPlatformWindow(viewport);
15309 IM_ASSERT(
g.PlatformIO.Viewports.contains(viewport) ==
false);
15310 IM_ASSERT(
g.Viewports[viewport->Idx] == viewport);
15311 g.Viewports.erase(
g.Viewports.Data + viewport->Idx);
15312 IM_DELETE(viewport);
15316static void ImGui::WindowSelectViewport(ImGuiWindow* window)
15319 ImGuiWindowFlags flags = window->Flags;
15320 window->ViewportAllowPlatformMonitorExtend = -1;
15323 ImGuiViewportP* main_viewport = (ImGuiViewportP*)(
void*)GetMainViewport();
15324 if (!(
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable))
15326 SetWindowViewport(window, main_viewport);
15329 window->ViewportOwned =
false;
15332 if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && window->Appearing)
15334 window->Viewport = NULL;
15335 window->ViewportId = 0;
15338 if ((
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasViewport) == 0)
15341 if (window->Viewport == NULL && window->ParentWindow && (!window->ParentWindow->IsFallbackWindow || window->ParentWindow->WasActive))
15342 window->Viewport = window->ParentWindow->Viewport;
15345 if (window->Viewport == NULL && window->ViewportId != 0)
15347 window->Viewport = (ImGuiViewportP*)FindViewportByID(window->ViewportId);
15348 if (window->Viewport == NULL && window->ViewportPos.x != FLT_MAX && window->ViewportPos.y != FLT_MAX)
15349 window->Viewport = AddUpdateViewport(window, window->ID, window->ViewportPos, window->Size, ImGuiViewportFlags_None);
15353 bool lock_viewport =
false;
15354 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasViewport)
15357 window->Viewport = (ImGuiViewportP*)FindViewportByID(
g.NextWindowData.ViewportId);
15358 window->ViewportId =
g.NextWindowData.ViewportId;
15359 if (window->Viewport && (window->Flags & ImGuiWindowFlags_DockNodeHost) != 0 && window->Viewport->Window != NULL)
15361 window->Viewport->Window = window;
15362 window->Viewport->ID = window->ViewportId = window->ID;
15364 lock_viewport =
true;
15366 else if ((flags & ImGuiWindowFlags_ChildWindow) || (flags & ImGuiWindowFlags_ChildMenu))
15369 if (window->DockNode && window->DockNode->HostWindow)
15370 IM_ASSERT(window->DockNode->HostWindow->Viewport == window->ParentWindow->Viewport);
15371 window->Viewport = window->ParentWindow->Viewport;
15373 else if (window->DockNode && window->DockNode->HostWindow)
15376 window->Viewport = window->DockNode->HostWindow->Viewport;
15378 else if (flags & ImGuiWindowFlags_Tooltip)
15380 window->Viewport =
g.MouseViewport;
15382 else if (GetWindowAlwaysWantOwnViewport(window))
15384 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
15386 else if (
g.MovingWindow &&
g.MovingWindow->RootWindowDockTree == window && IsMousePosValid())
15388 if (window->Viewport != NULL && window->Viewport->Window == window)
15389 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
15396 bool try_to_merge_into_host_viewport = (window->Viewport && window == window->Viewport->Window && (
g.ActiveId == 0 ||
g.ActiveIdAllowOverlap));
15397 if (try_to_merge_into_host_viewport)
15398 UpdateTryMergeWindowIntoHostViewports(window);
15402 if (window->Viewport == NULL)
15403 if (!UpdateTryMergeWindowIntoHostViewport(window, main_viewport))
15404 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
15407 if (!lock_viewport)
15409 if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
15413 ImVec2 mouse_ref = (flags & ImGuiWindowFlags_Tooltip) ?
g.IO.MousePos :
g.BeginPopupStack.back().OpenMousePos;
15414 bool use_mouse_ref = (
g.NavDisableHighlight || !
g.NavDisableMouseHover || !
g.NavWindow);
15415 bool mouse_valid = IsMousePosValid(&mouse_ref);
15416 if ((window->Appearing || (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_ChildMenu))) && (!use_mouse_ref || mouse_valid))
15417 window->ViewportAllowPlatformMonitorExtend = FindPlatformMonitorForPos((use_mouse_ref && mouse_valid) ? mouse_ref : NavCalcPreferredRefPos());
15419 window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor;
15421 else if (window->Viewport && window != window->Viewport->Window && window->Viewport->Window && !(flags & ImGuiWindowFlags_ChildWindow) && window->DockNode == NULL)
15424 const bool will_be_visible = (window->DockIsActive && !window->DockTabIsVisible) ?
false : true;
15425 if ((window->Flags & ImGuiWindowFlags_DockNodeHost) && window->Viewport->LastFrameActive <
g.FrameCount && will_be_visible)
15428 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Window '%s' steal Viewport %08X from Window '%s'\n", window->Name, window->Viewport->ID, window->Viewport->Window->Name);
15429 window->Viewport->Window = window;
15430 window->Viewport->ID = window->ID;
15431 window->Viewport->LastNameHash = 0;
15433 else if (!UpdateTryMergeWindowIntoHostViewports(window))
15436 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoFocusOnAppearing);
15439 else if (window->ViewportAllowPlatformMonitorExtend < 0 && (flags & ImGuiWindowFlags_ChildWindow) == 0)
15443 window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor;
15448 window->ViewportOwned = (window == window->Viewport->Window);
15449 window->ViewportId = window->Viewport->ID;
15456void ImGui::WindowSyncOwnedViewport(ImGuiWindow* window, ImGuiWindow* parent_window_in_stack)
15460 bool viewport_rect_changed =
false;
15464 if (window->Viewport->PlatformRequestMove)
15466 window->Pos = window->Viewport->Pos;
15467 MarkIniSettingsDirty(window);
15469 else if (memcmp(&window->Viewport->Pos, &window->Pos,
sizeof(window->Pos)) != 0)
15471 viewport_rect_changed =
true;
15472 window->Viewport->Pos = window->Pos;
15475 if (window->Viewport->PlatformRequestResize)
15477 window->Size = window->SizeFull = window->Viewport->Size;
15478 MarkIniSettingsDirty(window);
15480 else if (memcmp(&window->Viewport->Size, &window->Size,
sizeof(window->Size)) != 0)
15482 viewport_rect_changed =
true;
15483 window->Viewport->Size = window->Size;
15485 window->Viewport->UpdateWorkRect();
15489 if (viewport_rect_changed)
15490 UpdateViewportPlatformMonitor(window->Viewport);
15493 const ImGuiViewportFlags viewport_flags_to_clear = ImGuiViewportFlags_TopMost | ImGuiViewportFlags_NoTaskBarIcon | ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoRendererClear;
15494 ImGuiViewportFlags viewport_flags = window->Viewport->Flags & ~viewport_flags_to_clear;
15495 ImGuiWindowFlags window_flags = window->Flags;
15496 const bool is_modal = (window_flags & ImGuiWindowFlags_Modal) != 0;
15497 const bool is_short_lived_floating_window = (window_flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0;
15498 if (window_flags & ImGuiWindowFlags_Tooltip)
15499 viewport_flags |= ImGuiViewportFlags_TopMost;
15500 if ((
g.IO.ConfigViewportsNoTaskBarIcon || is_short_lived_floating_window) && !is_modal)
15501 viewport_flags |= ImGuiViewportFlags_NoTaskBarIcon;
15502 if (
g.IO.ConfigViewportsNoDecoration || is_short_lived_floating_window)
15503 viewport_flags |= ImGuiViewportFlags_NoDecoration;
15515 if (is_short_lived_floating_window && !is_modal)
15516 viewport_flags |= ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoFocusOnClick;
15519 if (window->WindowClass.ViewportFlagsOverrideSet)
15520 viewport_flags |= window->WindowClass.ViewportFlagsOverrideSet;
15521 if (window->WindowClass.ViewportFlagsOverrideClear)
15522 viewport_flags &= ~window->WindowClass.ViewportFlagsOverrideClear;
15527 if (!(window_flags & ImGuiWindowFlags_NoBackground))
15528 viewport_flags |= ImGuiViewportFlags_NoRendererClear;
15530 window->Viewport->Flags = viewport_flags;
15534 if (window->WindowClass.ParentViewportId != (ImGuiID)-1)
15535 window->Viewport->ParentViewportId = window->WindowClass.ParentViewportId;
15536 else if ((window_flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && parent_window_in_stack && (!parent_window_in_stack->IsFallbackWindow || parent_window_in_stack->WasActive))
15537 window->Viewport->ParentViewportId = parent_window_in_stack->Viewport->ID;
15544void ImGui::UpdatePlatformWindows()
15547 IM_ASSERT(
g.FrameCountEnded ==
g.FrameCount &&
"Forgot to call Render() or EndFrame() before UpdatePlatformWindows()?");
15548 IM_ASSERT(
g.FrameCountPlatformEnded <
g.FrameCount);
15549 g.FrameCountPlatformEnded =
g.FrameCount;
15550 if (!(
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable))
15555 for (
int i = 1; i <
g.Viewports.Size; i++)
15557 ImGuiViewportP* viewport =
g.Viewports[i];
15561 bool destroy_platform_window =
false;
15562 destroy_platform_window |= (viewport->LastFrameActive <
g.FrameCount - 1);
15563 destroy_platform_window |= (viewport->Window && !IsWindowActiveAndVisible(viewport->Window));
15564 if (destroy_platform_window)
15566 DestroyPlatformWindow(viewport);
15571 if (viewport->LastFrameActive <
g.FrameCount || viewport->Size.x <= 0 || viewport->Size.y <= 0)
15575 const bool is_new_platform_window = (viewport->PlatformWindowCreated ==
false);
15576 if (is_new_platform_window)
15578 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Create Platform Window %08X '%s'\n", viewport->ID, viewport->Window ? viewport->Window->Name :
"n/a");
15579 g.PlatformIO.Platform_CreateWindow(viewport);
15580 if (
g.PlatformIO.Renderer_CreateWindow != NULL)
15581 g.PlatformIO.Renderer_CreateWindow(viewport);
15582 g.PlatformWindowsCreatedCount++;
15583 viewport->LastNameHash = 0;
15584 viewport->LastPlatformPos = viewport->LastPlatformSize = ImVec2(FLT_MAX, FLT_MAX);
15585 viewport->LastRendererSize = viewport->Size;
15586 viewport->PlatformWindowCreated =
true;
15590 if ((viewport->LastPlatformPos.x != viewport->Pos.x || viewport->LastPlatformPos.y != viewport->Pos.y) && !viewport->PlatformRequestMove)
15591 g.PlatformIO.Platform_SetWindowPos(viewport, viewport->Pos);
15592 if ((viewport->LastPlatformSize.x != viewport->Size.x || viewport->LastPlatformSize.y != viewport->Size.y) && !viewport->PlatformRequestResize)
15593 g.PlatformIO.Platform_SetWindowSize(viewport, viewport->Size);
15594 if ((viewport->LastRendererSize.x != viewport->Size.x || viewport->LastRendererSize.y != viewport->Size.y) &&
g.PlatformIO.Renderer_SetWindowSize)
15595 g.PlatformIO.Renderer_SetWindowSize(viewport, viewport->Size);
15596 viewport->LastPlatformPos = viewport->Pos;
15597 viewport->LastPlatformSize = viewport->LastRendererSize = viewport->Size;
15600 if (ImGuiWindow* window_for_title = GetWindowForTitleDisplay(viewport->Window))
15602 const char* title_begin = window_for_title->Name;
15603 char* title_end = (
char*)(intptr_t)FindRenderedTextEnd(title_begin);
15604 const ImGuiID title_hash =
ImHashStr(title_begin, title_end - title_begin);
15605 if (viewport->LastNameHash != title_hash)
15607 char title_end_backup_c = *title_end;
15609 g.PlatformIO.Platform_SetWindowTitle(viewport, title_begin);
15610 *title_end = title_end_backup_c;
15611 viewport->LastNameHash = title_hash;
15616 if (viewport->LastAlpha != viewport->Alpha &&
g.PlatformIO.Platform_SetWindowAlpha)
15617 g.PlatformIO.Platform_SetWindowAlpha(viewport, viewport->Alpha);
15618 viewport->LastAlpha = viewport->Alpha;
15621 if (
g.PlatformIO.Platform_UpdateWindow)
15622 g.PlatformIO.Platform_UpdateWindow(viewport);
15624 if (is_new_platform_window)
15627 if (
g.FrameCount < 3)
15628 viewport->Flags |= ImGuiViewportFlags_NoFocusOnAppearing;
15631 g.PlatformIO.Platform_ShowWindow(viewport);
15635 if (viewport->LastFocusedStampCount !=
g.ViewportFocusedStampCount)
15636 viewport->LastFocusedStampCount = ++
g.ViewportFocusedStampCount;
15640 viewport->ClearRequestFlags();
15656void ImGui::RenderPlatformWindowsDefault(
void* platform_render_arg,
void* renderer_render_arg)
15659 ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
15660 for (
int i = 1; i < platform_io.Viewports.Size; i++)
15662 ImGuiViewport* viewport = platform_io.Viewports[i];
15663 if (viewport->Flags & ImGuiViewportFlags_IsMinimized)
15665 if (platform_io.Platform_RenderWindow) platform_io.Platform_RenderWindow(viewport, platform_render_arg);
15666 if (platform_io.Renderer_RenderWindow) platform_io.Renderer_RenderWindow(viewport, renderer_render_arg);
15668 for (
int i = 1; i < platform_io.Viewports.Size; i++)
15670 ImGuiViewport* viewport = platform_io.Viewports[i];
15671 if (viewport->Flags & ImGuiViewportFlags_IsMinimized)
15673 if (platform_io.Platform_SwapBuffers) platform_io.Platform_SwapBuffers(viewport, platform_render_arg);
15674 if (platform_io.Renderer_SwapBuffers) platform_io.Renderer_SwapBuffers(viewport, renderer_render_arg);
15678static int ImGui::FindPlatformMonitorForPos(
const ImVec2& pos)
15681 for (
int monitor_n = 0; monitor_n <
g.PlatformIO.Monitors.Size; monitor_n++)
15683 const ImGuiPlatformMonitor& monitor =
g.PlatformIO.Monitors[monitor_n];
15684 if (ImRect(monitor.MainPos, monitor.MainPos + monitor.MainSize).Contains(pos))
15693static int ImGui::FindPlatformMonitorForRect(
const ImRect& rect)
15697 const int monitor_count =
g.PlatformIO.Monitors.Size;
15698 if (monitor_count <= 1)
15699 return monitor_count - 1;
15703 const float surface_threshold = ImMax(rect.GetWidth() * rect.GetHeight() * 0.5f, 1.0f);
15704 int best_monitor_n = -1;
15705 float best_monitor_surface = 0.001f;
15707 for (
int monitor_n = 0; monitor_n <
g.PlatformIO.Monitors.Size && best_monitor_surface < surface_threshold; monitor_n++)
15709 const ImGuiPlatformMonitor& monitor =
g.PlatformIO.Monitors[monitor_n];
15710 const ImRect monitor_rect = ImRect(monitor.MainPos, monitor.MainPos + monitor.MainSize);
15711 if (monitor_rect.Contains(rect))
15713 ImRect overlapping_rect = rect;
15714 overlapping_rect.ClipWithFull(monitor_rect);
15715 float overlapping_surface = overlapping_rect.GetWidth() * overlapping_rect.GetHeight();
15716 if (overlapping_surface < best_monitor_surface)
15718 best_monitor_surface = overlapping_surface;
15719 best_monitor_n = monitor_n;
15721 return best_monitor_n;
15725static void ImGui::UpdateViewportPlatformMonitor(ImGuiViewportP* viewport)
15727 viewport->PlatformMonitor = (short)FindPlatformMonitorForRect(viewport->GetMainRect());
15731const ImGuiPlatformMonitor* ImGui::GetViewportPlatformMonitor(ImGuiViewport* viewport_p)
15734 ImGuiViewportP* viewport = (ImGuiViewportP*)(
void*)viewport_p;
15735 int monitor_idx = viewport->PlatformMonitor;
15736 if (monitor_idx >= 0 && monitor_idx <
g.PlatformIO.Monitors.Size)
15737 return &
g.PlatformIO.Monitors[monitor_idx];
15738 return &
g.FallbackMonitor;
15741void ImGui::DestroyPlatformWindow(ImGuiViewportP* viewport)
15744 if (viewport->PlatformWindowCreated)
15746 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Destroy Platform Window %08X '%s'\n", viewport->ID, viewport->Window ? viewport->Window->Name :
"n/a");
15747 if (
g.PlatformIO.Renderer_DestroyWindow)
15748 g.PlatformIO.Renderer_DestroyWindow(viewport);
15749 if (
g.PlatformIO.Platform_DestroyWindow)
15750 g.PlatformIO.Platform_DestroyWindow(viewport);
15751 IM_ASSERT(viewport->RendererUserData == NULL && viewport->PlatformUserData == NULL);
15755 if (viewport->ID != IMGUI_VIEWPORT_DEFAULT_ID)
15756 viewport->PlatformWindowCreated =
false;
15760 IM_ASSERT(viewport->RendererUserData == NULL && viewport->PlatformUserData == NULL && viewport->PlatformHandle == NULL);
15762 viewport->RendererUserData = viewport->PlatformUserData = viewport->PlatformHandle = NULL;
15763 viewport->ClearRequestFlags();
15766void ImGui::DestroyPlatformWindows()
15775 for (ImGuiViewportP* viewport :
g.Viewports)
15776 DestroyPlatformWindow(viewport);
15921 static ImGuiDockNode* DockContextAddNode(ImGuiContext* ctx, ImGuiID
id);
15922 static void DockContextRemoveNode(ImGuiContext* ctx, ImGuiDockNode* node,
bool merge_sibling_into_parent_node);
15923 static void DockContextQueueNotifyRemovedNode(ImGuiContext* ctx, ImGuiDockNode* node);
15924 static void DockContextProcessDock(ImGuiContext* ctx,
ImGuiDockRequest* req);
15925 static void DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx);
15926 static ImGuiDockNode* DockContextBindNodeToWindow(ImGuiContext* ctx, ImGuiWindow* window);
15927 static void DockContextBuildNodesFromSettings(ImGuiContext* ctx,
ImGuiDockNodeSettings* node_settings_array,
int node_settings_count);
15928 static void DockContextBuildAddWindowsToNodes(ImGuiContext* ctx, ImGuiID root_id);
15931 static void DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window,
bool add_to_tab_bar);
15932 static void DockNodeMoveWindows(ImGuiDockNode* dst_node, ImGuiDockNode* src_node);
15933 static void DockNodeMoveChildNodes(ImGuiDockNode* dst_node, ImGuiDockNode* src_node);
15934 static ImGuiWindow* DockNodeFindWindowByID(ImGuiDockNode* node, ImGuiID
id);
15935 static void DockNodeApplyPosSizeToWindows(ImGuiDockNode* node);
15936 static void DockNodeRemoveWindow(ImGuiDockNode* node, ImGuiWindow* window, ImGuiID save_dock_id);
15937 static void DockNodeHideHostWindow(ImGuiDockNode* node);
15938 static void DockNodeUpdate(ImGuiDockNode* node);
15939 static void DockNodeUpdateForRootNode(ImGuiDockNode* node);
15940 static void DockNodeUpdateFlagsAndCollapse(ImGuiDockNode* node);
15941 static void DockNodeUpdateHasCentralNodeChild(ImGuiDockNode* node);
15942 static void DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_window);
15943 static void DockNodeAddTabBar(ImGuiDockNode* node);
15944 static void DockNodeRemoveTabBar(ImGuiDockNode* node);
15945 static void DockNodeWindowMenuUpdate(ImGuiDockNode* node, ImGuiTabBar* tab_bar);
15946 static void DockNodeUpdateVisibleFlag(ImGuiDockNode* node);
15947 static void DockNodeStartMouseMovingWindow(ImGuiDockNode* node, ImGuiWindow* window);
15948 static bool DockNodeIsDropAllowed(ImGuiWindow* host_window, ImGuiWindow* payload_window);
15949 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);
15950 static void DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window,
const ImGuiDockPreviewData* preview_data);
15951 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);
15952 static void DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& pos_new, ImVec2& size_new, ImGuiDir dir, ImVec2 size_new_desired);
15953 static bool DockNodeCalcDropRectsAndTestMousePos(
const ImRect& parent, ImGuiDir dir, ImRect& out_draw,
bool outer_docking, ImVec2* test_mouse_pos);
15954 static const char* DockNodeGetHostWindowTitle(ImGuiDockNode* node,
char* buf,
int buf_size) {
ImFormatString(buf, buf_size,
"##DockNode_%02X", node->ID);
return buf; }
15955 static int DockNodeGetTabOrder(ImGuiWindow* window);
15958 static void DockNodeTreeSplit(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiAxis split_axis,
int split_first_child,
float split_ratio, ImGuiDockNode* new_node);
15959 static void DockNodeTreeMerge(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiDockNode* merge_lead_child);
15960 static void DockNodeTreeUpdatePosSize(ImGuiDockNode* node, ImVec2 pos, ImVec2 size, ImGuiDockNode* only_write_to_single_node = NULL);
15961 static void DockNodeTreeUpdateSplitter(ImGuiDockNode* node);
15962 static ImGuiDockNode* DockNodeTreeFindVisibleNodeByPos(ImGuiDockNode* node, ImVec2 pos);
15963 static ImGuiDockNode* DockNodeTreeFindFallbackLeafNode(ImGuiDockNode* node);
15966 static void DockSettingsRenameNodeReferences(ImGuiID old_node_id, ImGuiID new_node_id);
15967 static void DockSettingsRemoveNodeReferences(ImGuiID* node_ids,
int node_ids_count);
15969 static void DockSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*);
15970 static void DockSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*);
15971 static void* DockSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*,
const char* name);
15972 static void DockSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
void* entry,
const char* line);
15973 static void DockSettingsHandler_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf);
16004void ImGui::DockContextInitialize(ImGuiContext* ctx)
16006 ImGuiContext&
g = *ctx;
16009 ImGuiSettingsHandler ini_handler;
16010 ini_handler.TypeName =
"Docking";
16011 ini_handler.TypeHash =
ImHashStr(
"Docking");
16012 ini_handler.ClearAllFn = DockSettingsHandler_ClearAll;
16013 ini_handler.ReadInitFn = DockSettingsHandler_ClearAll;
16014 ini_handler.ReadOpenFn = DockSettingsHandler_ReadOpen;
16015 ini_handler.ReadLineFn = DockSettingsHandler_ReadLine;
16016 ini_handler.ApplyAllFn = DockSettingsHandler_ApplyAll;
16017 ini_handler.WriteAllFn = DockSettingsHandler_WriteAll;
16018 g.SettingsHandlers.push_back(ini_handler);
16020 g.DockNodeWindowMenuHandler = &DockNodeWindowMenuHandler_Default;
16023void ImGui::DockContextShutdown(ImGuiContext* ctx)
16025 ImGuiDockContext* dc = &ctx->DockContext;
16026 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
16027 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
16031void ImGui::DockContextClearNodes(ImGuiContext* ctx, ImGuiID root_id,
bool clear_settings_refs)
16034 IM_ASSERT(ctx ==
GImGui);
16035 DockBuilderRemoveNodeDockedWindows(root_id, clear_settings_refs);
16036 DockBuilderRemoveNodeChildNodes(root_id);
16041void ImGui::DockContextRebuildNodes(ImGuiContext* ctx)
16043 ImGuiContext&
g = *ctx;
16044 ImGuiDockContext* dc = &ctx->DockContext;
16045 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextRebuildNodes\n");
16046 SaveIniSettingsToMemory();
16047 ImGuiID root_id = 0;
16048 DockContextClearNodes(ctx, root_id,
false);
16049 DockContextBuildNodesFromSettings(ctx, dc->NodesSettings.Data, dc->NodesSettings.Size);
16050 DockContextBuildAddWindowsToNodes(ctx, root_id);
16054void ImGui::DockContextNewFrameUpdateUndocking(ImGuiContext* ctx)
16056 ImGuiContext&
g = *ctx;
16057 ImGuiDockContext* dc = &ctx->DockContext;
16058 if (!(
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
16060 if (dc->Nodes.Data.Size > 0 || dc->Requests.Size > 0)
16061 DockContextClearNodes(ctx, 0,
true);
16066 if (
g.IO.ConfigDockingNoSplit)
16067 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
16068 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
16069 if (node->IsRootNode() && node->IsSplitNode())
16071 DockBuilderRemoveNodeChildNodes(node->ID);
16077 if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_C)))
16078 dc->WantFullRebuild =
true;
16080 if (dc->WantFullRebuild)
16082 DockContextRebuildNodes(ctx);
16083 dc->WantFullRebuild =
false;
16090 DockContextProcessUndockWindow(ctx, req.UndockTargetWindow);
16092 DockContextProcessUndockNode(ctx, req.UndockTargetNode);
16097void ImGui::DockContextNewFrameUpdateDocking(ImGuiContext* ctx)
16099 ImGuiContext&
g = *ctx;
16100 ImGuiDockContext* dc = &ctx->DockContext;
16101 if (!(
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
16107 g.DebugHoveredDockNode = NULL;
16108 if (ImGuiWindow* hovered_window =
g.HoveredWindowUnderMovingWindow)
16110 if (hovered_window->DockNodeAsHost)
16111 g.DebugHoveredDockNode = DockNodeTreeFindVisibleNodeByPos(hovered_window->DockNodeAsHost,
g.IO.MousePos);
16112 else if (hovered_window->RootWindow->DockNode)
16113 g.DebugHoveredDockNode = hovered_window->RootWindow->DockNode;
16119 DockContextProcessDock(ctx, &req);
16120 dc->Requests.resize(0);
16124 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
16125 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
16126 if (node->IsFloatingNode())
16127 DockNodeUpdate(node);
16130void ImGui::DockContextEndFrame(ImGuiContext* ctx)
16133 ImGuiContext&
g = *ctx;
16134 ImGuiDockContext* dc = &
g.DockContext;
16135 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
16136 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
16137 if (node->LastFrameActive ==
g.FrameCount && node->IsVisible && node->HostWindow && node->IsLeafNode() && !node->IsBgDrawnThisFrame)
16139 ImRect bg_rect(node->Pos + ImVec2(0.0f, GetFrameHeight()), node->Pos + node->Size);
16140 ImDrawFlags bg_rounding_flags = CalcRoundingFlagsForRectInRect(bg_rect, node->HostWindow->Rect(),
g.Style.DockingSeparatorSize);
16141 node->HostWindow->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
16142 node->HostWindow->DrawList->AddRectFilled(bg_rect.Min, bg_rect.Max, node->LastBgColor, node->HostWindow->WindowRounding, bg_rounding_flags);
16146ImGuiDockNode* ImGui::DockContextFindNodeByID(ImGuiContext* ctx, ImGuiID
id)
16148 return (ImGuiDockNode*)ctx->DockContext.Nodes.GetVoidPtr(
id);
16151ImGuiID ImGui::DockContextGenNodeID(ImGuiContext* ctx)
16156 ImGuiID
id = 0x0001;
16157 while (DockContextFindNodeByID(ctx,
id) != NULL)
16162static ImGuiDockNode* ImGui::DockContextAddNode(ImGuiContext* ctx, ImGuiID
id)
16165 ImGuiContext&
g = *ctx;
16167 id = DockContextGenNodeID(ctx);
16169 IM_ASSERT(DockContextFindNodeByID(ctx,
id) == NULL);
16172 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextAddNode 0x%08X\n",
id);
16173 ImGuiDockNode* node = IM_NEW(ImGuiDockNode)(
id);
16174 ctx->DockContext.Nodes.SetVoidPtr(node->ID, node);
16178static void ImGui::DockContextRemoveNode(ImGuiContext* ctx, ImGuiDockNode* node,
bool merge_sibling_into_parent_node)
16180 ImGuiContext&
g = *ctx;
16181 ImGuiDockContext* dc = &ctx->DockContext;
16183 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextRemoveNode 0x%08X\n", node->ID);
16184 IM_ASSERT(DockContextFindNodeByID(ctx, node->ID) == node);
16185 IM_ASSERT(node->ChildNodes[0] == NULL && node->ChildNodes[1] == NULL);
16186 IM_ASSERT(node->Windows.Size == 0);
16188 if (node->HostWindow)
16189 node->HostWindow->DockNodeAsHost = NULL;
16191 ImGuiDockNode* parent_node = node->ParentNode;
16192 const bool merge = (merge_sibling_into_parent_node && parent_node != NULL);
16195 IM_ASSERT(parent_node->ChildNodes[0] == node || parent_node->ChildNodes[1] == node);
16196 ImGuiDockNode* sibling_node = (parent_node->ChildNodes[0] == node ? parent_node->ChildNodes[1] : parent_node->ChildNodes[0]);
16197 DockNodeTreeMerge(&
g, parent_node, sibling_node);
16201 for (
int n = 0; parent_node && n < IM_ARRAYSIZE(parent_node->ChildNodes); n++)
16202 if (parent_node->ChildNodes[n] == node)
16203 node->ParentNode->ChildNodes[n] = NULL;
16204 dc->Nodes.SetVoidPtr(node->ID, NULL);
16209static int IMGUI_CDECL DockNodeComparerDepthMostFirst(
const void* lhs,
const void* rhs)
16211 const ImGuiDockNode* a = *(
const ImGuiDockNode*
const*)lhs;
16212 const ImGuiDockNode* b = *(
const ImGuiDockNode*
const*)rhs;
16213 return ImGui::DockNodeGetDepth(b) - ImGui::DockNodeGetDepth(a);
16225static void ImGui::DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx)
16227 ImGuiContext&
g = *ctx;
16228 ImGuiDockContext* dc = &ctx->DockContext;
16229 IM_ASSERT(
g.Windows.Size == 0);
16231 ImPool<ImGuiDockContextPruneNodeData> pool;
16232 pool.Reserve(dc->NodesSettings.Size);
16235 for (
int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
16239 pool.GetOrAddByKey(settings->
ID)->RootId = parent_data ? parent_data->
RootId : settings->
ID;
16241 pool.GetOrAddByKey(settings->
ParentNodeId)->CountChildNodes++;
16246 for (
int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
16250 if (ImGuiWindowSettings* window_settings = FindWindowSettingsByID(settings->
ParentWindowId))
16251 if (window_settings->DockId)
16253 data->CountChildNodes++;
16258 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
16259 if (ImGuiID dock_id = settings->DockId)
16262 data->CountWindows++;
16264 data_root->CountChildWindows++;
16268 for (
int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
16282 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextPruneUnusedSettingsNodes: Prune 0x%08X\n", settings->
ID);
16283 DockSettingsRemoveNodeReferences(&settings->
ID, 1);
16289static void ImGui::DockContextBuildNodesFromSettings(ImGuiContext* ctx,
ImGuiDockNodeSettings* node_settings_array,
int node_settings_count)
16292 for (
int node_n = 0; node_n < node_settings_count; node_n++)
16295 if (settings->
ID == 0)
16297 ImGuiDockNode* node = DockContextAddNode(ctx, settings->
ID);
16299 node->Pos = ImVec2(settings->
Pos.x, settings->
Pos.y);
16300 node->Size = ImVec2(settings->
Size.x, settings->
Size.y);
16301 node->SizeRef = ImVec2(settings->
SizeRef.x, settings->
SizeRef.y);
16302 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_DockNode;
16303 if (node->ParentNode && node->ParentNode->ChildNodes[0] == NULL)
16304 node->ParentNode->ChildNodes[0] = node;
16305 else if (node->ParentNode && node->ParentNode->ChildNodes[1] == NULL)
16306 node->ParentNode->ChildNodes[1] = node;
16308 node->SplitAxis = (ImGuiAxis)settings->
SplitAxis;
16309 node->SetLocalFlags(settings->
Flags & ImGuiDockNodeFlags_SavedFlagsMask_);
16313 char host_window_title[20];
16314 ImGuiDockNode* root_node = DockNodeGetRootNode(node);
16315 node->HostWindow = FindWindowByName(DockNodeGetHostWindowTitle(root_node, host_window_title, IM_ARRAYSIZE(host_window_title)));
16319void ImGui::DockContextBuildAddWindowsToNodes(ImGuiContext* ctx, ImGuiID root_id)
16322 ImGuiContext&
g = *ctx;
16323 for (ImGuiWindow* window :
g.Windows)
16325 if (window->DockId == 0 || window->LastFrameActive <
g.FrameCount - 1)
16327 if (window->DockNode != NULL)
16330 ImGuiDockNode* node = DockContextFindNodeByID(ctx, window->DockId);
16331 IM_ASSERT(node != NULL);
16332 if (root_id == 0 || DockNodeGetRootNode(node)->ID == root_id)
16333 DockNodeAddWindow(node, window,
true);
16350void ImGui::DockContextQueueDock(ImGuiContext* ctx, ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload, ImGuiDir split_dir,
float split_ratio,
bool split_outer)
16352 IM_ASSERT(target != payload);
16361 ctx->DockContext.Requests.push_back(req);
16364void ImGui::DockContextQueueUndockWindow(ImGuiContext* ctx, ImGuiWindow* window)
16369 ctx->DockContext.Requests.push_back(req);
16372void ImGui::DockContextQueueUndockNode(ImGuiContext* ctx, ImGuiDockNode* node)
16377 ctx->DockContext.Requests.push_back(req);
16380void ImGui::DockContextQueueNotifyRemovedNode(ImGuiContext* ctx, ImGuiDockNode* node)
16382 ImGuiDockContext* dc = &ctx->DockContext;
16384 if (req.DockTargetNode == node)
16388void ImGui::DockContextProcessDock(ImGuiContext* ctx,
ImGuiDockRequest* req)
16393 ImGuiContext&
g = *ctx;
16399 if (payload_window)
16400 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);
16402 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextProcessDock node 0x%08X, split_dir %d\n", node ? node->ID : 0, req->DockSplitDir);
16405 ImGuiID next_selected_id = 0;
16406 ImGuiDockNode* payload_node = NULL;
16407 if (payload_window)
16409 payload_node = payload_window->DockNodeAsHost;
16410 payload_window->DockNodeAsHost = NULL;
16411 if (payload_node && payload_node->IsLeafNode())
16412 next_selected_id = payload_node->TabBar->NextSelectedTabId ? payload_node->TabBar->NextSelectedTabId : payload_node->TabBar->SelectedTabId;
16413 if (payload_node == NULL)
16414 next_selected_id = payload_window->TabId;
16420 IM_ASSERT(node->LastFrameAlive <=
g.FrameCount);
16421 if (node && target_window && node == target_window->DockNodeAsHost)
16422 IM_ASSERT(node->Windows.Size > 0 || node->IsSplitNode() || node->IsCentralNode());
16427 node = DockContextAddNode(ctx, 0);
16428 node->Pos = target_window->Pos;
16429 node->Size = target_window->Size;
16430 if (target_window->DockNodeAsHost == NULL)
16432 DockNodeAddWindow(node, target_window,
true);
16433 node->TabBar->Tabs[0].Flags &= ~ImGuiTabItemFlags_Unsorted;
16434 target_window->DockIsActive =
true;
16439 if (split_dir != ImGuiDir_None)
16442 const ImGuiAxis split_axis = (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
16443 const int split_inheritor_child_idx = (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up) ? 1 : 0;
16445 DockNodeTreeSplit(ctx, node, split_axis, split_inheritor_child_idx, split_ratio, payload_node);
16446 ImGuiDockNode* new_node = node->ChildNodes[split_inheritor_child_idx ^ 1];
16447 new_node->HostWindow = node->HostWindow;
16450 node->SetLocalFlags(node->LocalFlags & ~ImGuiDockNodeFlags_HiddenTabBar);
16452 if (node != payload_node)
16455 if (node->Windows.Size > 0 && node->TabBar == NULL)
16457 DockNodeAddTabBar(node);
16458 for (
int n = 0; n < node->Windows.Size; n++)
16459 TabBarAddTab(node->TabBar, ImGuiTabItemFlags_None, node->Windows[n]);
16462 if (payload_node != NULL)
16465 if (payload_node->IsSplitNode())
16467 if (node->Windows.Size > 0)
16472 IM_ASSERT(payload_node->OnlyNodeWithWindows != NULL);
16473 ImGuiDockNode* visible_node = payload_node->OnlyNodeWithWindows;
16474 if (visible_node->TabBar)
16475 IM_ASSERT(visible_node->TabBar->Tabs.Size > 0);
16476 DockNodeMoveWindows(node, visible_node);
16477 DockNodeMoveWindows(visible_node, node);
16478 DockSettingsRenameNodeReferences(node->ID, visible_node->ID);
16480 if (node->IsCentralNode())
16484 ImGuiDockNode* last_focused_node = DockContextFindNodeByID(ctx, payload_node->LastFocusedNodeId);
16485 IM_ASSERT(last_focused_node != NULL);
16486 ImGuiDockNode* last_focused_root_node = DockNodeGetRootNode(last_focused_node);
16487 IM_ASSERT(last_focused_root_node == DockNodeGetRootNode(payload_node));
16488 last_focused_node->SetLocalFlags(last_focused_node->LocalFlags | ImGuiDockNodeFlags_CentralNode);
16489 node->SetLocalFlags(node->LocalFlags & ~ImGuiDockNodeFlags_CentralNode);
16490 last_focused_root_node->CentralNode = last_focused_node;
16493 IM_ASSERT(node->Windows.Size == 0);
16494 DockNodeMoveChildNodes(node, payload_node);
16498 const ImGuiID payload_dock_id = payload_node->ID;
16499 DockNodeMoveWindows(node, payload_node);
16500 DockSettingsRenameNodeReferences(payload_dock_id, node->ID);
16502 DockContextRemoveNode(ctx, payload_node,
true);
16504 else if (payload_window)
16507 const ImGuiID payload_dock_id = payload_window->DockId;
16508 node->VisibleWindow = payload_window;
16509 DockNodeAddWindow(node, payload_window,
true);
16510 if (payload_dock_id != 0)
16511 DockSettingsRenameNodeReferences(payload_dock_id, node->ID);
16517 node->WantHiddenTabBarUpdate =
true;
16521 if (ImGuiTabBar* tab_bar = node->TabBar)
16522 tab_bar->NextSelectedTabId = next_selected_id;
16523 MarkIniSettingsDirty();
16534static ImVec2 FixLargeWindowsWhenUndocking(
const ImVec2& size, ImGuiViewport* ref_viewport)
16536 if (ref_viewport == NULL)
16540 ImVec2 max_size = ImTrunc(ref_viewport->WorkSize * 0.90f);
16541 if (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
16543 const ImGuiPlatformMonitor* monitor = ImGui::GetViewportPlatformMonitor(ref_viewport);
16544 max_size = ImTrunc(monitor->WorkSize * 0.90f);
16546 return ImMin(size, max_size);
16549void ImGui::DockContextProcessUndockWindow(ImGuiContext* ctx, ImGuiWindow* window,
bool clear_persistent_docking_ref)
16551 ImGuiContext&
g = *ctx;
16552 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextProcessUndockWindow window '%s', clear_persistent_docking_ref = %d\n", window->Name, clear_persistent_docking_ref);
16553 if (window->DockNode)
16554 DockNodeRemoveWindow(window->DockNode, window, clear_persistent_docking_ref ? 0 : window->DockId);
16556 window->DockId = 0;
16557 window->Collapsed =
false;
16558 window->DockIsActive =
false;
16559 window->DockNodeIsVisible = window->DockTabIsVisible =
false;
16560 window->Size = window->SizeFull = FixLargeWindowsWhenUndocking(window->SizeFull, window->Viewport);
16562 MarkIniSettingsDirty();
16565void ImGui::DockContextProcessUndockNode(ImGuiContext* ctx, ImGuiDockNode* node)
16567 ImGuiContext&
g = *ctx;
16568 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextProcessUndockNode node %08X\n", node->ID);
16569 IM_ASSERT(node->IsLeafNode());
16570 IM_ASSERT(node->Windows.Size >= 1);
16572 if (node->IsRootNode() || node->IsCentralNode())
16575 ImGuiDockNode* new_node = DockContextAddNode(ctx, 0);
16576 new_node->Pos = node->Pos;
16577 new_node->Size = node->Size;
16578 new_node->SizeRef = node->SizeRef;
16579 DockNodeMoveWindows(new_node, node);
16580 DockSettingsRenameNodeReferences(node->ID, new_node->ID);
16586 IM_ASSERT(node->ParentNode->ChildNodes[0] == node || node->ParentNode->ChildNodes[1] == node);
16587 int index_in_parent = (node->ParentNode->ChildNodes[0] == node) ? 0 : 1;
16588 node->ParentNode->ChildNodes[index_in_parent] = NULL;
16589 DockNodeTreeMerge(ctx, node->ParentNode, node->ParentNode->ChildNodes[index_in_parent ^ 1]);
16590 node->ParentNode->AuthorityForViewport = ImGuiDataAuthority_Window;
16591 node->ParentNode = NULL;
16593 for (ImGuiWindow* window : node->Windows)
16595 window->Flags &= ~ImGuiWindowFlags_ChildWindow;
16596 if (window->ParentWindow)
16597 window->ParentWindow->DC.ChildWindows.find_erase(window);
16598 UpdateWindowParentAndRootLinks(window, window->Flags, NULL);
16600 node->AuthorityForPos = node->AuthorityForSize = ImGuiDataAuthority_DockNode;
16601 node->Size = FixLargeWindowsWhenUndocking(node->Size, node->Windows[0]->Viewport);
16602 node->WantMouseMove =
true;
16603 MarkIniSettingsDirty();
16607bool ImGui::DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload_window, ImGuiDockNode* payload_node, ImGuiDir split_dir,
bool split_outer, ImVec2* out_pos)
16609 if (target != NULL && target_node == NULL)
16610 target_node = target->DockNode;
16614 if (target_node && target_node->ParentNode == NULL && target_node->IsCentralNode() && split_dir != ImGuiDir_None)
16615 split_outer =
true;
16617 DockNodePreviewDockSetup(target, target_node, payload_window, payload_node, &split_data,
false, split_outer);
16620 *out_pos = split_data.
DropRectsDraw[split_dir+1].GetCenter();
16657ImGuiDockNode::ImGuiDockNode(ImGuiID
id)
16660 SharedFlags = LocalFlags = LocalFlagsInWindows = MergedFlags = ImGuiDockNodeFlags_None;
16661 ParentNode = ChildNodes[0] = ChildNodes[1] = NULL;
16663 SplitAxis = ImGuiAxis_None;
16665 State = ImGuiDockNodeState_Unknown;
16666 LastBgColor = IM_COL32_WHITE;
16667 HostWindow = VisibleWindow = NULL;
16668 CentralNode = OnlyNodeWithWindows = NULL;
16669 CountNodeWithWindows = 0;
16670 LastFrameAlive = LastFrameActive = LastFrameFocused = -1;
16671 LastFocusedNodeId = 0;
16673 WantCloseTabId = 0;
16675 AuthorityForPos = AuthorityForSize = ImGuiDataAuthority_DockNode;
16676 AuthorityForViewport = ImGuiDataAuthority_Auto;
16678 IsFocused = HasCloseButton = HasWindowMenuButton = HasCentralNodeChild =
false;
16679 IsBgDrawnThisFrame =
false;
16680 WantCloseAll = WantLockSizeOnce = WantMouseMove = WantHiddenTabBarUpdate = WantHiddenTabBarToggle =
false;
16683ImGuiDockNode::~ImGuiDockNode()
16687 ChildNodes[0] = ChildNodes[1] = NULL;
16690int ImGui::DockNodeGetTabOrder(ImGuiWindow* window)
16692 ImGuiTabBar* tab_bar = window->DockNode->TabBar;
16693 if (tab_bar == NULL)
16695 ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, window->TabId);
16696 return tab ? TabBarGetTabOrder(tab_bar, tab) : -1;
16699static void DockNodeHideWindowDuringHostWindowCreation(ImGuiWindow* window)
16701 window->Hidden =
true;
16702 window->HiddenFramesCanSkipItems = window->Active ? 1 : 2;
16705static void ImGui::DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window,
bool add_to_tab_bar)
16707 ImGuiContext&
g = *
GImGui; (void)
g;
16708 if (window->DockNode)
16711 IM_ASSERT(window->DockNode->ID != node->ID);
16712 DockNodeRemoveWindow(window->DockNode, window, 0);
16714 IM_ASSERT(window->DockNode == NULL || window->DockNodeAsHost == NULL);
16715 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockNodeAddWindow node 0x%08X window '%s'\n", node->ID, window->Name);
16720 if (node->HostWindow == NULL && node->Windows.Size == 1 && node->Windows[0]->WasActive ==
false)
16721 DockNodeHideWindowDuringHostWindowCreation(node->Windows[0]);
16723 node->Windows.push_back(window);
16724 node->WantHiddenTabBarUpdate =
true;
16725 window->DockNode = node;
16726 window->DockId = node->ID;
16727 window->DockIsActive = (node->Windows.Size > 1);
16728 window->DockTabWantClose =
false;
16732 if (node->HostWindow == NULL && node->IsFloatingNode())
16734 if (node->AuthorityForPos == ImGuiDataAuthority_Auto)
16735 node->AuthorityForPos = ImGuiDataAuthority_Window;
16736 if (node->AuthorityForSize == ImGuiDataAuthority_Auto)
16737 node->AuthorityForSize = ImGuiDataAuthority_Window;
16738 if (node->AuthorityForViewport == ImGuiDataAuthority_Auto)
16739 node->AuthorityForViewport = ImGuiDataAuthority_Window;
16743 if (add_to_tab_bar)
16745 if (node->TabBar == NULL)
16747 DockNodeAddTabBar(node);
16748 node->TabBar->SelectedTabId = node->TabBar->NextSelectedTabId = node->SelectedTabId;
16751 for (
int n = 0; n < node->Windows.Size - 1; n++)
16752 TabBarAddTab(node->TabBar, ImGuiTabItemFlags_None, node->Windows[n]);
16754 TabBarAddTab(node->TabBar, ImGuiTabItemFlags_Unsorted, window);
16757 DockNodeUpdateVisibleFlag(node);
16760 if (node->HostWindow)
16761 UpdateWindowParentAndRootLinks(window, window->Flags | ImGuiWindowFlags_ChildWindow, node->HostWindow);
16764static void ImGui::DockNodeRemoveWindow(ImGuiDockNode* node, ImGuiWindow* window, ImGuiID save_dock_id)
16767 IM_ASSERT(window->DockNode == node);
16770 IM_ASSERT(save_dock_id == 0 || save_dock_id == node->ID);
16771 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockNodeRemoveWindow node 0x%08X window '%s'\n", node->ID, window->Name);
16773 window->DockNode = NULL;
16774 window->DockIsActive = window->DockTabWantClose =
false;
16775 window->DockId = save_dock_id;
16776 window->Flags &= ~ImGuiWindowFlags_ChildWindow;
16777 if (window->ParentWindow)
16778 window->ParentWindow->DC.ChildWindows.find_erase(window);
16779 UpdateWindowParentAndRootLinks(window, window->Flags, NULL);
16781 if (node->HostWindow && node->HostWindow->ViewportOwned)
16785 window->Viewport = NULL;
16786 window->ViewportId = 0;
16787 window->ViewportOwned =
false;
16788 window->Hidden =
true;
16792 bool erased =
false;
16793 for (
int n = 0; n < node->Windows.Size; n++)
16794 if (node->Windows[n] == window)
16796 node->Windows.erase(node->Windows.Data + n);
16802 if (node->VisibleWindow == window)
16803 node->VisibleWindow = NULL;
16806 node->WantHiddenTabBarUpdate =
true;
16809 TabBarRemoveTab(node->TabBar, window->TabId);
16810 const int tab_count_threshold_for_tab_bar = node->IsCentralNode() ? 1 : 2;
16811 if (node->Windows.Size < tab_count_threshold_for_tab_bar)
16812 DockNodeRemoveTabBar(node);
16815 if (node->Windows.Size == 0 && !node->IsCentralNode() && !node->IsDockSpace() && window->DockId != node->ID)
16818 DockContextRemoveNode(&
g, node,
true);
16822 if (node->Windows.Size == 1 && !node->IsCentralNode() && node->HostWindow)
16824 ImGuiWindow* remaining_window = node->Windows[0];
16826 remaining_window->Collapsed = node->HostWindow->Collapsed;
16830 DockNodeUpdateVisibleFlag(node);
16833static void ImGui::DockNodeMoveChildNodes(ImGuiDockNode* dst_node, ImGuiDockNode* src_node)
16835 IM_ASSERT(dst_node->Windows.Size == 0);
16836 dst_node->ChildNodes[0] = src_node->ChildNodes[0];
16837 dst_node->ChildNodes[1] = src_node->ChildNodes[1];
16838 if (dst_node->ChildNodes[0])
16839 dst_node->ChildNodes[0]->ParentNode = dst_node;
16840 if (dst_node->ChildNodes[1])
16841 dst_node->ChildNodes[1]->ParentNode = dst_node;
16842 dst_node->SplitAxis = src_node->SplitAxis;
16843 dst_node->SizeRef = src_node->SizeRef;
16844 src_node->ChildNodes[0] = src_node->ChildNodes[1] = NULL;
16847static void ImGui::DockNodeMoveWindows(ImGuiDockNode* dst_node, ImGuiDockNode* src_node)
16850 IM_ASSERT(src_node && dst_node && dst_node != src_node);
16851 ImGuiTabBar* src_tab_bar = src_node->TabBar;
16852 if (src_tab_bar != NULL)
16853 IM_ASSERT(src_node->Windows.Size <= src_node->TabBar->Tabs.Size);
16856 bool move_tab_bar = (src_tab_bar != NULL) && (dst_node->TabBar == NULL);
16859 dst_node->TabBar = src_node->TabBar;
16860 src_node->TabBar = NULL;
16864 for (ImGuiWindow* window : src_node->Windows)
16866 window->DockNode = NULL;
16867 window->DockIsActive =
false;
16868 DockNodeAddWindow(dst_node, window, !move_tab_bar);
16870 src_node->Windows.clear();
16872 if (!move_tab_bar && src_node->TabBar)
16874 if (dst_node->TabBar)
16875 dst_node->TabBar->SelectedTabId = src_node->TabBar->SelectedTabId;
16876 DockNodeRemoveTabBar(src_node);
16880static void ImGui::DockNodeApplyPosSizeToWindows(ImGuiDockNode* node)
16882 for (ImGuiWindow* window : node->Windows)
16884 SetWindowPos(window, node->Pos, ImGuiCond_Always);
16885 SetWindowSize(window, node->Size, ImGuiCond_Always);
16889static void ImGui::DockNodeHideHostWindow(ImGuiDockNode* node)
16891 if (node->HostWindow)
16893 if (node->HostWindow->DockNodeAsHost == node)
16894 node->HostWindow->DockNodeAsHost = NULL;
16895 node->HostWindow = NULL;
16898 if (node->Windows.Size == 1)
16900 node->VisibleWindow = node->Windows[0];
16901 node->Windows[0]->DockIsActive =
false;
16905 DockNodeRemoveTabBar(node);
16921 if (node->Windows.Size > 0)
16927 if (node->IsCentralNode())
16930 IM_ASSERT(node->IsLeafNode() &&
"If you get this assert: please submit .ini file + repro of actions leading to this.");
16935 if (node->ChildNodes[0])
16936 DockNodeFindInfo(node->ChildNodes[0], info);
16937 if (node->ChildNodes[1])
16938 DockNodeFindInfo(node->ChildNodes[1], info);
16941static ImGuiWindow* ImGui::DockNodeFindWindowByID(ImGuiDockNode* node, ImGuiID
id)
16943 IM_ASSERT(
id != 0);
16944 for (ImGuiWindow* window : node->Windows)
16945 if (window->
ID ==
id)
16952static void ImGui::DockNodeUpdateFlagsAndCollapse(ImGuiDockNode* node)
16955 IM_ASSERT(node->ParentNode == NULL || node->ParentNode->ChildNodes[0] == node || node->ParentNode->ChildNodes[1] == node);
16958 if (node->ParentNode)
16959 node->SharedFlags = node->ParentNode->SharedFlags & ImGuiDockNodeFlags_SharedFlagsInheritMask_;
16965 node->HasCentralNodeChild =
false;
16966 if (node->ChildNodes[0])
16967 DockNodeUpdateFlagsAndCollapse(node->ChildNodes[0]);
16968 if (node->ChildNodes[1])
16969 DockNodeUpdateFlagsAndCollapse(node->ChildNodes[1]);
16973 node->LocalFlagsInWindows = ImGuiDockNodeFlags_None;
16974 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
16976 ImGuiWindow* window = node->Windows[window_n];
16977 IM_ASSERT(window->DockNode == node);
16979 bool node_was_active = (node->LastFrameActive + 1 ==
g.FrameCount);
16981 remove |= node_was_active && (window->LastFrameActive + 1 <
g.FrameCount);
16982 remove |= node_was_active && (node->WantCloseAll || node->WantCloseTabId == window->TabId) && window->HasCloseButton && !(window->Flags & ImGuiWindowFlags_UnsavedDocument);
16983 remove |= (window->DockTabWantClose);
16986 window->DockTabWantClose =
false;
16987 if (node->Windows.Size == 1 && !node->IsCentralNode())
16989 DockNodeHideHostWindow(node);
16990 node->State = ImGuiDockNodeState_HostWindowHiddenBecauseSingleWindow;
16991 DockNodeRemoveWindow(node, window, node->ID);
16994 DockNodeRemoveWindow(node, window, node->ID);
17001 node->LocalFlagsInWindows |= window->WindowClass.DockNodeFlagsOverrideSet;
17003 node->UpdateMergedFlags();
17006 ImGuiDockNodeFlags node_flags = node->MergedFlags;
17007 if (node->WantHiddenTabBarUpdate && node->Windows.Size == 1 && (node_flags & ImGuiDockNodeFlags_AutoHideTabBar) && !node->IsHiddenTabBar())
17008 node->WantHiddenTabBarToggle =
true;
17009 node->WantHiddenTabBarUpdate =
false;
17012 if (node->WantHiddenTabBarToggle && node->VisibleWindow && (node->VisibleWindow->WindowClass.DockNodeFlagsOverrideSet & ImGuiDockNodeFlags_HiddenTabBar))
17013 node->WantHiddenTabBarToggle =
false;
17016 if (node->Windows.Size > 1)
17017 node->SetLocalFlags(node->LocalFlags & ~ImGuiDockNodeFlags_HiddenTabBar);
17018 else if (node->WantHiddenTabBarToggle)
17019 node->SetLocalFlags(node->LocalFlags ^ ImGuiDockNodeFlags_HiddenTabBar);
17020 node->WantHiddenTabBarToggle =
false;
17022 DockNodeUpdateVisibleFlag(node);
17026static void ImGui::DockNodeUpdateHasCentralNodeChild(ImGuiDockNode* node)
17028 node->HasCentralNodeChild =
false;
17029 if (node->ChildNodes[0])
17030 DockNodeUpdateHasCentralNodeChild(node->ChildNodes[0]);
17031 if (node->ChildNodes[1])
17032 DockNodeUpdateHasCentralNodeChild(node->ChildNodes[1]);
17033 if (node->IsRootNode())
17035 ImGuiDockNode* mark_node = node->CentralNode;
17038 mark_node->HasCentralNodeChild =
true;
17039 mark_node = mark_node->ParentNode;
17044static void ImGui::DockNodeUpdateVisibleFlag(ImGuiDockNode* node)
17047 bool is_visible = (node->ParentNode == NULL) ? node->IsDockSpace() : node->IsCentralNode();
17048 is_visible |= (node->Windows.Size > 0);
17049 is_visible |= (node->ChildNodes[0] && node->ChildNodes[0]->IsVisible);
17050 is_visible |= (node->ChildNodes[1] && node->ChildNodes[1]->IsVisible);
17051 node->IsVisible = is_visible;
17054static void ImGui::DockNodeStartMouseMovingWindow(ImGuiDockNode* node, ImGuiWindow* window)
17057 IM_ASSERT(node->WantMouseMove ==
true);
17058 StartMouseMovingWindow(window);
17059 g.ActiveIdClickOffset =
g.IO.MouseClickedPos[0] - node->Pos;
17060 g.MovingWindow = window;
17061 node->WantMouseMove =
false;
17065static void ImGui::DockNodeUpdateForRootNode(ImGuiDockNode* node)
17067 DockNodeUpdateFlagsAndCollapse(node);
17073 DockNodeFindInfo(node, &info);
17085 node->WindowClass = first_node_with_windows->Windows[0]->WindowClass;
17086 for (
int n = 1; n < first_node_with_windows->Windows.Size; n++)
17087 if (first_node_with_windows->Windows[n]->WindowClass.DockingAllowUnclassed ==
false)
17089 node->WindowClass = first_node_with_windows->Windows[n]->WindowClass;
17094 ImGuiDockNode* mark_node = node->CentralNode;
17097 mark_node->HasCentralNodeChild =
true;
17098 mark_node = mark_node->ParentNode;
17102static void DockNodeSetupHostWindow(ImGuiDockNode* node, ImGuiWindow* host_window)
17109 if (node->HostWindow && node->HostWindow != host_window && node->HostWindow->DockNodeAsHost == node)
17110 node->HostWindow->DockNodeAsHost = NULL;
17112 host_window->DockNodeAsHost = node;
17113 node->HostWindow = host_window;
17116static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
17119 IM_ASSERT(node->LastFrameActive !=
g.FrameCount);
17120 node->LastFrameAlive =
g.FrameCount;
17121 node->IsBgDrawnThisFrame =
false;
17123 node->CentralNode = node->OnlyNodeWithWindows = NULL;
17124 if (node->IsRootNode())
17125 DockNodeUpdateForRootNode(node);
17128 if (node->TabBar && node->IsNoTabBar())
17129 DockNodeRemoveTabBar(node);
17132 bool want_to_hide_host_window =
false;
17133 if (node->IsFloatingNode())
17135 if (node->Windows.Size <= 1 && node->IsLeafNode())
17136 if (!
g.IO.ConfigDockingAlwaysTabBar && (node->Windows.Size == 0 || !node->Windows[0]->WindowClass.DockingAlwaysTabBar))
17137 want_to_hide_host_window =
true;
17138 if (node->CountNodeWithWindows == 0)
17139 want_to_hide_host_window =
true;
17141 if (want_to_hide_host_window)
17143 if (node->Windows.Size == 1)
17146 ImGuiWindow* single_window = node->Windows[0];
17147 node->Pos = single_window->Pos;
17148 node->Size = single_window->SizeFull;
17149 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Window;
17152 if (node->HostWindow &&
g.NavWindow == node->HostWindow)
17153 FocusWindow(single_window);
17154 if (node->HostWindow)
17156 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);
17157 single_window->Viewport = node->HostWindow->Viewport;
17158 single_window->ViewportId = node->HostWindow->ViewportId;
17159 if (node->HostWindow->ViewportOwned)
17161 single_window->Viewport->ID = single_window->ID;
17162 single_window->Viewport->Window = single_window;
17163 single_window->ViewportOwned =
true;
17166 node->RefViewportId = single_window->ViewportId;
17169 DockNodeHideHostWindow(node);
17170 node->State = ImGuiDockNodeState_HostWindowHiddenBecauseSingleWindow;
17171 node->WantCloseAll =
false;
17172 node->WantCloseTabId = 0;
17173 node->HasCloseButton = node->HasWindowMenuButton =
false;
17174 node->LastFrameActive =
g.FrameCount;
17176 if (node->WantMouseMove && node->Windows.Size == 1)
17177 DockNodeStartMouseMovingWindow(node, node->Windows[0]);
17191 if (node->IsVisible && node->HostWindow == NULL && node->IsFloatingNode() && node->IsLeafNode())
17193 IM_ASSERT(node->Windows.Size > 0);
17194 ImGuiWindow* ref_window = NULL;
17195 if (node->SelectedTabId != 0)
17196 ref_window = DockNodeFindWindowByID(node, node->SelectedTabId);
17197 if (ref_window == NULL)
17198 ref_window = node->Windows[0];
17199 if (ref_window->AutoFitFramesX > 0 || ref_window->AutoFitFramesY > 0)
17201 node->State = ImGuiDockNodeState_HostWindowHiddenBecauseWindowsAreResizing;
17206 const ImGuiDockNodeFlags node_flags = node->MergedFlags;
17209 node->HasWindowMenuButton = (node->Windows.Size > 0) && (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0;
17210 node->HasCloseButton =
false;
17211 for (ImGuiWindow* window : node->Windows)
17214 node->HasCloseButton |= window->HasCloseButton;
17215 window->DockIsActive = (node->Windows.Size > 1);
17217 if (node_flags & ImGuiDockNodeFlags_NoCloseButton)
17218 node->HasCloseButton =
false;
17221 ImGuiWindow* host_window = NULL;
17222 bool beginned_into_host_window =
false;
17223 if (node->IsDockSpace())
17226 IM_ASSERT(node->HostWindow);
17227 host_window = node->HostWindow;
17232 if (node->IsRootNode() && node->IsVisible)
17234 ImGuiWindow* ref_window = (node->Windows.Size > 0) ? node->Windows[0] : NULL;
17237 if (node->AuthorityForPos == ImGuiDataAuthority_Window && ref_window)
17238 SetNextWindowPos(ref_window->Pos);
17239 else if (node->AuthorityForPos == ImGuiDataAuthority_DockNode)
17240 SetNextWindowPos(node->Pos);
17243 if (node->AuthorityForSize == ImGuiDataAuthority_Window && ref_window)
17244 SetNextWindowSize(ref_window->SizeFull);
17245 else if (node->AuthorityForSize == ImGuiDataAuthority_DockNode)
17246 SetNextWindowSize(node->Size);
17249 if (node->AuthorityForSize == ImGuiDataAuthority_Window && ref_window)
17250 SetNextWindowCollapsed(ref_window->Collapsed);
17253 if (node->AuthorityForViewport == ImGuiDataAuthority_Window && ref_window)
17254 SetNextWindowViewport(ref_window->ViewportId);
17255 else if (node->AuthorityForViewport == ImGuiDataAuthority_Window && node->RefViewportId != 0)
17256 SetNextWindowViewport(node->RefViewportId);
17258 SetNextWindowClass(&node->WindowClass);
17261 char window_label[20];
17262 DockNodeGetHostWindowTitle(node, window_label, IM_ARRAYSIZE(window_label));
17263 ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_DockNodeHost;
17264 window_flags |= ImGuiWindowFlags_NoFocusOnAppearing;
17265 window_flags |= ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoCollapse;
17266 window_flags |= ImGuiWindowFlags_NoTitleBar;
17268 SetNextWindowBgAlpha(0.0f);
17269 PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
17270 Begin(window_label, NULL, window_flags);
17272 beginned_into_host_window =
true;
17274 host_window =
g.CurrentWindow;
17275 DockNodeSetupHostWindow(node, host_window);
17276 host_window->DC.CursorPos = host_window->Pos;
17277 node->Pos = host_window->Pos;
17278 node->Size = host_window->Size;
17286 if (node->HostWindow->Appearing)
17287 BringWindowToDisplayFront(node->HostWindow);
17289 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Auto;
17291 else if (node->ParentNode)
17293 node->HostWindow = host_window = node->ParentNode->HostWindow;
17294 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Auto;
17296 if (node->WantMouseMove && node->HostWindow)
17297 DockNodeStartMouseMovingWindow(node, node->HostWindow);
17299 node->RefViewportId = 0;
17302 if (node->IsSplitNode())
17303 IM_ASSERT(node->TabBar == NULL);
17304 if (node->IsRootNode())
17305 if (ImGuiWindow* p_window =
g.NavWindow ?
g.NavWindow->RootWindow : NULL)
17306 while (p_window != NULL && p_window->DockNode != NULL)
17308 ImGuiDockNode* p_node = DockNodeGetRootNode(p_window->DockNode);
17309 if (p_node == node)
17311 node->LastFocusedNodeId = p_window->DockNode->ID;
17314 p_window = p_node->HostWindow ? p_node->HostWindow->RootWindow : NULL;
17318 ImGuiDockNode* central_node = node->CentralNode;
17319 const bool central_node_hole = node->IsRootNode() && host_window && (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0 && central_node != NULL && central_node->IsEmpty();
17320 bool central_node_hole_register_hit_test_hole = central_node_hole;
17321 if (central_node_hole)
17322 if (
const ImGuiPayload* payload = ImGui::GetDragDropPayload())
17323 if (payload->IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) && DockNodeIsDropAllowed(host_window, *(ImGuiWindow**)payload->Data))
17324 central_node_hole_register_hit_test_hole =
false;
17325 if (central_node_hole_register_hit_test_hole)
17330 IM_ASSERT(node->IsDockSpace());
17331 ImGuiDockNode* root_node = DockNodeGetRootNode(central_node);
17332 ImRect root_rect(root_node->Pos, root_node->Pos + root_node->Size);
17333 ImRect hole_rect(central_node->Pos, central_node->Pos + central_node->Size);
17334 if (hole_rect.Min.x > root_rect.Min.x) { hole_rect.Min.x += WINDOWS_HOVER_PADDING; }
17335 if (hole_rect.Max.x < root_rect.Max.x) { hole_rect.Max.x -= WINDOWS_HOVER_PADDING; }
17336 if (hole_rect.Min.y > root_rect.Min.y) { hole_rect.Min.y += WINDOWS_HOVER_PADDING; }
17337 if (hole_rect.Max.y < root_rect.Max.y) { hole_rect.Max.y -= WINDOWS_HOVER_PADDING; }
17339 if (central_node_hole && !hole_rect.IsInverted())
17341 SetWindowHitTestHole(host_window, hole_rect.Min, hole_rect.Max - hole_rect.Min);
17342 if (host_window->ParentWindow)
17343 SetWindowHitTestHole(host_window->ParentWindow, hole_rect.Min, hole_rect.Max - hole_rect.Min);
17348 if (node->IsRootNode() && host_window)
17350 DockNodeTreeUpdatePosSize(node, host_window->Pos, host_window->Size);
17351 PushStyleColor(ImGuiCol_Separator,
g.Style.Colors[ImGuiCol_Border]);
17352 PushStyleColor(ImGuiCol_SeparatorActive,
g.Style.Colors[ImGuiCol_ResizeGripActive]);
17353 PushStyleColor(ImGuiCol_SeparatorHovered,
g.Style.Colors[ImGuiCol_ResizeGripHovered]);
17354 DockNodeTreeUpdateSplitter(node);
17359 if (host_window && node->IsEmpty() && node->IsVisible)
17361 host_window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
17362 node->LastBgColor = (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) ? 0 : GetColorU32(ImGuiCol_DockingEmptyBg);
17363 if (node->LastBgColor != 0)
17364 host_window->DrawList->AddRectFilled(node->Pos, node->Pos + node->Size, node->LastBgColor);
17365 node->IsBgDrawnThisFrame =
true;
17371 const bool render_dockspace_bg = node->IsRootNode() && host_window && (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0;
17372 if (render_dockspace_bg && node->IsVisible)
17374 host_window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
17375 if (central_node_hole)
17376 RenderRectFilledWithHole(host_window->DrawList, node->Rect(), central_node->Rect(), GetColorU32(ImGuiCol_WindowBg), 0.0f);
17378 host_window->DrawList->AddRectFilled(node->Pos, node->Pos + node->Size, GetColorU32(ImGuiCol_WindowBg), 0.0f);
17383 host_window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_FG);
17384 if (host_window && node->Windows.Size > 0)
17386 DockNodeUpdateTabBar(node, host_window);
17390 node->WantCloseAll =
false;
17391 node->WantCloseTabId = 0;
17392 node->IsFocused =
false;
17394 if (node->TabBar && node->TabBar->SelectedTabId)
17395 node->SelectedTabId = node->TabBar->SelectedTabId;
17396 else if (node->Windows.Size > 0)
17397 node->SelectedTabId = node->Windows[0]->TabId;
17400 if (host_window && node->IsVisible)
17401 if (node->IsRootNode() && (
g.MovingWindow == NULL ||
g.MovingWindow->RootWindowDockTree != host_window))
17402 BeginDockableDragDropTarget(host_window);
17405 node->LastFrameActive =
g.FrameCount;
17411 if (node->ChildNodes[0])
17412 DockNodeUpdate(node->ChildNodes[0]);
17413 if (node->ChildNodes[1])
17414 DockNodeUpdate(node->ChildNodes[1]);
17417 if (node->IsRootNode())
17418 RenderWindowOuterBorders(host_window);
17422 if (beginned_into_host_window)
17427static int IMGUI_CDECL TabItemComparerByDockOrder(
const void* lhs,
const void* rhs)
17429 ImGuiWindow* a = ((
const ImGuiTabItem*)lhs)->Window;
17430 ImGuiWindow* b = ((
const ImGuiTabItem*)rhs)->Window;
17431 if (
int d = ((a->DockOrder == -1) ? INT_MAX : a->DockOrder) - ((b->DockOrder == -1) ? INT_MAX : b->DockOrder))
17433 return (a->BeginOrderWithinContext - b->BeginOrderWithinContext);
17441void ImGui::DockNodeWindowMenuHandler_Default(ImGuiContext* ctx, ImGuiDockNode* node, ImGuiTabBar* tab_bar)
17444 if (tab_bar->Tabs.Size == 1)
17447 if (MenuItem(LocalizeGetMsg(ImGuiLocKey_DockingHideTabBar), NULL, node->IsHiddenTabBar()))
17448 node->WantHiddenTabBarToggle =
true;
17453 for (
int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
17455 ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
17456 if (tab->Flags & ImGuiTabItemFlags_Button)
17458 if (Selectable(TabBarGetTabName(tab_bar, tab), tab->ID == tab_bar->SelectedTabId))
17459 TabBarQueueFocus(tab_bar, tab);
17466static void ImGui::DockNodeWindowMenuUpdate(ImGuiDockNode* node, ImGuiTabBar* tab_bar)
17470 if (
g.Style.WindowMenuButtonPosition == ImGuiDir_Left)
17471 SetNextWindowPos(ImVec2(node->Pos.x, node->Pos.y + GetFrameHeight()), ImGuiCond_Always, ImVec2(0.0f, 0.0f));
17473 SetNextWindowPos(ImVec2(node->Pos.x + node->Size.x, node->Pos.y + GetFrameHeight()), ImGuiCond_Always, ImVec2(1.0f, 0.0f));
17474 if (BeginPopup(
"#WindowMenu"))
17476 node->IsFocused =
true;
17477 g.DockNodeWindowMenuHandler(&
g, node, tab_bar);
17483bool ImGui::DockNodeBeginAmendTabBar(ImGuiDockNode* node)
17485 if (node->TabBar == NULL || node->HostWindow == NULL)
17487 if (node->MergedFlags & ImGuiDockNodeFlags_KeepAliveOnly)
17489 if (node->TabBar->ID == 0)
17491 Begin(node->HostWindow->Name);
17492 PushOverrideID(node->ID);
17493 bool ret = BeginTabBarEx(node->TabBar, node->TabBar->BarRect, node->TabBar->Flags);
17499void ImGui::DockNodeEndAmendTabBar()
17506static bool IsDockNodeTitleBarHighlighted(ImGuiDockNode* node, ImGuiDockNode* root_node)
17510 if (
g.NavWindowingTarget)
17511 return (
g.NavWindowingTarget->DockNode == node);
17514 if (
g.NavWindow && root_node->LastFocusedNodeId == node->ID)
17517 ImGuiWindow* parent_window =
g.NavWindow->RootWindow;
17518 while (parent_window->Flags & ImGuiWindowFlags_ChildMenu)
17519 parent_window = parent_window->ParentWindow->RootWindow;
17520 ImGuiDockNode* start_parent_node = parent_window->DockNodeAsHost ? parent_window->DockNodeAsHost : parent_window->DockNode;
17521 for (ImGuiDockNode* parent_node = start_parent_node; parent_node != NULL; parent_node = parent_node->HostWindow ? parent_node->HostWindow->RootWindow->DockNode : NULL)
17522 if ((parent_node = ImGui::DockNodeGetRootNode(parent_node)) == root_node)
17529static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_window)
17532 ImGuiStyle& style =
g.Style;
17534 const bool node_was_active = (node->LastFrameActive + 1 ==
g.FrameCount);
17535 const bool closed_all = node->WantCloseAll && node_was_active;
17536 const ImGuiID closed_one = node->WantCloseTabId && node_was_active;
17537 node->WantCloseAll =
false;
17538 node->WantCloseTabId = 0;
17541 bool is_focused =
false;
17542 ImGuiDockNode* root_node = DockNodeGetRootNode(node);
17543 if (IsDockNodeTitleBarHighlighted(node, root_node))
17547 if (node->IsHiddenTabBar() || node->IsNoTabBar())
17549 node->VisibleWindow = (node->Windows.Size > 0) ? node->Windows[0] : NULL;
17550 node->IsFocused = is_focused;
17552 node->LastFrameFocused =
g.FrameCount;
17553 if (node->VisibleWindow)
17556 if (is_focused || root_node->VisibleWindow == NULL)
17557 root_node->VisibleWindow = node->VisibleWindow;
17559 node->TabBar->VisibleTabId = node->VisibleWindow->TabId;
17565 bool backup_skip_item = host_window->SkipItems;
17566 if (!node->IsDockSpace())
17568 host_window->SkipItems =
false;
17569 host_window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
17575 PushOverrideID(node->ID);
17576 ImGuiTabBar* tab_bar = node->TabBar;
17577 bool tab_bar_is_recreated = (tab_bar == NULL);
17578 if (tab_bar == NULL)
17580 DockNodeAddTabBar(node);
17581 tab_bar = node->TabBar;
17584 ImGuiID focus_tab_id = 0;
17585 node->IsFocused = is_focused;
17587 const ImGuiDockNodeFlags node_flags = node->MergedFlags;
17588 const bool has_window_menu_button = (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0 && (style.WindowMenuButtonPosition != ImGuiDir_None);
17592 if (has_window_menu_button && IsPopupOpen(
"#WindowMenu"))
17594 ImGuiID next_selected_tab_id = tab_bar->NextSelectedTabId;
17595 DockNodeWindowMenuUpdate(node, tab_bar);
17596 if (tab_bar->NextSelectedTabId != 0 && tab_bar->NextSelectedTabId != next_selected_tab_id)
17597 focus_tab_id = tab_bar->NextSelectedTabId;
17598 is_focused |= node->IsFocused;
17602 ImRect title_bar_rect, tab_bar_rect;
17603 ImVec2 window_menu_button_pos;
17604 ImVec2 close_button_pos;
17605 DockNodeCalcTabBarLayout(node, &title_bar_rect, &tab_bar_rect, &window_menu_button_pos, &close_button_pos);
17608 const int tabs_count_old = tab_bar->Tabs.Size;
17609 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
17611 ImGuiWindow* window = node->Windows[window_n];
17612 if (TabBarFindTabByID(tab_bar, window->TabId) == NULL)
17613 TabBarAddTab(tab_bar, ImGuiTabItemFlags_Unsorted, window);
17618 node->LastFrameFocused =
g.FrameCount;
17619 ImU32 title_bar_col = GetColorU32(host_window->Collapsed ? ImGuiCol_TitleBgCollapsed : is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
17620 ImDrawFlags rounding_flags = CalcRoundingFlagsForRectInRect(title_bar_rect, host_window->Rect(),
g.Style.DockingSeparatorSize);
17621 host_window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, host_window->WindowRounding, rounding_flags);
17624 if (has_window_menu_button)
17626 if (CollapseButton(host_window->GetID(
"#COLLAPSE"), window_menu_button_pos, node))
17627 OpenPopup(
"#WindowMenu");
17628 if (IsItemActive())
17629 focus_tab_id = tab_bar->SelectedTabId;
17630 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_DelayNormal) &&
g.HoveredIdTimer > 0.5f)
17631 SetTooltip(
"%s", LocalizeGetMsg(ImGuiLocKey_DockingDragToUndockOrMoveNode));
17635 int tabs_unsorted_start = tab_bar->Tabs.Size;
17636 for (
int tab_n = tab_bar->Tabs.Size - 1; tab_n >= 0 && (tab_bar->Tabs[tab_n].Flags & ImGuiTabItemFlags_Unsorted); tab_n--)
17639 tab_bar->Tabs[tab_n].Flags &= ~ImGuiTabItemFlags_Unsorted;
17640 tabs_unsorted_start = tab_n;
17642 if (tab_bar->Tabs.Size > tabs_unsorted_start)
17644 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)" :
"");
17645 for (
int tab_n = tabs_unsorted_start; tab_n < tab_bar->Tabs.Size; tab_n++)
17647 ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
17648 IMGUI_DEBUG_LOG_DOCKING(
"[docking] - Tab 0x%08X '%s' Order %d\n", tab->ID, TabBarGetTabName(tab_bar, tab), tab->Window ? tab->Window->DockOrder : -1);
17650 IMGUI_DEBUG_LOG_DOCKING(
"[docking] SelectedTabId = 0x%08X, NavWindow->TabId = 0x%08X\n", node->SelectedTabId,
g.NavWindow ?
g.NavWindow->TabId : -1);
17651 if (tab_bar->Tabs.Size > tabs_unsorted_start + 1)
17652 ImQsort(tab_bar->Tabs.Data + tabs_unsorted_start, tab_bar->Tabs.Size - tabs_unsorted_start,
sizeof(ImGuiTabItem), TabItemComparerByDockOrder);
17656 if (
g.NavWindow &&
g.NavWindow->RootWindow->DockNode == node)
17657 tab_bar->SelectedTabId =
g.NavWindow->RootWindow->TabId;
17660 if (tab_bar_is_recreated && TabBarFindTabByID(tab_bar, node->SelectedTabId) != NULL)
17661 tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = node->SelectedTabId;
17662 else if (tab_bar->Tabs.Size > tabs_count_old)
17663 tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = tab_bar->Tabs.back().Window->TabId;
17666 ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_AutoSelectNewTabs;
17667 tab_bar_flags |= ImGuiTabBarFlags_SaveSettings | ImGuiTabBarFlags_DockNode;
17668 if (!host_window->Collapsed && is_focused)
17669 tab_bar_flags |= ImGuiTabBarFlags_IsFocused;
17670 tab_bar->ID = GetID(
"#TabBar");
17671 tab_bar->SeparatorMinX = node->Pos.x + host_window->WindowBorderSize;
17672 tab_bar->SeparatorMaxX = node->Pos.x + node->Size.x - host_window->WindowBorderSize;
17673 BeginTabBarEx(tab_bar, tab_bar_rect, tab_bar_flags);
17677 ImVec4 backup_style_cols[ImGuiWindowDockStyleCol_COUNT];
17678 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
17679 backup_style_cols[color_n] =
g.Style.Colors[GWindowDockStyleColors[color_n]];
17682 node->VisibleWindow = NULL;
17683 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
17685 ImGuiWindow* window = node->Windows[window_n];
17686 if ((closed_all || closed_one == window->TabId) && window->HasCloseButton && !(window->Flags & ImGuiWindowFlags_UnsavedDocument))
17688 if (window->LastFrameActive + 1 >=
g.FrameCount || !node_was_active)
17690 ImGuiTabItemFlags tab_item_flags = 0;
17691 tab_item_flags |= window->WindowClass.TabItemFlagsOverrideSet;
17692 if (window->Flags & ImGuiWindowFlags_UnsavedDocument)
17693 tab_item_flags |= ImGuiTabItemFlags_UnsavedDocument;
17694 if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
17695 tab_item_flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
17698 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
17699 g.Style.Colors[GWindowDockStyleColors[color_n]] = ColorConvertU32ToFloat4(window->DockStyle.Colors[color_n]);
17702 bool tab_open =
true;
17703 TabItemEx(tab_bar, window->Name, window->HasCloseButton ? &tab_open : NULL, tab_item_flags, window);
17705 node->WantCloseTabId = window->TabId;
17706 if (tab_bar->VisibleTabId == window->TabId)
17707 node->VisibleWindow = window;
17710 window->DockTabItemStatusFlags =
g.LastItemData.StatusFlags;
17711 window->DockTabItemRect =
g.LastItemData.Rect;
17714 if (
g.NavWindow &&
g.NavWindow->RootWindow == window && (window->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) == 0)
17715 host_window->NavLastIds[1] = window->TabId;
17720 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
17721 g.Style.Colors[GWindowDockStyleColors[color_n]] = backup_style_cols[color_n];
17724 if (node->VisibleWindow)
17725 if (is_focused || root_node->VisibleWindow == NULL)
17726 root_node->VisibleWindow = node->VisibleWindow;
17730 const bool close_button_is_enabled = node->HasCloseButton && node->VisibleWindow && node->VisibleWindow->HasCloseButton;
17731 const bool close_button_is_visible = node->HasCloseButton;
17733 if (close_button_is_visible)
17735 if (!close_button_is_enabled)
17737 PushItemFlag(ImGuiItemFlags_Disabled,
true);
17738 PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_Text] * ImVec4(1.0f,1.0f,1.0f,0.4f));
17740 if (CloseButton(host_window->GetID(
"#CLOSE"), close_button_pos))
17742 node->WantCloseAll =
true;
17743 for (
int n = 0; n < tab_bar->Tabs.Size; n++)
17744 TabBarCloseTab(tab_bar, &tab_bar->Tabs[n]);
17748 if (!close_button_is_enabled)
17757 ImGuiID title_bar_id = host_window->GetID(
"#TITLEBAR");
17758 if (
g.HoveredId == 0 ||
g.HoveredId == title_bar_id ||
g.ActiveId == title_bar_id)
17763 KeepAliveID(title_bar_id);
17764 ButtonBehavior(title_bar_rect, title_bar_id, NULL, &held, ImGuiButtonFlags_AllowOverlap);
17765 if (
g.HoveredId == title_bar_id)
17767 g.LastItemData.ID = title_bar_id;
17771 if (IsMouseClicked(0))
17772 focus_tab_id = tab_bar->SelectedTabId;
17775 if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
17776 StartMouseMovingWindowOrNode(tab->Window ? tab->Window : node->HostWindow, node, false);
17786 if (tab_bar->NextSelectedTabId)
17787 focus_tab_id = tab_bar->NextSelectedTabId;
17790 if (focus_tab_id != 0)
17791 if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, focus_tab_id))
17794 FocusWindow(tab->Window);
17795 NavInitWindow(tab->Window,
false);
17802 if (!node->IsDockSpace())
17804 host_window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
17805 host_window->SkipItems = backup_skip_item;
17809static void ImGui::DockNodeAddTabBar(ImGuiDockNode* node)
17811 IM_ASSERT(node->TabBar == NULL);
17812 node->TabBar = IM_NEW(ImGuiTabBar);
17815static void ImGui::DockNodeRemoveTabBar(ImGuiDockNode* node)
17817 if (node->TabBar == NULL)
17819 IM_DELETE(node->TabBar);
17820 node->TabBar = NULL;
17823static bool DockNodeIsDropAllowedOne(ImGuiWindow* payload, ImGuiWindow* host_window)
17825 if (host_window->DockNodeAsHost && host_window->DockNodeAsHost->IsDockSpace() && payload->BeginOrderWithinContext < host_window->BeginOrderWithinContext)
17828 ImGuiWindowClass* host_class = host_window->DockNodeAsHost ? &host_window->DockNodeAsHost->WindowClass : &host_window->WindowClass;
17829 ImGuiWindowClass* payload_class = &payload->WindowClass;
17830 if (host_class->ClassId != payload_class->ClassId)
17833 if (host_class->ClassId != 0 && host_class->DockingAllowUnclassed && payload_class->ClassId == 0)
17835 if (payload_class->ClassId != 0 && payload_class->DockingAllowUnclassed && host_class->ClassId == 0)
17847 for (
int i =
g.OpenPopupStack.Size - 1; i >= 0; i--)
17848 if (ImGuiWindow* popup_window =
g.OpenPopupStack[i].Window)
17849 if (ImGui::IsWindowWithinBeginStackOf(payload, popup_window))
17855static bool ImGui::DockNodeIsDropAllowed(ImGuiWindow* host_window, ImGuiWindow* root_payload)
17857 if (root_payload->DockNodeAsHost && root_payload->DockNodeAsHost->IsSplitNode())
17860 const int payload_count = root_payload->DockNodeAsHost ? root_payload->DockNodeAsHost->Windows.Size : 1;
17861 for (
int payload_n = 0; payload_n < payload_count; payload_n++)
17863 ImGuiWindow* payload = root_payload->DockNodeAsHost ? root_payload->DockNodeAsHost->Windows[payload_n] : root_payload;
17864 if (DockNodeIsDropAllowedOne(payload, host_window))
17872static 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)
17875 ImGuiStyle& style =
g.Style;
17877 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);
17878 if (out_title_rect) { *out_title_rect = r; }
17880 r.Min.x += style.WindowBorderSize;
17881 r.Max.x -= style.WindowBorderSize;
17883 float button_sz =
g.FontSize;
17884 r.Min.x += style.FramePadding.x;
17885 r.Max.x -= style.FramePadding.x;
17886 ImVec2 window_menu_button_pos = ImVec2(r.Min.x, r.Min.y + style.FramePadding.y);
17887 if (node->HasCloseButton)
17889 if (out_close_button_pos) *out_close_button_pos = ImVec2(r.Max.x - button_sz, r.Min.y + style.FramePadding.y);
17890 r.Max.x -= button_sz + style.ItemInnerSpacing.x;
17892 if (node->HasWindowMenuButton && style.WindowMenuButtonPosition == ImGuiDir_Left)
17894 r.Min.x += button_sz + style.ItemInnerSpacing.x;
17896 else if (node->HasWindowMenuButton && style.WindowMenuButtonPosition == ImGuiDir_Right)
17898 window_menu_button_pos = ImVec2(r.Max.x - button_sz, r.Min.y + style.FramePadding.y);
17899 r.Max.x -= button_sz + style.ItemInnerSpacing.x;
17901 if (out_tab_bar_rect) { *out_tab_bar_rect = r; }
17902 if (out_window_menu_button_pos) { *out_window_menu_button_pos = window_menu_button_pos; }
17905void ImGui::DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& pos_new, ImVec2& size_new, ImGuiDir dir, ImVec2 size_new_desired)
17908 const float dock_spacing =
g.Style.ItemInnerSpacing.x;
17909 const ImGuiAxis axis = (dir == ImGuiDir_Left || dir == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
17910 pos_new[axis ^ 1] = pos_old[axis ^ 1];
17911 size_new[axis ^ 1] = size_old[axis ^ 1];
17914 const float w_avail = size_old[axis] - dock_spacing;
17915 if (size_new_desired[axis] > 0.0f && size_new_desired[axis] <= w_avail * 0.5f)
17917 size_new[axis] = size_new_desired[axis];
17918 size_old[axis] = IM_TRUNC(w_avail - size_new[axis]);
17922 size_new[axis] = IM_TRUNC(w_avail * 0.5f);
17923 size_old[axis] = IM_TRUNC(w_avail - size_new[axis]);
17927 if (dir == ImGuiDir_Right || dir == ImGuiDir_Down)
17929 pos_new[axis] = pos_old[axis] + size_old[axis] + dock_spacing;
17931 else if (dir == ImGuiDir_Left || dir == ImGuiDir_Up)
17933 pos_new[axis] = pos_old[axis];
17934 pos_old[axis] = pos_new[axis] + size_new[axis] + dock_spacing;
17939bool ImGui::DockNodeCalcDropRectsAndTestMousePos(
const ImRect& parent, ImGuiDir dir, ImRect& out_r,
bool outer_docking, ImVec2* test_mouse_pos)
17943 const float parent_smaller_axis = ImMin(parent.GetWidth(), parent.GetHeight());
17944 const float hs_for_central_nodes = ImMin(
g.FontSize * 1.5f, ImMax(
g.FontSize * 0.5f, parent_smaller_axis / 8.0f));
17953 hs_w = ImTrunc(hs_for_central_nodes * 1.50f);
17954 hs_h = ImTrunc(hs_for_central_nodes * 0.80f);
17955 off = ImTrunc(ImVec2(parent.GetWidth() * 0.5f - hs_h, parent.GetHeight() * 0.5f - hs_h));
17959 hs_w = ImTrunc(hs_for_central_nodes);
17960 hs_h = ImTrunc(hs_for_central_nodes * 0.90f);
17961 off = ImTrunc(ImVec2(hs_w * 2.40f, hs_w * 2.40f));
17964 ImVec2 c = ImTrunc(parent.GetCenter());
17965 if (dir == ImGuiDir_None) { out_r = ImRect(c.x - hs_w, c.y - hs_w, c.x + hs_w, c.y + hs_w); }
17966 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); }
17967 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); }
17968 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); }
17969 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); }
17971 if (test_mouse_pos == NULL)
17974 ImRect hit_r = out_r;
17975 if (!outer_docking)
17978 hit_r.Expand(ImTrunc(hs_w * 0.30f));
17979 ImVec2 mouse_delta = (*test_mouse_pos - c);
17980 float mouse_delta_len2 = ImLengthSqr(mouse_delta);
17981 float r_threshold_center = hs_w * 1.4f;
17982 float r_threshold_sides = hs_w * (1.4f + 1.2f);
17983 if (mouse_delta_len2 < r_threshold_center * r_threshold_center)
17984 return (dir == ImGuiDir_None);
17985 if (mouse_delta_len2 < r_threshold_sides * r_threshold_sides)
17986 return (dir == ImGetDirQuadrantFromDelta(mouse_delta.x, mouse_delta.y));
17988 return hit_r.Contains(*test_mouse_pos);
17993static 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)
18000 if (payload_node == NULL)
18001 payload_node = payload_window->DockNodeAsHost;
18002 ImGuiDockNode* ref_node_for_rect = (host_node && !host_node->IsVisible) ? DockNodeGetRootNode(host_node) : host_node;
18003 if (ref_node_for_rect)
18004 IM_ASSERT(ref_node_for_rect->IsVisible ==
true);
18007 ImGuiDockNodeFlags src_node_flags = payload_node ? payload_node->MergedFlags : payload_window->WindowClass.DockNodeFlagsOverrideSet;
18008 ImGuiDockNodeFlags dst_node_flags = host_node ? host_node->MergedFlags : host_window->WindowClass.DockNodeFlagsOverrideSet;
18010 if (is_outer_docking)
18012 else if (dst_node_flags & ImGuiDockNodeFlags_NoDockingOverMe)
18014 else if (host_node && (dst_node_flags & ImGuiDockNodeFlags_NoDockingOverCentralNode) && host_node->IsCentralNode())
18016 else if ((!host_node || !host_node->IsEmpty()) && payload_node && payload_node->IsSplitNode() && (payload_node->OnlyNodeWithWindows == NULL))
18018 else if ((src_node_flags & ImGuiDockNodeFlags_NoDockingOverOther) && (!host_node || !host_node->IsEmpty()))
18020 else if ((src_node_flags & ImGuiDockNodeFlags_NoDockingOverEmpty) && host_node && host_node->IsEmpty())
18024 if ((dst_node_flags & ImGuiDockNodeFlags_NoDockingSplit) ||
g.IO.ConfigDockingNoSplit)
18026 else if (!is_outer_docking && host_node && host_node->ParentNode == NULL && host_node->IsCentralNode())
18028 else if (src_node_flags & ImGuiDockNodeFlags_NoDockingSplitOther)
18032 data->
FutureNode.HasCloseButton = (host_node ? host_node->HasCloseButton : host_window->HasCloseButton) || (payload_window->HasCloseButton);
18033 data->
FutureNode.HasWindowMenuButton = host_node ? true : ((host_window->Flags & ImGuiWindowFlags_NoCollapse) == 0);
18034 data->
FutureNode.Pos = ref_node_for_rect ? ref_node_for_rect->Pos : host_window->Pos;
18035 data->
FutureNode.Size = ref_node_for_rect ? ref_node_for_rect->Size : host_window->Size;
18038 IM_ASSERT(ImGuiDir_None == -1);
18042 if (!host_window->Collapsed)
18043 for (
int dir = ImGuiDir_None; dir < ImGuiDir_COUNT; dir++)
18049 if (DockNodeCalcDropRectsAndTestMousePos(data->
FutureNode.Rect(), (ImGuiDir)dir, data->
DropRectsDraw[dir+1], is_outer_docking, &
g.IO.MousePos))
18063 if (data->
SplitDir != ImGuiDir_None)
18065 ImGuiDir split_dir = data->
SplitDir;
18066 ImGuiAxis split_axis = (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
18067 ImVec2 pos_new, pos_old = data->
FutureNode.Pos;
18068 ImVec2 size_new, size_old = data->
FutureNode.Size;
18069 DockNodeCalcSplitRects(pos_old, size_old, pos_new, size_new, split_dir, payload_window->Size);
18072 float split_ratio = ImSaturate(size_new[split_axis] / data->
FutureNode.Size[split_axis]);
18075 data->
SplitRatio = (split_dir == ImGuiDir_Right || split_dir == ImGuiDir_Down) ? (1.0f - split_ratio) : (split_ratio);
18079static void ImGui::DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* root_payload,
const ImGuiDockPreviewData* data)
18082 IM_ASSERT(
g.CurrentWindow == host_window);
18086 const bool is_transparent_payload =
g.IO.ConfigDockingTransparentPayload;
18089 int overlay_draw_lists_count = 0;
18090 ImDrawList* overlay_draw_lists[2];
18091 overlay_draw_lists[overlay_draw_lists_count++] = GetForegroundDrawList(host_window->Viewport);
18092 if (host_window->Viewport != root_payload->Viewport && !is_transparent_payload)
18093 overlay_draw_lists[overlay_draw_lists_count++] = GetForegroundDrawList(root_payload->Viewport);
18096 const ImU32 overlay_col_main = GetColorU32(ImGuiCol_DockingPreview, is_transparent_payload ? 0.60f : 0.40f);
18097 const ImU32 overlay_col_drop = GetColorU32(ImGuiCol_DockingPreview, is_transparent_payload ? 0.90f : 0.70f);
18098 const ImU32 overlay_col_drop_hovered = GetColorU32(ImGuiCol_DockingPreview, is_transparent_payload ? 1.20f : 1.00f);
18099 const ImU32 overlay_col_lines = GetColorU32(ImGuiCol_NavWindowingHighlight, is_transparent_payload ? 0.80f : 0.60f);
18102 const bool can_preview_tabs = (root_payload->DockNodeAsHost == NULL || root_payload->DockNodeAsHost->Windows.Size > 0);
18105 ImRect overlay_rect = data->
FutureNode.Rect();
18106 if (data->
SplitDir == ImGuiDir_None && can_preview_tabs)
18107 overlay_rect.Min.y += GetFrameHeight();
18109 for (
int overlay_n = 0; overlay_n < overlay_draw_lists_count; overlay_n++)
18110 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));
18117 ImRect tab_bar_rect;
18118 DockNodeCalcTabBarLayout(&data->
FutureNode, NULL, &tab_bar_rect, NULL, NULL);
18119 ImVec2 tab_pos = tab_bar_rect.Min;
18120 if (host_node && host_node->TabBar)
18122 if (!host_node->IsHiddenTabBar() && !host_node->IsNoTabBar())
18123 tab_pos.x += host_node->TabBar->WidthAllTabs +
g.Style.ItemInnerSpacing.x;
18125 tab_pos.x +=
g.Style.ItemInnerSpacing.x + TabItemCalcSize(host_node->Windows[0]).x;
18127 else if (!(host_window->Flags & ImGuiWindowFlags_DockNodeHost))
18129 tab_pos.x +=
g.Style.ItemInnerSpacing.x + TabItemCalcSize(host_window).x;
18133 if (root_payload->DockNodeAsHost)
18134 IM_ASSERT(root_payload->DockNodeAsHost->Windows.Size <= root_payload->DockNodeAsHost->TabBar->Tabs.Size);
18135 ImGuiTabBar* tab_bar_with_payload = root_payload->DockNodeAsHost ? root_payload->DockNodeAsHost->TabBar : NULL;
18136 const int payload_count = tab_bar_with_payload ? tab_bar_with_payload->Tabs.Size : 1;
18137 for (
int payload_n = 0; payload_n < payload_count; payload_n++)
18140 ImGuiWindow* payload_window = tab_bar_with_payload ? tab_bar_with_payload->Tabs[payload_n].Window : root_payload;
18141 if (tab_bar_with_payload && payload_window == NULL)
18143 if (!DockNodeIsDropAllowedOne(payload_window, host_window))
18147 ImVec2 tab_size = TabItemCalcSize(payload_window);
18148 ImRect tab_bb(tab_pos.x, tab_pos.y, tab_pos.x + tab_size.x, tab_pos.y + tab_size.y);
18149 tab_pos.x += tab_size.x +
g.Style.ItemInnerSpacing.x;
18150 const ImU32 overlay_col_text = GetColorU32(payload_window->DockStyle.Colors[ImGuiWindowDockStyleCol_Text]);
18151 const ImU32 overlay_col_tabs = GetColorU32(payload_window->DockStyle.Colors[ImGuiWindowDockStyleCol_TabActive]);
18152 PushStyleColor(ImGuiCol_Text, overlay_col_text);
18153 for (
int overlay_n = 0; overlay_n < overlay_draw_lists_count; overlay_n++)
18155 ImGuiTabItemFlags tab_flags = (payload_window->Flags & ImGuiWindowFlags_UnsavedDocument) ? ImGuiTabItemFlags_UnsavedDocument : 0;
18156 if (!tab_bar_rect.Contains(tab_bb))
18157 overlay_draw_lists[overlay_n]->PushClipRect(tab_bar_rect.Min, tab_bar_rect.Max);
18158 TabItemBackground(overlay_draw_lists[overlay_n], tab_bb, tab_flags, overlay_col_tabs);
18159 TabItemLabelAndCloseButton(overlay_draw_lists[overlay_n], tab_bb, tab_flags,
g.Style.FramePadding, payload_window->Name, 0, 0,
false, NULL, NULL);
18160 if (!tab_bar_rect.Contains(tab_bb))
18161 overlay_draw_lists[overlay_n]->PopClipRect();
18168 const float overlay_rounding = ImMax(3.0f,
g.Style.FrameRounding);
18169 for (
int dir = ImGuiDir_None; dir < ImGuiDir_COUNT; dir++)
18174 ImRect draw_r_in = draw_r;
18175 draw_r_in.Expand(-2.0f);
18176 ImU32 overlay_col = (data->
SplitDir == (ImGuiDir)dir && data->
IsSplitDirExplicit) ? overlay_col_drop_hovered : overlay_col_drop;
18177 for (
int overlay_n = 0; overlay_n < overlay_draw_lists_count; overlay_n++)
18179 ImVec2 center = ImFloor(draw_r_in.GetCenter());
18180 overlay_draw_lists[overlay_n]->AddRectFilled(draw_r.Min, draw_r.Max, overlay_col, overlay_rounding);
18181 overlay_draw_lists[overlay_n]->AddRect(draw_r_in.Min, draw_r_in.Max, overlay_col_lines, overlay_rounding);
18182 if (dir == ImGuiDir_Left || dir == ImGuiDir_Right)
18183 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);
18184 if (dir == ImGuiDir_Up || dir == ImGuiDir_Down)
18185 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);
18190 if ((host_node && (host_node->MergedFlags & ImGuiDockNodeFlags_NoDockingSplit)) ||
g.IO.ConfigDockingNoSplit)
18207void ImGui::DockNodeTreeSplit(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiAxis split_axis,
int split_inheritor_child_idx,
float split_ratio, ImGuiDockNode* new_node)
18210 IM_ASSERT(split_axis != ImGuiAxis_None);
18212 ImGuiDockNode* child_0 = (new_node && split_inheritor_child_idx != 0) ? new_node : DockContextAddNode(ctx, 0);
18213 child_0->ParentNode = parent_node;
18215 ImGuiDockNode* child_1 = (new_node && split_inheritor_child_idx != 1) ? new_node : DockContextAddNode(ctx, 0);
18216 child_1->ParentNode = parent_node;
18218 ImGuiDockNode* child_inheritor = (split_inheritor_child_idx == 0) ? child_0 : child_1;
18219 DockNodeMoveChildNodes(child_inheritor, parent_node);
18220 parent_node->ChildNodes[0] = child_0;
18221 parent_node->ChildNodes[1] = child_1;
18222 parent_node->ChildNodes[split_inheritor_child_idx]->VisibleWindow = parent_node->VisibleWindow;
18223 parent_node->SplitAxis = split_axis;
18224 parent_node->VisibleWindow = NULL;
18225 parent_node->AuthorityForPos = parent_node->AuthorityForSize = ImGuiDataAuthority_DockNode;
18227 float size_avail = (parent_node->Size[split_axis] -
g.Style.DockingSeparatorSize);
18228 size_avail = ImMax(size_avail,
g.Style.WindowMinSize[split_axis] * 2.0f);
18229 IM_ASSERT(size_avail > 0.0f);
18230 child_0->SizeRef = child_1->SizeRef = parent_node->Size;
18231 child_0->SizeRef[split_axis] = ImTrunc(size_avail * split_ratio);
18232 child_1->SizeRef[split_axis] = ImTrunc(size_avail - child_0->SizeRef[split_axis]);
18234 DockNodeMoveWindows(parent_node->ChildNodes[split_inheritor_child_idx], parent_node);
18235 DockSettingsRenameNodeReferences(parent_node->ID, parent_node->ChildNodes[split_inheritor_child_idx]->ID);
18236 DockNodeUpdateHasCentralNodeChild(DockNodeGetRootNode(parent_node));
18237 DockNodeTreeUpdatePosSize(parent_node, parent_node->Pos, parent_node->Size);
18240 child_0->SharedFlags = parent_node->SharedFlags & ImGuiDockNodeFlags_SharedFlagsInheritMask_;
18241 child_1->SharedFlags = parent_node->SharedFlags & ImGuiDockNodeFlags_SharedFlagsInheritMask_;
18242 child_inheritor->LocalFlags = parent_node->LocalFlags & ImGuiDockNodeFlags_LocalFlagsTransferMask_;
18243 parent_node->LocalFlags &= ~ImGuiDockNodeFlags_LocalFlagsTransferMask_;
18244 child_0->UpdateMergedFlags();
18245 child_1->UpdateMergedFlags();
18246 parent_node->UpdateMergedFlags();
18247 if (child_inheritor->IsCentralNode())
18248 DockNodeGetRootNode(parent_node)->CentralNode = child_inheritor;
18251void ImGui::DockNodeTreeMerge(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiDockNode* merge_lead_child)
18255 ImGuiDockNode* child_0 = parent_node->ChildNodes[0];
18256 ImGuiDockNode* child_1 = parent_node->ChildNodes[1];
18257 IM_ASSERT(child_0 || child_1);
18258 IM_ASSERT(merge_lead_child == child_0 || merge_lead_child == child_1);
18259 if ((child_0 && child_0->Windows.Size > 0) || (child_1 && child_1->Windows.Size > 0))
18261 IM_ASSERT(parent_node->TabBar == NULL);
18262 IM_ASSERT(parent_node->Windows.Size == 0);
18264 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);
18266 ImVec2 backup_last_explicit_size = parent_node->SizeRef;
18267 DockNodeMoveChildNodes(parent_node, merge_lead_child);
18270 DockNodeMoveWindows(parent_node, child_0);
18271 DockSettingsRenameNodeReferences(child_0->ID, parent_node->ID);
18275 DockNodeMoveWindows(parent_node, child_1);
18276 DockSettingsRenameNodeReferences(child_1->ID, parent_node->ID);
18278 DockNodeApplyPosSizeToWindows(parent_node);
18279 parent_node->AuthorityForPos = parent_node->AuthorityForSize = parent_node->AuthorityForViewport = ImGuiDataAuthority_Auto;
18280 parent_node->VisibleWindow = merge_lead_child->VisibleWindow;
18281 parent_node->SizeRef = backup_last_explicit_size;
18284 parent_node->LocalFlags &= ~ImGuiDockNodeFlags_LocalFlagsTransferMask_;
18285 parent_node->LocalFlags |= (child_0 ? child_0->LocalFlags : 0) & ImGuiDockNodeFlags_LocalFlagsTransferMask_;
18286 parent_node->LocalFlags |= (child_1 ? child_1->LocalFlags : 0) & ImGuiDockNodeFlags_LocalFlagsTransferMask_;
18287 parent_node->LocalFlagsInWindows = (child_0 ? child_0->LocalFlagsInWindows : 0) | (child_1 ? child_1->LocalFlagsInWindows : 0);
18288 parent_node->UpdateMergedFlags();
18292 ctx->DockContext.Nodes.SetVoidPtr(child_0->ID, NULL);
18293 IM_DELETE(child_0);
18297 ctx->DockContext.Nodes.SetVoidPtr(child_1->ID, NULL);
18298 IM_DELETE(child_1);
18304void ImGui::DockNodeTreeUpdatePosSize(ImGuiDockNode* node, ImVec2 pos, ImVec2 size, ImGuiDockNode* only_write_to_single_node)
18309 const bool write_to_node = only_write_to_single_node == NULL || only_write_to_single_node == node;
18316 if (node->IsLeafNode())
18319 ImGuiDockNode* child_0 = node->ChildNodes[0];
18320 ImGuiDockNode* child_1 = node->ChildNodes[1];
18321 ImVec2 child_0_pos = pos, child_1_pos = pos;
18322 ImVec2 child_0_size =
size, child_1_size =
size;
18324 const bool child_0_is_toward_single_node = (only_write_to_single_node != NULL && DockNodeIsInHierarchyOf(only_write_to_single_node, child_0));
18325 const bool child_1_is_toward_single_node = (only_write_to_single_node != NULL && DockNodeIsInHierarchyOf(only_write_to_single_node, child_1));
18326 const bool child_0_is_or_will_be_visible = child_0->IsVisible || child_0_is_toward_single_node;
18327 const bool child_1_is_or_will_be_visible = child_1->IsVisible || child_1_is_toward_single_node;
18329 if (child_0_is_or_will_be_visible && child_1_is_or_will_be_visible)
18331 const float spacing =
g.Style.DockingSeparatorSize;
18332 const ImGuiAxis axis = (ImGuiAxis)node->SplitAxis;
18333 const float size_avail = ImMax(size[axis] - spacing, 0.0f);
18337 const float size_min_each = ImTrunc(ImMin(size_avail,
g.Style.WindowMinSize[axis] * 2.0f) * 0.5f);
18344 if (child_0->WantLockSizeOnce && !child_1->WantLockSizeOnce)
18346 child_0_size[axis] = child_0->SizeRef[axis] = ImMin(size_avail - 1.0f, child_0->Size[axis]);
18347 child_1_size[axis] = child_1->SizeRef[axis] = (size_avail - child_0_size[axis]);
18348 IM_ASSERT(child_0->SizeRef[axis] > 0.0f && child_1->SizeRef[axis] > 0.0f);
18350 else if (child_1->WantLockSizeOnce && !child_0->WantLockSizeOnce)
18352 child_1_size[axis] = child_1->SizeRef[axis] = ImMin(size_avail - 1.0f, child_1->Size[axis]);
18353 child_0_size[axis] = child_0->SizeRef[axis] = (size_avail - child_1_size[axis]);
18354 IM_ASSERT(child_0->SizeRef[axis] > 0.0f && child_1->SizeRef[axis] > 0.0f);
18356 else if (child_0->WantLockSizeOnce && child_1->WantLockSizeOnce)
18360 float split_ratio = child_0_size[axis] / (child_0_size[axis] + child_1_size[axis]);
18361 child_0_size[axis] = child_0->SizeRef[axis] = ImTrunc(size_avail * split_ratio);
18362 child_1_size[axis] = child_1->SizeRef[axis] = (size_avail - child_0_size[axis]);
18363 IM_ASSERT(child_0->SizeRef[axis] > 0.0f && child_1->SizeRef[axis] > 0.0f);
18367 else if (child_0->SizeRef[axis] != 0.0f && child_1->HasCentralNodeChild)
18369 child_0_size[axis] = ImMin(size_avail - size_min_each, child_0->SizeRef[axis]);
18370 child_1_size[axis] = (size_avail - child_0_size[axis]);
18372 else if (child_1->SizeRef[axis] != 0.0f && child_0->HasCentralNodeChild)
18374 child_1_size[axis] = ImMin(size_avail - size_min_each, child_1->SizeRef[axis]);
18375 child_0_size[axis] = (size_avail - child_1_size[axis]);
18380 float split_ratio = child_0->SizeRef[axis] / (child_0->SizeRef[axis] + child_1->SizeRef[axis]);
18381 child_0_size[axis] = ImMax(size_min_each, ImTrunc(size_avail * split_ratio + 0.5f));
18382 child_1_size[axis] = (size_avail - child_0_size[axis]);
18385 child_1_pos[axis] += spacing + child_0_size[axis];
18388 if (only_write_to_single_node == NULL)
18389 child_0->WantLockSizeOnce = child_1->WantLockSizeOnce =
false;
18391 const bool child_0_recurse = only_write_to_single_node ? child_0_is_toward_single_node : child_0->IsVisible;
18392 const bool child_1_recurse = only_write_to_single_node ? child_1_is_toward_single_node : child_1->IsVisible;
18393 if (child_0_recurse)
18394 DockNodeTreeUpdatePosSize(child_0, child_0_pos, child_0_size);
18395 if (child_1_recurse)
18396 DockNodeTreeUpdatePosSize(child_1, child_1_pos, child_1_size);
18399static void DockNodeTreeUpdateSplitterFindTouchingNode(ImGuiDockNode* node, ImGuiAxis axis,
int side, ImVector<ImGuiDockNode*>* touching_nodes)
18401 if (node->IsLeafNode())
18403 touching_nodes->push_back(node);
18406 if (node->ChildNodes[0]->IsVisible)
18407 if (node->SplitAxis != axis || side == 0 || !node->ChildNodes[1]->IsVisible)
18408 DockNodeTreeUpdateSplitterFindTouchingNode(node->ChildNodes[0], axis, side, touching_nodes);
18409 if (node->ChildNodes[1]->IsVisible)
18410 if (node->SplitAxis != axis || side == 1 || !node->ChildNodes[0]->IsVisible)
18411 DockNodeTreeUpdateSplitterFindTouchingNode(node->ChildNodes[1], axis, side, touching_nodes);
18415void ImGui::DockNodeTreeUpdateSplitter(ImGuiDockNode* node)
18417 if (node->IsLeafNode())
18422 ImGuiDockNode* child_0 = node->ChildNodes[0];
18423 ImGuiDockNode* child_1 = node->ChildNodes[1];
18424 if (child_0->IsVisible && child_1->IsVisible)
18427 const ImGuiAxis axis = (ImGuiAxis)node->SplitAxis;
18428 IM_ASSERT(axis != ImGuiAxis_None);
18430 bb.Min = child_0->Pos;
18431 bb.Max = child_1->Pos;
18432 bb.Min[axis] += child_0->Size[axis];
18433 bb.Max[axis ^ 1] += child_1->Size[axis ^ 1];
18436 const ImGuiDockNodeFlags merged_flags = child_0->MergedFlags | child_1->MergedFlags;
18437 const ImGuiDockNodeFlags no_resize_axis_flag = (axis == ImGuiAxis_X) ? ImGuiDockNodeFlags_NoResizeX : ImGuiDockNodeFlags_NoResizeY;
18438 if ((merged_flags & ImGuiDockNodeFlags_NoResize) || (merged_flags & no_resize_axis_flag))
18440 ImGuiWindow* window =
g.CurrentWindow;
18441 window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Separator),
g.Style.FrameRounding);
18450 ImVector<ImGuiDockNode*> touching_nodes[2];
18451 float min_size =
g.Style.WindowMinSize[axis];
18452 float resize_limits[2];
18453 resize_limits[0] = node->ChildNodes[0]->Pos[axis] + min_size;
18454 resize_limits[1] = node->ChildNodes[1]->Pos[axis] + node->ChildNodes[1]->Size[axis] - min_size;
18456 ImGuiID splitter_id = GetID(
"##Splitter");
18457 if (
g.ActiveId == splitter_id)
18459 DockNodeTreeUpdateSplitterFindTouchingNode(child_0, axis, 1, &touching_nodes[0]);
18460 DockNodeTreeUpdateSplitterFindTouchingNode(child_1, axis, 0, &touching_nodes[1]);
18461 for (
int touching_node_n = 0; touching_node_n < touching_nodes[0].Size; touching_node_n++)
18462 resize_limits[0] = ImMax(resize_limits[0], touching_nodes[0][touching_node_n]->Rect().Min[axis] + min_size);
18463 for (
int touching_node_n = 0; touching_node_n < touching_nodes[1].Size; touching_node_n++)
18464 resize_limits[1] = ImMin(resize_limits[1], touching_nodes[1][touching_node_n]->Rect().Max[axis] - min_size);
18482 float cur_size_0 = child_0->Size[axis];
18483 float cur_size_1 = child_1->Size[axis];
18484 float min_size_0 = resize_limits[0] - child_0->Pos[axis];
18485 float min_size_1 = child_1->Pos[axis] + child_1->Size[axis] - resize_limits[1];
18486 ImU32 bg_col = GetColorU32(ImGuiCol_WindowBg);
18487 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))
18489 if (touching_nodes[0].Size > 0 && touching_nodes[1].Size > 0)
18491 child_0->Size[axis] = child_0->SizeRef[axis] = cur_size_0;
18492 child_1->Pos[axis] -= cur_size_1 - child_1->Size[axis];
18493 child_1->Size[axis] = child_1->SizeRef[axis] = cur_size_1;
18497 for (
int side_n = 0; side_n < 2; side_n++)
18498 for (
int touching_node_n = 0; touching_node_n < touching_nodes[side_n].Size; touching_node_n++)
18500 ImGuiDockNode* touching_node = touching_nodes[side_n][touching_node_n];
18503 while (touching_node->ParentNode != node)
18505 if (touching_node->ParentNode->SplitAxis == axis)
18508 ImGuiDockNode* node_to_preserve = touching_node->ParentNode->ChildNodes[side_n];
18509 node_to_preserve->WantLockSizeOnce =
true;
18513 touching_node = touching_node->ParentNode;
18517 DockNodeTreeUpdatePosSize(child_0, child_0->Pos, child_0->Size);
18518 DockNodeTreeUpdatePosSize(child_1, child_1->Pos, child_1->Size);
18519 MarkIniSettingsDirty();
18526 if (child_0->IsVisible)
18527 DockNodeTreeUpdateSplitter(child_0);
18528 if (child_1->IsVisible)
18529 DockNodeTreeUpdateSplitter(child_1);
18532ImGuiDockNode* ImGui::DockNodeTreeFindFallbackLeafNode(ImGuiDockNode* node)
18534 if (node->IsLeafNode())
18536 if (ImGuiDockNode* leaf_node = DockNodeTreeFindFallbackLeafNode(node->ChildNodes[0]))
18538 if (ImGuiDockNode* leaf_node = DockNodeTreeFindFallbackLeafNode(node->ChildNodes[1]))
18543ImGuiDockNode* ImGui::DockNodeTreeFindVisibleNodeByPos(ImGuiDockNode* node, ImVec2 pos)
18545 if (!node->IsVisible)
18548 const float dock_spacing = 0.0f;
18549 ImRect r(node->Pos, node->Pos + node->Size);
18550 r.Expand(dock_spacing * 0.5f);
18551 bool inside = r.Contains(pos);
18555 if (node->IsLeafNode())
18557 if (ImGuiDockNode* hovered_node = DockNodeTreeFindVisibleNodeByPos(node->ChildNodes[0], pos))
18558 return hovered_node;
18559 if (ImGuiDockNode* hovered_node = DockNodeTreeFindVisibleNodeByPos(node->ChildNodes[1], pos))
18560 return hovered_node;
18575void ImGui::SetWindowDock(ImGuiWindow* window, ImGuiID dock_id, ImGuiCond cond)
18578 if (cond && (window->SetWindowDockAllowFlags & cond) == 0)
18580 window->SetWindowDockAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
18582 if (window->DockId == dock_id)
18587 if (ImGuiDockNode* new_node = DockContextFindNodeByID(&
g, dock_id))
18588 if (new_node->IsSplitNode())
18591 new_node = DockNodeGetRootNode(new_node);
18592 if (new_node->CentralNode)
18594 IM_ASSERT(new_node->CentralNode->IsCentralNode());
18595 dock_id = new_node->CentralNode->ID;
18599 dock_id = new_node->LastFocusedNodeId;
18603 if (window->DockId == dock_id)
18606 if (window->DockNode)
18607 DockNodeRemoveWindow(window->DockNode, window, 0);
18608 window->DockId = dock_id;
18615ImGuiID ImGui::DockSpace(ImGuiID dockspace_id,
const ImVec2& size_arg, ImGuiDockNodeFlags flags,
const ImGuiWindowClass* window_class)
18618 ImGuiWindow* window = GetCurrentWindowRead();
18619 if (!(
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
18625 if (window->SkipItems)
18626 flags |= ImGuiDockNodeFlags_KeepAliveOnly;
18627 if ((flags & ImGuiDockNodeFlags_KeepAliveOnly) == 0)
18628 window = GetCurrentWindow();
18630 IM_ASSERT((flags & ImGuiDockNodeFlags_DockSpace) == 0);
18631 IM_ASSERT(dockspace_id != 0);
18632 ImGuiDockNode* node = DockContextFindNodeByID(&
g, dockspace_id);
18635 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockSpace: dockspace node 0x%08X created\n", dockspace_id);
18636 node = DockContextAddNode(&
g, dockspace_id);
18637 node->SetLocalFlags(ImGuiDockNodeFlags_CentralNode);
18639 if (window_class && window_class->ClassId != node->WindowClass.ClassId)
18640 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);
18641 node->SharedFlags = flags;
18642 node->WindowClass = window_class ? *window_class : ImGuiWindowClass();
18646 if (node->LastFrameActive ==
g.FrameCount && !(flags & ImGuiDockNodeFlags_KeepAliveOnly))
18648 IM_ASSERT(node->IsDockSpace() ==
false &&
"Cannot call DockSpace() twice a frame with the same ID");
18649 node->SetLocalFlags(node->LocalFlags | ImGuiDockNodeFlags_DockSpace);
18650 return dockspace_id;
18652 node->SetLocalFlags(node->LocalFlags | ImGuiDockNodeFlags_DockSpace);
18655 if (flags & ImGuiDockNodeFlags_KeepAliveOnly)
18657 node->LastFrameAlive =
g.FrameCount;
18658 return dockspace_id;
18661 const ImVec2 content_avail = GetContentRegionAvail();
18662 ImVec2
size = ImTrunc(size_arg);
18663 if (
size.x <= 0.0f)
18664 size.x = ImMax(content_avail.x +
size.x, 4.0f);
18665 if (
size.y <= 0.0f)
18666 size.y = ImMax(content_avail.y +
size.y, 4.0f);
18667 IM_ASSERT(
size.x > 0.0f &&
size.y > 0.0f);
18669 node->Pos = window->DC.CursorPos;
18670 node->Size = node->SizeRef =
size;
18671 SetNextWindowPos(node->Pos);
18672 SetNextWindowSize(node->Size);
18673 g.NextWindowData.PosUndock =
false;
18677 ImGuiWindowFlags window_flags = ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_DockNodeHost;
18678 window_flags |= ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar;
18679 window_flags |= ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
18680 window_flags |= ImGuiWindowFlags_NoBackground;
18683 ImFormatString(title, IM_ARRAYSIZE(title),
"%s/DockSpace_%08X", window->Name, dockspace_id);
18685 PushStyleVar(ImGuiStyleVar_ChildBorderSize, 0.0f);
18686 Begin(title, NULL, window_flags);
18689 ImGuiWindow* host_window =
g.CurrentWindow;
18690 DockNodeSetupHostWindow(node, host_window);
18691 host_window->ChildId = window->GetID(title);
18692 node->OnlyNodeWithWindows = NULL;
18694 IM_ASSERT(node->IsRootNode());
18702 if (node->IsLeafNode() && !node->IsCentralNode())
18703 node->SetLocalFlags(node->LocalFlags | ImGuiDockNodeFlags_CentralNode);
18706 DockNodeUpdate(node);
18710 ImRect bb(node->Pos, node->Pos + size);
18712 ItemAdd(bb, dockspace_id, NULL, ImGuiItemFlags_NoNav);
18713 if ((
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && IsWindowChildOf(
g.HoveredWindow, host_window,
false,
true))
18714 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
18716 return dockspace_id;
18723ImGuiID ImGui::DockSpaceOverViewport(ImGuiID dockspace_id,
const ImGuiViewport* viewport, ImGuiDockNodeFlags dockspace_flags,
const ImGuiWindowClass* window_class)
18725 if (viewport == NULL)
18726 viewport = GetMainViewport();
18729 SetNextWindowPos(viewport->WorkPos);
18730 SetNextWindowSize(viewport->WorkSize);
18731 SetNextWindowViewport(viewport->ID);
18733 ImGuiWindowFlags host_window_flags = 0;
18734 host_window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking;
18735 host_window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
18736 if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
18737 host_window_flags |= ImGuiWindowFlags_NoBackground;
18740 ImFormatString(label, IM_ARRAYSIZE(label),
"WindowOverViewport_%08X", viewport->ID);
18742 PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
18743 PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
18744 PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
18745 Begin(label, NULL, host_window_flags);
18749 if (dockspace_id == 0)
18750 dockspace_id = GetID(
"DockSpace");
18751 DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags, window_class);
18755 return dockspace_id;
18781void ImGui::DockBuilderDockWindow(
const char* window_name, ImGuiID node_id)
18784 ImGuiContext&
g = *
GImGui; IM_UNUSED(
g);
18785 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderDockWindow '%s' to node 0x%08X\n", window_name, node_id);
18786 ImGuiID window_id =
ImHashStr(window_name);
18787 if (ImGuiWindow* window = FindWindowByID(window_id))
18790 ImGuiID prev_node_id = window->DockId;
18791 SetWindowDock(window, node_id, ImGuiCond_Always);
18792 if (window->DockId != prev_node_id)
18793 window->DockOrder = -1;
18798 ImGuiWindowSettings* settings = FindWindowSettingsByID(window_id);
18799 if (settings == NULL)
18800 settings = CreateNewWindowSettings(window_name);
18801 if (settings->DockId != node_id)
18802 settings->DockOrder = -1;
18803 settings->DockId = node_id;
18807ImGuiDockNode* ImGui::DockBuilderGetNode(ImGuiID node_id)
18810 return DockContextFindNodeByID(&
g, node_id);
18813void ImGui::DockBuilderSetNodePos(ImGuiID node_id, ImVec2 pos)
18816 ImGuiDockNode* node = DockContextFindNodeByID(&
g, node_id);
18820 node->AuthorityForPos = ImGuiDataAuthority_DockNode;
18823void ImGui::DockBuilderSetNodeSize(ImGuiID node_id, ImVec2 size)
18826 ImGuiDockNode* node = DockContextFindNodeByID(&
g, node_id);
18829 IM_ASSERT(
size.x > 0.0f &&
size.y > 0.0f);
18830 node->Size = node->SizeRef =
size;
18831 node->AuthorityForSize = ImGuiDataAuthority_DockNode;
18841ImGuiID ImGui::DockBuilderAddNode(ImGuiID node_id, ImGuiDockNodeFlags flags)
18843 ImGuiContext&
g = *
GImGui; IM_UNUSED(
g);
18844 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderAddNode 0x%08X flags=%08X\n", node_id, flags);
18847 DockBuilderRemoveNode(node_id);
18849 ImGuiDockNode* node = NULL;
18850 if (flags & ImGuiDockNodeFlags_DockSpace)
18852 DockSpace(node_id, ImVec2(0, 0), (flags & ~ImGuiDockNodeFlags_DockSpace) | ImGuiDockNodeFlags_KeepAliveOnly);
18853 node = DockContextFindNodeByID(&
g, node_id);
18857 node = DockContextAddNode(&
g, node_id);
18858 node->SetLocalFlags(flags);
18860 node->LastFrameAlive =
g.FrameCount;
18864void ImGui::DockBuilderRemoveNode(ImGuiID node_id)
18866 ImGuiContext&
g = *
GImGui; IM_UNUSED(
g);
18867 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderRemoveNode 0x%08X\n", node_id);
18869 ImGuiDockNode* node = DockContextFindNodeByID(&
g, node_id);
18872 DockBuilderRemoveNodeDockedWindows(node_id,
true);
18873 DockBuilderRemoveNodeChildNodes(node_id);
18875 node = DockContextFindNodeByID(&
g, node_id);
18878 if (node->IsCentralNode() && node->ParentNode)
18879 node->ParentNode->SetLocalFlags(node->ParentNode->LocalFlags | ImGuiDockNodeFlags_CentralNode);
18880 DockContextRemoveNode(&
g, node,
true);
18884void ImGui::DockBuilderRemoveNodeChildNodes(ImGuiID root_id)
18887 ImGuiDockContext* dc = &
g.DockContext;
18889 ImGuiDockNode* root_node = root_id ? DockContextFindNodeByID(&
g, root_id) : NULL;
18890 if (root_id && root_node == NULL)
18892 bool has_central_node =
false;
18894 ImGuiDataAuthority backup_root_node_authority_for_pos = root_node ? root_node->AuthorityForPos : ImGuiDataAuthority_Auto;
18895 ImGuiDataAuthority backup_root_node_authority_for_size = root_node ? root_node->AuthorityForSize : ImGuiDataAuthority_Auto;
18898 ImVector<ImGuiDockNode*> nodes_to_remove;
18899 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
18900 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
18902 bool want_removal = (root_id == 0) || (node->ID != root_id && DockNodeGetRootNode(node)->ID == root_id);
18905 if (node->IsCentralNode())
18906 has_central_node =
true;
18908 DockContextQueueNotifyRemovedNode(&
g, node);
18911 DockNodeMoveWindows(root_node, node);
18912 DockSettingsRenameNodeReferences(node->ID, root_node->ID);
18914 nodes_to_remove.push_back(node);
18922 root_node->AuthorityForPos = backup_root_node_authority_for_pos;
18923 root_node->AuthorityForSize = backup_root_node_authority_for_size;
18927 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
18928 if (ImGuiID window_settings_dock_id = settings->DockId)
18929 for (
int n = 0; n < nodes_to_remove.Size; n++)
18930 if (nodes_to_remove[n]->ID == window_settings_dock_id)
18932 settings->DockId = root_id;
18937 if (nodes_to_remove.Size > 1)
18938 ImQsort(nodes_to_remove.Data, nodes_to_remove.Size,
sizeof(ImGuiDockNode*), DockNodeComparerDepthMostFirst);
18939 for (
int n = 0; n < nodes_to_remove.Size; n++)
18940 DockContextRemoveNode(&
g, nodes_to_remove[n],
false);
18945 dc->Requests.clear();
18947 else if (has_central_node)
18949 root_node->CentralNode = root_node;
18950 root_node->SetLocalFlags(root_node->LocalFlags | ImGuiDockNodeFlags_CentralNode);
18954void ImGui::DockBuilderRemoveNodeDockedWindows(ImGuiID root_id,
bool clear_settings_refs)
18958 if (clear_settings_refs)
18960 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
18962 bool want_removal = (root_id == 0) || (settings->DockId == root_id);
18963 if (!want_removal && settings->DockId != 0)
18964 if (ImGuiDockNode* node = DockContextFindNodeByID(&
g, settings->DockId))
18965 if (DockNodeGetRootNode(node)->ID == root_id)
18966 want_removal =
true;
18968 settings->DockId = 0;
18973 for (
int n = 0; n <
g.Windows.Size; n++)
18975 ImGuiWindow* window =
g.Windows[n];
18976 bool want_removal = (root_id == 0) || (window->DockNode && DockNodeGetRootNode(window->DockNode)->ID == root_id) || (window->DockNodeAsHost && window->DockNodeAsHost->ID == root_id);
18979 const ImGuiID backup_dock_id = window->DockId;
18980 IM_UNUSED(backup_dock_id);
18981 DockContextProcessUndockWindow(&
g, window, clear_settings_refs);
18982 if (!clear_settings_refs)
18983 IM_ASSERT(window->DockId == backup_dock_id);
18991ImGuiID 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)
18994 IM_ASSERT(split_dir != ImGuiDir_None);
18995 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderSplitNode: node 0x%08X, split_dir %d\n",
id, split_dir);
18997 ImGuiDockNode* node = DockContextFindNodeByID(&
g,
id);
19000 IM_ASSERT(node != NULL);
19004 IM_ASSERT(!node->IsSplitNode());
19012 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);
19014 DockContextProcessDock(&
g, &req);
19016 ImGuiID id_at_dir = node->ChildNodes[(split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up) ? 0 : 1]->
ID;
19017 ImGuiID id_at_opposite_dir = node->ChildNodes[(split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up) ? 1 : 0]->
ID;
19019 *out_id_at_dir = id_at_dir;
19020 if (out_id_at_opposite_dir)
19021 *out_id_at_opposite_dir = id_at_opposite_dir;
19025static ImGuiDockNode* DockBuilderCopyNodeRec(ImGuiDockNode* src_node, ImGuiID dst_node_id_if_known, ImVector<ImGuiID>* out_node_remap_pairs)
19028 ImGuiDockNode* dst_node = ImGui::DockContextAddNode(&
g, dst_node_id_if_known);
19029 dst_node->SharedFlags = src_node->SharedFlags;
19030 dst_node->LocalFlags = src_node->LocalFlags;
19031 dst_node->LocalFlagsInWindows = ImGuiDockNodeFlags_None;
19032 dst_node->Pos = src_node->Pos;
19033 dst_node->Size = src_node->Size;
19034 dst_node->SizeRef = src_node->SizeRef;
19035 dst_node->SplitAxis = src_node->SplitAxis;
19036 dst_node->UpdateMergedFlags();
19038 out_node_remap_pairs->push_back(src_node->ID);
19039 out_node_remap_pairs->push_back(dst_node->ID);
19041 for (
int child_n = 0; child_n < IM_ARRAYSIZE(src_node->ChildNodes); child_n++)
19042 if (src_node->ChildNodes[child_n])
19044 dst_node->ChildNodes[child_n] = DockBuilderCopyNodeRec(src_node->ChildNodes[child_n], 0, out_node_remap_pairs);
19045 dst_node->ChildNodes[child_n]->ParentNode = dst_node;
19048 IMGUI_DEBUG_LOG_DOCKING(
"[docking] Fork node %08X -> %08X (%d childs)\n", src_node->ID, dst_node->ID, dst_node->IsSplitNode() ? 2 : 0);
19052void ImGui::DockBuilderCopyNode(ImGuiID src_node_id, ImGuiID dst_node_id, ImVector<ImGuiID>* out_node_remap_pairs)
19055 IM_ASSERT(src_node_id != 0);
19056 IM_ASSERT(dst_node_id != 0);
19057 IM_ASSERT(out_node_remap_pairs != NULL);
19059 DockBuilderRemoveNode(dst_node_id);
19061 ImGuiDockNode* src_node = DockContextFindNodeByID(&
g, src_node_id);
19062 IM_ASSERT(src_node != NULL);
19064 out_node_remap_pairs->clear();
19065 DockBuilderCopyNodeRec(src_node, dst_node_id, out_node_remap_pairs);
19067 IM_ASSERT((out_node_remap_pairs->Size % 2) == 0);
19070void ImGui::DockBuilderCopyWindowSettings(
const char* src_name,
const char* dst_name)
19072 ImGuiWindow* src_window = FindWindowByName(src_name);
19073 if (src_window == NULL)
19075 if (ImGuiWindow* dst_window = FindWindowByName(dst_name))
19077 dst_window->Pos = src_window->Pos;
19078 dst_window->Size = src_window->Size;
19079 dst_window->SizeFull = src_window->SizeFull;
19080 dst_window->Collapsed = src_window->Collapsed;
19084 ImGuiWindowSettings* dst_settings = FindWindowSettingsByID(
ImHashStr(dst_name));
19086 dst_settings = CreateNewWindowSettings(dst_name);
19087 ImVec2ih window_pos_2ih = ImVec2ih(src_window->Pos);
19088 if (src_window->ViewportId != 0 && src_window->ViewportId != IMGUI_VIEWPORT_DEFAULT_ID)
19090 dst_settings->ViewportPos = window_pos_2ih;
19091 dst_settings->ViewportId = src_window->ViewportId;
19092 dst_settings->Pos = ImVec2ih(0, 0);
19096 dst_settings->Pos = window_pos_2ih;
19098 dst_settings->Size = ImVec2ih(src_window->SizeFull);
19099 dst_settings->Collapsed = src_window->Collapsed;
19104void ImGui::DockBuilderCopyDockSpace(ImGuiID src_dockspace_id, ImGuiID dst_dockspace_id, ImVector<const char*>* in_window_remap_pairs)
19107 IM_ASSERT(src_dockspace_id != 0);
19108 IM_ASSERT(dst_dockspace_id != 0);
19109 IM_ASSERT(in_window_remap_pairs != NULL);
19110 IM_ASSERT((in_window_remap_pairs->Size % 2) == 0);
19115 ImVector<ImGuiID> node_remap_pairs;
19116 DockBuilderCopyNode(src_dockspace_id, dst_dockspace_id, &node_remap_pairs);
19120 ImVector<ImGuiID> src_windows;
19121 for (
int remap_window_n = 0; remap_window_n < in_window_remap_pairs->Size; remap_window_n += 2)
19123 const char* src_window_name = (*in_window_remap_pairs)[remap_window_n];
19124 const char* dst_window_name = (*in_window_remap_pairs)[remap_window_n + 1];
19125 ImGuiID src_window_id =
ImHashStr(src_window_name);
19126 src_windows.push_back(src_window_id);
19129 ImGuiID src_dock_id = 0;
19130 if (ImGuiWindow* src_window = FindWindowByID(src_window_id))
19131 src_dock_id = src_window->DockId;
19132 else if (ImGuiWindowSettings* src_window_settings = FindWindowSettingsByID(src_window_id))
19133 src_dock_id = src_window_settings->DockId;
19134 ImGuiID dst_dock_id = 0;
19135 for (
int dock_remap_n = 0; dock_remap_n < node_remap_pairs.Size; dock_remap_n += 2)
19136 if (node_remap_pairs[dock_remap_n] == src_dock_id)
19138 dst_dock_id = node_remap_pairs[dock_remap_n + 1];
19143 if (dst_dock_id != 0)
19146 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);
19147 DockBuilderDockWindow(dst_window_name, dst_dock_id);
19153 IMGUI_DEBUG_LOG_DOCKING(
"[docking] Remap window settings '%s' -> '%s'\n", src_window_name, dst_window_name);
19154 DockBuilderCopyWindowSettings(src_window_name, dst_window_name);
19161 struct DockRemainingWindowTask { ImGuiWindow*
Window; ImGuiID DockId; DockRemainingWindowTask(ImGuiWindow* window, ImGuiID dock_id) {
Window = window; DockId = dock_id; } };
19162 ImVector<DockRemainingWindowTask> dock_remaining_windows;
19163 for (
int dock_remap_n = 0; dock_remap_n < node_remap_pairs.Size; dock_remap_n += 2)
19164 if (ImGuiID src_dock_id = node_remap_pairs[dock_remap_n])
19166 ImGuiID dst_dock_id = node_remap_pairs[dock_remap_n + 1];
19167 ImGuiDockNode* node = DockBuilderGetNode(src_dock_id);
19168 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
19170 ImGuiWindow* window = node->Windows[window_n];
19171 if (src_windows.contains(window->ID))
19175 IMGUI_DEBUG_LOG_DOCKING(
"[docking] Remap window '%s' %08X -> %08X\n", window->Name, src_dock_id, dst_dock_id);
19176 dock_remaining_windows.push_back(DockRemainingWindowTask(window, dst_dock_id));
19179 for (
const DockRemainingWindowTask& task : dock_remaining_windows)
19180 DockBuilderDockWindow(task.
Window->Name, task.DockId);
19184void ImGui::DockBuilderFinish(ImGuiID root_id)
19188 DockContextBuildAddWindowsToNodes(&
g, root_id);
19201bool ImGui::GetWindowAlwaysWantOwnTabBar(ImGuiWindow* window)
19204 if (
g.IO.ConfigDockingAlwaysTabBar || window->WindowClass.DockingAlwaysTabBar)
19205 if ((window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDocking)) == 0)
19206 if (!window->IsFallbackWindow)
19211static ImGuiDockNode* ImGui::DockContextBindNodeToWindow(ImGuiContext* ctx, ImGuiWindow* window)
19213 ImGuiContext&
g = *ctx;
19214 ImGuiDockNode* node = DockContextFindNodeByID(ctx, window->DockId);
19215 IM_ASSERT(window->DockNode == NULL);
19218 if (node && node->IsSplitNode())
19220 DockContextProcessUndockWindow(ctx, window);
19227 node = DockContextAddNode(ctx, window->DockId);
19228 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Window;
19229 node->LastFrameAlive =
g.FrameCount;
19236 if (!node->IsVisible)
19238 ImGuiDockNode* ancestor_node = node;
19239 while (!ancestor_node->IsVisible && ancestor_node->ParentNode)
19240 ancestor_node = ancestor_node->ParentNode;
19241 IM_ASSERT(ancestor_node->Size.x > 0.0f && ancestor_node->Size.y > 0.0f);
19242 DockNodeUpdateHasCentralNodeChild(DockNodeGetRootNode(ancestor_node));
19243 DockNodeTreeUpdatePosSize(ancestor_node, ancestor_node->Pos, ancestor_node->Size, node);
19247 bool node_was_visible = node->IsVisible;
19248 DockNodeAddWindow(node, window,
true);
19249 node->IsVisible = node_was_visible;
19250 IM_ASSERT(node == window->DockNode);
19254static void StoreDockStyleForWindow(ImGuiWindow* window)
19257 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
19258 window->DockStyle.Colors[color_n] = ImGui::ColorConvertFloat4ToU32(
g.Style.Colors[GWindowDockStyleColors[color_n]]);
19261void ImGui::BeginDocked(ImGuiWindow* window,
bool* p_open)
19266 window->DockIsActive = window->DockNodeIsVisible = window->DockTabIsVisible =
false;
19268 const bool auto_dock_node = GetWindowAlwaysWantOwnTabBar(window);
19269 if (auto_dock_node)
19271 if (window->DockId == 0)
19273 IM_ASSERT(window->DockNode == NULL);
19274 window->DockId = DockContextGenNodeID(&
g);
19280 bool want_undock =
false;
19281 want_undock |= (window->Flags & ImGuiWindowFlags_NoDocking) != 0;
19282 want_undock |= (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) && (window->SetWindowPosAllowFlags &
g.NextWindowData.PosCond) &&
g.NextWindowData.PosUndock;
19285 DockContextProcessUndockWindow(&
g, window);
19291 ImGuiDockNode* node = window->DockNode;
19293 IM_ASSERT(window->DockId == node->ID);
19294 if (window->DockId != 0 && node == NULL)
19296 node = DockContextBindNodeToWindow(&
g, window);
19303 if (node->IsCentralNode && (node->Flags & ImGuiDockNodeFlags_NoDockingInCentralNode))
19305 DockContextProcessUndockWindow(ctx, window);
19312 if (node->LastFrameAlive <
g.FrameCount)
19315 ImGuiDockNode* root_node = DockNodeGetRootNode(node);
19316 if (root_node->LastFrameAlive <
g.FrameCount)
19317 DockContextProcessUndockWindow(&
g, window);
19319 window->DockIsActive =
true;
19324 StoreDockStyleForWindow(window);
19329 if (node->HostWindow == NULL)
19331 if (node->State == ImGuiDockNodeState_HostWindowHiddenBecauseWindowsAreResizing)
19332 window->DockIsActive =
true;
19333 if (node->Windows.Size > 1 && window->Appearing)
19334 DockNodeHideWindowDuringHostWindowCreation(window);
19339 IM_ASSERT(node->HostWindow);
19340 IM_ASSERT(node->IsLeafNode());
19341 IM_ASSERT(node->Size.x >= 0.0f && node->Size.y >= 0.0f);
19342 node->State = ImGuiDockNodeState_HostWindowVisible;
19345 if (!(node->MergedFlags & ImGuiDockNodeFlags_KeepAliveOnly) && window->BeginOrderWithinContext < node->HostWindow->BeginOrderWithinContext)
19347 DockContextProcessUndockWindow(&
g, window);
19352 SetNextWindowPos(node->Pos);
19353 SetNextWindowSize(node->Size);
19354 g.NextWindowData.PosUndock =
false;
19355 window->DockIsActive =
true;
19356 window->DockNodeIsVisible =
true;
19357 window->DockTabIsVisible =
false;
19358 if (node->MergedFlags & ImGuiDockNodeFlags_KeepAliveOnly)
19362 if (node->VisibleWindow == window)
19363 window->DockTabIsVisible =
true;
19366 IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) == 0);
19367 window->Flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoResize;
19368 window->ChildFlags |= ImGuiChildFlags_AlwaysUseWindowPadding;
19369 if (node->IsHiddenTabBar() || node->IsNoTabBar())
19370 window->Flags |= ImGuiWindowFlags_NoTitleBar;
19372 window->Flags &= ~ImGuiWindowFlags_NoTitleBar;
19376 if (node->TabBar && window->WasActive)
19377 window->DockOrder = (short)DockNodeGetTabOrder(window);
19379 if ((node->WantCloseAll || node->WantCloseTabId == window->TabId) && p_open != NULL)
19383 ImGuiWindow* parent_window = window->DockNode->HostWindow;
19384 window->ChildId = parent_window->GetID(window->Name);
19387void ImGui::BeginDockableDragDropSource(ImGuiWindow* window)
19390 IM_ASSERT(
g.ActiveId == window->MoveId);
19391 IM_ASSERT(
g.MovingWindow == window);
19392 IM_ASSERT(
g.CurrentWindow == window);
19395 if (
g.IO.ConfigDockingWithShift !=
g.IO.KeyShift)
19400 IM_ASSERT(
g.NextWindowData.Flags == 0);
19401 if (
g.IO.ConfigDockingWithShift &&
g.MouseStationaryTimer >= 1.0f &&
g.ActiveId >= 1.0f)
19402 SetTooltip(
"%s", LocalizeGetMsg(ImGuiLocKey_DockingHoldShiftToDock));
19406 g.LastItemData.ID = window->MoveId;
19407 window = window->RootWindowDockTree;
19408 IM_ASSERT((window->Flags & ImGuiWindowFlags_NoDocking) == 0);
19409 bool is_drag_docking = (
g.IO.ConfigDockingWithShift) || ImRect(0, 0, window->SizeFull.x, GetFrameHeight()).Contains(
g.ActiveIdClickOffset);
19410 if (is_drag_docking && BeginDragDropSource(ImGuiDragDropFlags_SourceNoPreviewTooltip | ImGuiDragDropFlags_SourceNoHoldToOpenOthers | ImGuiDragDropFlags_SourceAutoExpirePayload))
19412 SetDragDropPayload(IMGUI_PAYLOAD_TYPE_WINDOW, &window,
sizeof(window));
19413 EndDragDropSource();
19414 StoreDockStyleForWindow(window);
19418void ImGui::BeginDockableDragDropTarget(ImGuiWindow* window)
19423 IM_ASSERT((window->Flags & ImGuiWindowFlags_NoDocking) == 0);
19424 if (!
g.DragDropActive)
19427 if (!BeginDragDropTargetCustom(window->Rect(), window->ID))
19432 const ImGuiPayload* payload = &
g.DragDropPayload;
19433 if (!payload->IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) || !DockNodeIsDropAllowed(window, *(ImGuiWindow**)payload->Data))
19435 EndDragDropTarget();
19439 ImGuiWindow* payload_window = *(ImGuiWindow**)payload->Data;
19440 if (AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_WINDOW, ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect))
19444 bool dock_into_floating_window =
false;
19445 ImGuiDockNode* node = NULL;
19446 if (window->DockNodeAsHost)
19449 node = DockNodeTreeFindVisibleNodeByPos(window->DockNodeAsHost,
g.IO.MousePos);
19454 if (node && node->IsDockSpace() && node->IsRootNode())
19455 node = (node->CentralNode && node->IsLeafNode()) ? node->CentralNode : DockNodeTreeFindFallbackLeafNode(node);
19459 if (window->DockNode)
19460 node = window->DockNode;
19462 dock_into_floating_window =
true;
19465 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()));
19466 const bool is_explicit_target =
g.IO.ConfigDockingWithShift || IsMouseHoveringRect(explicit_target_rect.Min, explicit_target_rect.Max);
19470 const bool do_preview = payload->IsPreview() || payload->IsDelivery();
19471 if (do_preview && (node != NULL || dock_into_floating_window))
19477 if (node && (node->ParentNode || node->IsCentralNode() || !node->IsLeafNode()))
19478 if (ImGuiDockNode* root_node = DockNodeGetRootNode(node))
19480 DockNodePreviewDockSetup(window, root_node, payload_window, NULL, &split_outer, is_explicit_target,
true);
19482 split_data = &split_outer;
19484 if (!node || node->IsLeafNode())
19485 DockNodePreviewDockSetup(window, node, payload_window, NULL, &split_inner, is_explicit_target,
false);
19486 if (split_data == &split_outer)
19490 DockNodePreviewDockRender(window, node, payload_window, &split_inner);
19491 DockNodePreviewDockRender(window, node, payload_window, &split_outer);
19495 DockContextQueueDock(&
g, window, split_data->
SplitNode, payload_window, split_data->
SplitDir, split_data->
SplitRatio, split_data == &split_outer);
19498 EndDragDropTarget();
19514static void ImGui::DockSettingsRenameNodeReferences(ImGuiID old_node_id, ImGuiID new_node_id)
19517 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockSettingsRenameNodeReferences: from 0x%08X -> to 0x%08X\n", old_node_id, new_node_id);
19518 for (
int window_n = 0; window_n <
g.Windows.Size; window_n++)
19520 ImGuiWindow* window =
g.Windows[window_n];
19521 if (window->DockId == old_node_id && window->DockNode == NULL)
19522 window->DockId = new_node_id;
19525 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
19526 if (settings->DockId == old_node_id)
19527 settings->DockId = new_node_id;
19531static void ImGui::DockSettingsRemoveNodeReferences(ImGuiID* node_ids,
int node_ids_count)
19536 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
19537 for (
int node_n = 0; node_n < node_ids_count; node_n++)
19538 if (settings->DockId == node_ids[node_n])
19540 settings->DockId = 0;
19541 settings->DockOrder = -1;
19542 if (++found < node_ids_count)
19551 ImGuiDockContext* dc = &ctx->DockContext;
19552 for (
int n = 0; n < dc->NodesSettings.Size; n++)
19553 if (dc->NodesSettings[n].ID ==
id)
19554 return &dc->NodesSettings[n];
19559static void ImGui::DockSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
19561 ImGuiDockContext* dc = &ctx->DockContext;
19562 dc->NodesSettings.clear();
19563 DockContextClearNodes(ctx, 0,
true);
19567static void ImGui::DockSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
19570 ImGuiDockContext* dc = &ctx->DockContext;
19571 if (ctx->Windows.Size == 0)
19572 DockContextPruneUnusedSettingsNodes(ctx);
19573 DockContextBuildNodesFromSettings(ctx, dc->NodesSettings.Data, dc->NodesSettings.Size);
19574 DockContextBuildAddWindowsToNodes(ctx, 0);
19577static void* ImGui::DockSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*,
const char* name)
19579 if (strcmp(name,
"Data") != 0)
19584static void ImGui::DockSettingsHandler_ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler*,
void*,
const char* line)
19596 if (strncmp(line,
"DockNode", 8) == 0) { line =
ImStrSkipBlank(line + strlen(
"DockNode")); }
19597 else if (strncmp(line,
"DockSpace", 9) == 0) { line =
ImStrSkipBlank(line + strlen(
"DockSpace")); node.
Flags |= ImGuiDockNodeFlags_DockSpace; }
19599 if (sscanf(line,
"ID=0x%08X%n", &node.
ID, &r) == 1) { line += r; }
else return;
19600 if (sscanf(line,
" Parent=0x%08X%n", &node.
ParentNodeId, &r) == 1) { line += r;
if (node.
ParentNodeId == 0)
return; }
19604 if (sscanf(line,
" Pos=%i,%i%n", &x, &y, &r) == 2) { line += r; node.
Pos = ImVec2ih((
short)x, (
short)y); }
else return;
19605 if (sscanf(line,
" Size=%i,%i%n", &x, &y, &r) == 2) { line += r; node.
Size = ImVec2ih((
short)x, (
short)y); }
else return;
19609 if (sscanf(line,
" SizeRef=%i,%i%n", &x, &y, &r) == 2) { line += r; node.
SizeRef = ImVec2ih((
short)x, (
short)y); }
19611 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; }
19612 if (sscanf(line,
" NoResize=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_NoResize; }
19613 if (sscanf(line,
" CentralNode=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_CentralNode; }
19614 if (sscanf(line,
" NoTabBar=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_NoTabBar; }
19615 if (sscanf(line,
" HiddenTabBar=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_HiddenTabBar; }
19616 if (sscanf(line,
" NoWindowMenuButton=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_NoWindowMenuButton; }
19617 if (sscanf(line,
" NoCloseButton=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_NoCloseButton; }
19618 if (sscanf(line,
" Selected=0x%08X%n", &node.
SelectedTabId,&r) == 1) { line += r; }
19621 node.
Depth = parent_settings->Depth + 1;
19622 ctx->DockContext.NodesSettings.push_back(node);
19625static void DockSettingsHandler_DockNodeToSettings(ImGuiDockContext* dc, ImGuiDockNode* node,
int depth)
19628 IM_ASSERT(depth < (1 << (
sizeof(node_settings.
Depth) << 3)));
19629 node_settings.
ID = node->ID;
19630 node_settings.
ParentNodeId = node->ParentNode ? node->ParentNode->ID : 0;
19631 node_settings.
ParentWindowId = (node->IsDockSpace() && node->HostWindow && node->HostWindow->ParentWindow) ? node->HostWindow->ParentWindow->ID : 0;
19633 node_settings.
SplitAxis = (
signed char)(node->IsSplitNode() ? node->SplitAxis : ImGuiAxis_None);
19634 node_settings.
Depth = (char)depth;
19635 node_settings.
Flags = (node->LocalFlags & ImGuiDockNodeFlags_SavedFlagsMask_);
19636 node_settings.
Pos = ImVec2ih(node->Pos);
19637 node_settings.
Size = ImVec2ih(node->Size);
19638 node_settings.
SizeRef = ImVec2ih(node->SizeRef);
19639 dc->NodesSettings.push_back(node_settings);
19640 if (node->ChildNodes[0])
19641 DockSettingsHandler_DockNodeToSettings(dc, node->ChildNodes[0], depth + 1);
19642 if (node->ChildNodes[1])
19643 DockSettingsHandler_DockNodeToSettings(dc, node->ChildNodes[1], depth + 1);
19646static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
19648 ImGuiContext&
g = *ctx;
19649 ImGuiDockContext* dc = &ctx->DockContext;
19650 if (!(
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
19655 dc->NodesSettings.resize(0);
19656 dc->NodesSettings.reserve(dc->Nodes.Data.Size);
19657 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
19658 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
19659 if (node->IsRootNode())
19660 DockSettingsHandler_DockNodeToSettings(dc, node, 0);
19663 for (
int node_n = 0; node_n < dc->NodesSettings.Size; node_n++)
19664 max_depth = ImMax((
int)dc->NodesSettings[node_n].Depth, max_depth);
19667 buf->appendf(
"[%s][Data]\n", handler->TypeName);
19668 for (
int node_n = 0; node_n < dc->NodesSettings.Size; node_n++)
19670 const int line_start_pos = buf->size(); (void)line_start_pos;
19672 buf->appendf(
"%*s%s%*s", node_settings->
Depth * 2,
"", (node_settings->
Flags & ImGuiDockNodeFlags_DockSpace) ?
"DockSpace" :
"DockNode ", (max_depth - node_settings->
Depth) * 2,
"");
19673 buf->appendf(
" ID=0x%08X", node_settings->
ID);
19676 buf->appendf(
" Parent=0x%08X SizeRef=%d,%d", node_settings->
ParentNodeId, node_settings->
SizeRef.x, node_settings->
SizeRef.y);
19682 buf->appendf(
" Pos=%d,%d Size=%d,%d", node_settings->
Pos.x, node_settings->
Pos.y, node_settings->
Size.x, node_settings->
Size.y);
19684 if (node_settings->
SplitAxis != ImGuiAxis_None)
19685 buf->appendf(
" Split=%c", (node_settings->
SplitAxis == ImGuiAxis_X) ?
'X' :
'Y');
19686 if (node_settings->
Flags & ImGuiDockNodeFlags_NoResize)
19687 buf->appendf(
" NoResize=1");
19688 if (node_settings->
Flags & ImGuiDockNodeFlags_CentralNode)
19689 buf->appendf(
" CentralNode=1");
19690 if (node_settings->
Flags & ImGuiDockNodeFlags_NoTabBar)
19691 buf->appendf(
" NoTabBar=1");
19692 if (node_settings->
Flags & ImGuiDockNodeFlags_HiddenTabBar)
19693 buf->appendf(
" HiddenTabBar=1");
19694 if (node_settings->
Flags & ImGuiDockNodeFlags_NoWindowMenuButton)
19695 buf->appendf(
" NoWindowMenuButton=1");
19696 if (node_settings->
Flags & ImGuiDockNodeFlags_NoCloseButton)
19697 buf->appendf(
" NoCloseButton=1");
19699 buf->appendf(
" Selected=0x%08X", node_settings->
SelectedTabId);
19702 if (
g.IO.ConfigDebugIniSettings)
19703 if (ImGuiDockNode* node = DockContextFindNodeByID(ctx, node_settings->
ID))
19705 buf->appendf(
"%*s", ImMax(2, (line_start_pos + 92) - buf->size()),
"");
19706 if (node->IsDockSpace() && node->HostWindow && node->HostWindow->ParentWindow)
19707 buf->appendf(
" ; in '%s'", node->HostWindow->ParentWindow->Name);
19709 int contains_window = 0;
19710 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
19711 if (settings->DockId == node_settings->
ID)
19713 if (contains_window++ == 0)
19714 buf->appendf(
" ; contains ");
19715 buf->appendf(
"'%s' ", settings->GetName());
19719 buf->appendf(
"\n");
19721 buf->appendf(
"\n");
19729#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS)
19732#pragma comment(lib, "user32")
19733#pragma comment(lib, "kernel32")
19738static const char* GetClipboardTextFn_DefaultImpl(
void* user_data_ctx)
19740 ImGuiContext&
g = *(ImGuiContext*)user_data_ctx;
19741 g.ClipboardHandlerData.clear();
19742 if (!::OpenClipboard(NULL))
19744 HANDLE wbuf_handle = ::GetClipboardData(CF_UNICODETEXT);
19745 if (wbuf_handle == NULL)
19747 ::CloseClipboard();
19750 if (
const WCHAR* wbuf_global = (
const WCHAR*)::GlobalLock(wbuf_handle))
19752 int buf_len = ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, NULL, 0, NULL, NULL);
19753 g.ClipboardHandlerData.resize(buf_len);
19754 ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1,
g.ClipboardHandlerData.Data, buf_len, NULL, NULL);
19756 ::GlobalUnlock(wbuf_handle);
19757 ::CloseClipboard();
19758 return g.ClipboardHandlerData.Data;
19761static void SetClipboardTextFn_DefaultImpl(
void*,
const char* text)
19763 if (!::OpenClipboard(NULL))
19765 const int wbuf_length = ::MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
19766 HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length *
sizeof(WCHAR));
19767 if (wbuf_handle == NULL)
19769 ::CloseClipboard();
19772 WCHAR* wbuf_global = (WCHAR*)::GlobalLock(wbuf_handle);
19773 ::MultiByteToWideChar(CP_UTF8, 0, text, -1, wbuf_global, wbuf_length);
19774 ::GlobalUnlock(wbuf_handle);
19775 ::EmptyClipboard();
19776 if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL)
19777 ::GlobalFree(wbuf_handle);
19778 ::CloseClipboard();
19781#elif defined(__APPLE__) && TARGET_OS_OSX && defined(IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS)
19783#include <Carbon/Carbon.h>
19784static PasteboardRef main_clipboard = 0;
19788static void SetClipboardTextFn_DefaultImpl(
void*,
const char* text)
19790 if (!main_clipboard)
19791 PasteboardCreate(kPasteboardClipboard, &main_clipboard);
19792 PasteboardClear(main_clipboard);
19793 CFDataRef cf_data = CFDataCreate(kCFAllocatorDefault, (
const UInt8*)text, strlen(text));
19796 PasteboardPutItemFlavor(main_clipboard, (PasteboardItemID)1, CFSTR(
"public.utf8-plain-text"), cf_data, 0);
19797 CFRelease(cf_data);
19801static const char* GetClipboardTextFn_DefaultImpl(
void* user_data_ctx)
19803 ImGuiContext&
g = *(ImGuiContext*)user_data_ctx;
19804 if (!main_clipboard)
19805 PasteboardCreate(kPasteboardClipboard, &main_clipboard);
19806 PasteboardSynchronize(main_clipboard);
19808 ItemCount item_count = 0;
19809 PasteboardGetItemCount(main_clipboard, &item_count);
19810 for (ItemCount i = 0; i < item_count; i++)
19812 PasteboardItemID item_id = 0;
19813 PasteboardGetItemIdentifier(main_clipboard, i + 1, &item_id);
19814 CFArrayRef flavor_type_array = 0;
19815 PasteboardCopyItemFlavors(main_clipboard, item_id, &flavor_type_array);
19816 for (CFIndex j = 0, nj = CFArrayGetCount(flavor_type_array); j < nj; j++)
19819 if (PasteboardCopyItemFlavorData(main_clipboard, item_id, CFSTR(
"public.utf8-plain-text"), &cf_data) == noErr)
19821 g.ClipboardHandlerData.clear();
19822 int length = (int)CFDataGetLength(cf_data);
19823 g.ClipboardHandlerData.resize(length + 1);
19824 CFDataGetBytes(cf_data, CFRangeMake(0, length), (UInt8*)
g.ClipboardHandlerData.Data);
19825 g.ClipboardHandlerData[
length] = 0;
19826 CFRelease(cf_data);
19827 return g.ClipboardHandlerData.Data;
19837static const char* GetClipboardTextFn_DefaultImpl(
void* user_data_ctx)
19839 ImGuiContext&
g = *(ImGuiContext*)user_data_ctx;
19840 return g.ClipboardHandlerData.empty() ? NULL :
g.ClipboardHandlerData.begin();
19843static void SetClipboardTextFn_DefaultImpl(
void* user_data_ctx,
const char* text)
19845 ImGuiContext&
g = *(ImGuiContext*)user_data_ctx;
19846 g.ClipboardHandlerData.clear();
19847 const char* text_end = text + strlen(text);
19848 g.ClipboardHandlerData.resize((
int)(text_end - text) + 1);
19849 memcpy(&
g.ClipboardHandlerData[0], text, (
size_t)(text_end - text));
19850 g.ClipboardHandlerData[(int)(text_end - text)] = 0;
19856#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
19860#pragma comment(lib, "imm32")
19863static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatformImeData* data)
19866 HWND hwnd = (HWND)viewport->PlatformHandleRaw;
19871 if (HIMC himc = ::ImmGetContext(hwnd))
19873 COMPOSITIONFORM composition_form = {};
19874 composition_form.ptCurrentPos.x = (LONG)(data->InputPos.x - viewport->Pos.x);
19875 composition_form.ptCurrentPos.y = (LONG)(data->InputPos.y - viewport->Pos.y);
19876 composition_form.dwStyle = CFS_FORCE_POSITION;
19877 ::ImmSetCompositionWindow(himc, &composition_form);
19878 CANDIDATEFORM candidate_form = {};
19879 candidate_form.dwStyle = CFS_CANDIDATEPOS;
19880 candidate_form.ptCurrentPos.x = (LONG)(data->InputPos.x - viewport->Pos.x);
19881 candidate_form.ptCurrentPos.y = (LONG)(data->InputPos.y - viewport->Pos.y);
19882 ::ImmSetCandidateWindow(himc, &candidate_form);
19883 ::ImmReleaseContext(hwnd, himc);
19889static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport*, ImGuiPlatformImeData*) {}
19917#ifndef IMGUI_DISABLE_DEBUG_TOOLS
19919void ImGui::DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport,
const ImRect& bb)
19922 ImGuiWindow* window =
g.CurrentWindow;
19924 ImVec2
scale = bb.GetSize() / viewport->Size;
19925 ImVec2 off = bb.Min - viewport->Pos *
scale;
19926 float alpha_mul = (viewport->Flags & ImGuiViewportFlags_IsMinimized) ? 0.30f : 1.00f;
19927 window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul * 0.40f));
19928 for (ImGuiWindow* thumb_window :
g.Windows)
19930 if (!thumb_window->WasActive || (thumb_window->Flags & ImGuiWindowFlags_ChildWindow))
19932 if (thumb_window->Viewport != viewport)
19935 ImRect thumb_r = thumb_window->Rect();
19936 ImRect title_r = thumb_window->TitleBarRect();
19937 thumb_r = ImRect(ImTrunc(off + thumb_r.Min * scale), ImTrunc(off + thumb_r.Max * scale));
19938 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));
19939 thumb_r.ClipWithFull(bb);
19940 title_r.ClipWithFull(bb);
19941 const bool window_is_focused = (
g.NavWindow && thumb_window->RootWindowForTitleBarHighlight ==
g.NavWindow->RootWindowForTitleBarHighlight);
19942 window->DrawList->AddRectFilled(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_WindowBg, alpha_mul));
19943 window->DrawList->AddRectFilled(title_r.Min, title_r.Max, GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg, alpha_mul));
19944 window->DrawList->AddRect(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_Border, alpha_mul));
19945 window->DrawList->AddText(
g.Font,
g.FontSize * 1.0f, title_r.Min, GetColorU32(ImGuiCol_Text, alpha_mul), thumb_window->Name, FindRenderedTextEnd(thumb_window->Name));
19947 draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul));
19948 if (viewport->ID ==
g.DebugMetricsConfig.HighlightViewportID)
19949 window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
19952static void RenderViewportsThumbnails()
19955 ImGuiWindow* window =
g.CurrentWindow;
19958 float SCALE = 1.0f / 8.0f;
19959 ImRect bb_full(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
19960 for (ImGuiPlatformMonitor& monitor :
g.PlatformIO.Monitors)
19961 bb_full.Add(ImRect(monitor.MainPos, monitor.MainPos + monitor.MainSize));
19962 ImVec2 p = window->DC.CursorPos;
19963 ImVec2 off = p - bb_full.Min * SCALE;
19964 for (ImGuiPlatformMonitor& monitor :
g.PlatformIO.Monitors)
19966 ImRect monitor_draw_bb(off + (monitor.MainPos) * SCALE, off + (monitor.MainPos + monitor.MainSize) * SCALE);
19967 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);
19968 window->DrawList->AddRectFilled(monitor_draw_bb.Min, monitor_draw_bb.Max, ImGui::GetColorU32(ImGuiCol_Border, 0.10f), 4.0f);
19972 for (ImGuiViewportP* viewport :
g.Viewports)
19974 ImRect viewport_draw_bb(off + (viewport->Pos) * SCALE, off + (viewport->Pos + viewport->Size) * SCALE);
19975 ImGui::DebugRenderViewportThumbnail(window->DrawList, viewport, viewport_draw_bb);
19977 ImGui::Dummy(bb_full.GetSize() * SCALE);
19980static int IMGUI_CDECL ViewportComparerByLastFocusedStampCount(
const void* lhs,
const void* rhs)
19982 const ImGuiViewportP* a = *(
const ImGuiViewportP*
const*)lhs;
19983 const ImGuiViewportP* b = *(
const ImGuiViewportP*
const*)rhs;
19984 return b->LastFocusedStampCount - a->LastFocusedStampCount;
19988void ImGui::DebugRenderKeyboardPreview(ImDrawList* draw_list)
19990 const float scale = ImGui::GetFontSize() / 13.0f;
19991 const ImVec2 key_size = ImVec2(35.0f, 35.0f) *
scale;
19992 const float key_rounding = 3.0f *
scale;
19993 const ImVec2 key_face_size = ImVec2(25.0f, 25.0f) *
scale;
19994 const ImVec2 key_face_pos = ImVec2(5.0f, 3.0f) *
scale;
19995 const float key_face_rounding = 2.0f *
scale;
19996 const ImVec2 key_label_pos = ImVec2(7.0f, 4.0f) *
scale;
19997 const ImVec2 key_step = ImVec2(key_size.x - 1.0f, key_size.y - 1.0f);
19998 const float key_row_offset = 9.0f *
scale;
20000 ImVec2 board_min = GetCursorScreenPos();
20001 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);
20002 ImVec2 start_pos = ImVec2(board_min.x + 5.0f - key_step.x, board_min.y);
20004 struct KeyLayoutData {
int Row, Col;
const char* Label; ImGuiKey Key; };
20005 const KeyLayoutData keys_to_display[] =
20007 { 0, 0,
"", ImGuiKey_Tab }, { 0, 1,
"Q", ImGuiKey_Q }, { 0, 2,
"W", ImGuiKey_W }, { 0, 3,
"E", ImGuiKey_E }, { 0, 4,
"R", ImGuiKey_R },
20008 { 1, 0,
"", ImGuiKey_CapsLock }, { 1, 1,
"A", ImGuiKey_A }, { 1, 2,
"S", ImGuiKey_S }, { 1, 3,
"D", ImGuiKey_D }, { 1, 4,
"F", ImGuiKey_F },
20009 { 2, 0,
"", ImGuiKey_LeftShift },{ 2, 1,
"Z", ImGuiKey_Z }, { 2, 2,
"X", ImGuiKey_X }, { 2, 3,
"C", ImGuiKey_C }, { 2, 4,
"V", ImGuiKey_V }
20014 Dummy(board_max - board_min);
20015 if (!IsItemVisible())
20017 draw_list->PushClipRect(board_min, board_max,
true);
20018 for (
int n = 0; n < IM_ARRAYSIZE(keys_to_display); n++)
20020 const KeyLayoutData* key_data = &keys_to_display[n];
20021 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);
20022 ImVec2 key_max = key_min + key_size;
20023 draw_list->AddRectFilled(key_min, key_max, IM_COL32(204, 204, 204, 255), key_rounding);
20024 draw_list->AddRect(key_min, key_max, IM_COL32(24, 24, 24, 255), key_rounding);
20025 ImVec2 face_min = ImVec2(key_min.x + key_face_pos.x, key_min.y + key_face_pos.y);
20026 ImVec2 face_max = ImVec2(face_min.x + key_face_size.x, face_min.y + key_face_size.y);
20027 draw_list->AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, ImDrawFlags_None, 2.0f);
20028 draw_list->AddRectFilled(face_min, face_max, IM_COL32(252, 252, 252, 255), key_face_rounding);
20029 ImVec2 label_min = ImVec2(key_min.x + key_label_pos.x, key_min.y + key_label_pos.y);
20030 draw_list->AddText(label_min, IM_COL32(64, 64, 64, 255), key_data->Label);
20031 if (IsKeyDown(key_data->Key))
20032 draw_list->AddRectFilled(key_min, key_max, IM_COL32(255, 0, 0, 128), key_rounding);
20034 draw_list->PopClipRect();
20038void ImGui::DebugTextEncoding(
const char* str)
20040 Text(
"Text: \"%s\"", str);
20041 if (!BeginTable(
"##DebugTextEncoding", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable))
20043 TableSetupColumn(
"Offset");
20044 TableSetupColumn(
"UTF-8");
20045 TableSetupColumn(
"Glyph");
20046 TableSetupColumn(
"Codepoint");
20048 for (
const char* p = str; *p != 0; )
20053 Text(
"%d", (
int)(p - str));
20055 for (
int byte_index = 0; byte_index < c_utf8_len; byte_index++)
20057 if (byte_index > 0)
20059 Text(
"0x%02X", (
int)(
unsigned char)p[byte_index]);
20062 if (GetFont()->FindGlyphNoFallback((ImWchar)c))
20065 TextUnformatted((c == IM_UNICODE_CODEPOINT_INVALID) ?
"[invalid]" :
"[missing]");
20067 Text(
"U+%04X", (
int)c);
20073static void DebugFlashStyleColorStop()
20076 if (
g.DebugFlashStyleColorIdx != ImGuiCol_COUNT)
20077 g.Style.Colors[
g.DebugFlashStyleColorIdx] =
g.DebugFlashStyleColorBackup;
20078 g.DebugFlashStyleColorIdx = ImGuiCol_COUNT;
20082void ImGui::DebugFlashStyleColor(ImGuiCol idx)
20085 DebugFlashStyleColorStop();
20086 g.DebugFlashStyleColorTime = 0.5f;
20087 g.DebugFlashStyleColorIdx = idx;
20088 g.DebugFlashStyleColorBackup =
g.Style.Colors[idx];
20091void ImGui::UpdateDebugToolFlashStyleColor()
20094 if (
g.DebugFlashStyleColorTime <= 0.0f)
20096 ColorConvertHSVtoRGB(cosf(
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);
20097 g.Style.Colors[
g.DebugFlashStyleColorIdx].w = 1.0f;
20098 if ((
g.DebugFlashStyleColorTime -=
g.IO.DeltaTime) <= 0.0f)
20099 DebugFlashStyleColorStop();
20103static void MetricsHelpMarker(
const char* desc)
20105 ImGui::TextDisabled(
"(?)");
20106 if (ImGui::BeginItemTooltip())
20108 ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
20110 ImGui::PopTextWrapPos();
20111 ImGui::EndTooltip();
20118 for (ImFont* font : atlas->Fonts)
20121 DebugNodeFont(font);
20124 if (TreeNode(
"Font Atlas",
"Font Atlas (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
20127 ImGuiMetricsConfig* cfg = &
g.DebugMetricsConfig;
20128 Checkbox(
"Tint with Text Color", &cfg->ShowAtlasTintedWithTextColor);
20129 ImVec4 tint_col = cfg->ShowAtlasTintedWithTextColor ? GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
20130 ImVec4 border_col = GetStyleColorVec4(ImGuiCol_Border);
20131 Image(atlas->TexID, ImVec2((
float)atlas->TexWidth, (
float)atlas->TexHeight), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), tint_col, border_col);
20136void ImGui::ShowMetricsWindow(
bool* p_open)
20139 ImGuiIO& io =
g.IO;
20140 ImGuiMetricsConfig* cfg = &
g.DebugMetricsConfig;
20141 if (cfg->ShowDebugLog)
20142 ShowDebugLogWindow(&cfg->ShowDebugLog);
20143 if (cfg->ShowIDStackTool)
20144 ShowIDStackToolWindow(&cfg->ShowIDStackTool);
20146 if (!Begin(
"Dear ImGui Metrics/Debugger", p_open) || GetCurrentWindow()->BeginCount > 1)
20153 DebugBreakClearData();
20156 Text(
"Dear ImGui %s", GetVersion());
20157 Text(
"Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
20158 Text(
"%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3);
20159 Text(
"%d visible windows, %d current allocations", io.MetricsRenderWindows,
g.DebugAllocInfo.TotalAllocCount -
g.DebugAllocInfo.TotalFreeCount);
20165 enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentIdeal, WRT_ContentRegionRect, WRT_Count };
20166 const char* wrt_rects_names[WRT_Count] = {
"OuterRect",
"OuterRectClipped",
"InnerRect",
"InnerClipRect",
"WorkRect",
"Content",
"ContentIdeal",
"ContentRegionRect" };
20167 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 };
20168 const char* trt_rects_names[TRT_Count] = {
"OuterRect",
"InnerRect",
"WorkRect",
"HostClipRect",
"InnerClipRect",
"BackgroundClipRect",
"ColumnsRect",
"ColumnsWorkRect",
"ColumnsClipRect",
"ColumnsContentHeadersUsed",
"ColumnsContentHeadersIdeal",
"ColumnsContentFrozen",
"ColumnsContentUnfrozen" };
20169 if (cfg->ShowWindowsRectsType < 0)
20170 cfg->ShowWindowsRectsType = WRT_WorkRect;
20171 if (cfg->ShowTablesRectsType < 0)
20172 cfg->ShowTablesRectsType = TRT_WorkRect;
20176 static ImRect GetTableRect(ImGuiTable* table,
int rect_type,
int n)
20178 ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
20179 if (rect_type == TRT_OuterRect) {
return table->OuterRect; }
20180 else if (rect_type == TRT_InnerRect) {
return table->InnerRect; }
20181 else if (rect_type == TRT_WorkRect) {
return table->WorkRect; }
20182 else if (rect_type == TRT_HostClipRect) {
return table->HostClipRect; }
20183 else if (rect_type == TRT_InnerClipRect) {
return table->InnerClipRect; }
20184 else if (rect_type == TRT_BackgroundClipRect) {
return table->BgClipRect; }
20185 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); }
20186 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); }
20187 else if (rect_type == TRT_ColumnsClipRect) { ImGuiTableColumn* c = &table->Columns[n];
return c->ClipRect; }
20188 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); }
20189 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); }
20190 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); }
20191 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); }
20196 static ImRect GetWindowRect(ImGuiWindow* window,
int rect_type)
20198 if (rect_type == WRT_OuterRect) {
return window->Rect(); }
20199 else if (rect_type == WRT_OuterRectClipped) {
return window->OuterRectClipped; }
20200 else if (rect_type == WRT_InnerRect) {
return window->InnerRect; }
20201 else if (rect_type == WRT_InnerClipRect) {
return window->InnerClipRect; }
20202 else if (rect_type == WRT_WorkRect) {
return window->WorkRect; }
20203 else if (rect_type == WRT_Content) { ImVec2
min = window->InnerRect.Min - window->Scroll + window->WindowPadding;
return ImRect(min, min + window->ContentSize); }
20204 else if (rect_type == WRT_ContentIdeal) { ImVec2
min = window->InnerRect.Min - window->Scroll + window->WindowPadding;
return ImRect(min, min + window->ContentSizeIdeal); }
20205 else if (rect_type == WRT_ContentRegionRect) {
return window->ContentRegionRect; }
20216 SeparatorTextEx(0,
"Debug breaks", NULL,
CalcTextSize(
"(?)").x +
g.Style.SeparatorTextPadding.x);
20218 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.");
20219 if (
Checkbox(
"Show Item Picker", &
g.DebugItemPickerActive) &&
g.DebugItemPickerActive)
20220 DebugStartItemPicker();
20221 Checkbox(
"Show \"Debug Break\" buttons in other sections (io.ConfigDebugIsDebuggerPresent)", &
g.IO.ConfigDebugIsDebuggerPresent);
20223 SeparatorText(
"Visualize");
20225 Checkbox(
"Show Debug Log", &cfg->ShowDebugLog);
20227 MetricsHelpMarker(
"You can also call ImGui::ShowDebugLogWindow() from your code.");
20229 Checkbox(
"Show ID Stack Tool", &cfg->ShowIDStackTool);
20231 MetricsHelpMarker(
"You can also call ImGui::ShowIDStackToolWindow() from your code.");
20233 Checkbox(
"Show windows begin order", &cfg->ShowWindowsBeginOrder);
20234 Checkbox(
"Show windows rectangles", &cfg->ShowWindowsRects);
20236 SetNextItemWidth(GetFontSize() * 12);
20237 cfg->ShowWindowsRects |=
Combo(
"##show_windows_rect_type", &cfg->ShowWindowsRectsType, wrt_rects_names, WRT_Count, WRT_Count);
20238 if (cfg->ShowWindowsRects &&
g.NavWindow != NULL)
20240 BulletText(
"'%s':",
g.NavWindow->Name);
20242 for (
int rect_n = 0; rect_n < WRT_Count; rect_n++)
20244 ImRect r = Funcs::GetWindowRect(
g.NavWindow, rect_n);
20245 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]);
20250 Checkbox(
"Show tables rectangles", &cfg->ShowTablesRects);
20252 SetNextItemWidth(GetFontSize() * 12);
20253 cfg->ShowTablesRects |=
Combo(
"##show_table_rects_type", &cfg->ShowTablesRectsType, trt_rects_names, TRT_Count, TRT_Count);
20254 if (cfg->ShowTablesRects &&
g.NavWindow != NULL)
20256 for (
int table_n = 0; table_n <
g.Tables.GetMapSize(); table_n++)
20258 ImGuiTable* table =
g.Tables.TryGetMapData(table_n);
20259 if (table == NULL || table->LastFrameActive <
g.FrameCount - 1 || (table->OuterWindow !=
g.NavWindow && table->InnerWindow !=
g.NavWindow))
20262 BulletText(
"Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);
20263 if (IsItemHovered())
20264 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);
20267 for (
int rect_n = 0; rect_n < TRT_Count; rect_n++)
20269 if (rect_n >= TRT_ColumnsRect)
20271 if (rect_n != TRT_ColumnsRect && rect_n != TRT_ColumnsClipRect)
20273 for (
int column_n = 0; column_n < table->ColumnsCount; column_n++)
20275 ImRect r = Funcs::GetTableRect(table, rect_n, column_n);
20276 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]);
20278 if (IsItemHovered())
20279 GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
20284 ImRect r = Funcs::GetTableRect(table, rect_n, -1);
20285 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]);
20287 if (IsItemHovered())
20288 GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
20294 Checkbox(
"Show groups rectangles", &
g.DebugShowGroupRects);
20296 SeparatorText(
"Validate");
20298 Checkbox(
"Debug Begin/BeginChild return value", &io.ConfigDebugBeginReturnValueLoop);
20300 MetricsHelpMarker(
"Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running.");
20302 Checkbox(
"UTF-8 Encoding viewer", &cfg->ShowTextEncodingViewer);
20304 MetricsHelpMarker(
"You can also call ImGui::DebugTextEncoding() from your code with a given string to test that your UTF-8 encoding settings are correct.");
20305 if (cfg->ShowTextEncodingViewer)
20307 static char buf[64] =
"";
20308 SetNextItemWidth(-FLT_MIN);
20309 InputText(
"##DebugTextEncodingBuf", buf, IM_ARRAYSIZE(buf));
20311 DebugTextEncoding(buf);
20318 if (
TreeNode(
"Windows",
"Windows (%d)",
g.Windows.Size))
20321 DebugNodeWindowsList(&
g.Windows,
"By display order");
20322 DebugNodeWindowsList(&
g.WindowsFocusOrder,
"By focus order (root windows)");
20323 if (
TreeNode(
"By submission order (begin stack)"))
20326 ImVector<ImGuiWindow*>& temp_buffer =
g.WindowsTempSortBuffer;
20327 temp_buffer.resize(0);
20328 for (ImGuiWindow* window :
g.Windows)
20329 if (window->LastFrameActive + 1 >=
g.FrameCount)
20330 temp_buffer.push_back(window);
20331 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); } };
20332 ImQsort(temp_buffer.Data, (
size_t)temp_buffer.Size,
sizeof(ImGuiWindow*), Func::WindowComparerByBeginOrder);
20333 DebugNodeWindowsListByBeginStackParent(temp_buffer.Data, temp_buffer.Size, NULL);
20341 int drawlist_count = 0;
20342 for (ImGuiViewportP* viewport :
g.Viewports)
20343 drawlist_count += viewport->DrawDataP.CmdLists.Size;
20344 if (
TreeNode(
"DrawLists",
"DrawLists (%d)", drawlist_count))
20346 Checkbox(
"Show ImDrawCmd mesh when hovering", &cfg->ShowDrawCmdMesh);
20347 Checkbox(
"Show ImDrawCmd bounding boxes when hovering", &cfg->ShowDrawCmdBoundingBoxes);
20348 for (ImGuiViewportP* viewport :
g.Viewports)
20350 bool viewport_has_drawlist =
false;
20351 for (ImDrawList* draw_list : viewport->DrawDataP.CmdLists)
20353 if (!viewport_has_drawlist)
20354 Text(
"Active DrawLists in Viewport #%d, ID: 0x%08X", viewport->Idx, viewport->ID);
20355 viewport_has_drawlist =
true;
20356 DebugNodeDrawList(NULL, viewport, draw_list,
"DrawList");
20363 if (
TreeNode(
"Viewports",
"Viewports (%d)",
g.Viewports.Size))
20365 cfg->HighlightMonitorIdx = -1;
20366 bool open =
TreeNode(
"Monitors",
"Monitors (%d)",
g.PlatformIO.Monitors.Size);
20368 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.");
20371 for (
int i = 0; i <
g.PlatformIO.Monitors.Size; i++)
20373 const ImGuiPlatformMonitor& mon =
g.PlatformIO.Monitors[i];
20374 BulletText(
"Monitor #%d: DPI %.0f%%\n MainMin (%.0f,%.0f), MainMax (%.0f,%.0f), MainSize (%.0f,%.0f)\n WorkMin (%.0f,%.0f), WorkMax (%.0f,%.0f), WorkSize (%.0f,%.0f)",
20375 i, mon.DpiScale * 100.0f,
20376 mon.MainPos.x, mon.MainPos.y, mon.MainPos.x + mon.MainSize.x, mon.MainPos.y + mon.MainSize.y, mon.MainSize.x, mon.MainSize.y,
20377 mon.WorkPos.x, mon.WorkPos.y, mon.WorkPos.x + mon.WorkSize.x, mon.WorkPos.y + mon.WorkSize.y, mon.WorkSize.x, mon.WorkSize.y);
20378 if (IsItemHovered())
20379 cfg->HighlightMonitorIdx = i;
20384 SetNextItemOpen(
true, ImGuiCond_Once);
20387 RenderViewportsThumbnails();
20390 cfg->HighlightViewportID = 0;
20392 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);
20393 if (
TreeNode(
"Inferred Z order (front-to-back)"))
20395 static ImVector<ImGuiViewportP*> viewports;
20396 viewports.resize(
g.Viewports.Size);
20397 memcpy(viewports.Data,
g.Viewports.Data,
g.Viewports.size_in_bytes());
20398 if (viewports.Size > 1)
20399 ImQsort(viewports.Data, viewports.Size,
sizeof(ImGuiViewport*), ViewportComparerByLastFocusedStampCount);
20400 for (ImGuiViewportP* viewport : viewports)
20402 BulletText(
"Viewport #%d, ID: 0x%08X, LastFocused = %08d, PlatformFocused = %s, Window: \"%s\"",
20403 viewport->Idx, viewport->ID, viewport->LastFocusedStampCount,
20404 (
g.PlatformIO.Platform_GetWindowFocus && viewport->PlatformWindowCreated) ? (
g.PlatformIO.Platform_GetWindowFocus(viewport) ?
"1" :
"0") :
"N/A",
20406 if (IsItemHovered())
20407 cfg->HighlightViewportID = viewport->ID;
20412 for (ImGuiViewportP* viewport :
g.Viewports)
20413 DebugNodeViewport(viewport);
20418 if (
TreeNode(
"Popups",
"Popups (%d)",
g.OpenPopupStack.Size))
20420 for (
const ImGuiPopupData& popup_data :
g.OpenPopupStack)
20423 ImGuiWindow* window = popup_data.Window;
20424 BulletText(
"PopupID: %08x, Window: '%s' (%s%s), RestoreNavWindow '%s', ParentWindow '%s'",
20425 popup_data.PopupId, window ? window->Name :
"NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ?
"Child;" :
"", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ?
"Menu;" :
"",
20426 popup_data.RestoreNavWindow ? popup_data.RestoreNavWindow->Name :
"NULL", window && window->ParentWindow ? window->ParentWindow->Name :
"NULL");
20432 if (
TreeNode(
"TabBars",
"Tab Bars (%d)",
g.TabBars.GetAliveCount()))
20434 for (
int n = 0; n <
g.TabBars.GetMapSize(); n++)
20435 if (ImGuiTabBar* tab_bar =
g.TabBars.TryGetMapData(n))
20438 DebugNodeTabBar(tab_bar,
"TabBar");
20445 if (
TreeNode(
"Tables",
"Tables (%d)",
g.Tables.GetAliveCount()))
20447 for (
int n = 0; n <
g.Tables.GetMapSize(); n++)
20448 if (ImGuiTable* table =
g.Tables.TryGetMapData(n))
20449 DebugNodeTable(table);
20454 ImFontAtlas* atlas =
g.IO.Fonts;
20455 if (
TreeNode(
"Fonts",
"Fonts (%d)", atlas->Fonts.Size))
20464 DebugNodeInputTextState(&
g.InputTextState);
20469 if (
TreeNode(
"TypingSelect",
"TypingSelect (%d)",
g.TypingSelectState.SearchBuffer[0] != 0 ? 1 : 0))
20471 DebugNodeTypingSelectState(&
g.TypingSelectState);
20476#ifdef IMGUI_HAS_DOCK
20479 static bool root_nodes_only =
true;
20480 ImGuiDockContext* dc = &
g.DockContext;
20481 Checkbox(
"List root nodes", &root_nodes_only);
20482 Checkbox(
"Ctrl shows window dock info", &cfg->ShowDockingNodes);
20483 if (SmallButton(
"Clear nodes")) { DockContextClearNodes(&
g, 0,
true); }
20485 if (SmallButton(
"Rebuild all")) { dc->WantFullRebuild =
true; }
20486 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
20487 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
20488 if (!root_nodes_only || node->IsRootNode())
20489 DebugNodeDockNode(node,
"Node");
20497 if (SmallButton(
"Clear"))
20498 ClearIniSettings();
20500 if (SmallButton(
"Save to memory"))
20501 SaveIniSettingsToMemory();
20503 if (SmallButton(
"Save to disk"))
20504 SaveIniSettingsToDisk(
g.IO.IniFilename);
20506 if (
g.IO.IniFilename)
20507 Text(
"\"%s\"",
g.IO.IniFilename);
20510 Checkbox(
"io.ConfigDebugIniSettings", &io.ConfigDebugIniSettings);
20511 Text(
"SettingsDirtyTimer %.2f",
g.SettingsDirtyTimer);
20512 if (
TreeNode(
"SettingsHandlers",
"Settings handlers: (%d)",
g.SettingsHandlers.Size))
20514 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
20515 BulletText(
"\"%s\"", handler.TypeName);
20518 if (
TreeNode(
"SettingsWindows",
"Settings packed data: Windows: %d bytes",
g.SettingsWindows.size()))
20520 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
20521 DebugNodeWindowSettings(settings);
20525 if (
TreeNode(
"SettingsTables",
"Settings packed data: Tables: %d bytes",
g.SettingsTables.size()))
20527 for (ImGuiTableSettings* settings =
g.SettingsTables.begin(); settings != NULL; settings =
g.SettingsTables.next_chunk(settings))
20528 DebugNodeTableSettings(settings);
20532#ifdef IMGUI_HAS_DOCK
20533 if (
TreeNode(
"SettingsDocking",
"Settings packed data: Docking"))
20535 ImGuiDockContext* dc = &
g.DockContext;
20536 Text(
"In SettingsWindows:");
20537 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
20538 if (settings->DockId != 0)
20539 BulletText(
"Window '%s' -> DockId %08X DockOrder=%d", settings->GetName(), settings->DockId, settings->DockOrder);
20540 Text(
"In SettingsNodes:");
20541 for (
int n = 0; n < dc->NodesSettings.Size; n++)
20544 const char* selected_tab_name = NULL;
20547 if (ImGuiWindow* window = FindWindowByID(settings->
SelectedTabId))
20548 selected_tab_name = window->Name;
20549 else if (ImGuiWindowSettings* window_settings = FindWindowSettingsByID(settings->
SelectedTabId))
20550 selected_tab_name = window_settings->GetName();
20552 BulletText(
"Node %08X, Parent %08X, SelectedTab %08X ('%s')", settings->
ID, settings->
ParentNodeId, settings->
SelectedTabId, selected_tab_name ? selected_tab_name : settings->SelectedTabId ?
"N/A" :
"");
20558 if (
TreeNode(
"SettingsIniData",
"Settings unpacked data (.ini): %d bytes",
g.SettingsIniData.size()))
20560 InputTextMultiline(
"##Ini", (
char*)(
void*)
g.SettingsIniData.c_str(),
g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, GetTextLineHeight() * 20), ImGuiInputTextFlags_ReadOnly);
20567 if (
TreeNode(
"Memory allocations"))
20569 ImGuiDebugAllocInfo* info = &
g.DebugAllocInfo;
20570 Text(
"%d current allocations", info->TotalAllocCount - info->TotalFreeCount);
20571 if (SmallButton(
"GC now")) {
g.GcCompactAll =
true; }
20572 Text(
"Recent frames with allocations:");
20573 int buf_size = IM_ARRAYSIZE(info->LastEntriesBuf);
20574 for (
int n = buf_size - 1; n >= 0; n--)
20576 ImGuiDebugAllocEntry* entry = &info->LastEntriesBuf[(info->LastEntriesIdx - n + buf_size) % buf_size];
20577 BulletText(
"Frame %06d: %+3d ( %2d malloc, %2d free )%s", entry->FrameCount, entry->AllocCount - entry->FreeCount, entry->AllocCount, entry->FreeCount, (n == 0) ?
" (most recent)" :
"");
20584 Text(
"KEYBOARD/GAMEPAD/MOUSE KEYS");
20589#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
20590 struct funcs {
static bool IsLegacyNativeDupe(ImGuiKey) {
return false; } };
20592 struct funcs {
static bool IsLegacyNativeDupe(ImGuiKey key) {
return key >= 0 && key < 512 && GetIO().KeyMap[key] != -1; } };
20595 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); }
20596 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); }
20597 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); }
20598 Text(
"Keys mods: %s%s%s%s", io.KeyCtrl ?
"CTRL " :
"", io.KeyShift ?
"SHIFT " :
"", io.KeyAlt ?
"ALT " :
"", io.KeySuper ?
"SUPER " :
"");
20599 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); }
20600 DebugRenderKeyboardPreview(GetWindowDrawList());
20604 Text(
"MOUSE STATE");
20607 if (IsMousePosValid())
20608 Text(
"Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
20610 Text(
"Mouse pos: <INVALID>");
20611 Text(
"Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
20612 int count = IM_ARRAYSIZE(io.MouseDown);
20613 Text(
"Mouse down:");
for (
int i = 0; i <
count; i++)
if (IsMouseDown(i)) { SameLine(); Text(
"b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
20614 Text(
"Mouse clicked:");
for (
int i = 0; i <
count; i++)
if (IsMouseClicked(i)) { SameLine(); Text(
"b%d (%d)", i, io.MouseClickedCount[i]); }
20615 Text(
"Mouse released:");
for (
int i = 0; i <
count; i++)
if (IsMouseReleased(i)) { SameLine(); Text(
"b%d", i); }
20616 Text(
"Mouse wheel: %.1f", io.MouseWheel);
20617 Text(
"MouseStationaryTimer: %.2f",
g.MouseStationaryTimer);
20618 Text(
"Mouse source: %s", GetMouseSourceName(io.MouseSource));
20619 Text(
"Pen Pressure: %.1f", io.PenPressure);
20623 Text(
"MOUSE WHEELING");
20626 Text(
"WheelingWindow: '%s'",
g.WheelingWindow ?
g.WheelingWindow->Name :
"NULL");
20627 Text(
"WheelingWindowReleaseTimer: %.2f",
g.WheelingWindowReleaseTimer);
20628 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>");
20632 Text(
"KEY OWNERS");
20635 if (BeginChild(
"##owners", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_NoSavedSettings))
20636 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
20638 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
20639 if (owner_data->OwnerCurr == ImGuiKeyOwner_NoOwner)
20641 Text(
"%s: 0x%08X%s", GetKeyName(key), owner_data->OwnerCurr,
20642 owner_data->LockUntilRelease ?
" LockUntilRelease" : owner_data->LockThisFrame ?
" LockThisFrame" :
"");
20643 DebugLocateItemOnHover(owner_data->OwnerCurr);
20648 Text(
"SHORTCUT ROUTING");
20650 MetricsHelpMarker(
"Declared shortcut routes automatically set key owner when mods matches.");
20653 if (BeginChild(
"##routes", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_NoSavedSettings))
20654 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
20656 ImGuiKeyRoutingTable* rt = &
g.KeysRoutingTable;
20657 for (ImGuiKeyRoutingIndex idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; idx != -1; )
20659 ImGuiKeyRoutingData* routing_data = &rt->Entries[idx];
20660 ImGuiKeyChord key_chord = key | routing_data->Mods;
20661 Text(
"%s: 0x%08X (scored %d)", GetKeyChordName(key_chord), routing_data->RoutingCurr, routing_data->RoutingCurrScore);
20662 DebugLocateItemOnHover(routing_data->RoutingCurr);
20663 if (
g.IO.ConfigDebugIsDebuggerPresent)
20666 if (DebugBreakButton(
"**DebugBreak**",
"in SetShortcutRouting() for this KeyChord"))
20667 g.DebugBreakInShortcutRouting = key_chord;
20669 idx = routing_data->NextEntryIndex;
20673 Text(
"(ActiveIdUsing: AllKeyboardKeys: %d, NavDirMask: 0x%X)",
g.ActiveIdUsingAllKeyboardKeys,
g.ActiveIdUsingNavDirMask);
20683 Text(
"HoveredWindow: '%s'",
g.HoveredWindow ?
g.HoveredWindow->Name :
"NULL");
20684 Text(
"HoveredWindow->Root: '%s'",
g.HoveredWindow ?
g.HoveredWindow->RootWindowDockTree->Name :
"NULL");
20685 Text(
"HoveredWindowUnderMovingWindow: '%s'",
g.HoveredWindowUnderMovingWindow ?
g.HoveredWindowUnderMovingWindow->Name :
"NULL");
20686 Text(
"HoveredDockNode: 0x%08X",
g.DebugHoveredDockNode ?
g.DebugHoveredDockNode->ID : 0);
20687 Text(
"MovingWindow: '%s'",
g.MovingWindow ?
g.MovingWindow->Name :
"NULL");
20688 Text(
"MouseViewport: 0x%08X (UserHovered 0x%08X, LastHovered 0x%08X)",
g.MouseViewport->ID,
g.IO.MouseHoveredViewport,
g.MouseLastHoveredViewport ?
g.MouseLastHoveredViewport->ID : 0);
20693 Text(
"ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s",
g.ActiveId,
g.ActiveIdPreviousFrame,
g.ActiveIdTimer,
g.ActiveIdAllowOverlap, GetInputSourceName(
g.ActiveIdSource));
20694 DebugLocateItemOnHover(
g.ActiveId);
20695 Text(
"ActiveIdWindow: '%s'",
g.ActiveIdWindow ?
g.ActiveIdWindow->Name :
"NULL");
20696 Text(
"ActiveIdUsing: AllKeyboardKeys: %d, NavDirMask: %X",
g.ActiveIdUsingAllKeyboardKeys,
g.ActiveIdUsingNavDirMask);
20697 Text(
"HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d",
g.HoveredIdPreviousFrame,
g.HoveredIdTimer,
g.HoveredIdAllowOverlap);
20698 Text(
"HoverItemDelayId: 0x%08X, Timer: %.2f, ClearTimer: %.2f",
g.HoverItemDelayId,
g.HoverItemDelayTimer,
g.HoverItemDelayClearTimer);
20699 Text(
"DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)",
g.DragDropActive,
g.DragDropPayload.SourceId,
g.DragDropPayload.DataType,
g.DragDropPayload.DataSize);
20700 DebugLocateItemOnHover(
g.DragDropPayload.SourceId);
20705 Text(
"NavWindow: '%s'",
g.NavWindow ?
g.NavWindow->Name :
"NULL");
20706 Text(
"NavId: 0x%08X, NavLayer: %d",
g.NavId,
g.NavLayer);
20707 DebugLocateItemOnHover(
g.NavId);
20708 Text(
"NavInputSource: %s", GetInputSourceName(
g.NavInputSource));
20709 Text(
"NavLastValidSelectionUserData = %" IM_PRId64
" (0x%" IM_PRIX64
")",
g.NavLastValidSelectionUserData,
g.NavLastValidSelectionUserData);
20710 Text(
"NavActive: %d, NavVisible: %d",
g.IO.NavActive,
g.IO.NavVisible);
20711 Text(
"NavActivateId/DownId/PressedId: %08X/%08X/%08X",
g.NavActivateId,
g.NavActivateDownId,
g.NavActivatePressedId);
20712 Text(
"NavActivateFlags: %04X",
g.NavActivateFlags);
20713 Text(
"NavDisableHighlight: %d, NavDisableMouseHover: %d",
g.NavDisableHighlight,
g.NavDisableMouseHover);
20714 Text(
"NavFocusScopeId = 0x%08X",
g.NavFocusScopeId);
20715 Text(
"NavFocusRoute[] = ");
20716 for (
int path_n =
g.NavFocusRoute.Size - 1; path_n >= 0; path_n--)
20718 const ImGuiFocusScopeData& focus_scope =
g.NavFocusRoute[path_n];
20719 SameLine(0.0f, 0.0f);
20720 Text(
"0x%08X/", focus_scope.ID);
20721 SetItemTooltip(
"In window \"%s\"", FindWindowByID(focus_scope.WindowID)->Name);
20723 Text(
"NavWindowingTarget: '%s'",
g.NavWindowingTarget ?
g.NavWindowingTarget->Name :
"NULL");
20730 if (cfg->ShowWindowsRects || cfg->ShowWindowsBeginOrder)
20732 for (ImGuiWindow* window :
g.Windows)
20734 if (!window->WasActive)
20736 ImDrawList* draw_list = GetForegroundDrawList(window);
20737 if (cfg->ShowWindowsRects)
20739 ImRect r = Funcs::GetWindowRect(window, cfg->ShowWindowsRectsType);
20740 draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255));
20742 if (cfg->ShowWindowsBeginOrder && !(window->Flags & ImGuiWindowFlags_ChildWindow))
20745 ImFormatString(buf, IM_ARRAYSIZE(buf),
"%d", window->BeginOrderWithinContext);
20746 float font_size = GetFontSize();
20747 draw_list->AddRectFilled(window->Pos, window->Pos + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255));
20748 draw_list->AddText(window->Pos, IM_COL32(255, 255, 255, 255), buf);
20754 if (cfg->ShowTablesRects)
20756 for (
int table_n = 0; table_n <
g.Tables.GetMapSize(); table_n++)
20758 ImGuiTable* table =
g.Tables.TryGetMapData(table_n);
20759 if (table == NULL || table->LastFrameActive <
g.FrameCount - 1)
20761 ImDrawList* draw_list = GetForegroundDrawList(table->OuterWindow);
20762 if (cfg->ShowTablesRectsType >= TRT_ColumnsRect)
20764 for (
int column_n = 0; column_n < table->ColumnsCount; column_n++)
20766 ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, column_n);
20767 ImU32 col = (table->HoveredColumnBody == column_n) ? IM_COL32(255, 255, 128, 255) : IM_COL32(255, 0, 128, 255);
20768 float thickness = (table->HoveredColumnBody == column_n) ? 3.0f : 1.0f;
20769 draw_list->AddRect(r.Min, r.Max, col, 0.0f, 0, thickness);
20774 ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, -1);
20775 draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255));
20780#ifdef IMGUI_HAS_DOCK
20782 if (cfg->ShowDockingNodes &&
g.IO.KeyCtrl &&
g.DebugHoveredDockNode)
20786 ImGuiDockNode* node =
g.DebugHoveredDockNode;
20787 ImDrawList* overlay_draw_list = node->HostWindow ? GetForegroundDrawList(node->HostWindow) : GetForegroundDrawList(GetMainViewport());
20788 p +=
ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"DockId: %X%s\n", node->ID, node->IsCentralNode() ?
" *CentralNode*" :
"");
20789 p +=
ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"WindowClass: %08X\n", node->WindowClass.ClassId);
20790 p +=
ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"Size: (%.0f, %.0f)\n", node->Size.x, node->Size.y);
20791 p +=
ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"SizeRef: (%.0f, %.0f)\n", node->SizeRef.x, node->SizeRef.y);
20792 int depth = DockNodeGetDepth(node);
20793 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));
20794 ImVec2 pos = node->Pos + ImVec2(3, 3) * (float)depth;
20795 overlay_draw_list->AddRectFilled(pos - ImVec2(1, 1), pos +
CalcTextSize(buf) + ImVec2(1, 1), IM_COL32(200, 100, 100, 255));
20796 overlay_draw_list->AddText(NULL, 0.0f, pos, IM_COL32(255, 255, 255, 255), buf);
20803void ImGui::DebugBreakClearData()
20807 g.DebugBreakInWindow = 0;
20808 g.DebugBreakInTable = 0;
20809 g.DebugBreakInShortcutRouting = ImGuiKey_None;
20812void ImGui::DebugBreakButtonTooltip(
bool keyboard_only,
const char* description_of_location)
20814 if (!BeginItemTooltip())
20816 Text(
"To call IM_DEBUG_BREAK() %s:", description_of_location);
20818 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.");
20820 TextUnformatted(
"Choose one way that doesn't interfere with what you are trying to debug!\nYou need a debugger attached or this will crash!");
20826bool ImGui::DebugBreakButton(
const char* label,
const char* description_of_location)
20828 ImGuiWindow* window = GetCurrentWindow();
20829 if (window->SkipItems)
20833 const ImGuiID
id = window->GetID(label);
20834 const ImVec2 label_size =
CalcTextSize(label, NULL,
true);
20835 ImVec2 pos = window->DC.CursorPos + ImVec2(0.0f, window->DC.CurrLineTextBaseOffset);
20836 ImVec2
size = ImVec2(label_size.x +
g.Style.FramePadding.x * 2.0f, label_size.y);
20838 const ImRect bb(pos, pos + size);
20839 ItemSize(size, 0.0f);
20840 if (!ItemAdd(bb,
id))
20844 bool hovered = ItemHoverable(bb,
id,
g.CurrentItemFlags);
20845 bool pressed = hovered && (IsKeyChordPressed(
g.DebugBreakKeyChord) || IsMouseClicked(0) ||
g.NavActivateId ==
id);
20846 DebugBreakButtonTooltip(
false, description_of_location);
20848 ImVec4 col4f = GetStyleColorVec4(hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
20850 ColorConvertRGBtoHSV(col4f.x, col4f.y, col4f.z, hsv.x, hsv.y, hsv.z);
20851 ColorConvertHSVtoRGB(hsv.x + 0.20f, hsv.y, hsv.z, col4f.x, col4f.y, col4f.z);
20853 RenderNavHighlight(bb,
id);
20854 RenderFrame(bb.Min, bb.Max, GetColorU32(col4f),
true,
g.Style.FrameRounding);
20855 RenderTextClipped(bb.Min, bb.Max, label, NULL, &label_size,
g.Style.ButtonTextAlign, &bb);
20857 IMGUI_TEST_ENGINE_ITEM_INFO(
id, label,
g.LastItemData.StatusFlags);
20862void ImGui::DebugNodeColumns(ImGuiOldColumns* columns)
20864 if (!
TreeNode((
void*)(uintptr_t)columns->ID,
"Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags))
20866 BulletText(
"Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->OffMaxX - columns->OffMinX, columns->OffMinX, columns->OffMaxX);
20867 for (ImGuiOldColumnData& column : columns->Columns)
20868 BulletText(
"Column %02d: OffsetNorm %.3f (= %.1f px)", (int)columns->Columns.index_from_ptr(&column), column.OffsetNorm, GetColumnOffsetFromNorm(columns, column.OffsetNorm));
20872static void DebugNodeDockNodeFlags(ImGuiDockNodeFlags* p_flags,
const char* label,
bool enabled)
20874 using namespace ImGui;
20876 PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
20877 Text(
"%s:", label);
20880 CheckboxFlags(
"NoResize", p_flags, ImGuiDockNodeFlags_NoResize);
20881 CheckboxFlags(
"NoResizeX", p_flags, ImGuiDockNodeFlags_NoResizeX);
20882 CheckboxFlags(
"NoResizeY",p_flags, ImGuiDockNodeFlags_NoResizeY);
20883 CheckboxFlags(
"NoTabBar", p_flags, ImGuiDockNodeFlags_NoTabBar);
20884 CheckboxFlags(
"HiddenTabBar", p_flags, ImGuiDockNodeFlags_HiddenTabBar);
20885 CheckboxFlags(
"NoWindowMenuButton", p_flags, ImGuiDockNodeFlags_NoWindowMenuButton);
20886 CheckboxFlags(
"NoCloseButton", p_flags, ImGuiDockNodeFlags_NoCloseButton);
20887 CheckboxFlags(
"DockedWindowsInFocusRoute", p_flags, ImGuiDockNodeFlags_DockedWindowsInFocusRoute);
20888 CheckboxFlags(
"NoDocking", p_flags, ImGuiDockNodeFlags_NoDocking);
20889 CheckboxFlags(
"NoDockingSplit", p_flags, ImGuiDockNodeFlags_NoDockingSplit);
20890 CheckboxFlags(
"NoDockingSplitOther", p_flags, ImGuiDockNodeFlags_NoDockingSplitOther);
20891 CheckboxFlags(
"NoDockingOver", p_flags, ImGuiDockNodeFlags_NoDockingOverMe);
20892 CheckboxFlags(
"NoDockingOverOther", p_flags, ImGuiDockNodeFlags_NoDockingOverOther);
20893 CheckboxFlags(
"NoDockingOverEmpty", p_flags, ImGuiDockNodeFlags_NoDockingOverEmpty);
20894 CheckboxFlags(
"NoUndocking", p_flags, ImGuiDockNodeFlags_NoUndocking);
20902void ImGui::DebugNodeDockNode(ImGuiDockNode* node,
const char* label)
20905 const bool is_alive = (
g.FrameCount - node->LastFrameAlive < 2);
20906 const bool is_active = (
g.FrameCount - node->LastFrameActive < 2);
20907 if (!is_alive) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
20909 ImGuiTreeNodeFlags tree_node_flags = node->IsFocused ? ImGuiTreeNodeFlags_Selected : ImGuiTreeNodeFlags_None;
20910 if (node->Windows.Size > 0)
20911 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");
20913 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");
20914 if (!is_alive) { PopStyleColor(); }
20915 if (is_active && IsItemHovered())
20916 if (ImGuiWindow* window = node->HostWindow ? node->HostWindow : node->VisibleWindow)
20917 GetForegroundDrawList(window)->AddRect(node->Pos, node->Pos + node->Size, IM_COL32(255, 255, 0, 255));
20920 IM_ASSERT(node->ChildNodes[0] == NULL || node->ChildNodes[0]->ParentNode == node);
20921 IM_ASSERT(node->ChildNodes[1] == NULL || node->ChildNodes[1]->ParentNode == node);
20922 BulletText(
"Pos (%.0f,%.0f), Size (%.0f, %.0f) Ref (%.0f, %.0f)",
20923 node->Pos.x, node->Pos.y, node->Size.x, node->Size.y, node->SizeRef.x, node->SizeRef.y);
20924 DebugNodeWindow(node->HostWindow,
"HostWindow");
20925 DebugNodeWindow(node->VisibleWindow,
"VisibleWindow");
20926 BulletText(
"SelectedTabID: 0x%08X, LastFocusedNodeID: 0x%08X", node->SelectedTabId, node->LastFocusedNodeId);
20927 BulletText(
"Misc:%s%s%s%s%s%s%s",
20928 node->IsDockSpace() ?
" IsDockSpace" :
"",
20929 node->IsCentralNode() ?
" IsCentralNode" :
"",
20930 is_alive ?
" IsAlive" :
"", is_active ?
" IsActive" :
"", node->IsFocused ?
" IsFocused" :
"",
20931 node->WantLockSizeOnce ?
" WantLockSizeOnce" :
"",
20932 node->HasCentralNodeChild ?
" HasCentralNodeChild" :
"");
20933 if (
TreeNode(
"flags",
"Flags Merged: 0x%04X, Local: 0x%04X, InWindows: 0x%04X, Shared: 0x%04X", node->MergedFlags, node->LocalFlags, node->LocalFlagsInWindows, node->SharedFlags))
20935 if (BeginTable(
"flags", 4))
20937 TableNextColumn(); DebugNodeDockNodeFlags(&node->MergedFlags,
"MergedFlags",
false);
20938 TableNextColumn(); DebugNodeDockNodeFlags(&node->LocalFlags,
"LocalFlags",
true);
20939 TableNextColumn(); DebugNodeDockNodeFlags(&node->LocalFlagsInWindows,
"LocalFlagsInWindows",
false);
20940 TableNextColumn(); DebugNodeDockNodeFlags(&node->SharedFlags,
"SharedFlags",
true);
20945 if (node->ParentNode)
20946 DebugNodeDockNode(node->ParentNode,
"ParentNode");
20947 if (node->ChildNodes[0])
20948 DebugNodeDockNode(node->ChildNodes[0],
"Child[0]");
20949 if (node->ChildNodes[1])
20950 DebugNodeDockNode(node->ChildNodes[1],
"Child[1]");
20952 DebugNodeTabBar(node->TabBar,
"TabBar");
20953 DebugNodeWindowsList(&node->Windows,
"Windows");
20959static void FormatTextureIDForDebugDisplay(
char* buf,
int buf_size, ImTextureID tex_id)
20961 union {
void* ptr;
int integer; } tex_id_opaque;
20962 memcpy(&tex_id_opaque, &tex_id, ImMin(
sizeof(
void*),
sizeof(tex_id)));
20963 if (
sizeof(tex_id) >=
sizeof(
void*))
20971void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport,
const ImDrawList* draw_list,
const char* label)
20974 ImGuiMetricsConfig* cfg = &
g.DebugMetricsConfig;
20975 int cmd_count = draw_list->CmdBuffer.Size;
20976 if (cmd_count > 0 && draw_list->CmdBuffer.back().ElemCount == 0 && draw_list->CmdBuffer.back().UserCallback == NULL)
20978 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);
20979 if (draw_list == GetWindowDrawList())
20982 TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f),
"CURRENTLY APPENDING");
20988 ImDrawList* fg_draw_list = viewport ? GetForegroundDrawList(viewport) : NULL;
20989 if (window && IsItemHovered() && fg_draw_list)
20990 fg_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
20994 if (window && !window->WasActive)
20995 TextDisabled(
"Warning: owning Window is inactive. This DrawList is not being rendered!");
20997 for (
const ImDrawCmd* pcmd = draw_list->CmdBuffer.Data; pcmd < draw_list->CmdBuffer.Data + cmd_count; pcmd++)
20999 if (pcmd->UserCallback)
21001 BulletText(
"Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData);
21005 char texid_desc[20];
21006 FormatTextureIDForDebugDisplay(texid_desc, IM_ARRAYSIZE(texid_desc), pcmd->TextureId);
21008 ImFormatString(buf, IM_ARRAYSIZE(buf),
"DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
21009 pcmd->ElemCount / 3, texid_desc, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
21010 bool pcmd_node_open =
TreeNode((
void*)(pcmd - draw_list->CmdBuffer.begin()),
"%s", buf);
21011 if (IsItemHovered() && (cfg->ShowDrawCmdMesh || cfg->ShowDrawCmdBoundingBoxes) && fg_draw_list)
21012 DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, cfg->ShowDrawCmdMesh, cfg->ShowDrawCmdBoundingBoxes);
21013 if (!pcmd_node_open)
21018 const ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
21019 const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + pcmd->VtxOffset;
21020 float total_area = 0.0f;
21021 for (
unsigned int idx_n = pcmd->IdxOffset; idx_n < pcmd->IdxOffset + pcmd->ElemCount; )
21023 ImVec2 triangle[3];
21024 for (
int n = 0; n < 3; n++, idx_n++)
21025 triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos;
21026 total_area += ImTriangleArea(triangle[0], triangle[1], triangle[2]);
21030 ImFormatString(buf, IM_ARRAYSIZE(buf),
"Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area);
21032 if (IsItemHovered() && fg_draw_list)
21033 DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd,
true,
false);
21036 ImGuiListClipper clipper;
21037 clipper.Begin(pcmd->ElemCount / 3);
21038 while (clipper.Step())
21039 for (
int prim = clipper.DisplayStart, idx_i = pcmd->IdxOffset + clipper.DisplayStart * 3; prim < clipper.DisplayEnd; prim++)
21041 char* buf_p = buf, * buf_end = buf + IM_ARRAYSIZE(buf);
21042 ImVec2 triangle[3];
21043 for (
int n = 0; n < 3; n++, idx_i++)
21045 const ImDrawVert& v = vtx_buffer[idx_buffer ? idx_buffer[idx_i] : idx_i];
21046 triangle[n] = v.pos;
21047 buf_p +=
ImFormatString(buf_p, buf_end - buf_p,
"%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n",
21048 (n == 0) ?
"Vert:" :
" ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);
21051 Selectable(buf,
false);
21052 if (fg_draw_list && IsItemHovered())
21054 ImDrawListFlags backup_flags = fg_draw_list->Flags;
21055 fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines;
21056 fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f);
21057 fg_draw_list->Flags = backup_flags;
21066void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list,
const ImDrawList* draw_list,
const ImDrawCmd* draw_cmd,
bool show_mesh,
bool show_aabb)
21068 IM_ASSERT(show_mesh || show_aabb);
21071 ImRect clip_rect = draw_cmd->ClipRect;
21072 ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
21073 ImDrawListFlags backup_flags = out_draw_list->Flags;
21074 out_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines;
21075 for (
unsigned int idx_n = draw_cmd->IdxOffset, idx_end = draw_cmd->IdxOffset + draw_cmd->ElemCount; idx_n < idx_end; )
21077 ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
21078 ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + draw_cmd->VtxOffset;
21080 ImVec2 triangle[3];
21081 for (
int n = 0; n < 3; n++, idx_n++)
21082 vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos));
21084 out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f);
21089 out_draw_list->AddRect(ImTrunc(clip_rect.Min), ImTrunc(clip_rect.Max), IM_COL32(255, 0, 255, 255));
21090 out_draw_list->AddRect(ImTrunc(vtxs_rect.Min), ImTrunc(vtxs_rect.Max), IM_COL32(0, 255, 255, 255));
21092 out_draw_list->Flags = backup_flags;
21096void ImGui::DebugNodeFont(ImFont* font)
21098 bool opened =
TreeNode(font,
"Font: \"%s\"\n%.2f px, %d glyphs, %d file(s)",
21099 font->ConfigData ? font->ConfigData[0].Name :
"", font->FontSize, font->Glyphs.Size, font->ConfigDataCount);
21101 if (SmallButton(
"Set as default"))
21102 GetIO().FontDefault = font;
21108 Text(
"The quick brown fox jumps over the lazy dog");
21112 SetNextItemWidth(GetFontSize() * 8);
21113 DragFloat(
"Font scale", &font->Scale, 0.005f, 0.3f, 2.0f,
"%.1f");
21114 SameLine(); MetricsHelpMarker(
21115 "Note that the default embedded font is NOT meant to be scaled.\n\n"
21116 "Font are currently rendered into bitmaps at a given size at the time of building the atlas. "
21117 "You may oversample them to get some flexibility with scaling. "
21118 "You can also render at multiple sizes and select which one to use at runtime.\n\n"
21119 "(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)");
21120 Text(
"Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
21122 Text(
"Fallback character: '%s' (U+%04X)",
ImTextCharToUtf8(c_str, font->FallbackChar), font->FallbackChar);
21123 Text(
"Ellipsis character: '%s' (U+%04X)",
ImTextCharToUtf8(c_str, font->EllipsisChar), font->EllipsisChar);
21124 const int surface_sqrt = (int)ImSqrt((
float)font->MetricsTotalSurface);
21125 Text(
"Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt);
21126 for (
int config_i = 0; config_i < font->ConfigDataCount; config_i++)
21127 if (font->ConfigData)
21128 if (
const ImFontConfig* cfg = &font->ConfigData[config_i])
21129 BulletText(
"Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d, Offset: (%.1f,%.1f)",
21130 config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y);
21133 if (
TreeNode(
"Glyphs",
"Glyphs (%d)", font->Glyphs.Size))
21135 ImDrawList* draw_list = GetWindowDrawList();
21136 const ImU32 glyph_col = GetColorU32(ImGuiCol_Text);
21137 const float cell_size = font->FontSize * 1;
21138 const float cell_spacing = GetStyle().ItemSpacing.y;
21139 for (
unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256)
21144 if (!(base & 4095) && font->IsGlyphRangeUnused(base, base + 4095))
21146 base += 4096 - 256;
21151 for (
unsigned int n = 0; n < 256; n++)
21152 if (font->FindGlyphNoFallback((ImWchar)(base + n)))
21156 if (!
TreeNode((
void*)(intptr_t)base,
"U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ?
"glyphs" :
"glyph"))
21160 ImVec2 base_pos = GetCursorScreenPos();
21161 for (
unsigned int n = 0; n < 256; n++)
21165 ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));
21166 ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
21167 const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));
21168 draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
21171 font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n));
21172 if (IsMouseHoveringRect(cell_p1, cell_p2) && BeginTooltip())
21174 DebugNodeFontGlyph(font, glyph);
21178 Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));
21186void ImGui::DebugNodeFontGlyph(ImFont*,
const ImFontGlyph* glyph)
21188 Text(
"Codepoint: U+%04X", glyph->Codepoint);
21190 Text(
"Visible: %d", glyph->Visible);
21191 Text(
"AdvanceX: %.1f", glyph->AdvanceX);
21192 Text(
"Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
21193 Text(
"UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
21197void ImGui::DebugNodeStorage(ImGuiStorage* storage,
const char* label)
21199 if (!
TreeNode(label,
"%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes()))
21201 for (
const ImGuiStorage::ImGuiStoragePair& p : storage->Data)
21202 BulletText(
"Key 0x%08X Value { i: %d }", p.key, p.val_i);
21207void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar,
const char* label)
21212 const char* buf_end = buf + IM_ARRAYSIZE(buf);
21213 const bool is_active = (tab_bar->PrevFrameVisible >= GetFrameCount() - 2);
21214 p +=
ImFormatString(p, buf_end - p,
"%s 0x%08X (%d tabs)%s {", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ?
"" :
" *Inactive*");
21215 for (
int tab_n = 0; tab_n < ImMin(tab_bar->Tabs.Size, 3); tab_n++)
21217 ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
21218 p +=
ImFormatString(p, buf_end - p,
"%s'%s'", tab_n > 0 ?
", " :
"", TabBarGetTabName(tab_bar, tab));
21220 p +=
ImFormatString(p, buf_end - p, (tab_bar->Tabs.Size > 3) ?
" ... }" :
" } ");
21221 if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
21222 bool open =
TreeNode(label,
"%s", buf);
21223 if (!is_active) { PopStyleColor(); }
21224 if (is_active && IsItemHovered())
21226 ImDrawList* draw_list = GetForegroundDrawList();
21227 draw_list->AddRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, IM_COL32(255, 255, 0, 255));
21228 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));
21229 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));
21233 for (
int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
21235 ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
21237 if (SmallButton(
"<")) { TabBarQueueReorder(tab_bar, tab, -1); } SameLine(0, 2);
21238 if (SmallButton(
">")) { TabBarQueueReorder(tab_bar, tab, +1); } SameLine();
21239 Text(
"%02d%c Tab 0x%08X '%s' Offset: %.2f, Width: %.2f/%.2f",
21240 tab_n, (tab->ID == tab_bar->SelectedTabId) ?
'*' :
' ', tab->
ID, TabBarGetTabName(tab_bar, tab), tab->Offset, tab->Width, tab->ContentWidth);
21247void ImGui::DebugNodeViewport(ImGuiViewportP* viewport)
21250 SetNextItemOpen(
true, ImGuiCond_Once);
21251 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");
21252 if (IsItemHovered())
21253 g.DebugMetricsConfig.HighlightViewportID = viewport->ID;
21256 ImGuiWindowFlags flags = viewport->Flags;
21257 BulletText(
"Main Pos: (%.0f,%.0f), Size: (%.0f,%.0f)\nWorkArea Offset Left: %.0f Top: %.0f, Right: %.0f, Bottom: %.0f\nMonitor: %d, DpiScale: %.0f%%",
21258 viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y,
21259 viewport->WorkOffsetMin.x, viewport->WorkOffsetMin.y, viewport->WorkOffsetMax.x, viewport->WorkOffsetMax.y,
21260 viewport->PlatformMonitor, viewport->DpiScale * 100.0f);
21261 if (viewport->Idx > 0) { SameLine();
if (SmallButton(
"Reset Pos")) { viewport->Pos = ImVec2(200, 200); viewport->UpdateWorkRect();
if (viewport->Window) viewport->Window->Pos = viewport->Pos; } }
21262 BulletText(
"Flags: 0x%04X =%s%s%s%s%s%s%s%s%s%s%s%s%s", viewport->Flags,
21264 (flags & ImGuiViewportFlags_IsPlatformMonitor) ?
" IsPlatformMonitor" :
"",
21265 (flags & ImGuiViewportFlags_IsMinimized) ?
" IsMinimized" :
"",
21266 (flags & ImGuiViewportFlags_IsFocused) ?
" IsFocused" :
"",
21267 (flags & ImGuiViewportFlags_OwnedByApp) ?
" OwnedByApp" :
"",
21268 (flags & ImGuiViewportFlags_NoDecoration) ?
" NoDecoration" :
"",
21269 (flags & ImGuiViewportFlags_NoTaskBarIcon) ?
" NoTaskBarIcon" :
"",
21270 (flags & ImGuiViewportFlags_NoFocusOnAppearing) ?
" NoFocusOnAppearing" :
"",
21271 (flags & ImGuiViewportFlags_NoFocusOnClick) ?
" NoFocusOnClick" :
"",
21272 (flags & ImGuiViewportFlags_NoInputs) ?
" NoInputs" :
"",
21273 (flags & ImGuiViewportFlags_NoRendererClear) ?
" NoRendererClear" :
"",
21274 (flags & ImGuiViewportFlags_NoAutoMerge) ?
" NoAutoMerge" :
"",
21275 (flags & ImGuiViewportFlags_TopMost) ?
" TopMost" :
"",
21276 (flags & ImGuiViewportFlags_CanHostOtherWindows) ?
" CanHostOtherWindows" :
"");
21277 for (ImDrawList* draw_list : viewport->DrawDataP.CmdLists)
21278 DebugNodeDrawList(NULL, viewport, draw_list,
"DrawList");
21283void ImGui::DebugNodeWindow(ImGuiWindow* window,
const char* label)
21285 if (window == NULL)
21287 BulletText(
"%s: NULL", label);
21292 const bool is_active = window->WasActive;
21293 ImGuiTreeNodeFlags tree_node_flags = (window ==
g.NavWindow) ? ImGuiTreeNodeFlags_Selected : ImGuiTreeNodeFlags_None;
21294 if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
21295 const bool open = TreeNodeEx(label, tree_node_flags,
"%s '%s'%s", label, window->Name, is_active ?
"" :
" *Inactive*");
21296 if (!is_active) { PopStyleColor(); }
21297 if (IsItemHovered() && is_active)
21298 GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
21302 if (window->MemoryCompacted)
21303 TextDisabled(
"Note: some memory buffers have been compacted/freed.");
21305 if (
g.IO.ConfigDebugIsDebuggerPresent && DebugBreakButton(
"**DebugBreak**",
"in Begin()"))
21306 g.DebugBreakInWindow = window->ID;
21308 ImGuiWindowFlags flags = window->Flags;
21309 DebugNodeDrawList(window, window->Viewport, window->DrawList,
"DrawList");
21310 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);
21311 BulletText(
"Flags: 0x%08X (%s%s%s%s%s%s%s%s%s..)", flags,
21312 (flags & ImGuiWindowFlags_ChildWindow) ?
"Child " :
"", (flags & ImGuiWindowFlags_Tooltip) ?
"Tooltip " :
"", (flags & ImGuiWindowFlags_Popup) ?
"Popup " :
"",
21313 (flags & ImGuiWindowFlags_Modal) ?
"Modal " :
"", (flags & ImGuiWindowFlags_ChildMenu) ?
"ChildMenu " :
"", (flags & ImGuiWindowFlags_NoSavedSettings) ?
"NoSavedSettings " :
"",
21314 (flags & ImGuiWindowFlags_NoMouseInputs)?
"NoMouseInputs":
"", (flags & ImGuiWindowFlags_NoNavInputs) ?
"NoNavInputs" :
"", (flags & ImGuiWindowFlags_AlwaysAutoResize) ?
"AlwaysAutoResize" :
"");
21315 BulletText(
"WindowClassId: 0x%08X", window->WindowClass.ClassId);
21316 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" :
"");
21317 BulletText(
"Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1);
21318 BulletText(
"Appearing: %d, Hidden: %d (CanSkip %d Cannot %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesCanSkipItems, window->HiddenFramesCannotSkipItems, window->SkipItems);
21319 for (
int layer = 0; layer < ImGuiNavLayer_COUNT; layer++)
21321 ImRect r = window->NavRectRel[layer];
21322 if (r.Min.x >= r.Max.y && r.Min.y >= r.Max.y)
21323 BulletText(
"NavLastIds[%d]: 0x%08X", layer, window->NavLastIds[layer]);
21325 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);
21326 DebugLocateItemOnHover(window->NavLastIds[layer]);
21328 const ImVec2* pr = window->NavPreferredScoringPosRel;
21329 for (
int layer = 0; layer < ImGuiNavLayer_COUNT; layer++)
21330 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));
21331 BulletText(
"NavLayersActiveMask: %X, NavLastChildNavWindow: %s", window->DC.NavLayersActiveMask, window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name :
"NULL");
21333 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);
21334 BulletText(
"ViewportMonitor: %d", window->Viewport ? window->Viewport->PlatformMonitor : -1);
21335 BulletText(
"DockId: 0x%04X, DockOrder: %d, Act: %d, Vis: %d", window->DockId, window->DockOrder, window->DockIsActive, window->DockTabIsVisible);
21336 if (window->DockNode || window->DockNodeAsHost)
21337 DebugNodeDockNode(window->DockNodeAsHost ? window->DockNodeAsHost : window->DockNode, window->DockNodeAsHost ?
"DockNodeAsHost" :
"DockNode");
21339 if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow,
"RootWindow"); }
21340 if (window->RootWindowDockTree != window->RootWindow) { DebugNodeWindow(window->RootWindowDockTree,
"RootWindowDockTree"); }
21341 if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow,
"ParentWindow"); }
21342 if (window->ParentWindowForFocusRoute != NULL) { DebugNodeWindow(window->ParentWindowForFocusRoute,
"ParentWindowForFocusRoute"); }
21343 if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows,
"ChildWindows"); }
21344 if (window->ColumnsStorage.Size > 0 &&
TreeNode(
"Columns",
"Columns sets (%d)", window->ColumnsStorage.Size))
21346 for (ImGuiOldColumns& columns : window->ColumnsStorage)
21347 DebugNodeColumns(&columns);
21350 DebugNodeStorage(&window->StateStorage,
"Storage");
21354void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings* settings)
21356 if (settings->WantDelete)
21358 Text(
"0x%08X \"%s\" Pos (%d,%d) Size (%d,%d) Collapsed=%d",
21359 settings->ID, settings->GetName(), settings->Pos.x, settings->Pos.y, settings->Size.x, settings->Size.y, settings->Collapsed);
21360 if (settings->WantDelete)
21364void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows,
const char* label)
21366 if (!
TreeNode(label,
"%s (%d)", label, windows->Size))
21368 for (
int i = windows->Size - 1; i >= 0; i--)
21370 PushID((*windows)[i]);
21371 DebugNodeWindow((*windows)[i],
"Window");
21378void ImGui::DebugNodeWindowsListByBeginStackParent(ImGuiWindow** windows,
int windows_size, ImGuiWindow* parent_in_begin_stack)
21380 for (
int i = 0; i < windows_size; i++)
21382 ImGuiWindow* window = windows[i];
21383 if (window->ParentWindowInBeginStack != parent_in_begin_stack)
21386 ImFormatString(buf, IM_ARRAYSIZE(buf),
"[%04d] Window", window->BeginOrderWithinContext);
21388 DebugNodeWindow(window, buf);
21390 DebugNodeWindowsListByBeginStackParent(windows + i + 1, windows_size - i - 1, window);
21399void ImGui::DebugLog(
const char* fmt, ...)
21402 va_start(args, fmt);
21403 DebugLogV(fmt, args);
21407void ImGui::DebugLogV(
const char* fmt, va_list args)
21410 const int old_size =
g.DebugLogBuf.size();
21411 g.DebugLogBuf.appendf(
"[%05d] ",
g.FrameCount);
21412 g.DebugLogBuf.appendfv(fmt, args);
21413 g.DebugLogIndex.append(
g.DebugLogBuf.c_str(), old_size,
g.DebugLogBuf.size());
21414 if (
g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTTY)
21415 IMGUI_DEBUG_PRINTF(
"%s",
g.DebugLogBuf.begin() + old_size);
21416#ifdef IMGUI_ENABLE_TEST_ENGINE
21417 if (
g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTestEngine)
21418 IMGUI_TEST_ENGINE_LOG(
"%s",
g.DebugLogBuf.begin() + old_size);
21423static void SameLineOrWrap(
const ImVec2& size)
21426 ImGuiWindow* window =
g.CurrentWindow;
21427 ImVec2 pos(window->DC.CursorPosPrevLine.x +
g.Style.ItemSpacing.x, window->DC.CursorPosPrevLine.y);
21428 if (window->ClipRect.Contains(ImRect(pos, pos + size)))
21432static void ShowDebugLogFlag(
const char* name, ImGuiDebugLogFlags flags)
21435 ImVec2
size(ImGui::GetFrameHeight() +
g.Style.ItemInnerSpacing.x +
ImGui::CalcTextSize(name).x, ImGui::GetFrameHeight());
21436 SameLineOrWrap(size);
21437 if (ImGui::CheckboxFlags(name, &
g.DebugLogFlags, flags) &&
g.IO.KeyShift && (
g.DebugLogFlags & flags) != 0)
21439 g.DebugLogAutoDisableFrames = 2;
21440 g.DebugLogAutoDisableFlags |= flags;
21442 ImGui::SetItemTooltip(
"Hold SHIFT when clicking to enable for 2 frames only (useful for spammy log entries)");
21445void ImGui::ShowDebugLogWindow(
bool* p_open)
21448 if (!(
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize))
21449 SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 12.0f), ImGuiCond_FirstUseEver);
21450 if (!Begin(
"Dear ImGui Debug Log", p_open) || GetCurrentWindow()->BeginCount > 1)
21456 ImGuiDebugLogFlags all_enable_flags = ImGuiDebugLogFlags_EventMask_ & ~ImGuiDebugLogFlags_EventInputRouting;
21457 CheckboxFlags(
"All", &
g.DebugLogFlags, all_enable_flags);
21458 SetItemTooltip(
"(except InputRouting which is spammy)");
21460 ShowDebugLogFlag(
"ActiveId", ImGuiDebugLogFlags_EventActiveId);
21461 ShowDebugLogFlag(
"Clipper", ImGuiDebugLogFlags_EventClipper);
21462 ShowDebugLogFlag(
"Docking", ImGuiDebugLogFlags_EventDocking);
21463 ShowDebugLogFlag(
"Focus", ImGuiDebugLogFlags_EventFocus);
21464 ShowDebugLogFlag(
"IO", ImGuiDebugLogFlags_EventIO);
21465 ShowDebugLogFlag(
"Nav", ImGuiDebugLogFlags_EventNav);
21466 ShowDebugLogFlag(
"Popup", ImGuiDebugLogFlags_EventPopup);
21468 ShowDebugLogFlag(
"Viewport", ImGuiDebugLogFlags_EventViewport);
21469 ShowDebugLogFlag(
"InputRouting", ImGuiDebugLogFlags_EventInputRouting);
21471 if (SmallButton(
"Clear"))
21473 g.DebugLogBuf.clear();
21474 g.DebugLogIndex.clear();
21477 if (SmallButton(
"Copy"))
21478 SetClipboardText(
g.DebugLogBuf.c_str());
21479 BeginChild(
"##log", ImVec2(0.0f, 0.0f), ImGuiChildFlags_Border, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar);
21481 const ImGuiDebugLogFlags backup_log_flags =
g.DebugLogFlags;
21482 g.DebugLogFlags &= ~ImGuiDebugLogFlags_EventClipper;
21484 ImGuiListClipper clipper;
21485 clipper.Begin(
g.DebugLogIndex.size());
21486 while (clipper.Step())
21487 for (
int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
21489 const char* line_begin =
g.DebugLogIndex.get_line_begin(
g.DebugLogBuf.c_str(), line_no);
21490 const char* line_end =
g.DebugLogIndex.get_line_end(
g.DebugLogBuf.c_str(), line_no);
21492 ImRect text_rect =
g.LastItemData.Rect;
21493 if (IsItemHovered())
21494 for (
const char* p = line_begin; p <= line_end - 10; p++)
21497 if (p[0] !=
'0' || (p[1] !=
'x' && p[1] !=
'X') || sscanf(p + 2,
"%X", &
id) != 1)
21501 g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0f), text_rect.Min + ImVec2(p0.x + p1.x, p1.y));
21502 if (IsMouseHoveringRect(
g.LastItemData.Rect.Min,
g.LastItemData.Rect.Max,
true))
21503 DebugLocateItemOnHover(
id);
21507 g.DebugLogFlags = backup_log_flags;
21508 if (GetScrollY() >= GetScrollMaxY())
21509 SetScrollHereY(1.0f);
21520void ImGui::DebugDrawCursorPos(ImU32 col)
21523 ImGuiWindow* window =
g.CurrentWindow;
21524 ImVec2 pos = window->DC.CursorPos;
21525 window->DrawList->AddLine(ImVec2(pos.x, pos.y - 3.0f), ImVec2(pos.x, pos.y + 4.0f), col, 1.0f);
21526 window->DrawList->AddLine(ImVec2(pos.x - 3.0f, pos.y), ImVec2(pos.x + 4.0f, pos.y), col, 1.0f);
21530void ImGui::DebugDrawLineExtents(ImU32 col)
21533 ImGuiWindow* window =
g.CurrentWindow;
21534 float curr_x = window->DC.CursorPos.x;
21535 float line_y1 = (window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y);
21536 float line_y2 = line_y1 + (window->DC.IsSameLine ? window->DC.PrevLineSize.y : window->DC.CurrLineSize.y);
21537 window->DrawList->AddLine(ImVec2(curr_x - 5.0f, line_y1), ImVec2(curr_x + 5.0f, line_y1), col, 1.0f);
21538 window->DrawList->AddLine(ImVec2(curr_x - 0.5f, line_y1), ImVec2(curr_x - 0.5f, line_y2), col, 1.0f);
21539 window->DrawList->AddLine(ImVec2(curr_x - 5.0f, line_y2), ImVec2(curr_x + 5.0f, line_y2), col, 1.0f);
21543void ImGui::DebugDrawItemRect(ImU32 col)
21546 ImGuiWindow* window =
g.CurrentWindow;
21547 GetForegroundDrawList(window)->AddRect(
g.LastItemData.Rect.Min,
g.LastItemData.Rect.Max, col);
21551static const ImU32 DEBUG_LOCATE_ITEM_COLOR = IM_COL32(0, 255, 0, 255);
21553void ImGui::DebugLocateItem(ImGuiID target_id)
21556 g.DebugLocateId = target_id;
21557 g.DebugLocateFrames = 2;
21558 g.DebugBreakInLocateId =
false;
21562void ImGui::DebugLocateItemOnHover(ImGuiID target_id)
21564 if (target_id == 0 || !IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenBlockedByPopup))
21567 DebugLocateItem(target_id);
21568 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);
21571 if (
g.IO.ConfigDebugIsDebuggerPresent &&
g.MouseStationaryTimer > 1.0f)
21573 DebugBreakButtonTooltip(
false,
"in ItemAdd()");
21574 if (IsKeyChordPressed(
g.DebugBreakKeyChord))
21575 g.DebugBreakInLocateId =
true;
21579void ImGui::DebugLocateItemResolveWithLastItem()
21584 if (
g.DebugBreakInLocateId)
21587 ImGuiLastItemData item_data =
g.LastItemData;
21588 g.DebugLocateId = 0;
21589 ImDrawList* draw_list = GetForegroundDrawList(
g.CurrentWindow);
21590 ImRect r = item_data.Rect;
21592 ImVec2 p1 =
g.IO.MousePos;
21593 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);
21594 draw_list->AddRect(r.Min, r.Max, DEBUG_LOCATE_ITEM_COLOR);
21595 draw_list->AddLine(p1, p2, DEBUG_LOCATE_ITEM_COLOR);
21598void ImGui::DebugStartItemPicker()
21601 g.DebugItemPickerActive =
true;
21605void ImGui::UpdateDebugToolItemPicker()
21608 g.DebugItemPickerBreakId = 0;
21609 if (!
g.DebugItemPickerActive)
21612 const ImGuiID hovered_id =
g.HoveredIdPreviousFrame;
21613 SetMouseCursor(ImGuiMouseCursor_Hand);
21614 if (IsKeyPressed(ImGuiKey_Escape))
21615 g.DebugItemPickerActive =
false;
21616 const bool change_mapping =
g.IO.KeyMods == (ImGuiMod_Ctrl | ImGuiMod_Shift);
21617 if (!change_mapping && IsMouseClicked(
g.DebugItemPickerMouseButton) && hovered_id)
21619 g.DebugItemPickerBreakId = hovered_id;
21620 g.DebugItemPickerActive =
false;
21622 for (
int mouse_button = 0; mouse_button < 3; mouse_button++)
21623 if (change_mapping && IsMouseClicked(mouse_button))
21624 g.DebugItemPickerMouseButton = (ImU8)mouse_button;
21625 SetNextWindowBgAlpha(0.70f);
21626 if (!BeginTooltip())
21628 Text(
"HoveredId: 0x%08X", hovered_id);
21629 Text(
"Press ESC to abort picking.");
21630 const char* mouse_button_names[] = {
"Left",
"Right",
"Middle" };
21631 if (change_mapping)
21632 Text(
"Remap w/ Ctrl+Shift: click anywhere to select new mouse button.");
21634 TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled),
"Click %s Button to break in debugger! (remap w/ Ctrl+Shift)", mouse_button_names[
g.DebugItemPickerMouseButton]);
21639void ImGui::UpdateDebugToolStackQueries()
21642 ImGuiIDStackTool* tool = &
g.DebugIDStackTool;
21645 g.DebugHookIdInfo = 0;
21646 if (
g.FrameCount != tool->LastActiveFrame + 1)
21651 const ImGuiID query_id =
g.HoveredIdPreviousFrame ?
g.HoveredIdPreviousFrame :
g.ActiveId;
21652 if (tool->QueryId != query_id)
21654 tool->QueryId = query_id;
21655 tool->StackLevel = -1;
21656 tool->Results.resize(0);
21662 int stack_level = tool->StackLevel;
21663 if (stack_level >= 0 && stack_level < tool->Results.Size)
21664 if (tool->Results[stack_level].QuerySuccess || tool->Results[stack_level].QueryFrameCount > 2)
21665 tool->StackLevel++;
21668 stack_level = tool->StackLevel;
21669 if (stack_level == -1)
21670 g.DebugHookIdInfo = query_id;
21671 if (stack_level >= 0 && stack_level < tool->Results.Size)
21673 g.DebugHookIdInfo = tool->Results[stack_level].ID;
21674 tool->Results[stack_level].QueryFrameCount++;
21679void ImGui::DebugHookIdInfo(ImGuiID
id, ImGuiDataType data_type,
const void* data_id,
const void* data_id_end)
21682 ImGuiWindow* window =
g.CurrentWindow;
21683 ImGuiIDStackTool* tool = &
g.DebugIDStackTool;
21687 if (tool->StackLevel == -1)
21689 tool->StackLevel++;
21690 tool->Results.resize(window->IDStack.Size + 1, ImGuiStackLevelInfo());
21691 for (
int n = 0; n < window->IDStack.Size + 1; n++)
21692 tool->Results[n].ID = (n < window->IDStack.Size) ? window->IDStack[n] :
id;
21697 IM_ASSERT(tool->StackLevel >= 0);
21698 if (tool->StackLevel != window->IDStack.Size)
21700 ImGuiStackLevelInfo* info = &tool->Results[tool->StackLevel];
21701 IM_ASSERT(info->ID ==
id && info->QueryFrameCount > 0);
21705 case ImGuiDataType_S32:
21706 ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc),
"%d", (
int)(intptr_t)data_id);
21708 case ImGuiDataType_String:
21709 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);
21711 case ImGuiDataType_Pointer:
21712 ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc),
"(void*)0x%p", data_id);
21714 case ImGuiDataType_ID:
21715 if (info->Desc[0] != 0)
21717 ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc),
"0x%08X [override]",
id);
21722 info->QuerySuccess =
true;
21723 info->DataType = data_type;
21726static int StackToolFormatLevelInfo(ImGuiIDStackTool* tool,
int n,
bool format_for_ui,
char* buf,
size_t buf_size)
21728 ImGuiStackLevelInfo* info = &tool->Results[n];
21729 ImGuiWindow* window = (info->Desc[0] == 0 && n == 0) ? ImGui::FindWindowByID(info->ID) : NULL;
21731 return ImFormatString(buf, buf_size, format_for_ui ?
"\"%s\" [window]" :
"%s", window->Name);
21732 if (info->QuerySuccess)
21733 return ImFormatString(buf, buf_size, (format_for_ui && info->DataType == ImGuiDataType_String) ?
"\"%s\"" :
"%s", info->Desc);
21734 if (tool->StackLevel < tool->Results.Size)
21736#ifdef IMGUI_ENABLE_TEST_ENGINE
21737 if (
const char* label = ImGuiTestEngine_FindItemDebugLabel(
GImGui, info->ID))
21738 return ImFormatString(buf, buf_size, format_for_ui ?
"??? \"%s\"" :
"%s", label);
21744void ImGui::ShowIDStackToolWindow(
bool* p_open)
21747 if (!(
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize))
21748 SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 8.0f), ImGuiCond_FirstUseEver);
21749 if (!Begin(
"Dear ImGui ID Stack Tool", p_open) || GetCurrentWindow()->BeginCount > 1)
21756 ImGuiIDStackTool* tool = &
g.DebugIDStackTool;
21757 const ImGuiID hovered_id =
g.HoveredIdPreviousFrame;
21758 const ImGuiID active_id =
g.ActiveId;
21759#ifdef IMGUI_ENABLE_TEST_ENGINE
21760 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) :
"");
21762 Text(
"HoveredId: 0x%08X, ActiveId: 0x%08X", hovered_id, active_id);
21765 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.");
21768 const float time_since_copy = (float)
g.Time - tool->CopyToClipboardLastTime;
21769 Checkbox(
"Ctrl+C: copy path to clipboard", &tool->CopyToClipboardOnCtrlC);
21771 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*");
21772 if (tool->CopyToClipboardOnCtrlC && Shortcut(ImGuiMod_Ctrl | ImGuiKey_C, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused))
21774 tool->CopyToClipboardLastTime = (float)
g.Time;
21775 char* p =
g.TempBuffer.Data;
21776 char* p_end = p +
g.TempBuffer.Size;
21777 for (
int stack_n = 0; stack_n < tool->Results.Size && p + 3 < p_end; stack_n++)
21780 char level_desc[256];
21781 StackToolFormatLevelInfo(tool, stack_n,
false, level_desc, IM_ARRAYSIZE(level_desc));
21782 for (
int n = 0; level_desc[n] && p + 2 < p_end; n++)
21784 if (level_desc[n] ==
'/')
21786 *p++ = level_desc[n];
21790 SetClipboardText(
g.TempBuffer.Data);
21794 tool->LastActiveFrame =
g.FrameCount;
21795 if (tool->Results.Size > 0 && BeginTable(
"##table", 3, ImGuiTableFlags_Borders))
21798 TableSetupColumn(
"Seed", ImGuiTableColumnFlags_WidthFixed, id_width);
21799 TableSetupColumn(
"PushID", ImGuiTableColumnFlags_WidthStretch);
21800 TableSetupColumn(
"Result", ImGuiTableColumnFlags_WidthFixed, id_width);
21802 for (
int n = 0; n < tool->Results.Size; n++)
21804 ImGuiStackLevelInfo* info = &tool->Results[n];
21806 Text(
"0x%08X", (n > 0) ? tool->Results[n - 1].ID : 0);
21808 StackToolFormatLevelInfo(tool, n,
true,
g.TempBuffer.Data,
g.TempBuffer.Size);
21811 Text(
"0x%08X", info->ID);
21812 if (n == tool->Results.Size - 1)
21813 TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_Header));
21822void ImGui::ShowMetricsWindow(
bool*) {}
21824void ImGui::DebugNodeColumns(ImGuiOldColumns*) {}
21825void ImGui::DebugNodeDrawList(ImGuiWindow*, ImGuiViewportP*,
const ImDrawList*,
const char*) {}
21826void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList*,
const ImDrawList*,
const ImDrawCmd*,
bool,
bool) {}
21827void ImGui::DebugNodeFont(ImFont*) {}
21828void ImGui::DebugNodeStorage(ImGuiStorage*,
const char*) {}
21829void ImGui::DebugNodeTabBar(ImGuiTabBar*,
const char*) {}
21830void ImGui::DebugNodeWindow(ImGuiWindow*,
const char*) {}
21831void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings*) {}
21832void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>*,
const char*) {}
21833void ImGui::DebugNodeViewport(ImGuiViewportP*) {}
21835void ImGui::DebugLog(
const char*, ...) {}
21836void ImGui::DebugLogV(
const char*, va_list) {}
21837void ImGui::ShowDebugLogWindow(
bool*) {}
21838void ImGui::ShowIDStackToolWindow(
bool*) {}
21839void ImGui::DebugStartItemPicker() {}
21840void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType,
const void*,
const void*) {}
21848#ifdef IMGUI_INCLUDE_IMGUI_USER_INL
21849#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)
#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)
const ImWchar * ImStrbolW(const ImWchar *buf_mid_line, const ImWchar *buf_begin)
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)
ALWAYS_INLINE unsigned count(const uint8_t *pIn, const uint8_t *pMatch, const uint8_t *pInLimit)
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 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)
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.