964#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
965#define _CRT_SECURE_NO_WARNINGS
968#ifndef IMGUI_DEFINE_MATH_OPERATORS
969#define IMGUI_DEFINE_MATH_OPERATORS
974#include "imgui_internal.h"
981#if defined(_WIN32) && !defined(_MSC_VER) && !defined(IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
982#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
986#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)
987#define IMGUI_DISABLE_WIN32_FUNCTIONS
989#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
990#ifndef WIN32_LEAN_AND_MEAN
991#define WIN32_LEAN_AND_MEAN
1001#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
1002#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
1003#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
1008#if defined(__APPLE__)
1009#include <TargetConditionals.h>
1014#pragma warning (disable: 4127)
1015#pragma warning (disable: 4996)
1016#if defined(_MSC_VER) && _MSC_VER >= 1922
1017#pragma warning (disable: 5054)
1019#pragma warning (disable: 26451)
1020#pragma warning (disable: 26495)
1021#pragma warning (disable: 26812)
1025#if defined(__clang__)
1026#if __has_warning("-Wunknown-warning-option")
1027#pragma clang diagnostic ignored "-Wunknown-warning-option"
1029#pragma clang diagnostic ignored "-Wunknown-pragmas"
1030#pragma clang diagnostic ignored "-Wold-style-cast"
1031#pragma clang diagnostic ignored "-Wfloat-equal"
1032#pragma clang diagnostic ignored "-Wformat-nonliteral"
1033#pragma clang diagnostic ignored "-Wexit-time-destructors"
1034#pragma clang diagnostic ignored "-Wglobal-constructors"
1035#pragma clang diagnostic ignored "-Wsign-conversion"
1036#pragma clang diagnostic ignored "-Wformat-pedantic"
1037#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"
1038#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
1039#pragma clang diagnostic ignored "-Wdouble-promotion"
1040#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
1041#elif defined(__GNUC__)
1043#pragma GCC diagnostic ignored "-Wpragmas"
1044#pragma GCC diagnostic ignored "-Wunused-function"
1045#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
1046#pragma GCC diagnostic ignored "-Wformat"
1047#pragma GCC diagnostic ignored "-Wdouble-promotion"
1048#pragma GCC diagnostic ignored "-Wconversion"
1049#pragma GCC diagnostic ignored "-Wformat-nonliteral"
1050#pragma GCC diagnostic ignored "-Wstrict-overflow"
1051#pragma GCC diagnostic ignored "-Wclass-memaccess"
1055#define IMGUI_DEBUG_NAV_SCORING 0
1056#define IMGUI_DEBUG_NAV_RECTS 0
1059static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f;
1060static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f;
1062static const float NAV_ACTIVATE_HIGHLIGHT_TIMER = 0.10f;
1065static const float WINDOWS_HOVER_PADDING = 4.0f;
1066static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f;
1067static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 0.70f;
1070static const ImVec2 TOOLTIP_DEFAULT_OFFSET = ImVec2(16, 10);
1073static const float DOCKING_TRANSPARENT_PAYLOAD_ALPHA = 0.50f;
1079static void SetCurrentWindow(ImGuiWindow* window);
1080static void FindHoveredWindow();
1081static ImGuiWindow* CreateNewWindow(
const char* name, ImGuiWindowFlags flags);
1082static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window);
1084static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
1087static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*);
1088static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*,
const char* name);
1089static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
void* entry,
const char* line);
1090static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*);
1091static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf);
1094static const char* GetClipboardTextFn_DefaultImpl(
void* user_data_ctx);
1095static void SetClipboardTextFn_DefaultImpl(
void* user_data_ctx,
const char* text);
1096static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatformImeData* data);
1101static void NavUpdate();
1102static void NavUpdateWindowing();
1103static void NavUpdateWindowingOverlay();
1104static void NavUpdateCancelRequest();
1105static void NavUpdateCreateMoveRequest();
1106static void NavUpdateCreateTabbingRequest();
1107static float NavUpdatePageUpPageDown();
1108static inline void NavUpdateAnyRequestFlag();
1109static void NavUpdateCreateWrappingRequest();
1110static void NavEndFrame();
1111static bool NavScoreItem(ImGuiNavItemData* result);
1112static void NavApplyItemToResult(ImGuiNavItemData* result);
1113static void NavProcessItem();
1114static void NavProcessItemForTabbingRequest(ImGuiID
id, ImGuiItemFlags item_flags, ImGuiNavMoveFlags move_flags);
1115static ImVec2 NavCalcPreferredRefPos();
1116static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
1117static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
1118static void NavRestoreLayer(ImGuiNavLayer layer);
1119static int FindWindowFocusIndex(ImGuiWindow* window);
1122static void ErrorCheckNewFrameSanityChecks();
1123static void ErrorCheckEndFrameSanityChecks();
1124static void UpdateDebugToolItemPicker();
1125static void UpdateDebugToolStackQueries();
1126static void UpdateDebugToolFlashStyleColor();
1129static void UpdateKeyboardInputs();
1130static void UpdateMouseInputs();
1131static void UpdateMouseWheel();
1132static void UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt);
1135static void UpdateSettings();
1136static 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);
1137static void RenderWindowOuterBorders(ImGuiWindow* window);
1138static 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);
1139static void RenderWindowTitleBarContents(ImGuiWindow* window,
const ImRect& title_bar_rect,
const char* name,
bool* p_open);
1140static void RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col);
1141static void RenderDimmedBackgrounds();
1145static ImGuiViewportP* AddUpdateViewport(ImGuiWindow* window, ImGuiID
id,
const ImVec2& platform_pos,
const ImVec2& size, ImGuiViewportFlags flags);
1146static void DestroyViewport(ImGuiViewportP* viewport);
1147static void UpdateViewportsNewFrame();
1148static void UpdateViewportsEndFrame();
1149static void WindowSelectViewport(ImGuiWindow* window);
1150static void WindowSyncOwnedViewport(ImGuiWindow* window, ImGuiWindow* parent_window_in_stack);
1151static bool UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* host_viewport);
1152static bool UpdateTryMergeWindowIntoHostViewports(ImGuiWindow* window);
1153static bool GetWindowAlwaysWantOwnViewport(ImGuiWindow* window);
1154static int FindPlatformMonitorForPos(
const ImVec2& pos);
1155static int FindPlatformMonitorForRect(
const ImRect& r);
1156static void UpdateViewportPlatformMonitor(ImGuiViewportP* viewport);
1191#ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS
1192static void* MallocWrapper(
size_t size,
void* user_data) { IM_UNUSED(user_data);
return malloc(size); }
1193static void FreeWrapper(
void* ptr,
void* user_data) { IM_UNUSED(user_data); free(ptr); }
1195static void* MallocWrapper(
size_t size,
void* user_data) { IM_UNUSED(user_data); IM_UNUSED(size); IM_ASSERT(0);
return NULL; }
1196static void FreeWrapper(
void* ptr,
void* user_data) { IM_UNUSED(user_data); IM_UNUSED(ptr); IM_ASSERT(0); }
1198static ImGuiMemAllocFunc GImAllocatorAllocFunc = MallocWrapper;
1199static ImGuiMemFreeFunc GImAllocatorFreeFunc = FreeWrapper;
1200static void* GImAllocatorUserData = NULL;
1206ImGuiStyle::ImGuiStyle()
1209 DisabledAlpha = 0.60f;
1210 WindowPadding = ImVec2(8,8);
1211 WindowRounding = 0.0f;
1212 WindowBorderSize = 1.0f;
1213 WindowMinSize = ImVec2(32,32);
1214 WindowTitleAlign = ImVec2(0.0f,0.5f);
1215 WindowMenuButtonPosition= ImGuiDir_Left;
1216 ChildRounding = 0.0f;
1217 ChildBorderSize = 1.0f;
1218 PopupRounding = 0.0f;
1219 PopupBorderSize = 1.0f;
1220 FramePadding = ImVec2(4,3);
1221 FrameRounding = 0.0f;
1222 FrameBorderSize = 0.0f;
1223 ItemSpacing = ImVec2(8,4);
1224 ItemInnerSpacing = ImVec2(4,4);
1225 CellPadding = ImVec2(4,2);
1226 TouchExtraPadding = ImVec2(0,0);
1227 IndentSpacing = 21.0f;
1228 ColumnsMinSpacing = 6.0f;
1229 ScrollbarSize = 14.0f;
1230 ScrollbarRounding = 9.0f;
1231 GrabMinSize = 12.0f;
1232 GrabRounding = 0.0f;
1233 LogSliderDeadzone = 4.0f;
1235 TabBorderSize = 0.0f;
1236 TabMinWidthForCloseButton = 0.0f;
1237 TabBarBorderSize = 1.0f;
1238 TableAngledHeadersAngle = 35.0f * (IM_PI / 180.0f);
1239 ColorButtonPosition = ImGuiDir_Right;
1240 ButtonTextAlign = ImVec2(0.5f,0.5f);
1241 SelectableTextAlign = ImVec2(0.0f,0.0f);
1242 SeparatorTextBorderSize = 3.0f;
1243 SeparatorTextAlign = ImVec2(0.0f,0.5f);
1244 SeparatorTextPadding = ImVec2(20.0f,3.f);
1245 DisplayWindowPadding = ImVec2(19,19);
1246 DisplaySafeAreaPadding = ImVec2(3,3);
1247 DockingSeparatorSize = 2.0f;
1248 MouseCursorScale = 1.0f;
1249 AntiAliasedLines =
true;
1250 AntiAliasedLinesUseTex =
true;
1251 AntiAliasedFill =
true;
1252 CurveTessellationTol = 1.25f;
1253 CircleTessellationMaxError = 0.30f;
1256 HoverStationaryDelay = 0.15f;
1257 HoverDelayShort = 0.15f;
1258 HoverDelayNormal = 0.40f;
1259 HoverFlagsForTooltipMouse = ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_AllowWhenDisabled;
1260 HoverFlagsForTooltipNav = ImGuiHoveredFlags_NoSharedDelay | ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_AllowWhenDisabled;
1263 ImGui::StyleColorsDark(
this);
1268void ImGuiStyle::ScaleAllSizes(
float scale_factor)
1270 WindowPadding = ImTrunc(WindowPadding * scale_factor);
1271 WindowRounding = ImTrunc(WindowRounding * scale_factor);
1272 WindowMinSize = ImTrunc(WindowMinSize * scale_factor);
1273 ChildRounding = ImTrunc(ChildRounding * scale_factor);
1274 PopupRounding = ImTrunc(PopupRounding * scale_factor);
1275 FramePadding = ImTrunc(FramePadding * scale_factor);
1276 FrameRounding = ImTrunc(FrameRounding * scale_factor);
1277 ItemSpacing = ImTrunc(ItemSpacing * scale_factor);
1278 ItemInnerSpacing = ImTrunc(ItemInnerSpacing * scale_factor);
1279 CellPadding = ImTrunc(CellPadding * scale_factor);
1280 TouchExtraPadding = ImTrunc(TouchExtraPadding * scale_factor);
1281 IndentSpacing = ImTrunc(IndentSpacing * scale_factor);
1282 ColumnsMinSpacing = ImTrunc(ColumnsMinSpacing * scale_factor);
1283 ScrollbarSize = ImTrunc(ScrollbarSize * scale_factor);
1284 ScrollbarRounding = ImTrunc(ScrollbarRounding * scale_factor);
1285 GrabMinSize = ImTrunc(GrabMinSize * scale_factor);
1286 GrabRounding = ImTrunc(GrabRounding * scale_factor);
1287 LogSliderDeadzone = ImTrunc(LogSliderDeadzone * scale_factor);
1288 TabRounding = ImTrunc(TabRounding * scale_factor);
1289 TabMinWidthForCloseButton = (TabMinWidthForCloseButton != FLT_MAX) ? ImTrunc(TabMinWidthForCloseButton * scale_factor) : FLT_MAX;
1290 SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor);
1291 DockingSeparatorSize = ImTrunc(DockingSeparatorSize * scale_factor);
1292 DisplayWindowPadding = ImTrunc(DisplayWindowPadding * scale_factor);
1293 DisplaySafeAreaPadding = ImTrunc(DisplaySafeAreaPadding * scale_factor);
1294 MouseCursorScale = ImTrunc(MouseCursorScale * scale_factor);
1300 memset(
this, 0,
sizeof(*
this));
1301 IM_STATIC_ASSERT(IM_ARRAYSIZE(ImGuiIO::MouseDown) == ImGuiMouseButton_COUNT && IM_ARRAYSIZE(ImGuiIO::MouseClicked) == ImGuiMouseButton_COUNT);
1304 ConfigFlags = ImGuiConfigFlags_None;
1305 BackendFlags = ImGuiBackendFlags_None;
1306 DisplaySize = ImVec2(-1.0f, -1.0f);
1307 DeltaTime = 1.0f / 60.0f;
1308 IniSavingRate = 5.0f;
1309 IniFilename =
"imgui.ini";
1310 LogFilename =
"imgui_log.txt";
1311#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
1312 for (
int i = 0; i < ImGuiKey_COUNT; i++)
1318 FontGlobalScale = 1.0f;
1320 FontAllowUserScaling =
false;
1321 DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
1324 ConfigDockingNoSplit =
false;
1325 ConfigDockingWithShift =
false;
1326 ConfigDockingAlwaysTabBar =
false;
1327 ConfigDockingTransparentPayload =
false;
1330 ConfigViewportsNoAutoMerge =
false;
1331 ConfigViewportsNoTaskBarIcon =
false;
1332 ConfigViewportsNoDecoration =
true;
1333 ConfigViewportsNoDefaultParent =
false;
1336 MouseDrawCursor =
false;
1338 ConfigMacOSXBehaviors =
true;
1340 ConfigMacOSXBehaviors =
false;
1342 ConfigInputTrickleEventQueue =
true;
1343 ConfigInputTextCursorBlink =
true;
1344 ConfigInputTextEnterKeepActive =
false;
1345 ConfigDragClickToInputText =
false;
1346 ConfigWindowsResizeFromEdges =
true;
1347 ConfigWindowsMoveFromTitleBarOnly =
false;
1348 ConfigMemoryCompactTimer = 60.0f;
1349 ConfigDebugBeginReturnValueOnce =
false;
1350 ConfigDebugBeginReturnValueLoop =
false;
1353 MouseDoubleClickTime = 0.30f;
1354 MouseDoubleClickMaxDist = 6.0f;
1355 MouseDragThreshold = 6.0f;
1356 KeyRepeatDelay = 0.275f;
1357 KeyRepeatRate = 0.050f;
1361 BackendPlatformName = BackendRendererName = NULL;
1362 BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL;
1363 PlatformLocaleDecimalPoint =
'.';
1366 MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
1367 MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX);
1368 MouseSource = ImGuiMouseSource_Mouse;
1369 for (
int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
1370 for (
int i = 0; i < IM_ARRAYSIZE(KeysData); i++) { KeysData[i].DownDuration = KeysData[i].DownDurationPrev = -1.0f; }
1371 AppAcceptingEvents =
true;
1372 BackendUsingLegacyKeyArrays = (ImS8)-1;
1373 BackendUsingLegacyNavInputArray =
true;
1380void ImGuiIO::AddInputCharacter(
unsigned int c)
1382 IM_ASSERT(Ctx != NULL);
1383 ImGuiContext&
g = *Ctx;
1384 if (c == 0 || !AppAcceptingEvents)
1388 e.Type = ImGuiInputEventType_Text;
1389 e.Source = ImGuiInputSource_Keyboard;
1390 e.EventId =
g.InputEventsNextEventId++;
1392 g.InputEventsQueue.push_back(e);
1397void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c)
1399 if ((c == 0 && InputQueueSurrogate == 0) || !AppAcceptingEvents)
1402 if ((c & 0xFC00) == 0xD800)
1404 if (InputQueueSurrogate != 0)
1405 AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID);
1406 InputQueueSurrogate = c;
1411 if (InputQueueSurrogate != 0)
1413 if ((c & 0xFC00) != 0xDC00)
1415 AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID);
1419#if IM_UNICODE_CODEPOINT_MAX == 0xFFFF
1420 cp = IM_UNICODE_CODEPOINT_INVALID;
1422 cp = (ImWchar)(((InputQueueSurrogate - 0xD800) << 10) + (c - 0xDC00) + 0x10000);
1426 InputQueueSurrogate = 0;
1428 AddInputCharacter((
unsigned)cp);
1431void ImGuiIO::AddInputCharactersUTF8(
const char* utf8_chars)
1433 if (!AppAcceptingEvents)
1435 while (*utf8_chars != 0)
1439 AddInputCharacter(c);
1444void ImGuiIO::ClearEventsQueue()
1446 IM_ASSERT(Ctx != NULL);
1447 ImGuiContext&
g = *Ctx;
1448 g.InputEventsQueue.clear();
1452void ImGuiIO::ClearInputKeys()
1454#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
1455 memset(KeysDown, 0,
sizeof(KeysDown));
1457 for (
int n = 0; n < IM_ARRAYSIZE(KeysData); n++)
1459 KeysData[n].Down =
false;
1460 KeysData[n].DownDuration = -1.0f;
1461 KeysData[n].DownDurationPrev = -1.0f;
1463 KeyCtrl = KeyShift = KeyAlt = KeySuper =
false;
1464 KeyMods = ImGuiMod_None;
1465 MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
1466 for (
int n = 0; n < IM_ARRAYSIZE(MouseDown); n++)
1468 MouseDown[n] =
false;
1469 MouseDownDuration[n] = MouseDownDurationPrev[n] = -1.0f;
1471 MouseWheel = MouseWheelH = 0.0f;
1472 InputQueueCharacters.resize(0);
1477#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
1478void ImGuiIO::ClearInputCharacters()
1480 InputQueueCharacters.resize(0);
1484static ImGuiInputEvent* FindLatestInputEvent(ImGuiContext* ctx, ImGuiInputEventType type,
int arg = -1)
1486 ImGuiContext&
g = *ctx;
1487 for (
int n =
g.InputEventsQueue.Size - 1; n >= 0; n--)
1489 ImGuiInputEvent*
e = &
g.InputEventsQueue[n];
1490 if (
e->Type != type)
1492 if (type == ImGuiInputEventType_Key &&
e->Key.Key != arg)
1494 if (type == ImGuiInputEventType_MouseButton &&
e->MouseButton.Button != arg)
1507void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key,
bool down,
float analog_value)
1510 IM_ASSERT(Ctx != NULL);
1511 if (key == ImGuiKey_None || !AppAcceptingEvents)
1513 ImGuiContext&
g = *Ctx;
1514 IM_ASSERT(ImGui::IsNamedKeyOrModKey(key));
1515 IM_ASSERT(ImGui::IsAliasKey(key) ==
false);
1516 IM_ASSERT(key != ImGuiMod_Shortcut);
1519#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
1520 IM_ASSERT((BackendUsingLegacyKeyArrays == -1 || BackendUsingLegacyKeyArrays == 0) &&
"Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
1521 if (BackendUsingLegacyKeyArrays == -1)
1522 for (
int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++)
1523 IM_ASSERT(KeyMap[n] == -1 &&
"Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
1524 BackendUsingLegacyKeyArrays = 0;
1526 if (ImGui::IsGamepadKey(key))
1527 BackendUsingLegacyNavInputArray =
false;
1530 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_Key, (
int)key);
1531 const ImGuiKeyData* key_data = ImGui::GetKeyData(&
g, key);
1532 const bool latest_key_down = latest_event ? latest_event->Key.Down : key_data->Down;
1533 const float latest_key_analog = latest_event ? latest_event->Key.AnalogValue : key_data->AnalogValue;
1534 if (latest_key_down == down && latest_key_analog == analog_value)
1539 e.Type = ImGuiInputEventType_Key;
1540 e.Source = ImGui::IsGamepadKey(key) ? ImGuiInputSource_Gamepad : ImGuiInputSource_Keyboard;
1541 e.EventId =
g.InputEventsNextEventId++;
1544 e.Key.AnalogValue = analog_value;
1545 g.InputEventsQueue.push_back(e);
1548void ImGuiIO::AddKeyEvent(ImGuiKey key,
bool down)
1550 if (!AppAcceptingEvents)
1552 AddKeyAnalogEvent(key, down, down ? 1.0f : 0.0f);
1558void ImGuiIO::SetKeyEventNativeData(ImGuiKey key,
int native_keycode,
int native_scancode,
int native_legacy_index)
1560 if (key == ImGuiKey_None)
1562 IM_ASSERT(ImGui::IsNamedKey(key));
1563 IM_ASSERT(native_legacy_index == -1 || ImGui::IsLegacyKey((ImGuiKey)native_legacy_index));
1564 IM_UNUSED(native_keycode);
1565 IM_UNUSED(native_scancode);
1568#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
1569 const int legacy_key = (native_legacy_index != -1) ? native_legacy_index : native_keycode;
1570 if (!ImGui::IsLegacyKey((ImGuiKey)legacy_key))
1572 KeyMap[legacy_key] = key;
1573 KeyMap[key] = legacy_key;
1576 IM_UNUSED(native_legacy_index);
1581void ImGuiIO::SetAppAcceptingEvents(
bool accepting_events)
1583 AppAcceptingEvents = accepting_events;
1587void ImGuiIO::AddMousePosEvent(
float x,
float y)
1589 IM_ASSERT(Ctx != NULL);
1590 ImGuiContext&
g = *Ctx;
1591 if (!AppAcceptingEvents)
1595 ImVec2 pos((x > -FLT_MAX) ? ImFloor(x) : x, (y > -FLT_MAX) ? ImFloor(y) : y);
1598 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_MousePos);
1599 const ImVec2 latest_pos = latest_event ? ImVec2(latest_event->MousePos.PosX, latest_event->MousePos.PosY) :
g.IO.MousePos;
1600 if (latest_pos.x == pos.x && latest_pos.y == pos.y)
1604 e.Type = ImGuiInputEventType_MousePos;
1605 e.Source = ImGuiInputSource_Mouse;
1606 e.EventId =
g.InputEventsNextEventId++;
1607 e.MousePos.PosX = pos.x;
1608 e.MousePos.PosY = pos.y;
1609 e.MousePos.MouseSource =
g.InputEventsNextMouseSource;
1610 g.InputEventsQueue.push_back(e);
1613void ImGuiIO::AddMouseButtonEvent(
int mouse_button,
bool down)
1615 IM_ASSERT(Ctx != NULL);
1616 ImGuiContext&
g = *Ctx;
1617 IM_ASSERT(mouse_button >= 0 && mouse_button < ImGuiMouseButton_COUNT);
1618 if (!AppAcceptingEvents)
1622 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_MouseButton, (
int)mouse_button);
1623 const bool latest_button_down = latest_event ? latest_event->MouseButton.Down :
g.IO.MouseDown[mouse_button];
1624 if (latest_button_down == down)
1628 e.Type = ImGuiInputEventType_MouseButton;
1629 e.Source = ImGuiInputSource_Mouse;
1630 e.EventId =
g.InputEventsNextEventId++;
1631 e.MouseButton.Button = mouse_button;
1632 e.MouseButton.Down = down;
1633 e.MouseButton.MouseSource =
g.InputEventsNextMouseSource;
1634 g.InputEventsQueue.push_back(e);
1638void ImGuiIO::AddMouseWheelEvent(
float wheel_x,
float wheel_y)
1640 IM_ASSERT(Ctx != NULL);
1641 ImGuiContext&
g = *Ctx;
1644 if (!AppAcceptingEvents || (wheel_x == 0.0f && wheel_y == 0.0f))
1648 e.Type = ImGuiInputEventType_MouseWheel;
1649 e.Source = ImGuiInputSource_Mouse;
1650 e.EventId =
g.InputEventsNextEventId++;
1651 e.MouseWheel.WheelX = wheel_x;
1652 e.MouseWheel.WheelY = wheel_y;
1653 e.MouseWheel.MouseSource =
g.InputEventsNextMouseSource;
1654 g.InputEventsQueue.push_back(e);
1659void ImGuiIO::AddMouseSourceEvent(ImGuiMouseSource source)
1661 IM_ASSERT(Ctx != NULL);
1662 ImGuiContext&
g = *Ctx;
1663 g.InputEventsNextMouseSource = source;
1666void ImGuiIO::AddMouseViewportEvent(ImGuiID viewport_id)
1668 IM_ASSERT(Ctx != NULL);
1669 ImGuiContext&
g = *Ctx;
1671 if (!AppAcceptingEvents)
1675 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_MouseViewport);
1676 const ImGuiID latest_viewport_id = latest_event ? latest_event->MouseViewport.HoveredViewportID :
g.IO.MouseHoveredViewport;
1677 if (latest_viewport_id == viewport_id)
1681 e.Type = ImGuiInputEventType_MouseViewport;
1682 e.Source = ImGuiInputSource_Mouse;
1683 e.MouseViewport.HoveredViewportID = viewport_id;
1684 g.InputEventsQueue.push_back(e);
1687void ImGuiIO::AddFocusEvent(
bool focused)
1689 IM_ASSERT(Ctx != NULL);
1690 ImGuiContext&
g = *Ctx;
1693 const ImGuiInputEvent* latest_event = FindLatestInputEvent(&
g, ImGuiInputEventType_Focus);
1694 const bool latest_focused = latest_event ? latest_event->AppFocused.Focused : !
g.IO.AppFocusLost;
1695 if (latest_focused == focused || (ConfigDebugIgnoreFocusLoss && !focused))
1699 e.Type = ImGuiInputEventType_Focus;
1700 e.EventId =
g.InputEventsNextEventId++;
1701 e.AppFocused.Focused = focused;
1702 g.InputEventsQueue.push_back(e);
1711 IM_ASSERT(num_segments > 0);
1714 float p_closest_dist2 = FLT_MAX;
1715 float t_step = 1.0f / (float)num_segments;
1716 for (
int i_step = 1; i_step <= num_segments; i_step++)
1720 float dist2 = ImLengthSqr(p - p_line);
1721 if (dist2 < p_closest_dist2)
1724 p_closest_dist2 = dist2;
1732static 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)
1736 float d2 = ((x2 - x4) * dy - (y2 - y4) * dx);
1737 float d3 = ((x3 - x4) * dy - (y3 - y4) * dx);
1738 d2 = (d2 >= 0) ? d2 : -d2;
1739 d3 = (d3 >= 0) ? d3 : -d3;
1740 if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy))
1742 ImVec2 p_current(x4, y4);
1744 float dist2 = ImLengthSqr(p - p_line);
1745 if (dist2 < p_closest_dist2)
1748 p_closest_dist2 = dist2;
1752 else if (level < 10)
1754 float x12 = (x1 + x2)*0.5f, y12 = (y1 + y2)*0.5f;
1755 float x23 = (x2 + x3)*0.5f, y23 = (y2 + y3)*0.5f;
1756 float x34 = (x3 + x4)*0.5f, y34 = (y3 + y4)*0.5f;
1757 float x123 = (x12 + x23)*0.5f, y123 = (y12 + y23)*0.5f;
1758 float x234 = (x23 + x34)*0.5f, y234 = (y23 + y34)*0.5f;
1759 float x1234 = (x123 + x234)*0.5f, y1234 = (y123 + y234)*0.5f;
1760 ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1);
1761 ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1);
1769 IM_ASSERT(tess_tol > 0.0f);
1772 float p_closest_dist2 = FLT_MAX;
1773 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);
1780 ImVec2 ab_dir = b - a;
1781 float dot = ap.x * ab_dir.x + ap.y * ab_dir.y;
1784 float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y;
1785 if (dot > ab_len_sqr)
1787 return a + ab_dir * dot / ab_len_sqr;
1792 bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f;
1793 bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f;
1794 bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f;
1795 return ((b1 == b2) && (b2 == b3));
1803 const float denom = v0.x * v1.y - v1.x * v0.y;
1804 out_v = (v2.x * v1.y - v1.x * v2.y) / denom;
1805 out_w = (v0.x * v2.y - v2.x * v0.y) / denom;
1806 out_u = 1.0f - out_v - out_w;
1814 float dist2_ab = ImLengthSqr(p - proj_ab);
1815 float dist2_bc = ImLengthSqr(p - proj_bc);
1816 float dist2_ca = ImLengthSqr(p - proj_ca);
1817 float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca));
1833 while ((d = ImToUpper(*str2) - ImToUpper(*str1)) == 0 && *str1) { str1++; str2++; }
1840 while (count > 0 && (d = ImToUpper(*str2) - ImToUpper(*str1)) == 0 && *str1) { str1++; str2++; count--; }
1849 strncpy(dst, src, count - 1);
1855 size_t len = strlen(str);
1856 void* buf = IM_ALLOC(len + 1);
1857 return (
char*)memcpy(buf, (
const void*)str, len + 1);
1862 size_t dst_buf_size = p_dst_size ? *p_dst_size : strlen(dst) + 1;
1863 size_t src_size = strlen(src) + 1;
1864 if (dst_buf_size < src_size)
1867 dst = (
char*)IM_ALLOC(src_size);
1869 *p_dst_size = src_size;
1871 return (
char*)memcpy(dst, (
const void*)src, src_size);
1876 const char* p = (
const char*)memchr(str, (
int)c, str_end - str);
1891 const char* p = (
const char*)memchr(str,
'\n', str_end - str);
1892 return p ? p : str_end;
1895const ImWchar*
ImStrbolW(
const ImWchar* buf_mid_line,
const ImWchar* buf_begin)
1897 while (buf_mid_line > buf_begin && buf_mid_line[-1] !=
'\n')
1899 return buf_mid_line;
1902const char*
ImStristr(
const char* haystack,
const char* haystack_end,
const char* needle,
const char* needle_end)
1905 needle_end = needle + strlen(needle);
1907 const char un0 = (char)ImToUpper(*needle);
1908 while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))
1910 if (ImToUpper(*haystack) == un0)
1912 const char* b = needle + 1;
1913 for (
const char* a = haystack + 1; b < needle_end; a++, b++)
1914 if (ImToUpper(*a) != ImToUpper(*b))
1916 if (b == needle_end)
1928 while (p[0] ==
' ' || p[0] ==
'\t')
1933 while (p > p_start && (p[-1] ==
' ' || p[-1] ==
'\t'))
1936 memmove(buf, p_start, p - p_start);
1937 buf[p - p_start] = 0;
1942 while (str[0] ==
' ' || str[0] ==
'\t')
1950#ifndef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
1956#ifdef IMGUI_USE_STB_SPRINTF
1957#ifndef IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION
1958#define STB_SPRINTF_IMPLEMENTATION
1960#ifdef IMGUI_STB_SPRINTF_FILENAME
1961#include IMGUI_STB_SPRINTF_FILENAME
1963#include "stb_sprintf.h"
1967#if defined(_MSC_VER) && !defined(vsnprintf)
1968#define vsnprintf _vsnprintf
1974 va_start(args, fmt);
1975#ifdef IMGUI_USE_STB_SPRINTF
1976 int w = stbsp_vsnprintf(buf, (
int)buf_size, fmt, args);
1978 int w = vsnprintf(buf, buf_size, fmt, args);
1983 if (w == -1 || w >= (
int)buf_size)
1984 w = (int)buf_size - 1;
1991#ifdef IMGUI_USE_STB_SPRINTF
1992 int w = stbsp_vsnprintf(buf, (
int)buf_size, fmt, args);
1994 int w = vsnprintf(buf, buf_size, fmt, args);
1998 if (w == -1 || w >= (
int)buf_size)
1999 w = (int)buf_size - 1;
2008 va_start(args, fmt);
2016 if (fmt[0] ==
'%' && fmt[1] ==
's' && fmt[2] == 0)
2018 const char* buf = va_arg(args,
const char*);
2022 if (out_buf_end) { *out_buf_end = buf + strlen(buf); }
2024 else if (fmt[0] ==
'%' && fmt[1] ==
'.' && fmt[2] ==
'*' && fmt[3] ==
's' && fmt[4] == 0)
2026 int buf_len = va_arg(args,
int);
2027 const char* buf = va_arg(args,
const char*);
2031 buf_len = ImMin(buf_len, 6);
2034 *out_buf_end = buf + buf_len;
2039 *out_buf =
g.TempBuffer.Data;
2040 if (out_buf_end) { *out_buf_end =
g.TempBuffer.Data + buf_len; }
2047static const ImU32 GCrc32LookupTable[256] =
2049 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,
2050 0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,
2051 0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,
2052 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,
2053 0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01,
2054 0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,
2055 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,
2056 0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD,
2057 0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
2058 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,
2059 0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79,
2060 0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,
2061 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,
2062 0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,
2063 0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,
2064 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D,
2070ImGuiID
ImHashData(
const void* data_p,
size_t data_size, ImGuiID seed)
2073 const unsigned char* data = (
const unsigned char*)data_p;
2074 const ImU32* crc32_lut = GCrc32LookupTable;
2075 while (data_size-- != 0)
2076 crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *data++];
2086ImGuiID
ImHashStr(
const char* data_p,
size_t data_size, ImGuiID seed)
2090 const unsigned char* data = (
const unsigned char*)data_p;
2091 const ImU32* crc32_lut = GCrc32LookupTable;
2094 while (data_size-- != 0)
2096 unsigned char c = *data++;
2097 if (c ==
'#' && data_size >= 2 && data[0] ==
'#' && data[1] ==
'#')
2099 crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
2104 while (
unsigned char c = *data++)
2106 if (c ==
'#' && data[0] ==
'#' && data[1] ==
'#')
2108 crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
2119#ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
2123#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(__CYGWIN__) && !defined(__GNUC__)
2126 const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
2127 const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
2131 wchar_t local_temp_stack[FILENAME_MAX];
2132 ImVector<wchar_t> local_temp_heap;
2133 if (filename_wsize + mode_wsize > IM_ARRAYSIZE(local_temp_stack))
2134 local_temp_heap.resize(filename_wsize + mode_wsize);
2135 wchar_t* filename_wbuf = local_temp_heap.Data ? local_temp_heap.Data : local_temp_stack;
2136 wchar_t* mode_wbuf = filename_wbuf + filename_wsize;
2137 ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, filename_wbuf, filename_wsize);
2138 ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, mode_wbuf, mode_wsize);
2139 return ::_wfopen(filename_wbuf, mode_wbuf);
2141 return fopen(filename, mode);
2147ImU64
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; }
2148ImU64
ImFileRead(
void* data, ImU64 sz, ImU64 count, ImFileHandle f) {
return fread(data, (
size_t)sz, (
size_t)count, f); }
2149ImU64
ImFileWrite(
const void* data, ImU64 sz, ImU64 count, ImFileHandle f) {
return fwrite(data, (
size_t)sz, (
size_t)count, f); }
2155void*
ImFileLoadToMemory(
const char* filename,
const char* mode,
size_t* out_file_size,
int padding_bytes)
2157 IM_ASSERT(filename && mode);
2162 if ((f =
ImFileOpen(filename, mode)) == NULL)
2166 if (file_size == (
size_t)-1)
2172 void* file_data = IM_ALLOC(file_size + padding_bytes);
2173 if (file_data == NULL)
2178 if (
ImFileRead(file_data, 1, file_size, f) != file_size)
2184 if (padding_bytes > 0)
2185 memset((
void*)(((
char*)file_data) + file_size), 0, (
size_t)padding_bytes);
2189 *out_file_size = file_size;
2198IM_MSVC_RUNTIME_CHECKS_OFF
2205 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 };
2206 static const int masks[] = { 0x00, 0x7f, 0x1f, 0x0f, 0x07 };
2207 static const uint32_t mins[] = { 0x400000, 0, 0x80, 0x800, 0x10000 };
2208 static const int shiftc[] = { 0, 18, 12, 6, 0 };
2209 static const int shifte[] = { 0, 6, 4, 2, 0 };
2210 int len = lengths[*(
const unsigned char*)in_text >> 3];
2211 int wanted = len + (len ? 0 : 1);
2213 if (in_text_end == NULL)
2214 in_text_end = in_text + wanted;
2219 s[0] = in_text + 0 < in_text_end ? in_text[0] : 0;
2220 s[1] = in_text + 1 < in_text_end ? in_text[1] : 0;
2221 s[2] = in_text + 2 < in_text_end ? in_text[2] : 0;
2222 s[3] = in_text + 3 < in_text_end ? in_text[3] : 0;
2225 *out_char = (uint32_t)(s[0] & masks[len]) << 18;
2226 *out_char |= (uint32_t)(s[1] & 0x3f) << 12;
2227 *out_char |= (uint32_t)(s[2] & 0x3f) << 6;
2228 *out_char |= (uint32_t)(s[3] & 0x3f) << 0;
2229 *out_char >>= shiftc[len];
2233 e = (*out_char < mins[len]) << 6;
2234 e |= ((*out_char >> 11) == 0x1b) << 7;
2235 e |= (*out_char > IM_UNICODE_CODEPOINT_MAX) << 8;
2236 e |= (s[1] & 0xc0) >> 2;
2237 e |= (s[2] & 0xc0) >> 4;
2248 wanted = ImMin(wanted, !!s[0] + !!s[1] + !!s[2] + !!s[3]);
2249 *out_char = IM_UNICODE_CODEPOINT_INVALID;
2255int ImTextStrFromUtf8(ImWchar* buf,
int buf_size,
const char* in_text,
const char* in_text_end,
const char** in_text_remaining)
2257 ImWchar* buf_out = buf;
2258 ImWchar* buf_end = buf + buf_size;
2259 while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
2263 *buf_out++ = (ImWchar)c;
2266 if (in_text_remaining)
2267 *in_text_remaining = in_text;
2268 return (
int)(buf_out - buf);
2274 while ((!in_text_end || in_text < in_text_end) && *in_text)
2284static inline int ImTextCharToUtf8_inline(
char* buf,
int buf_size,
unsigned int c)
2293 if (buf_size < 2)
return 0;
2294 buf[0] = (char)(0xc0 + (c >> 6));
2295 buf[1] = (char)(0x80 + (c & 0x3f));
2300 if (buf_size < 3)
return 0;
2301 buf[0] = (char)(0xe0 + (c >> 12));
2302 buf[1] = (char)(0x80 + ((c >> 6) & 0x3f));
2303 buf[2] = (char)(0x80 + ((c ) & 0x3f));
2308 if (buf_size < 4)
return 0;
2309 buf[0] = (char)(0xf0 + (c >> 18));
2310 buf[1] = (char)(0x80 + ((c >> 12) & 0x3f));
2311 buf[2] = (char)(0x80 + ((c >> 6) & 0x3f));
2312 buf[3] = (char)(0x80 + ((c ) & 0x3f));
2321 int count = ImTextCharToUtf8_inline(out_buf, 5, c);
2329 unsigned int unused = 0;
2335 if (c < 0x80)
return 1;
2336 if (c < 0x800)
return 2;
2337 if (c < 0x10000)
return 3;
2338 if (c <= 0x10FFFF)
return 4;
2342int ImTextStrToUtf8(
char* out_buf,
int out_buf_size,
const ImWchar* in_text,
const ImWchar* in_text_end)
2344 char* buf_p = out_buf;
2345 const char* buf_end = out_buf + out_buf_size;
2346 while (buf_p < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
2348 unsigned int c = (
unsigned int)(*in_text++);
2352 buf_p += ImTextCharToUtf8_inline(buf_p, (
int)(buf_end - buf_p - 1), c);
2355 return (
int)(buf_p - out_buf);
2360 int bytes_count = 0;
2361 while ((!in_text_end || in_text < in_text_end) && *in_text)
2363 unsigned int c = (
unsigned int)(*in_text++);
2374 while (in_text_curr > in_text_start)
2377 if ((*in_text_curr & 0xC0) != 0x80)
2378 return in_text_curr;
2380 return in_text_start;
2383IM_MSVC_RUNTIME_CHECKS_RESTORE
2392 float t = ((col_b >> IM_COL32_A_SHIFT) & 0xFF) / 255.f;
2393 int r = ImLerp((
int)(col_a >> IM_COL32_R_SHIFT) & 0xFF, (
int)(col_b >> IM_COL32_R_SHIFT) & 0xFF,
t);
2394 int g = ImLerp((
int)(col_a >> IM_COL32_G_SHIFT) & 0xFF, (
int)(col_b >> IM_COL32_G_SHIFT) & 0xFF,
t);
2395 int b = ImLerp((
int)(col_a >> IM_COL32_B_SHIFT) & 0xFF, (
int)(col_b >> IM_COL32_B_SHIFT) & 0xFF,
t);
2396 return IM_COL32(r,
g, b, 0xFF);
2399ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in)
2401 float s = 1.0f / 255.0f;
2403 ((in >> IM_COL32_R_SHIFT) & 0xFF) * s,
2404 ((in >> IM_COL32_G_SHIFT) & 0xFF) * s,
2405 ((in >> IM_COL32_B_SHIFT) & 0xFF) * s,
2406 ((in >> IM_COL32_A_SHIFT) & 0xFF) * s);
2409ImU32 ImGui::ColorConvertFloat4ToU32(
const ImVec4& in)
2412 out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT;
2413 out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT;
2414 out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT;
2415 out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT;
2421void ImGui::ColorConvertRGBtoHSV(
float r,
float g,
float b,
float& out_h,
float& out_s,
float& out_v)
2435 const float chroma = r - (
g < b ?
g : b);
2436 out_h = ImFabs(K + (
g - b) / (6.f * chroma + 1e-20f));
2437 out_s = chroma / (r + 1e-20f);
2443void ImGui::ColorConvertHSVtoRGB(
float h,
float s,
float v,
float& out_r,
float& out_g,
float& out_b)
2448 out_r = out_g = out_b = v;
2452 h = ImFmod(h, 1.0f) / (60.0f / 360.0f);
2454 float f = h - (float)i;
2455 float p = v * (1.0f - s);
2456 float q = v * (1.0f - s * f);
2457 float t = v * (1.0f - s * (1.0f - f));
2461 case 0: out_r = v; out_g =
t; out_b = p;
break;
2462 case 1: out_r = q; out_g = v; out_b = p;
break;
2463 case 2: out_r = p; out_g = v; out_b =
t;
break;
2464 case 3: out_r = p; out_g = q; out_b = v;
break;
2465 case 4: out_r =
t; out_g = p; out_b = v;
break;
2466 case 5:
default: out_r = v; out_g = p; out_b = q;
break;
2476static ImGuiStorage::ImGuiStoragePair* LowerBound(ImVector<ImGuiStorage::ImGuiStoragePair>& data, ImGuiID key)
2478 ImGuiStorage::ImGuiStoragePair* first = data.Data;
2479 ImGuiStorage::ImGuiStoragePair* last = data.Data + data.Size;
2480 size_t count = (size_t)(last - first);
2483 size_t count2 =
count >> 1;
2484 ImGuiStorage::ImGuiStoragePair* mid = first + count2;
2488 count -= count2 + 1;
2499void ImGuiStorage::BuildSortByKey()
2503 static int IMGUI_CDECL PairComparerByID(
const void* lhs,
const void* rhs)
2506 if (((
const ImGuiStoragePair*)lhs)->key > ((
const ImGuiStoragePair*)rhs)->key)
return +1;
2507 if (((
const ImGuiStoragePair*)lhs)->key < ((
const ImGuiStoragePair*)rhs)->key)
return -1;
2511 ImQsort(Data.Data, (
size_t)Data.Size,
sizeof(ImGuiStoragePair), StaticFunc::PairComparerByID);
2514int ImGuiStorage::GetInt(ImGuiID key,
int default_val)
const
2516 ImGuiStoragePair* it = LowerBound(
const_cast<ImVector<ImGuiStoragePair>&
>(Data), key);
2517 if (it == Data.end() || it->key != key)
2522bool ImGuiStorage::GetBool(ImGuiID key,
bool default_val)
const
2524 return GetInt(key, default_val ? 1 : 0) != 0;
2527float ImGuiStorage::GetFloat(ImGuiID key,
float default_val)
const
2529 ImGuiStoragePair* it = LowerBound(
const_cast<ImVector<ImGuiStoragePair>&
>(Data), key);
2530 if (it == Data.end() || it->key != key)
2535void* ImGuiStorage::GetVoidPtr(ImGuiID key)
const
2537 ImGuiStoragePair* it = LowerBound(
const_cast<ImVector<ImGuiStoragePair>&
>(Data), key);
2538 if (it == Data.end() || it->key != key)
2544int* ImGuiStorage::GetIntRef(ImGuiID key,
int default_val)
2546 ImGuiStoragePair* it = LowerBound(Data, key);
2547 if (it == Data.end() || it->key != key)
2548 it = Data.insert(it, ImGuiStoragePair(key, default_val));
2552bool* ImGuiStorage::GetBoolRef(ImGuiID key,
bool default_val)
2554 return (
bool*)GetIntRef(key, default_val ? 1 : 0);
2557float* ImGuiStorage::GetFloatRef(ImGuiID key,
float default_val)
2559 ImGuiStoragePair* it = LowerBound(Data, key);
2560 if (it == Data.end() || it->key != key)
2561 it = Data.insert(it, ImGuiStoragePair(key, default_val));
2565void** ImGuiStorage::GetVoidPtrRef(ImGuiID key,
void* default_val)
2567 ImGuiStoragePair* it = LowerBound(Data, key);
2568 if (it == Data.end() || it->key != key)
2569 it = Data.insert(it, ImGuiStoragePair(key, default_val));
2574void ImGuiStorage::SetInt(ImGuiID key,
int val)
2576 ImGuiStoragePair* it = LowerBound(Data, key);
2577 if (it == Data.end() || it->key != key)
2578 Data.insert(it, ImGuiStoragePair(key, val));
2583void ImGuiStorage::SetBool(ImGuiID key,
bool val)
2585 SetInt(key, val ? 1 : 0);
2588void ImGuiStorage::SetFloat(ImGuiID key,
float val)
2590 ImGuiStoragePair* it = LowerBound(Data, key);
2591 if (it == Data.end() || it->key != key)
2592 Data.insert(it, ImGuiStoragePair(key, val));
2597void ImGuiStorage::SetVoidPtr(ImGuiID key,
void* val)
2599 ImGuiStoragePair* it = LowerBound(Data, key);
2600 if (it == Data.end() || it->key != key)
2601 Data.insert(it, ImGuiStoragePair(key, val));
2606void ImGuiStorage::SetAllInt(
int v)
2608 for (
int i = 0; i < Data.Size; i++)
2617ImGuiTextFilter::ImGuiTextFilter(
const char* default_filter)
2623 ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf));
2628bool ImGuiTextFilter::Draw(
const char* label,
float width)
2631 ImGui::SetNextItemWidth(width);
2632 bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
2635 return value_changed;
2638void ImGuiTextFilter::ImGuiTextRange::split(
char separator, ImVector<ImGuiTextRange>* out)
const
2642 const char* we = wb;
2645 if (*we == separator)
2647 out->push_back(ImGuiTextRange(wb, we));
2653 out->push_back(ImGuiTextRange(wb, we));
2656void ImGuiTextFilter::Build()
2659 ImGuiTextRange input_range(InputBuf, InputBuf + strlen(InputBuf));
2660 input_range.split(
',', &Filters);
2663 for (ImGuiTextRange& f : Filters)
2665 while (f.b < f.e && ImCharIsBlankA(f.b[0]))
2667 while (f.e > f.b && ImCharIsBlankA(f.e[-1]))
2676bool ImGuiTextFilter::PassFilter(
const char* text,
const char* text_end)
const
2678 if (Filters.empty())
2684 for (
const ImGuiTextRange& f : Filters)
2691 if (
ImStristr(text, text_end, f.b + 1, f.e) != NULL)
2697 if (
ImStristr(text, text_end, f.b, f.e) != NULL)
2716#if defined(__GNUC__) || defined(__clang__)
2717#define va_copy(dest, src) __builtin_va_copy(dest, src)
2719#define va_copy(dest, src) (dest = src)
2723char ImGuiTextBuffer::EmptyString[1] = { 0 };
2725void ImGuiTextBuffer::append(
const char* str,
const char* str_end)
2727 int len = str_end ? (int)(str_end - str) : (int)strlen(str);
2730 const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
2731 const int needed_sz = write_off + len;
2732 if (write_off + len >= Buf.Capacity)
2734 int new_capacity = Buf.Capacity * 2;
2735 Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity);
2738 Buf.resize(needed_sz);
2739 memcpy(&Buf[write_off - 1], str, (
size_t)len);
2740 Buf[write_off - 1 + len] = 0;
2743void ImGuiTextBuffer::appendf(
const char* fmt, ...)
2746 va_start(args, fmt);
2747 appendfv(fmt, args);
2752void ImGuiTextBuffer::appendfv(
const char* fmt, va_list args)
2765 const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
2766 const int needed_sz = write_off + len;
2767 if (write_off + len >= Buf.Capacity)
2769 int new_capacity = Buf.Capacity * 2;
2770 Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity);
2773 Buf.resize(needed_sz);
2774 ImFormatStringV(&Buf[write_off - 1], (
size_t)len + 1, fmt, args_copy);
2778void ImGuiTextIndex::append(
const char* base,
int old_size,
int new_size)
2780 IM_ASSERT(old_size >= 0 && new_size >= old_size && new_size >= EndOffset);
2781 if (old_size == new_size)
2783 if (EndOffset == 0 || base[EndOffset - 1] ==
'\n')
2784 LineOffsets.push_back(EndOffset);
2785 const char* base_end = base + new_size;
2786 for (
const char* p = base + old_size; (p = (
const char*)memchr(p,
'\n', base_end - p)) != 0; )
2788 LineOffsets.push_back((
int)(intptr_t)(p - base));
2789 EndOffset = ImMax(EndOffset, new_size);
2798static bool GetSkipItemForListClipping()
2801 return (
g.CurrentTable ?
g.CurrentTable->HostSkipItems :
g.CurrentWindow->SkipItems);
2804static void ImGuiListClipper_SortAndFuseRanges(ImVector<ImGuiListClipperRange>&
ranges,
int offset = 0)
2806 if (
ranges.Size - offset <= 1)
2810 for (
int sort_end =
ranges.Size - offset - 1; sort_end > 0; --sort_end)
2811 for (
int i = offset; i < sort_end + offset; ++i)
2816 for (
int i = 1 + offset; i <
ranges.Size; i++)
2818 IM_ASSERT(!
ranges[i].PosToIndexConvert && !
ranges[i - 1].PosToIndexConvert);
2828static void ImGuiListClipper_SeekCursorAndSetupPrevLine(
float pos_y,
float line_height)
2834 ImGuiWindow* window =
g.CurrentWindow;
2835 float off_y = pos_y - window->DC.CursorPos.y;
2836 window->DC.CursorPos.y = pos_y;
2837 window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, pos_y -
g.Style.ItemSpacing.y);
2838 window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height;
2839 window->DC.PrevLineSize.y = (line_height -
g.Style.ItemSpacing.y);
2840 if (ImGuiOldColumns* columns = window->DC.CurrentColumns)
2841 columns->LineMinY = window->DC.CursorPos.y;
2842 if (ImGuiTable* table =
g.CurrentTable)
2844 if (table->IsInsideRow)
2845 ImGui::TableEndRow(table);
2846 table->RowPosY2 = window->DC.CursorPos.y;
2847 const int row_increase = (int)((off_y / line_height) + 0.5f);
2849 table->RowBgColorCounter += row_increase;
2853static void ImGuiListClipper_SeekCursorForItem(ImGuiListClipper* clipper,
int item_n)
2857 ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData;
2858 float pos_y = (float)((
double)clipper->StartPosY + data->LossynessOffset + (double)(item_n - data->ItemsFrozen) * clipper->ItemsHeight);
2859 ImGuiListClipper_SeekCursorAndSetupPrevLine(pos_y, clipper->ItemsHeight);
2862ImGuiListClipper::ImGuiListClipper()
2864 memset(
this, 0,
sizeof(*
this));
2867ImGuiListClipper::~ImGuiListClipper()
2872void ImGuiListClipper::Begin(
int items_count,
float items_height)
2875 Ctx = ImGui::GetCurrentContext();
2877 ImGuiContext&
g = *Ctx;
2878 ImGuiWindow* window =
g.CurrentWindow;
2879 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Begin(%d,%.2f) in '%s'\n", items_count, items_height, window->Name);
2881 if (ImGuiTable* table =
g.CurrentTable)
2882 if (table->IsInsideRow)
2883 ImGui::TableEndRow(table);
2885 StartPosY = window->DC.CursorPos.y;
2886 ItemsHeight = items_height;
2887 ItemsCount = items_count;
2892 if (++
g.ClipperTempDataStacked >
g.ClipperTempData.Size)
2893 g.ClipperTempData.resize(
g.ClipperTempDataStacked, ImGuiListClipperData());
2894 ImGuiListClipperData* data = &
g.ClipperTempData[
g.ClipperTempDataStacked - 1];
2896 data->LossynessOffset = window->DC.CursorStartPosLossyness.y;
2900void ImGuiListClipper::End()
2902 if (ImGuiListClipperData* data = (ImGuiListClipperData*)TempData)
2905 ImGuiContext&
g = *Ctx;
2906 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: End() in '%s'\n",
g.CurrentWindow->Name);
2907 if (ItemsCount >= 0 && ItemsCount < INT_MAX && DisplayStart >= 0)
2908 ImGuiListClipper_SeekCursorForItem(
this, ItemsCount);
2911 IM_ASSERT(data->ListClipper ==
this);
2912 data->StepNo = data->Ranges.Size;
2913 if (--
g.ClipperTempDataStacked > 0)
2915 data = &
g.ClipperTempData[
g.ClipperTempDataStacked - 1];
2916 data->ListClipper->TempData = data;
2923void ImGuiListClipper::IncludeItemsByIndex(
int item_begin,
int item_end)
2925 ImGuiListClipperData* data = (ImGuiListClipperData*)TempData;
2926 IM_ASSERT(DisplayStart < 0);
2927 IM_ASSERT(item_begin <= item_end);
2928 if (item_begin < item_end)
2929 data->Ranges.push_back(ImGuiListClipperRange::FromIndices(item_begin, item_end));
2932static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
2934 ImGuiContext&
g = *clipper->Ctx;
2935 ImGuiWindow* window =
g.CurrentWindow;
2936 ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData;
2937 IM_ASSERT(data != NULL &&
"Called ImGuiListClipper::Step() too many times, or before ImGuiListClipper::Begin() ?");
2939 ImGuiTable* table =
g.CurrentTable;
2940 if (table && table->IsInsideRow)
2941 ImGui::TableEndRow(table);
2944 if (clipper->ItemsCount == 0 || GetSkipItemForListClipping())
2949 if (data->StepNo == 0 && table != NULL && !table->IsUnfrozenRows)
2951 clipper->DisplayStart = data->ItemsFrozen;
2952 clipper->DisplayEnd = ImMin(data->ItemsFrozen + 1, clipper->ItemsCount);
2953 if (clipper->DisplayStart < clipper->DisplayEnd)
2954 data->ItemsFrozen++;
2959 bool calc_clipping =
false;
2960 if (data->StepNo == 0)
2962 clipper->StartPosY = window->DC.CursorPos.y;
2963 if (clipper->ItemsHeight <= 0.0f)
2966 data->Ranges.push_front(ImGuiListClipperRange::FromIndices(data->ItemsFrozen, data->ItemsFrozen + 1));
2967 clipper->DisplayStart = ImMax(data->Ranges[0].Min, data->ItemsFrozen);
2968 clipper->DisplayEnd = ImMin(data->Ranges[0].Max, clipper->ItemsCount);
2972 calc_clipping =
true;
2976 if (clipper->ItemsHeight <= 0.0f)
2978 IM_ASSERT(data->StepNo == 1);
2980 IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y);
2982 clipper->ItemsHeight = (window->DC.CursorPos.y - clipper->StartPosY) / (
float)(clipper->DisplayEnd - clipper->DisplayStart);
2983 bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision(clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y);
2984 if (affected_by_floating_point_precision)
2985 clipper->ItemsHeight = window->DC.PrevLineSize.y +
g.Style.ItemSpacing.y;
2987 IM_ASSERT(clipper->ItemsHeight > 0.0f &&
"Unable to calculate item height! First item hasn't moved the cursor vertically!");
2988 calc_clipping =
true;
2992 const int already_submitted = clipper->DisplayEnd;
2998 data->Ranges.push_back(ImGuiListClipperRange::FromIndices(0, clipper->ItemsCount));
3003 const bool is_nav_request = (
g.NavMoveScoringItems &&
g.NavWindow &&
g.NavWindow->RootWindowForNav == window->RootWindowForNav);
3005 data->Ranges.push_back(ImGuiListClipperRange::FromPositions(
g.NavScoringNoClipRect.Min.y,
g.NavScoringNoClipRect.Max.y, 0, 0));
3006 if (is_nav_request && (
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) &&
g.NavTabbingDir == -1)
3007 data->Ranges.push_back(ImGuiListClipperRange::FromIndices(clipper->ItemsCount - 1, clipper->ItemsCount));
3010 ImRect nav_rect_abs = ImGui::WindowRectRelToAbs(window, window->NavRectRel[0]);
3011 if (
g.NavId != 0 && window->NavLastIds[0] ==
g.NavId)
3012 data->Ranges.push_back(ImGuiListClipperRange::FromPositions(nav_rect_abs.Min.y, nav_rect_abs.Max.y, 0, 0));
3015 const int off_min = (is_nav_request &&
g.NavMoveClipDir == ImGuiDir_Up) ? -1 : 0;
3016 const int off_max = (is_nav_request &&
g.NavMoveClipDir == ImGuiDir_Down) ? 1 : 0;
3017 data->Ranges.push_back(ImGuiListClipperRange::FromPositions(window->ClipRect.Min.y, window->ClipRect.Max.y, off_min, off_max));
3024 for (ImGuiListClipperRange& range : data->Ranges)
3025 if (range.PosToIndexConvert)
3027 int m1 = (int)(((
double)range.Min - window->DC.CursorPos.y - data->LossynessOffset) / clipper->ItemsHeight);
3028 int m2 = (int)((((
double)range.Max - window->DC.CursorPos.y - data->LossynessOffset) / clipper->ItemsHeight) + 0.999999f);
3029 range.Min = ImClamp(already_submitted + m1 + range.PosToIndexOffsetMin, already_submitted, clipper->ItemsCount - 1);
3030 range.Max = ImClamp(already_submitted + m2 + range.PosToIndexOffsetMax, range.Min + 1, clipper->ItemsCount);
3031 range.PosToIndexConvert =
false;
3033 ImGuiListClipper_SortAndFuseRanges(data->Ranges, data->StepNo);
3037 while (data->StepNo < data->Ranges.Size)
3039 clipper->DisplayStart = ImMax(data->Ranges[data->StepNo].Min, already_submitted);
3040 clipper->DisplayEnd = ImMin(data->Ranges[data->StepNo].Max, clipper->ItemsCount);
3041 if (clipper->DisplayStart > already_submitted)
3042 ImGuiListClipper_SeekCursorForItem(clipper, clipper->DisplayStart);
3044 if (clipper->DisplayStart == clipper->DisplayEnd && data->StepNo < data->Ranges.Size)
3051 if (clipper->ItemsCount < INT_MAX)
3052 ImGuiListClipper_SeekCursorForItem(clipper, clipper->ItemsCount);
3057bool ImGuiListClipper::Step()
3059 ImGuiContext&
g = *Ctx;
3060 bool need_items_height = (ItemsHeight <= 0.0f);
3061 bool ret = ImGuiListClipper_StepInternal(
this);
3062 if (ret && (DisplayStart == DisplayEnd))
3064 if (
g.CurrentTable &&
g.CurrentTable->IsUnfrozenRows ==
false)
3065 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): inside frozen table row.\n");
3066 if (need_items_height && ItemsHeight > 0.0f)
3067 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): computed ItemsHeight: %.2f.\n", ItemsHeight);
3070 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): display %d to %d.\n", DisplayStart, DisplayEnd);
3074 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): End.\n");
3084ImGuiStyle& ImGui::GetStyle()
3086 IM_ASSERT(
GImGui != NULL &&
"No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
3090ImU32 ImGui::GetColorU32(ImGuiCol idx,
float alpha_mul)
3092 ImGuiStyle& style =
GImGui->Style;
3093 ImVec4 c = style.Colors[idx];
3094 c.w *= style.Alpha * alpha_mul;
3095 return ColorConvertFloat4ToU32(c);
3098ImU32 ImGui::GetColorU32(
const ImVec4& col)
3100 ImGuiStyle& style =
GImGui->Style;
3103 return ColorConvertFloat4ToU32(c);
3106const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx)
3108 ImGuiStyle& style =
GImGui->Style;
3109 return style.Colors[idx];
3112ImU32 ImGui::GetColorU32(ImU32 col,
float alpha_mul)
3114 ImGuiStyle& style =
GImGui->Style;
3115 alpha_mul *= style.Alpha;
3116 if (alpha_mul >= 1.0f)
3118 ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
3119 a = (ImU32)(a * alpha_mul);
3120 return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT);
3124void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col)
3127 ImGuiColorMod backup;
3129 backup.BackupValue =
g.Style.Colors[idx];
3130 g.ColorStack.push_back(backup);
3131 if (
g.DebugFlashStyleColorIdx != idx)
3132 g.Style.Colors[idx] = ColorConvertU32ToFloat4(col);
3135void ImGui::PushStyleColor(ImGuiCol idx,
const ImVec4& col)
3138 ImGuiColorMod backup;
3140 backup.BackupValue =
g.Style.Colors[idx];
3141 g.ColorStack.push_back(backup);
3142 if (
g.DebugFlashStyleColorIdx != idx)
3143 g.Style.Colors[idx] = col;
3146void ImGui::PopStyleColor(
int count)
3149 if (
g.ColorStack.Size < count)
3151 IM_ASSERT_USER_ERROR(
g.ColorStack.Size > count,
"Calling PopStyleColor() too many times!");
3152 count =
g.ColorStack.Size;
3156 ImGuiColorMod& backup =
g.ColorStack.back();
3157 g.Style.Colors[backup.Col] = backup.BackupValue;
3158 g.ColorStack.pop_back();
3163static const ImGuiCol GWindowDockStyleColors[ImGuiWindowDockStyleCol_COUNT] =
3165 ImGuiCol_Text, ImGuiCol_Tab, ImGuiCol_TabHovered, ImGuiCol_TabActive, ImGuiCol_TabUnfocused, ImGuiCol_TabUnfocusedActive
3168static const ImGuiDataVarInfo GStyleVarInfo[] =
3170 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, Alpha) },
3171 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, DisabledAlpha) },
3172 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowPadding) },
3173 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, WindowRounding) },
3174 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, WindowBorderSize) },
3175 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowMinSize) },
3176 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowTitleAlign) },
3177 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ChildRounding) },
3178 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ChildBorderSize) },
3179 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, PopupRounding) },
3180 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, PopupBorderSize) },
3181 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, FramePadding) },
3182 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, FrameRounding) },
3183 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, FrameBorderSize) },
3184 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ItemSpacing) },
3185 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ItemInnerSpacing) },
3186 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, IndentSpacing) },
3187 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, CellPadding) },
3188 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ScrollbarSize) },
3189 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ScrollbarRounding) },
3190 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, GrabMinSize) },
3191 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, GrabRounding) },
3192 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabRounding) },
3193 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBarBorderSize) },
3194 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) },
3195 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) },
3196 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, SeparatorTextBorderSize) },
3197 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SeparatorTextAlign) },
3198 { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SeparatorTextPadding) },
3199 { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, DockingSeparatorSize) },
3202const ImGuiDataVarInfo* ImGui::GetStyleVarInfo(ImGuiStyleVar idx)
3204 IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT);
3206 return &GStyleVarInfo[idx];
3209void ImGui::PushStyleVar(ImGuiStyleVar idx,
float val)
3212 const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx);
3213 if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1)
3215 float* pvar = (
float*)var_info->GetVarPtr(&
g.Style);
3216 g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
3220 IM_ASSERT_USER_ERROR(0,
"Calling PushStyleVar() variant with wrong type!");
3223void ImGui::PushStyleVar(ImGuiStyleVar idx,
const ImVec2& val)
3226 const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx);
3227 if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2)
3229 ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&
g.Style);
3230 g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
3234 IM_ASSERT_USER_ERROR(0,
"Calling PushStyleVar() variant with wrong type!");
3237void ImGui::PopStyleVar(
int count)
3240 if (
g.StyleVarStack.Size < count)
3242 IM_ASSERT_USER_ERROR(
g.StyleVarStack.Size > count,
"Calling PopStyleVar() too many times!");
3243 count =
g.StyleVarStack.Size;
3248 ImGuiStyleMod& backup =
g.StyleVarStack.back();
3249 const ImGuiDataVarInfo* info = GetStyleVarInfo(backup.VarIdx);
3250 void* data = info->GetVarPtr(&
g.Style);
3251 if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((
float*)data)[0] = backup.BackupFloat[0]; }
3252 else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((
float*)data)[0] = backup.BackupFloat[0]; ((
float*)data)[1] = backup.BackupFloat[1]; }
3253 g.StyleVarStack.pop_back();
3258const char* ImGui::GetStyleColorName(ImGuiCol idx)
3263 case ImGuiCol_Text:
return "Text";
3264 case ImGuiCol_TextDisabled:
return "TextDisabled";
3265 case ImGuiCol_WindowBg:
return "WindowBg";
3266 case ImGuiCol_ChildBg:
return "ChildBg";
3267 case ImGuiCol_PopupBg:
return "PopupBg";
3268 case ImGuiCol_Border:
return "Border";
3269 case ImGuiCol_BorderShadow:
return "BorderShadow";
3270 case ImGuiCol_FrameBg:
return "FrameBg";
3271 case ImGuiCol_FrameBgHovered:
return "FrameBgHovered";
3272 case ImGuiCol_FrameBgActive:
return "FrameBgActive";
3273 case ImGuiCol_TitleBg:
return "TitleBg";
3274 case ImGuiCol_TitleBgActive:
return "TitleBgActive";
3275 case ImGuiCol_TitleBgCollapsed:
return "TitleBgCollapsed";
3276 case ImGuiCol_MenuBarBg:
return "MenuBarBg";
3277 case ImGuiCol_ScrollbarBg:
return "ScrollbarBg";
3278 case ImGuiCol_ScrollbarGrab:
return "ScrollbarGrab";
3279 case ImGuiCol_ScrollbarGrabHovered:
return "ScrollbarGrabHovered";
3280 case ImGuiCol_ScrollbarGrabActive:
return "ScrollbarGrabActive";
3281 case ImGuiCol_CheckMark:
return "CheckMark";
3282 case ImGuiCol_SliderGrab:
return "SliderGrab";
3283 case ImGuiCol_SliderGrabActive:
return "SliderGrabActive";
3284 case ImGuiCol_Button:
return "Button";
3285 case ImGuiCol_ButtonHovered:
return "ButtonHovered";
3286 case ImGuiCol_ButtonActive:
return "ButtonActive";
3287 case ImGuiCol_Header:
return "Header";
3288 case ImGuiCol_HeaderHovered:
return "HeaderHovered";
3289 case ImGuiCol_HeaderActive:
return "HeaderActive";
3290 case ImGuiCol_Separator:
return "Separator";
3291 case ImGuiCol_SeparatorHovered:
return "SeparatorHovered";
3292 case ImGuiCol_SeparatorActive:
return "SeparatorActive";
3293 case ImGuiCol_ResizeGrip:
return "ResizeGrip";
3294 case ImGuiCol_ResizeGripHovered:
return "ResizeGripHovered";
3295 case ImGuiCol_ResizeGripActive:
return "ResizeGripActive";
3296 case ImGuiCol_Tab:
return "Tab";
3297 case ImGuiCol_TabHovered:
return "TabHovered";
3298 case ImGuiCol_TabActive:
return "TabActive";
3299 case ImGuiCol_TabUnfocused:
return "TabUnfocused";
3300 case ImGuiCol_TabUnfocusedActive:
return "TabUnfocusedActive";
3301 case ImGuiCol_DockingPreview:
return "DockingPreview";
3302 case ImGuiCol_DockingEmptyBg:
return "DockingEmptyBg";
3303 case ImGuiCol_PlotLines:
return "PlotLines";
3304 case ImGuiCol_PlotLinesHovered:
return "PlotLinesHovered";
3305 case ImGuiCol_PlotHistogram:
return "PlotHistogram";
3306 case ImGuiCol_PlotHistogramHovered:
return "PlotHistogramHovered";
3307 case ImGuiCol_TableHeaderBg:
return "TableHeaderBg";
3308 case ImGuiCol_TableBorderStrong:
return "TableBorderStrong";
3309 case ImGuiCol_TableBorderLight:
return "TableBorderLight";
3310 case ImGuiCol_TableRowBg:
return "TableRowBg";
3311 case ImGuiCol_TableRowBgAlt:
return "TableRowBgAlt";
3312 case ImGuiCol_TextSelectedBg:
return "TextSelectedBg";
3313 case ImGuiCol_DragDropTarget:
return "DragDropTarget";
3314 case ImGuiCol_NavHighlight:
return "NavHighlight";
3315 case ImGuiCol_NavWindowingHighlight:
return "NavWindowingHighlight";
3316 case ImGuiCol_NavWindowingDimBg:
return "NavWindowingDimBg";
3317 case ImGuiCol_ModalWindowDimBg:
return "ModalWindowDimBg";
3331const char* ImGui::FindRenderedTextEnd(
const char* text,
const char* text_end)
3333 const char* text_display_end = text;
3335 text_end = (
const char*)-1;
3337 while (text_display_end < text_end && *text_display_end !=
'\0' && (text_display_end[0] !=
'#' || text_display_end[1] !=
'#'))
3339 return text_display_end;
3344void ImGui::RenderText(ImVec2 pos,
const char* text,
const char* text_end,
bool hide_text_after_hash)
3347 ImGuiWindow* window =
g.CurrentWindow;
3350 const char* text_display_end;
3351 if (hide_text_after_hash)
3353 text_display_end = FindRenderedTextEnd(text, text_end);
3358 text_end = text + strlen(text);
3359 text_display_end = text_end;
3362 if (text != text_display_end)
3364 window->DrawList->AddText(
g.Font,
g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
3366 LogRenderedText(&pos, text, text_display_end);
3370void ImGui::RenderTextWrapped(ImVec2 pos,
const char* text,
const char* text_end,
float wrap_width)
3373 ImGuiWindow* window =
g.CurrentWindow;
3376 text_end = text + strlen(text);
3378 if (text != text_end)
3380 window->DrawList->AddText(
g.Font,
g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width);
3382 LogRenderedText(&pos, text, text_end);
3391void 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)
3394 ImVec2 pos = pos_min;
3395 const ImVec2 text_size = text_size_if_known ? *text_size_if_known :
CalcTextSize(text, text_display_end,
false, 0.0f);
3397 const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min;
3398 const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max;
3399 bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y);
3401 need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y);
3404 if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x);
3405 if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y);
3410 ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y);
3411 draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect);
3415 draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL);
3419void 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)
3422 const char* text_display_end = FindRenderedTextEnd(text, text_end);
3423 const int text_len = (int)(text_display_end - text);
3428 ImGuiWindow* window =
g.CurrentWindow;
3429 RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect);
3431 LogRenderedText(&pos_min, text, text_display_end);
3437void 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)
3440 if (text_end_full == NULL)
3441 text_end_full = FindRenderedTextEnd(text);
3442 const ImVec2 text_size = text_size_if_known ? *text_size_if_known :
CalcTextSize(text, text_end_full,
false, 0.0f);
3448 if (text_size.x > pos_max.x - pos_min.x)
3455 const ImFont* font = draw_list->_Data->Font;
3456 const float font_size = draw_list->_Data->FontSize;
3457 const float font_scale = font_size / font->FontSize;
3458 const char* text_end_ellipsis = NULL;
3459 const float ellipsis_width = font->EllipsisWidth * font_scale;
3462 const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_width) - pos_min.x, 1.0f);
3463 float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
3464 if (text == text_end_ellipsis && text_end_ellipsis < text_end_full)
3468 text_size_clipped_x = font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text, text_end_ellipsis).x;
3470 while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1]))
3473 text_end_ellipsis--;
3474 text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x;
3478 RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f));
3479 ImVec2 ellipsis_pos = ImTrunc(ImVec2(pos_min.x + text_size_clipped_x, pos_min.y));
3480 if (ellipsis_pos.x + ellipsis_width <= ellipsis_max_x)
3481 for (
int i = 0; i < font->EllipsisCharCount; i++, ellipsis_pos.x += font->EllipsisCharStep * font_scale)
3482 font->RenderChar(draw_list, font_size, ellipsis_pos, GetColorU32(ImGuiCol_Text), font->EllipsisChar);
3486 RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_full, &text_size, ImVec2(0.0f, 0.0f));
3490 LogRenderedText(&pos_min, text, text_end_full);
3494void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col,
bool border,
float rounding)
3497 ImGuiWindow* window =
g.CurrentWindow;
3498 window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
3499 const float border_size =
g.Style.FrameBorderSize;
3500 if (border && border_size > 0.0f)
3502 window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
3503 window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
3507void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max,
float rounding)
3510 ImGuiWindow* window =
g.CurrentWindow;
3511 const float border_size =
g.Style.FrameBorderSize;
3512 if (border_size > 0.0f)
3514 window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
3515 window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
3519void ImGui::RenderNavHighlight(
const ImRect& bb, ImGuiID
id, ImGuiNavHighlightFlags flags)
3524 if (
g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw))
3526 ImGuiWindow* window =
g.CurrentWindow;
3527 if (window->DC.NavHideHighlightOneFrame)
3530 float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f :
g.Style.FrameRounding;
3531 ImRect display_rect = bb;
3532 display_rect.ClipWith(window->ClipRect);
3533 const float thickness = 2.0f;
3534 if (flags & ImGuiNavHighlightFlags_Compact)
3536 window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, thickness);
3540 const float distance = 3.0f + thickness * 0.5f;
3541 display_rect.Expand(ImVec2(distance, distance));
3542 bool fully_visible = window->ClipRect.Contains(display_rect);
3544 window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
3545 window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, thickness);
3547 window->DrawList->PopClipRect();
3551void ImGui::RenderMouseCursor(ImVec2 base_pos,
float base_scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow)
3554 IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT);
3555 ImFontAtlas* font_atlas =
g.DrawListSharedData.Font->ContainerAtlas;
3556 for (ImGuiViewportP* viewport :
g.Viewports)
3559 ImVec2 offset,
size, uv[4];
3560 if (!font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2]))
3562 const ImVec2 pos = base_pos - offset;
3563 const float scale = base_scale * viewport->DpiScale;
3564 if (!viewport->GetMainRect().Overlaps(ImRect(pos, pos + ImVec2(
size.x + 2,
size.y + 2) * scale)))
3566 ImDrawList* draw_list = GetForegroundDrawList(viewport);
3567 ImTextureID tex_id = font_atlas->TexID;
3568 draw_list->PushTextureID(tex_id);
3569 draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow);
3570 draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow);
3571 draw_list->AddImage(tex_id, pos, pos + size * scale, uv[2], uv[3], col_border);
3572 draw_list->AddImage(tex_id, pos, pos + size * scale, uv[0], uv[1], col_fill);
3573 draw_list->PopTextureID();
3583ImGuiContext* ImGui::GetCurrentContext()
3588void ImGui::SetCurrentContext(ImGuiContext* ctx)
3590#ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC
3591 IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx);
3597void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func,
void* user_data)
3599 GImAllocatorAllocFunc = alloc_func;
3600 GImAllocatorFreeFunc = free_func;
3601 GImAllocatorUserData = user_data;
3605void ImGui::GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func,
void** p_user_data)
3607 *p_alloc_func = GImAllocatorAllocFunc;
3608 *p_free_func = GImAllocatorFreeFunc;
3609 *p_user_data = GImAllocatorUserData;
3612ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas)
3614 ImGuiContext* prev_ctx = GetCurrentContext();
3615 ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);
3616 SetCurrentContext(ctx);
3618 if (prev_ctx != NULL)
3619 SetCurrentContext(prev_ctx);
3623void ImGui::DestroyContext(ImGuiContext* ctx)
3625 ImGuiContext* prev_ctx = GetCurrentContext();
3628 SetCurrentContext(ctx);
3630 SetCurrentContext((prev_ctx != ctx) ? prev_ctx : NULL);
3635static const ImGuiLocEntry GLocalizationEntriesEnUS[] =
3637 { ImGuiLocKey_VersionStr,
"Dear ImGui " IMGUI_VERSION
" (" IM_STRINGIFY(IMGUI_VERSION_NUM)
")" },
3638 { ImGuiLocKey_TableSizeOne,
"Size column to fit###SizeOne" },
3639 { ImGuiLocKey_TableSizeAllFit,
"Size all columns to fit###SizeAll" },
3640 { ImGuiLocKey_TableSizeAllDefault,
"Size all columns to default###SizeAll" },
3641 { ImGuiLocKey_TableResetOrder,
"Reset order###ResetOrder" },
3642 { ImGuiLocKey_WindowingMainMenuBar,
"(Main menu bar)" },
3643 { ImGuiLocKey_WindowingPopup,
"(Popup)" },
3644 { ImGuiLocKey_WindowingUntitled,
"(Untitled)" },
3645 { ImGuiLocKey_DockingHideTabBar,
"Hide tab bar###HideTabBar" },
3646 { ImGuiLocKey_DockingHoldShiftToDock,
"Hold SHIFT to enable Docking window." },
3647 { ImGuiLocKey_DockingDragToUndockOrMoveNode,
"Click and drag to move or undock whole node." },
3650void ImGui::Initialize()
3653 IM_ASSERT(!
g.Initialized && !
g.SettingsLoaded);
3657 ImGuiSettingsHandler ini_handler;
3658 ini_handler.TypeName =
"Window";
3659 ini_handler.TypeHash =
ImHashStr(
"Window");
3660 ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll;
3661 ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen;
3662 ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine;
3663 ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll;
3664 ini_handler.WriteAllFn = WindowSettingsHandler_WriteAll;
3665 AddSettingsHandler(&ini_handler);
3667 TableSettingsAddSettingsHandler();
3670 LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_ARRAYSIZE(GLocalizationEntriesEnUS));
3673 g.IO.GetClipboardTextFn = GetClipboardTextFn_DefaultImpl;
3674 g.IO.SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
3675 g.IO.ClipboardUserData = (
void*)&
g;
3676 g.IO.SetPlatformImeDataFn = SetPlatformImeDataFn_DefaultImpl;
3679 ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)();
3682 viewport->PlatformWindowCreated =
true;
3683 viewport->Flags = ImGuiViewportFlags_OwnedByApp;
3684 g.Viewports.push_back(viewport);
3685 g.TempBuffer.resize(1024 * 3 + 1, 0);
3686 g.ViewportCreatedCount++;
3687 g.PlatformIO.Viewports.push_back(
g.Viewports[0]);
3690 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
3691 if ((key >= ImGuiKey_0 && key <= ImGuiKey_9) || (key >= ImGuiKey_A && key <= ImGuiKey_Z) || (key >= ImGuiKey_Keypad0 && key <= ImGuiKey_Keypad9)
3692 || key == ImGuiKey_Tab || key == ImGuiKey_Space || key == ImGuiKey_Apostrophe || key == ImGuiKey_Comma || key == ImGuiKey_Minus || key == ImGuiKey_Period
3693 || key == ImGuiKey_Slash || key == ImGuiKey_Semicolon || key == ImGuiKey_Equal || key == ImGuiKey_LeftBracket || key == ImGuiKey_RightBracket || key == ImGuiKey_GraveAccent
3694 || key == ImGuiKey_KeypadDecimal || key == ImGuiKey_KeypadDivide || key == ImGuiKey_KeypadMultiply || key == ImGuiKey_KeypadSubtract || key == ImGuiKey_KeypadAdd || key == ImGuiKey_KeypadEqual)
3695 g.KeysMayBeCharInput.SetBit(key);
3697#ifdef IMGUI_HAS_DOCK
3699 DockContextInitialize(&
g);
3702 g.Initialized =
true;
3706void ImGui::Shutdown()
3709 IM_ASSERT_USER_ERROR(
g.IO.BackendPlatformUserData == NULL,
"Forgot to shutdown Platform backend?");
3710 IM_ASSERT_USER_ERROR(
g.IO.BackendRendererUserData == NULL,
"Forgot to shutdown Renderer backend?");
3713 if (
g.IO.Fonts &&
g.FontAtlasOwnedByContext)
3715 g.IO.Fonts->Locked =
false;
3716 IM_DELETE(
g.IO.Fonts);
3719 g.DrawListSharedData.TempBuffer.clear();
3726 if (
g.SettingsLoaded &&
g.IO.IniFilename != NULL)
3727 SaveIniSettingsToDisk(
g.IO.IniFilename);
3730 DestroyPlatformWindows();
3733 DockContextShutdown(&
g);
3735 CallContextHooks(&
g, ImGuiContextHookType_Shutdown);
3738 g.Windows.clear_delete();
3739 g.WindowsFocusOrder.clear();
3740 g.WindowsTempSortBuffer.clear();
3741 g.CurrentWindow = NULL;
3742 g.CurrentWindowStack.clear();
3743 g.WindowsById.Clear();
3745 g.HoveredWindow =
g.HoveredWindowUnderMovingWindow = NULL;
3746 g.ActiveIdWindow =
g.ActiveIdPreviousFrameWindow = NULL;
3747 g.MovingWindow = NULL;
3749 g.KeysRoutingTable.Clear();
3751 g.ColorStack.clear();
3752 g.StyleVarStack.clear();
3753 g.FontStack.clear();
3754 g.OpenPopupStack.clear();
3755 g.BeginPopupStack.clear();
3756 g.NavTreeNodeStack.clear();
3758 g.CurrentViewport =
g.MouseViewport =
g.MouseLastHoveredViewport = NULL;
3759 g.Viewports.clear_delete();
3762 g.CurrentTabBarStack.clear();
3763 g.ShrinkWidthBuffer.clear();
3765 g.ClipperTempData.clear_destruct();
3768 g.TablesTempData.clear_destruct();
3769 g.DrawChannelsTempMergeBuffer.clear();
3771 g.ClipboardHandlerData.clear();
3772 g.MenusIdSubmittedThisFrame.clear();
3773 g.InputTextState.ClearFreeMemory();
3774 g.InputTextDeactivatedState.ClearFreeMemory();
3776 g.SettingsWindows.clear();
3777 g.SettingsHandlers.clear();
3781#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
3782 if (
g.LogFile != stdout)
3787 g.LogBuffer.clear();
3788 g.DebugLogBuf.clear();
3789 g.DebugLogIndex.clear();
3791 g.Initialized =
false;
3795ImGuiID ImGui::AddContextHook(ImGuiContext* ctx,
const ImGuiContextHook* hook)
3797 ImGuiContext&
g = *ctx;
3798 IM_ASSERT(hook->Callback != NULL && hook->HookId == 0 && hook->Type != ImGuiContextHookType_PendingRemoval_);
3799 g.Hooks.push_back(*hook);
3800 g.Hooks.back().HookId = ++
g.HookIdNext;
3801 return g.HookIdNext;
3805void ImGui::RemoveContextHook(ImGuiContext* ctx, ImGuiID hook_id)
3807 ImGuiContext&
g = *ctx;
3808 IM_ASSERT(hook_id != 0);
3809 for (ImGuiContextHook& hook :
g.Hooks)
3810 if (hook.HookId == hook_id)
3811 hook.Type = ImGuiContextHookType_PendingRemoval_;
3816void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type)
3818 ImGuiContext&
g = *ctx;
3819 for (ImGuiContextHook& hook :
g.Hooks)
3820 if (hook.Type == hook_type)
3821 hook.Callback(&
g, &hook);
3830ImGuiWindow::ImGuiWindow(ImGuiContext* ctx,
const char* name) : DrawListInst(NULL)
3832 memset(
this, 0,
sizeof(*
this));
3835 NameBufLen = (int)strlen(name) + 1;
3837 IDStack.push_back(ID);
3838 ViewportAllowPlatformMonitorExtend = -1;
3839 ViewportPos = ImVec2(FLT_MAX, FLT_MAX);
3840 MoveId = GetID(
"#MOVE");
3841 TabId = GetID(
"#TAB");
3842 ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
3843 ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
3844 AutoFitFramesX = AutoFitFramesY = -1;
3845 AutoPosLastDirection = ImGuiDir_None;
3846 SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = SetWindowDockAllowFlags = 0;
3847 SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX);
3848 LastFrameActive = -1;
3849 LastFrameJustFocused = -1;
3850 LastTimeActive = -1.0f;
3851 FontWindowScale = FontDpiScale = 1.0f;
3852 SettingsOffset = -1;
3854 DrawList = &DrawListInst;
3855 DrawList->_Data = &Ctx->DrawListSharedData;
3856 DrawList->_OwnerName = Name;
3857 NavPreferredScoringPosRel[0] = NavPreferredScoringPosRel[1] = ImVec2(FLT_MAX, FLT_MAX);
3858 IM_PLACEMENT_NEW(&WindowClass) ImGuiWindowClass();
3861ImGuiWindow::~ImGuiWindow()
3863 IM_ASSERT(DrawList == &DrawListInst);
3865 ColumnsStorage.clear_destruct();
3868ImGuiID ImGuiWindow::GetID(
const char* str,
const char* str_end)
3870 ImGuiID seed = IDStack.back();
3871 ImGuiID
id =
ImHashStr(str, str_end ? (str_end - str) : 0, seed);
3872 ImGuiContext&
g = *Ctx;
3873 if (
g.DebugHookIdInfo ==
id)
3874 ImGui::DebugHookIdInfo(
id, ImGuiDataType_String, str, str_end);
3878ImGuiID ImGuiWindow::GetID(
const void* ptr)
3880 ImGuiID seed = IDStack.back();
3881 ImGuiID
id =
ImHashData(&ptr,
sizeof(
void*), seed);
3882 ImGuiContext&
g = *Ctx;
3883 if (
g.DebugHookIdInfo ==
id)
3884 ImGui::DebugHookIdInfo(
id, ImGuiDataType_Pointer, ptr, NULL);
3888ImGuiID ImGuiWindow::GetID(
int n)
3890 ImGuiID seed = IDStack.back();
3891 ImGuiID
id =
ImHashData(&n,
sizeof(n), seed);
3892 ImGuiContext&
g = *Ctx;
3893 if (
g.DebugHookIdInfo ==
id)
3894 ImGui::DebugHookIdInfo(
id, ImGuiDataType_S32, (
void*)(intptr_t)n, NULL);
3899ImGuiID ImGuiWindow::GetIDFromRectangle(
const ImRect& r_abs)
3901 ImGuiID seed = IDStack.back();
3902 ImRect r_rel = ImGui::WindowRectAbsToRel(
this, r_abs);
3903 ImGuiID
id =
ImHashData(&r_rel,
sizeof(r_rel), seed);
3907static void SetCurrentWindow(ImGuiWindow* window)
3910 g.CurrentWindow = window;
3911 g.CurrentTable = window && window->DC.CurrentTableIdx != -1 ?
g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL;
3914 g.FontSize =
g.DrawListSharedData.FontSize = window->CalcFontSize();
3915 ImGui::NavUpdateCurrentWindowIsScrollPushableX();
3919void ImGui::GcCompactTransientMiscBuffers()
3922 g.ItemFlagsStack.clear();
3923 g.GroupStack.clear();
3924 TableGcCompactSettings();
3931void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window)
3933 window->MemoryCompacted =
true;
3934 window->MemoryDrawListIdxCapacity = window->DrawList->IdxBuffer.Capacity;
3935 window->MemoryDrawListVtxCapacity = window->DrawList->VtxBuffer.Capacity;
3936 window->IDStack.clear();
3937 window->DrawList->_ClearFreeMemory();
3938 window->DC.ChildWindows.clear();
3939 window->DC.ItemWidthStack.clear();
3940 window->DC.TextWrapPosStack.clear();
3943void ImGui::GcAwakeTransientWindowBuffers(ImGuiWindow* window)
3947 window->MemoryCompacted =
false;
3948 window->DrawList->IdxBuffer.reserve(window->MemoryDrawListIdxCapacity);
3949 window->DrawList->VtxBuffer.reserve(window->MemoryDrawListVtxCapacity);
3950 window->MemoryDrawListIdxCapacity = window->MemoryDrawListVtxCapacity = 0;
3953void ImGui::SetActiveID(ImGuiID
id, ImGuiWindow* window)
3958 if (
g.ActiveId != 0)
3963 if (
g.MovingWindow != NULL &&
g.ActiveId ==
g.MovingWindow->MoveId)
3965 IMGUI_DEBUG_LOG_ACTIVEID(
"SetActiveID() cancel MovingWindow\n");
3966 g.MovingWindow = NULL;
3972 if (
g.InputTextState.ID ==
g.ActiveId)
3973 InputTextDeactivateHook(
g.ActiveId);
3977 g.ActiveIdIsJustActivated = (
g.ActiveId !=
id);
3978 if (
g.ActiveIdIsJustActivated)
3980 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 :
"");
3981 g.ActiveIdTimer = 0.0f;
3982 g.ActiveIdHasBeenPressedBefore =
false;
3983 g.ActiveIdHasBeenEditedBefore =
false;
3984 g.ActiveIdMouseButton = -1;
3987 g.LastActiveId =
id;
3988 g.LastActiveIdTimer = 0.0f;
3992 g.ActiveIdAllowOverlap =
false;
3993 g.ActiveIdNoClearOnFocusLoss =
false;
3994 g.ActiveIdWindow = window;
3995 g.ActiveIdHasBeenEditedThisFrame =
false;
3996 g.ActiveIdFromShortcut =
false;
3999 g.ActiveIdIsAlive =
id;
4000 g.ActiveIdSource = (
g.NavActivateId ==
id ||
g.NavJustMovedToId ==
id) ?
g.NavInputSource : ImGuiInputSource_Mouse;
4001 IM_ASSERT(
g.ActiveIdSource != ImGuiInputSource_None);
4006 g.ActiveIdUsingNavDirMask = 0x00;
4007 g.ActiveIdUsingAllKeyboardKeys =
false;
4008#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
4009 g.ActiveIdUsingNavInputMask = 0x00;
4013void ImGui::ClearActiveID()
4015 SetActiveID(0, NULL);
4018void ImGui::SetHoveredID(ImGuiID
id)
4022 g.HoveredIdAllowOverlap =
false;
4023 if (
id != 0 &&
g.HoveredIdPreviousFrame !=
id)
4024 g.HoveredIdTimer =
g.HoveredIdNotActiveTimer = 0.0f;
4027ImGuiID ImGui::GetHoveredID()
4030 return g.HoveredId ?
g.HoveredId :
g.HoveredIdPreviousFrame;
4033void ImGui::MarkItemEdited(ImGuiID
id)
4038 if (
g.LockMarkEdited > 0)
4040 if (
g.ActiveId ==
id ||
g.ActiveId == 0)
4042 g.ActiveIdHasBeenEditedThisFrame =
true;
4043 g.ActiveIdHasBeenEditedBefore =
true;
4048 IM_ASSERT(
g.DragDropActive ||
g.ActiveId ==
id ||
g.ActiveId == 0 ||
g.ActiveIdPreviousFrame ==
id);
4051 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
4054bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
4060 if (ImGuiWindow* focused_root_window =
g.NavWindow->RootWindowDockTree)
4061 if (focused_root_window->WasActive && focused_root_window != window->RootWindowDockTree)
4065 bool want_inhibit =
false;
4066 if (focused_root_window->Flags & ImGuiWindowFlags_Modal)
4067 want_inhibit =
true;
4068 else if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup))
4069 want_inhibit =
true;
4073 if (!IsWindowWithinBeginStackOf(window->RootWindow, focused_root_window))
4078 if (window->Viewport !=
g.MouseViewport)
4079 if (
g.MovingWindow == NULL || window->RootWindowDockTree !=
g.MovingWindow->RootWindowDockTree)
4085static inline float CalcDelayFromHoveredFlags(ImGuiHoveredFlags flags)
4088 if (flags & ImGuiHoveredFlags_DelayNormal)
4089 return g.Style.HoverDelayNormal;
4090 if (flags & ImGuiHoveredFlags_DelayShort)
4091 return g.Style.HoverDelayShort;
4095static ImGuiHoveredFlags ApplyHoverFlagsForTooltip(ImGuiHoveredFlags user_flags, ImGuiHoveredFlags shared_flags)
4098 if (user_flags & (ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal))
4099 shared_flags &= ~(ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal);
4100 return user_flags | shared_flags;
4106bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
4109 ImGuiWindow* window =
g.CurrentWindow;
4110 IM_ASSERT((flags & ~ImGuiHoveredFlags_AllowedMaskForIsItemHovered) == 0 &&
"Invalid flags for IsItemHovered()!");
4112 if (
g.NavDisableMouseHover && !
g.NavDisableHighlight && !(flags & ImGuiHoveredFlags_NoNavOverride))
4114 if ((
g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
4116 if (!IsItemFocused())
4119 if (flags & ImGuiHoveredFlags_ForTooltip)
4120 flags = ApplyHoverFlagsForTooltip(flags,
g.Style.HoverFlagsForTooltipNav);
4125 ImGuiItemStatusFlags status_flags =
g.LastItemData.StatusFlags;
4126 if (!(status_flags & ImGuiItemStatusFlags_HoveredRect))
4129 if (flags & ImGuiHoveredFlags_ForTooltip)
4130 flags = ApplyHoverFlagsForTooltip(flags,
g.Style.HoverFlagsForTooltipMouse);
4132 IM_ASSERT((flags & (ImGuiHoveredFlags_AnyWindow | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy | ImGuiHoveredFlags_DockHierarchy)) == 0);
4140 if (
g.HoveredWindow != window && (status_flags & ImGuiItemStatusFlags_HoveredWindow) == 0)
4141 if ((flags & ImGuiHoveredFlags_AllowWhenOverlappedByWindow) == 0)
4145 const ImGuiID
id =
g.LastItemData.ID;
4146 if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0)
4147 if (
g.ActiveId != 0 &&
g.ActiveId !=
id && !
g.ActiveIdAllowOverlap)
4148 if (
g.ActiveId != window->MoveId &&
g.ActiveId != window->TabId)
4153 if (!IsWindowContentHoverable(window, flags) && !(
g.LastItemData.InFlags & ImGuiItemFlags_NoWindowHoverableCheck))
4157 if ((
g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
4163 if (
id == window->MoveId && window->WriteAccessed)
4167 if ((
g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap) &&
id != 0)
4168 if ((flags & ImGuiHoveredFlags_AllowWhenOverlappedByItem) == 0)
4169 if (
g.HoveredIdPreviousFrame !=
g.LastItemData.ID)
4175 const float delay = CalcDelayFromHoveredFlags(flags);
4176 if (delay > 0.0f || (flags & ImGuiHoveredFlags_Stationary))
4178 ImGuiID hover_delay_id = (
g.LastItemData.ID != 0) ?
g.LastItemData.ID : window->GetIDFromRectangle(
g.LastItemData.Rect);
4179 if ((flags & ImGuiHoveredFlags_NoSharedDelay) && (
g.HoverItemDelayIdPreviousFrame != hover_delay_id))
4180 g.HoverItemDelayTimer = 0.0f;
4181 g.HoverItemDelayId = hover_delay_id;
4186 if ((flags & ImGuiHoveredFlags_Stationary) != 0 &&
g.HoverItemUnlockedStationaryId != hover_delay_id)
4189 if (
g.HoverItemDelayTimer < delay)
4202bool ImGui::ItemHoverable(
const ImRect& bb, ImGuiID
id, ImGuiItemFlags item_flags)
4205 ImGuiWindow* window =
g.CurrentWindow;
4206 if (
g.HoveredWindow != window)
4208 if (!IsMouseHoveringRect(bb.Min, bb.Max))
4211 if (
g.HoveredId != 0 &&
g.HoveredId !=
id && !
g.HoveredIdAllowOverlap)
4213 if (
g.ActiveId != 0 &&
g.ActiveId !=
id && !
g.ActiveIdAllowOverlap)
4214 if (!
g.ActiveIdFromShortcut)
4218 if (!(item_flags & ImGuiItemFlags_NoWindowHoverableCheck) && !IsWindowContentHoverable(window, ImGuiHoveredFlags_None))
4220 g.HoveredIdDisabled =
true;
4229 if (
g.DragDropActive &&
g.DragDropPayload.SourceId ==
id && !(
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoDisableHover))
4236 if (item_flags & ImGuiItemFlags_AllowOverlap)
4238 g.HoveredIdAllowOverlap =
true;
4239 if (
g.HoveredIdPreviousFrame !=
id)
4245 if (item_flags & ImGuiItemFlags_Disabled)
4248 if (
g.ActiveId ==
id &&
id != 0)
4250 g.HoveredIdDisabled =
true;
4254#ifndef IMGUI_DISABLE_DEBUG_TOOLS
4261 if (
g.DebugItemPickerActive &&
g.HoveredIdPreviousFrame ==
id)
4262 GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
4263 if (
g.DebugItemPickerBreakId ==
id)
4268 if (
g.NavDisableMouseHover)
4276bool ImGui::IsClippedEx(
const ImRect& bb, ImGuiID
id)
4279 ImGuiWindow* window =
g.CurrentWindow;
4280 if (!bb.Overlaps(window->ClipRect))
4281 if (
id == 0 || (
id !=
g.ActiveId &&
id !=
g.ActiveIdPreviousFrame &&
id !=
g.NavId &&
id !=
g.NavActivateId))
4289void ImGui::SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags item_flags,
const ImRect& item_rect)
4292 g.LastItemData.ID = item_id;
4293 g.LastItemData.InFlags = in_flags;
4294 g.LastItemData.StatusFlags = item_flags;
4295 g.LastItemData.Rect =
g.LastItemData.NavRect = item_rect;
4298float ImGui::CalcWrapWidthForPos(
const ImVec2& pos,
float wrap_pos_x)
4300 if (wrap_pos_x < 0.0f)
4304 ImGuiWindow* window =
g.CurrentWindow;
4305 if (wrap_pos_x == 0.0f)
4312 wrap_pos_x = window->WorkRect.Max.x;
4314 else if (wrap_pos_x > 0.0f)
4316 wrap_pos_x += window->Pos.x - window->Scroll.x;
4319 return ImMax(wrap_pos_x - pos.x, 1.0f);
4323void* ImGui::MemAlloc(
size_t size)
4325 void* ptr = (*GImAllocatorAllocFunc)(
size, GImAllocatorUserData);
4326#ifndef IMGUI_DISABLE_DEBUG_TOOLS
4327 if (ImGuiContext* ctx =
GImGui)
4328 DebugAllocHook(&ctx->DebugAllocInfo, ctx->FrameCount, ptr, size);
4334void ImGui::MemFree(
void* ptr)
4336#ifndef IMGUI_DISABLE_DEBUG_TOOLS
4338 if (ImGuiContext* ctx =
GImGui)
4339 DebugAllocHook(&ctx->DebugAllocInfo, ctx->FrameCount, ptr, (
size_t)-1);
4341 return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData);
4345void ImGui::DebugAllocHook(ImGuiDebugAllocInfo* info,
int frame_count,
void* ptr,
size_t size)
4347 ImGuiDebugAllocEntry* entry = &info->LastEntriesBuf[info->LastEntriesIdx];
4349 if (entry->FrameCount != frame_count)
4351 info->LastEntriesIdx = (info->LastEntriesIdx + 1) % IM_ARRAYSIZE(info->LastEntriesBuf);
4352 entry = &info->LastEntriesBuf[info->LastEntriesIdx];
4353 entry->FrameCount = frame_count;
4354 entry->AllocCount = entry->FreeCount = 0;
4356 if (size != (
size_t)-1)
4358 entry->AllocCount++;
4359 info->TotalAllocCount++;
4365 info->TotalFreeCount++;
4370const char* ImGui::GetClipboardText()
4373 return g.IO.GetClipboardTextFn ?
g.IO.GetClipboardTextFn(
g.IO.ClipboardUserData) :
"";
4376void ImGui::SetClipboardText(
const char* text)
4379 if (
g.IO.SetClipboardTextFn)
4380 g.IO.SetClipboardTextFn(
g.IO.ClipboardUserData, text);
4383const char* ImGui::GetVersion()
4385 return IMGUI_VERSION;
4388ImGuiIO& ImGui::GetIO()
4390 IM_ASSERT(
GImGui != NULL &&
"No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
4394ImGuiPlatformIO& ImGui::GetPlatformIO()
4396 IM_ASSERT(
GImGui != NULL &&
"No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
4397 return GImGui->PlatformIO;
4401ImDrawData* ImGui::GetDrawData()
4404 ImGuiViewportP* viewport =
g.Viewports[0];
4405 return viewport->DrawDataP.Valid ? &viewport->DrawDataP : NULL;
4408double ImGui::GetTime()
4413int ImGui::GetFrameCount()
4415 return GImGui->FrameCount;
4418static ImDrawList* GetViewportBgFgDrawList(ImGuiViewportP* viewport,
size_t drawlist_no,
const char* drawlist_name)
4422 IM_ASSERT(drawlist_no < IM_ARRAYSIZE(viewport->BgFgDrawLists));
4423 ImDrawList* draw_list = viewport->BgFgDrawLists[drawlist_no];
4424 if (draw_list == NULL)
4426 draw_list = IM_NEW(ImDrawList)(&
g.DrawListSharedData);
4427 draw_list->_OwnerName = drawlist_name;
4428 viewport->BgFgDrawLists[drawlist_no] = draw_list;
4432 if (viewport->BgFgDrawListsLastFrame[drawlist_no] !=
g.FrameCount)
4434 draw_list->_ResetForNewFrame();
4435 draw_list->PushTextureID(
g.IO.Fonts->TexID);
4436 draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size,
false);
4437 viewport->BgFgDrawListsLastFrame[drawlist_no] =
g.FrameCount;
4442ImDrawList* ImGui::GetBackgroundDrawList(ImGuiViewport* viewport)
4444 return GetViewportBgFgDrawList((ImGuiViewportP*)viewport, 0,
"##Background");
4447ImDrawList* ImGui::GetBackgroundDrawList()
4450 return GetBackgroundDrawList(
g.CurrentWindow->Viewport);
4453ImDrawList* ImGui::GetForegroundDrawList(ImGuiViewport* viewport)
4455 return GetViewportBgFgDrawList((ImGuiViewportP*)viewport, 1,
"##Foreground");
4458ImDrawList* ImGui::GetForegroundDrawList()
4461 return GetForegroundDrawList(
g.CurrentWindow->Viewport);
4464ImDrawListSharedData* ImGui::GetDrawListSharedData()
4466 return &
GImGui->DrawListSharedData;
4469void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
4475 FocusWindow(window);
4476 SetActiveID(window->MoveId, window);
4477 g.NavDisableHighlight =
true;
4478 g.ActiveIdClickOffset =
g.IO.MouseClickedPos[0] - window->RootWindowDockTree->Pos;
4479 g.ActiveIdNoClearOnFocusLoss =
true;
4480 SetActiveIdUsingAllKeyboardKeys();
4482 bool can_move_window =
true;
4483 if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindowDockTree->Flags & ImGuiWindowFlags_NoMove))
4484 can_move_window =
false;
4485 if (ImGuiDockNode* node = window->DockNodeAsHost)
4486 if (node->VisibleWindow && (node->VisibleWindow->Flags & ImGuiWindowFlags_NoMove))
4487 can_move_window =
false;
4488 if (can_move_window)
4489 g.MovingWindow = window;
4493void ImGui::StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* node,
bool undock)
4496 bool can_undock_node =
false;
4497 if (undock && node != NULL && node->VisibleWindow && (node->VisibleWindow->Flags & ImGuiWindowFlags_NoMove) == 0 && (node->MergedFlags & ImGuiDockNodeFlags_NoUndocking) == 0)
4502 ImGuiDockNode* root_node = DockNodeGetRootNode(node);
4503 if (root_node->OnlyNodeWithWindows != node || root_node->CentralNode != NULL)
4504 can_undock_node =
true;
4507 const bool clicked = IsMouseClicked(0);
4508 const bool dragging = IsMouseDragging(0);
4509 if (can_undock_node && dragging)
4510 DockContextQueueUndockNode(&
g, node);
4511 else if (!can_undock_node && (clicked || dragging) &&
g.MovingWindow != window)
4512 StartMouseMovingWindow(window);
4520void ImGui::UpdateMouseMovingWindowNewFrame()
4523 if (
g.MovingWindow != NULL)
4527 KeepAliveID(
g.ActiveId);
4528 IM_ASSERT(
g.MovingWindow &&
g.MovingWindow->RootWindowDockTree);
4529 ImGuiWindow* moving_window =
g.MovingWindow->RootWindowDockTree;
4532 const bool window_disappared = (!moving_window->WasActive && !moving_window->Active);
4533 if (
g.IO.MouseDown[0] && IsMousePosValid(&
g.IO.MousePos) && !window_disappared)
4535 ImVec2 pos =
g.IO.MousePos -
g.ActiveIdClickOffset;
4536 if (moving_window->Pos.x != pos.x || moving_window->Pos.y != pos.y)
4538 SetWindowPos(moving_window, pos, ImGuiCond_Always);
4539 if (moving_window->Viewport && moving_window->ViewportOwned)
4541 moving_window->Viewport->Pos = pos;
4542 moving_window->Viewport->UpdateWorkRect();
4545 FocusWindow(
g.MovingWindow);
4549 if (!window_disappared)
4553 if (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
4554 UpdateTryMergeWindowIntoHostViewport(moving_window,
g.MouseViewport);
4557 if (moving_window->Viewport && !IsDragDropPayloadBeingAccepted())
4558 g.MouseViewport = moving_window->Viewport;
4561 if (moving_window->Viewport)
4562 moving_window->Viewport->Flags &= ~ImGuiViewportFlags_NoInputs;
4565 g.MovingWindow = NULL;
4572 if (
g.ActiveIdWindow &&
g.ActiveIdWindow->MoveId ==
g.ActiveId)
4574 KeepAliveID(
g.ActiveId);
4575 if (!
g.IO.MouseDown[0])
4583void ImGui::UpdateMouseMovingWindowEndFrame()
4586 if (
g.ActiveId != 0 ||
g.HoveredId != 0)
4590 if (
g.NavWindow &&
g.NavWindow->Appearing)
4595 if (
g.IO.MouseClicked[0])
4599 ImGuiWindow* root_window =
g.HoveredWindow ?
g.HoveredWindow->RootWindow : NULL;
4600 const bool is_closed_popup = root_window && (root_window->Flags & ImGuiWindowFlags_Popup) && !IsPopupOpen(root_window->PopupId, ImGuiPopupFlags_AnyPopupLevel);
4602 if (root_window != NULL && !is_closed_popup)
4604 StartMouseMovingWindow(
g.HoveredWindow);
4607 if (
g.IO.ConfigWindowsMoveFromTitleBarOnly)
4608 if (!(root_window->Flags & ImGuiWindowFlags_NoTitleBar) || root_window->DockIsActive)
4609 if (!root_window->TitleBarRect().Contains(
g.IO.MouseClickedPos[0]))
4610 g.MovingWindow = NULL;
4613 if (
g.HoveredIdDisabled)
4614 g.MovingWindow = NULL;
4616 else if (root_window == NULL &&
g.NavWindow != NULL)
4619 FocusWindow(NULL, ImGuiFocusRequestFlags_UnlessBelowModal);
4626 if (
g.IO.MouseClicked[1])
4630 ImGuiWindow* modal = GetTopMostPopupModal();
4631 bool hovered_window_above_modal =
g.HoveredWindow && (modal == NULL || IsWindowAbove(
g.HoveredWindow, modal));
4632 ClosePopupsOverWindow(hovered_window_above_modal ?
g.HoveredWindow : modal, true);
4638static void TranslateWindow(ImGuiWindow* window,
const ImVec2& delta)
4640 window->Pos += delta;
4641 window->ClipRect.Translate(delta);
4642 window->OuterRectClipped.Translate(delta);
4643 window->InnerRect.Translate(delta);
4644 window->DC.CursorPos += delta;
4645 window->DC.CursorStartPos += delta;
4646 window->DC.CursorMaxPos += delta;
4647 window->DC.IdealMaxPos += delta;
4650static void ScaleWindow(ImGuiWindow* window,
float scale)
4652 ImVec2 origin = window->Viewport->Pos;
4653 window->Pos = ImFloor((window->Pos - origin) * scale + origin);
4654 window->Size = ImTrunc(window->Size * scale);
4655 window->SizeFull = ImTrunc(window->SizeFull * scale);
4656 window->ContentSize = ImTrunc(window->ContentSize * scale);
4659static bool IsWindowActiveAndVisible(ImGuiWindow* window)
4661 return (window->Active) && (!window->Hidden);
4665void ImGui::UpdateHoveredWindowAndCaptureFlags()
4669 g.WindowsHoverPadding = ImMax(
g.Style.TouchExtraPadding, ImVec2(WINDOWS_HOVER_PADDING, WINDOWS_HOVER_PADDING));
4675 bool clear_hovered_windows =
false;
4676 FindHoveredWindow();
4677 IM_ASSERT(
g.HoveredWindow == NULL ||
g.HoveredWindow ==
g.MovingWindow ||
g.HoveredWindow->Viewport ==
g.MouseViewport);
4680 ImGuiWindow* modal_window = GetTopMostPopupModal();
4681 if (modal_window &&
g.HoveredWindow && !IsWindowWithinBeginStackOf(
g.HoveredWindow->RootWindow, modal_window))
4682 clear_hovered_windows =
true;
4685 if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)
4686 clear_hovered_windows =
true;
4690 const bool has_open_popup = (
g.OpenPopupStack.Size > 0);
4691 const bool has_open_modal = (modal_window != NULL);
4692 int mouse_earliest_down = -1;
4693 bool mouse_any_down =
false;
4694 for (
int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
4696 if (io.MouseClicked[i])
4698 io.MouseDownOwned[i] = (
g.HoveredWindow != NULL) || has_open_popup;
4699 io.MouseDownOwnedUnlessPopupClose[i] = (
g.HoveredWindow != NULL) || has_open_modal;
4701 mouse_any_down |= io.MouseDown[i];
4702 if (io.MouseDown[i])
4703 if (mouse_earliest_down == -1 || io.MouseClickedTime[i] < io.MouseClickedTime[mouse_earliest_down])
4704 mouse_earliest_down = i;
4706 const bool mouse_avail = (mouse_earliest_down == -1) || io.MouseDownOwned[mouse_earliest_down];
4707 const bool mouse_avail_unless_popup_close = (mouse_earliest_down == -1) || io.MouseDownOwnedUnlessPopupClose[mouse_earliest_down];
4711 const bool mouse_dragging_extern_payload =
g.DragDropActive && (
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0;
4712 if (!mouse_avail && !mouse_dragging_extern_payload)
4713 clear_hovered_windows =
true;
4715 if (clear_hovered_windows)
4716 g.HoveredWindow =
g.HoveredWindowUnderMovingWindow = NULL;
4720 if (
g.WantCaptureMouseNextFrame != -1)
4722 io.WantCaptureMouse = io.WantCaptureMouseUnlessPopupClose = (
g.WantCaptureMouseNextFrame != 0);
4726 io.WantCaptureMouse = (mouse_avail && (
g.HoveredWindow != NULL || mouse_any_down)) || has_open_popup;
4727 io.WantCaptureMouseUnlessPopupClose = (mouse_avail_unless_popup_close && (
g.HoveredWindow != NULL || mouse_any_down)) || has_open_modal;
4731 io.WantCaptureKeyboard = (
g.ActiveId != 0) || (modal_window != NULL);
4732 if (io.NavActive && (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard))
4733 io.WantCaptureKeyboard =
true;
4734 if (
g.WantCaptureKeyboardNextFrame != -1)
4735 io.WantCaptureKeyboard = (
g.WantCaptureKeyboardNextFrame != 0);
4738 io.WantTextInput = (
g.WantTextInputNextFrame != -1) ? (
g.WantTextInputNextFrame != 0) :
false;
4741void ImGui::NewFrame()
4743 IM_ASSERT(
GImGui != NULL &&
"No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
4748 for (
int n =
g.Hooks.Size - 1; n >= 0; n--)
4749 if (
g.Hooks[n].Type == ImGuiContextHookType_PendingRemoval_)
4750 g.Hooks.erase(&
g.Hooks[n]);
4752 CallContextHooks(&
g, ImGuiContextHookType_NewFramePre);
4755 g.ConfigFlagsLastFrame =
g.ConfigFlagsCurrFrame;
4756 ErrorCheckNewFrameSanityChecks();
4757 g.ConfigFlagsCurrFrame =
g.IO.ConfigFlags;
4762 g.Time +=
g.IO.DeltaTime;
4763 g.WithinFrameScope =
true;
4765 g.TooltipOverrideCount = 0;
4766 g.WindowsActiveCount = 0;
4767 g.MenusIdSubmittedThisFrame.resize(0);
4770 g.FramerateSecPerFrameAccum +=
g.IO.DeltaTime -
g.FramerateSecPerFrame[
g.FramerateSecPerFrameIdx];
4771 g.FramerateSecPerFrame[
g.FramerateSecPerFrameIdx] =
g.IO.DeltaTime;
4772 g.FramerateSecPerFrameIdx = (
g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(
g.FramerateSecPerFrame);
4773 g.FramerateSecPerFrameCount = ImMin(
g.FramerateSecPerFrameCount + 1, IM_ARRAYSIZE(
g.FramerateSecPerFrame));
4774 g.IO.Framerate = (
g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (
g.FramerateSecPerFrameAccum / (
float)
g.FramerateSecPerFrameCount)) : FLT_MAX;
4777 g.InputEventsTrail.resize(0);
4778 UpdateInputEvents(
g.IO.ConfigInputTrickleEventQueue);
4781 UpdateViewportsNewFrame();
4785 g.IO.Fonts->Locked =
true;
4786 SetCurrentFont(GetDefaultFont());
4787 IM_ASSERT(
g.Font->IsLoaded());
4788 ImRect virtual_space(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
4789 for (ImGuiViewportP* viewport :
g.Viewports)
4790 virtual_space.Add(viewport->GetMainRect());
4791 g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4();
4792 g.DrawListSharedData.CurveTessellationTol =
g.Style.CurveTessellationTol;
4793 g.DrawListSharedData.SetCircleTessellationMaxError(
g.Style.CircleTessellationMaxError);
4794 g.DrawListSharedData.InitialFlags = ImDrawListFlags_None;
4795 if (
g.Style.AntiAliasedLines)
4796 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines;
4797 if (
g.Style.AntiAliasedLinesUseTex && !(
g.Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedLines))
4798 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLinesUseTex;
4799 if (
g.Style.AntiAliasedFill)
4800 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill;
4801 if (
g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)
4802 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset;
4805 for (ImGuiViewportP* viewport :
g.Viewports)
4807 viewport->DrawData = NULL;
4808 viewport->DrawDataP.Valid =
false;
4812 if (
g.DragDropActive &&
g.DragDropPayload.SourceId ==
g.ActiveId)
4813 KeepAliveID(
g.DragDropPayload.SourceId);
4816 if (!
g.HoveredIdPreviousFrame)
4817 g.HoveredIdTimer = 0.0f;
4818 if (!
g.HoveredIdPreviousFrame || (
g.HoveredId &&
g.ActiveId ==
g.HoveredId))
4819 g.HoveredIdNotActiveTimer = 0.0f;
4821 g.HoveredIdTimer +=
g.IO.DeltaTime;
4822 if (
g.HoveredId &&
g.ActiveId !=
g.HoveredId)
4823 g.HoveredIdNotActiveTimer +=
g.IO.DeltaTime;
4824 g.HoveredIdPreviousFrame =
g.HoveredId;
4826 g.HoveredIdAllowOverlap =
false;
4827 g.HoveredIdDisabled =
false;
4832 if (
g.ActiveId != 0 &&
g.ActiveIdIsAlive !=
g.ActiveId &&
g.ActiveIdPreviousFrame ==
g.ActiveId)
4834 IMGUI_DEBUG_LOG_ACTIVEID(
"NewFrame(): ClearActiveID() because it isn't marked alive anymore!\n");
4840 g.ActiveIdTimer +=
g.IO.DeltaTime;
4841 g.LastActiveIdTimer +=
g.IO.DeltaTime;
4842 g.ActiveIdPreviousFrame =
g.ActiveId;
4843 g.ActiveIdPreviousFrameWindow =
g.ActiveIdWindow;
4844 g.ActiveIdPreviousFrameHasBeenEditedBefore =
g.ActiveIdHasBeenEditedBefore;
4845 g.ActiveIdIsAlive = 0;
4846 g.ActiveIdHasBeenEditedThisFrame =
false;
4847 g.ActiveIdPreviousFrameIsAlive =
false;
4848 g.ActiveIdIsJustActivated =
false;
4849 if (
g.TempInputId != 0 &&
g.ActiveId !=
g.TempInputId)
4851 if (
g.ActiveId == 0)
4853 g.ActiveIdUsingNavDirMask = 0x00;
4854 g.ActiveIdUsingAllKeyboardKeys =
false;
4855#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
4856 g.ActiveIdUsingNavInputMask = 0x00;
4860#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
4861 if (
g.ActiveId == 0)
4862 g.ActiveIdUsingNavInputMask = 0;
4863 else if (
g.ActiveIdUsingNavInputMask != 0)
4867 if (
g.ActiveIdUsingNavInputMask & (1 << ImGuiNavInput_Cancel))
4868 SetKeyOwner(ImGuiKey_Escape,
g.ActiveId);
4869 if (
g.ActiveIdUsingNavInputMask & ~(1 << ImGuiNavInput_Cancel))
4877 if (
g.HoverItemDelayId != 0 &&
g.MouseStationaryTimer >=
g.Style.HoverStationaryDelay)
4878 g.HoverItemUnlockedStationaryId =
g.HoverItemDelayId;
4879 else if (
g.HoverItemDelayId == 0)
4880 g.HoverItemUnlockedStationaryId = 0;
4881 if (
g.HoveredWindow != NULL &&
g.MouseStationaryTimer >=
g.Style.HoverStationaryDelay)
4882 g.HoverWindowUnlockedStationaryId =
g.HoveredWindow->ID;
4883 else if (
g.HoveredWindow == NULL)
4884 g.HoverWindowUnlockedStationaryId = 0;
4887 g.HoverItemDelayIdPreviousFrame =
g.HoverItemDelayId;
4888 if (
g.HoverItemDelayId != 0)
4890 g.HoverItemDelayTimer +=
g.IO.DeltaTime;
4891 g.HoverItemDelayClearTimer = 0.0f;
4892 g.HoverItemDelayId = 0;
4894 else if (
g.HoverItemDelayTimer > 0.0f)
4898 g.HoverItemDelayClearTimer +=
g.IO.DeltaTime;
4899 if (
g.HoverItemDelayClearTimer >= ImMax(0.25f,
g.IO.DeltaTime * 2.0f))
4900 g.HoverItemDelayTimer =
g.HoverItemDelayClearTimer = 0.0f;
4904 g.DragDropAcceptIdPrev =
g.DragDropAcceptIdCurr;
4905 g.DragDropAcceptIdCurr = 0;
4906 g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
4907 g.DragDropWithinSource =
false;
4908 g.DragDropWithinTarget =
false;
4909 g.DragDropHoldJustPressedId = 0;
4916 UpdateKeyboardInputs();
4927 UpdateMouseInputs();
4931 DockContextNewFrameUpdateUndocking(&
g);
4935 UpdateHoveredWindowAndCaptureFlags();
4938 UpdateMouseMovingWindowNewFrame();
4941 if (GetTopMostPopupModal() != NULL || (
g.NavWindowingTarget != NULL &&
g.NavWindowingHighlightAlpha > 0.0f))
4942 g.DimBgRatio = ImMin(
g.DimBgRatio +
g.IO.DeltaTime * 6.0f, 1.0f);
4944 g.DimBgRatio = ImMax(
g.DimBgRatio -
g.IO.DeltaTime * 10.0f, 0.0f);
4946 g.MouseCursor = ImGuiMouseCursor_Arrow;
4947 g.WantCaptureMouseNextFrame =
g.WantCaptureKeyboardNextFrame =
g.WantTextInputNextFrame = -1;
4950 g.PlatformImeDataPrev =
g.PlatformImeData;
4951 g.PlatformImeData.WantVisible =
false;
4957 IM_ASSERT(
g.WindowsFocusOrder.Size <=
g.Windows.Size);
4958 const float memory_compact_start_time = (
g.GcCompactAll ||
g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)
g.Time -
g.IO.ConfigMemoryCompactTimer;
4959 for (ImGuiWindow* window :
g.Windows)
4961 window->WasActive = window->Active;
4962 window->Active =
false;
4963 window->WriteAccessed =
false;
4964 window->BeginCountPreviousFrame = window->BeginCount;
4965 window->BeginCount = 0;
4968 if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
4969 GcCompactTransientWindowBuffers(window);
4973 for (
int i = 0; i <
g.TablesLastTimeActive.Size; i++)
4974 if (
g.TablesLastTimeActive[i] >= 0.0f &&
g.TablesLastTimeActive[i] < memory_compact_start_time)
4975 TableGcCompactTransientBuffers(
g.Tables.GetByIndex(i));
4976 for (ImGuiTableTempData& table_temp_data :
g.TablesTempData)
4977 if (table_temp_data.LastTimeActive >= 0.0f && table_temp_data.LastTimeActive < memory_compact_start_time)
4978 TableGcCompactTransientBuffers(&table_temp_data);
4980 GcCompactTransientMiscBuffers();
4981 g.GcCompactAll =
false;
4984 if (
g.NavWindow && !
g.NavWindow->WasActive)
4985 FocusTopMostWindowUnderOne(NULL, NULL, NULL, ImGuiFocusRequestFlags_RestoreFocusedChild);
4989 g.CurrentWindowStack.resize(0);
4990 g.BeginPopupStack.resize(0);
4991 g.ItemFlagsStack.resize(0);
4992 g.ItemFlagsStack.push_back(ImGuiItemFlags_None);
4993 g.GroupStack.resize(0);
4996 DockContextNewFrameUpdateDocking(&
g);
4999#ifndef IMGUI_DISABLE_DEBUG_TOOLS
5000 UpdateDebugToolItemPicker();
5001 UpdateDebugToolStackQueries();
5002 UpdateDebugToolFlashStyleColor();
5003 if (
g.DebugLocateFrames > 0 && --
g.DebugLocateFrames == 0)
5005 g.DebugLocateId = 0;
5006 g.DebugBreakInLocateId =
false;
5008 if (
g.DebugLogAutoDisableFrames > 0 && --
g.DebugLogAutoDisableFrames == 0)
5010 DebugLog(
"(Debug Log: Auto-disabled some ImGuiDebugLogFlags after 2 frames)\n");
5011 g.DebugLogFlags &= ~g.DebugLogAutoDisableFlags;
5012 g.DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
5019 g.WithinFrameScopeWithImplicitWindow =
true;
5020 SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
5021 Begin(
"Debug##Default");
5022 IM_ASSERT(
g.CurrentWindow->IsFallbackWindow ==
true);
5026#ifndef IMGUI_DISABLE_DEBUG_TOOLS
5027 if (
g.IO.ConfigDebugBeginReturnValueLoop)
5028 g.DebugBeginReturnValueCullDepth = (
g.DebugBeginReturnValueCullDepth == -1) ? 0 : ((
g.DebugBeginReturnValueCullDepth + ((
g.FrameCount % 4) == 0 ? 1 : 0)) % 10);
5030 g.DebugBeginReturnValueCullDepth = -1;
5033 CallContextHooks(&
g, ImGuiContextHookType_NewFramePost);
5037static int IMGUI_CDECL ChildWindowComparer(
const void* lhs,
const void* rhs)
5039 const ImGuiWindow*
const a = *(
const ImGuiWindow*
const *)lhs;
5040 const ImGuiWindow*
const b = *(
const ImGuiWindow*
const *)rhs;
5041 if (
int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup))
5043 if (
int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip))
5045 return (a->BeginOrderWithinParent - b->BeginOrderWithinParent);
5048static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window)
5050 out_sorted_windows->push_back(window);
5053 int count = window->DC.ChildWindows.Size;
5054 ImQsort(window->DC.ChildWindows.Data, (
size_t)count,
sizeof(ImGuiWindow*), ChildWindowComparer);
5055 for (
int i = 0; i <
count; i++)
5057 ImGuiWindow* child = window->DC.ChildWindows[i];
5059 AddWindowToSortBuffer(out_sorted_windows, child);
5064static void AddWindowToDrawData(ImGuiWindow* window,
int layer)
5067 ImGuiViewportP* viewport = window->Viewport;
5068 IM_ASSERT(viewport != NULL);
5069 g.IO.MetricsRenderWindows++;
5070 if (window->DrawList->_Splitter._Count > 1)
5071 window->DrawList->ChannelsMerge();
5072 ImGui::AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[layer], window->DrawList);
5073 for (ImGuiWindow* child : window->DC.ChildWindows)
5074 if (IsWindowActiveAndVisible(child))
5075 AddWindowToDrawData(child, layer);
5078static inline int GetWindowDisplayLayer(ImGuiWindow* window)
5080 return (window->Flags & ImGuiWindowFlags_Tooltip) ? 1 : 0;
5084static inline void AddRootWindowToDrawData(ImGuiWindow* window)
5086 AddWindowToDrawData(window, GetWindowDisplayLayer(window));
5089static void FlattenDrawDataIntoSingleLayer(ImDrawDataBuilder* builder)
5091 int n = builder->Layers[0]->Size;
5093 for (
int i = 1; i < IM_ARRAYSIZE(builder->Layers); i++)
5094 full_size += builder->Layers[i]->Size;
5095 builder->Layers[0]->resize(full_size);
5096 for (
int layer_n = 1; layer_n < IM_ARRAYSIZE(builder->Layers); layer_n++)
5098 ImVector<ImDrawList*>* layer = builder->Layers[layer_n];
5101 memcpy(builder->Layers[0]->Data + n, layer->Data, layer->Size *
sizeof(ImDrawList*));
5107static void InitViewportDrawData(ImGuiViewportP* viewport)
5109 ImGuiIO& io = ImGui::GetIO();
5110 ImDrawData* draw_data = &viewport->DrawDataP;
5112 viewport->DrawData = draw_data;
5113 viewport->DrawDataBuilder.Layers[0] = &draw_data->CmdLists;
5114 viewport->DrawDataBuilder.Layers[1] = &viewport->DrawDataBuilder.LayerData1;
5115 viewport->DrawDataBuilder.Layers[0]->resize(0);
5116 viewport->DrawDataBuilder.Layers[1]->resize(0);
5123 const bool is_minimized = (viewport->Flags & ImGuiViewportFlags_IsMinimized) != 0;
5125 draw_data->Valid =
true;
5126 draw_data->CmdListsCount = 0;
5127 draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0;
5128 draw_data->DisplayPos = viewport->Pos;
5129 draw_data->DisplaySize = is_minimized ? ImVec2(0.0f, 0.0f) : viewport->Size;
5130 draw_data->FramebufferScale = io.DisplayFramebufferScale;
5131 draw_data->OwnerViewport = viewport;
5140void ImGui::PushClipRect(
const ImVec2& clip_rect_min,
const ImVec2& clip_rect_max,
bool intersect_with_current_clip_rect)
5142 ImGuiWindow* window = GetCurrentWindow();
5143 window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect);
5144 window->ClipRect = window->DrawList->_ClipRectStack.back();
5147void ImGui::PopClipRect()
5149 ImGuiWindow* window = GetCurrentWindow();
5150 window->DrawList->PopClipRect();
5151 window->ClipRect = window->DrawList->_ClipRectStack.back();
5154static ImGuiWindow* FindFrontMostVisibleChildWindow(ImGuiWindow* window)
5156 for (
int n = window->DC.ChildWindows.Size - 1; n >= 0; n--)
5157 if (IsWindowActiveAndVisible(window->DC.ChildWindows[n]))
5158 return FindFrontMostVisibleChildWindow(window->DC.ChildWindows[n]);
5162static void ImGui::RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col)
5164 if ((col & IM_COL32_A_MASK) == 0)
5167 ImGuiViewportP* viewport = window->Viewport;
5168 ImRect viewport_rect = viewport->GetMainRect();
5174 ImDrawList* draw_list = window->RootWindowDockTree->DrawList;
5175 draw_list->ChannelsMerge();
5176 if (draw_list->CmdBuffer.Size == 0)
5177 draw_list->AddDrawCmd();
5178 draw_list->PushClipRect(viewport_rect.Min - ImVec2(1, 1), viewport_rect.Max + ImVec2(1, 1),
false);
5179 draw_list->AddRectFilled(viewport_rect.Min, viewport_rect.Max, col);
5180 ImDrawCmd cmd = draw_list->CmdBuffer.back();
5181 IM_ASSERT(cmd.ElemCount == 6);
5182 draw_list->CmdBuffer.pop_back();
5183 draw_list->CmdBuffer.push_front(cmd);
5184 draw_list->AddDrawCmd();
5185 draw_list->PopClipRect();
5189 if (window->RootWindow->DockIsActive)
5191 ImDrawList* draw_list = FindFrontMostVisibleChildWindow(window->RootWindowDockTree)->DrawList;
5192 draw_list->ChannelsMerge();
5193 if (draw_list->CmdBuffer.Size == 0)
5194 draw_list->AddDrawCmd();
5195 draw_list->PushClipRect(viewport_rect.Min, viewport_rect.Max,
false);
5196 RenderRectFilledWithHole(draw_list, window->RootWindowDockTree->Rect(), window->RootWindow->Rect(), col, 0.0f);
5197 draw_list->PopClipRect();
5201ImGuiWindow* ImGui::FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* parent_window)
5204 ImGuiWindow* bottom_most_visible_window = parent_window;
5205 for (
int i = FindWindowDisplayIndex(parent_window); i >= 0; i--)
5207 ImGuiWindow* window =
g.Windows[i];
5208 if (window->Flags & ImGuiWindowFlags_ChildWindow)
5210 if (!IsWindowWithinBeginStackOf(window, parent_window))
5212 if (IsWindowActiveAndVisible(window) && GetWindowDisplayLayer(window) <= GetWindowDisplayLayer(parent_window))
5213 bottom_most_visible_window = window;
5215 return bottom_most_visible_window;
5220static void ImGui::RenderDimmedBackgrounds()
5223 ImGuiWindow* modal_window = GetTopMostAndVisiblePopupModal();
5224 if (
g.DimBgRatio <= 0.0f &&
g.NavWindowingHighlightAlpha <= 0.0f)
5226 const bool dim_bg_for_modal = (modal_window != NULL);
5227 const bool dim_bg_for_window_list = (
g.NavWindowingTargetAnim != NULL &&
g.NavWindowingTargetAnim->Active);
5228 if (!dim_bg_for_modal && !dim_bg_for_window_list)
5231 ImGuiViewport* viewports_already_dimmed[2] = { NULL, NULL };
5232 if (dim_bg_for_modal)
5235 ImGuiWindow* dim_behind_window = FindBottomMostVisibleWindowWithinBeginStack(modal_window);
5236 RenderDimmedBackgroundBehindWindow(dim_behind_window, GetColorU32(modal_window->DC.ModalDimBgColor,
g.DimBgRatio));
5237 viewports_already_dimmed[0] = modal_window->Viewport;
5239 else if (dim_bg_for_window_list)
5242 RenderDimmedBackgroundBehindWindow(
g.NavWindowingTargetAnim, GetColorU32(ImGuiCol_NavWindowingDimBg,
g.DimBgRatio));
5243 if (
g.NavWindowingListWindow != NULL &&
g.NavWindowingListWindow->Viewport &&
g.NavWindowingListWindow->Viewport !=
g.NavWindowingTargetAnim->Viewport)
5244 RenderDimmedBackgroundBehindWindow(
g.NavWindowingListWindow, GetColorU32(ImGuiCol_NavWindowingDimBg,
g.DimBgRatio));
5245 viewports_already_dimmed[0] =
g.NavWindowingTargetAnim->Viewport;
5246 viewports_already_dimmed[1] =
g.NavWindowingListWindow ?
g.NavWindowingListWindow->Viewport : NULL;
5249 ImGuiWindow* window =
g.NavWindowingTargetAnim;
5250 ImGuiViewport* viewport = window->Viewport;
5252 ImRect bb = window->Rect();
5253 bb.Expand(distance);
5254 if (bb.GetWidth() >= viewport->Size.x && bb.GetHeight() >= viewport->Size.y)
5255 bb.Expand(-distance - 1.0f);
5256 window->DrawList->ChannelsMerge();
5257 if (window->DrawList->CmdBuffer.Size == 0)
5258 window->DrawList->AddDrawCmd();
5259 window->DrawList->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size);
5260 window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight,
g.NavWindowingHighlightAlpha), window->WindowRounding, 0, 3.0f);
5261 window->DrawList->PopClipRect();
5265 for (ImGuiViewportP* viewport :
g.Viewports)
5267 if (viewport == viewports_already_dimmed[0] || viewport == viewports_already_dimmed[1])
5269 if (modal_window && viewport->Window && IsWindowAbove(viewport->Window, modal_window))
5271 ImDrawList* draw_list = GetForegroundDrawList(viewport);
5272 const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg,
g.DimBgRatio);
5273 draw_list->AddRectFilled(viewport->Pos, viewport->Pos + viewport->Size, dim_bg_col);
5278void ImGui::EndFrame()
5281 IM_ASSERT(
g.Initialized);
5284 if (
g.FrameCountEnded ==
g.FrameCount)
5286 IM_ASSERT(
g.WithinFrameScope &&
"Forgot to call ImGui::NewFrame()?");
5288 CallContextHooks(&
g, ImGuiContextHookType_EndFramePre);
5290 ErrorCheckEndFrameSanityChecks();
5293 ImGuiPlatformImeData* ime_data = &
g.PlatformImeData;
5294 if (
g.IO.SetPlatformImeDataFn && memcmp(ime_data, &
g.PlatformImeDataPrev,
sizeof(ImGuiPlatformImeData)) != 0)
5296 ImGuiViewport* viewport = FindViewportByID(
g.PlatformImeViewport);
5297 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);
5298 if (viewport == NULL)
5299 viewport = GetMainViewport();
5300 g.IO.SetPlatformImeDataFn(viewport, ime_data);
5304 g.WithinFrameScopeWithImplicitWindow =
false;
5305 if (
g.CurrentWindow && !
g.CurrentWindow->WriteAccessed)
5306 g.CurrentWindow->Active =
false;
5313 DockContextEndFrame(&
g);
5315 SetCurrentViewport(NULL, NULL);
5318 if (
g.DragDropActive)
5320 bool is_delivered =
g.DragDropPayload.Delivery;
5321 bool is_elapsed = (
g.DragDropPayload.DataFrameCount + 1 <
g.FrameCount) && ((
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceAutoExpirePayload) || !IsMouseDown(
g.DragDropMouseButton));
5322 if (is_delivered || is_elapsed)
5327 if (
g.DragDropActive &&
g.DragDropSourceFrameCount <
g.FrameCount && !(
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
5329 g.DragDropWithinSource =
true;
5331 g.DragDropWithinSource =
false;
5335 g.WithinFrameScope =
false;
5336 g.FrameCountEnded =
g.FrameCount;
5339 UpdateMouseMovingWindowEndFrame();
5342 UpdateViewportsEndFrame();
5346 g.WindowsTempSortBuffer.resize(0);
5347 g.WindowsTempSortBuffer.reserve(
g.Windows.Size);
5348 for (ImGuiWindow* window :
g.Windows)
5350 if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow))
5352 AddWindowToSortBuffer(&
g.WindowsTempSortBuffer, window);
5356 IM_ASSERT(
g.Windows.Size ==
g.WindowsTempSortBuffer.Size);
5357 g.Windows.swap(
g.WindowsTempSortBuffer);
5358 g.IO.MetricsActiveWindows =
g.WindowsActiveCount;
5361 g.IO.Fonts->Locked =
false;
5364 g.IO.MousePosPrev =
g.IO.MousePos;
5365 g.IO.AppFocusLost =
false;
5366 g.IO.MouseWheel =
g.IO.MouseWheelH = 0.0f;
5367 g.IO.InputQueueCharacters.resize(0);
5369 CallContextHooks(&
g, ImGuiContextHookType_EndFramePost);
5378 IM_ASSERT(
g.Initialized);
5380 if (
g.FrameCountEnded !=
g.FrameCount)
5382 if (
g.FrameCountRendered ==
g.FrameCount)
5384 g.FrameCountRendered =
g.FrameCount;
5386 g.IO.MetricsRenderWindows = 0;
5387 CallContextHooks(&
g, ImGuiContextHookType_RenderPre);
5390 for (ImGuiViewportP* viewport :
g.Viewports)
5392 InitViewportDrawData(viewport);
5393 if (viewport->BgFgDrawLists[0] != NULL)
5394 AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport));
5398 RenderDimmedBackgrounds();
5401 ImGuiWindow* windows_to_render_top_most[2];
5402 windows_to_render_top_most[0] = (
g.NavWindowingTarget && !(
g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ?
g.NavWindowingTarget->RootWindowDockTree : NULL;
5403 windows_to_render_top_most[1] = (
g.NavWindowingTarget ?
g.NavWindowingListWindow : NULL);
5404 for (ImGuiWindow* window :
g.Windows)
5406 IM_MSVC_WARNING_SUPPRESS(6011);
5407 if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1])
5408 AddRootWindowToDrawData(window);
5410 for (
int n = 0; n < IM_ARRAYSIZE(windows_to_render_top_most); n++)
5411 if (windows_to_render_top_most[n] && IsWindowActiveAndVisible(windows_to_render_top_most[n]))
5412 AddRootWindowToDrawData(windows_to_render_top_most[n]);
5415 if (
g.IO.MouseDrawCursor &&
g.MouseCursor != ImGuiMouseCursor_None)
5416 RenderMouseCursor(
g.IO.MousePos,
g.Style.MouseCursorScale,
g.MouseCursor, IM_COL32_WHITE, IM_COL32_BLACK, IM_COL32(0, 0, 0, 48));
5419 g.IO.MetricsRenderVertices =
g.IO.MetricsRenderIndices = 0;
5420 for (ImGuiViewportP* viewport :
g.Viewports)
5422 FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder);
5425 if (viewport->BgFgDrawLists[1] != NULL)
5426 AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport));
5429 ImDrawData* draw_data = &viewport->DrawDataP;
5430 IM_ASSERT(draw_data->CmdLists.Size == draw_data->CmdListsCount);
5431 for (ImDrawList* draw_list : draw_data->CmdLists)
5432 draw_list->_PopUnusedDrawCmd();
5434 g.IO.MetricsRenderVertices += draw_data->TotalVtxCount;
5435 g.IO.MetricsRenderIndices += draw_data->TotalIdxCount;
5438 CallContextHooks(&
g, ImGuiContextHookType_RenderPost);
5443ImVec2
ImGui::CalcTextSize(
const char* text,
const char* text_end,
bool hide_text_after_double_hash,
float wrap_width)
5447 const char* text_display_end;
5448 if (hide_text_after_double_hash)
5449 text_display_end = FindRenderedTextEnd(text, text_end);
5451 text_display_end = text_end;
5453 ImFont* font =
g.Font;
5454 const float font_size =
g.FontSize;
5455 if (text == text_display_end)
5456 return ImVec2(0.0f, font_size);
5457 ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);
5464 text_size.x = IM_TRUNC(text_size.x + 0.99999f);
5473static void FindHoveredWindow()
5478 ImGuiViewportP* moving_window_viewport =
g.MovingWindow ?
g.MovingWindow->Viewport : NULL;
5480 g.MovingWindow->Viewport =
g.MouseViewport;
5482 ImGuiWindow* hovered_window = NULL;
5483 ImGuiWindow* hovered_window_ignoring_moving_window = NULL;
5484 if (
g.MovingWindow && !(
g.MovingWindow->Flags & ImGuiWindowFlags_NoMouseInputs))
5485 hovered_window =
g.MovingWindow;
5487 ImVec2 padding_regular =
g.Style.TouchExtraPadding;
5488 ImVec2 padding_for_resize =
g.IO.ConfigWindowsResizeFromEdges ?
g.WindowsHoverPadding : padding_regular;
5489 for (
int i =
g.Windows.Size - 1; i >= 0; i--)
5491 ImGuiWindow* window =
g.Windows[i];
5492 IM_MSVC_WARNING_SUPPRESS(28182);
5493 if (!window->Active || window->Hidden)
5495 if (window->Flags & ImGuiWindowFlags_NoMouseInputs)
5497 IM_ASSERT(window->Viewport);
5498 if (window->Viewport !=
g.MouseViewport)
5502 ImVec2 hit_padding = (window->Flags & (ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) ? padding_regular : padding_for_resize;
5503 if (!window->OuterRectClipped.ContainsWithPad(
g.IO.MousePos, hit_padding))
5508 if (window->HitTestHoleSize.x != 0)
5510 ImVec2 hole_pos(window->Pos.x + (
float)window->HitTestHoleOffset.x, window->Pos.y + (
float)window->HitTestHoleOffset.y);
5511 ImVec2 hole_size((
float)window->HitTestHoleSize.x, (
float)window->HitTestHoleSize.y);
5512 if (ImRect(hole_pos, hole_pos + hole_size).Contains(
g.IO.MousePos))
5516 if (hovered_window == NULL)
5517 hovered_window = window;
5518 IM_MSVC_WARNING_SUPPRESS(28182);
5519 if (hovered_window_ignoring_moving_window == NULL && (!
g.MovingWindow || window->RootWindowDockTree !=
g.MovingWindow->RootWindowDockTree))
5520 hovered_window_ignoring_moving_window = window;
5521 if (hovered_window && hovered_window_ignoring_moving_window)
5525 g.HoveredWindow = hovered_window;
5526 g.HoveredWindowUnderMovingWindow = hovered_window_ignoring_moving_window;
5529 g.MovingWindow->Viewport = moving_window_viewport;
5532bool ImGui::IsItemActive()
5536 return g.ActiveId ==
g.LastItemData.ID;
5540bool ImGui::IsItemActivated()
5544 if (
g.ActiveId ==
g.LastItemData.ID &&
g.ActiveIdPreviousFrame !=
g.LastItemData.ID)
5549bool ImGui::IsItemDeactivated()
5552 if (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDeactivated)
5553 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Deactivated) != 0;
5554 return (
g.ActiveIdPreviousFrame ==
g.LastItemData.ID &&
g.ActiveIdPreviousFrame != 0 &&
g.ActiveId !=
g.LastItemData.ID);
5557bool ImGui::IsItemDeactivatedAfterEdit()
5560 return IsItemDeactivated() && (
g.ActiveIdPreviousFrameHasBeenEditedBefore || (
g.ActiveId == 0 &&
g.ActiveIdHasBeenEditedBefore));
5564bool ImGui::IsItemFocused()
5567 if (
g.NavId !=
g.LastItemData.ID ||
g.NavId == 0)
5572 ImGuiWindow* window =
g.CurrentWindow;
5573 if (
g.LastItemData.ID == window->ID && window->WriteAccessed)
5581bool ImGui::IsItemClicked(ImGuiMouseButton mouse_button)
5583 return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None);
5586bool ImGui::IsItemToggledOpen()
5589 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true :
false;
5592bool ImGui::IsItemToggledSelection()
5595 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true :
false;
5601bool ImGui::IsAnyItemHovered()
5604 return g.HoveredId != 0 ||
g.HoveredIdPreviousFrame != 0;
5607bool ImGui::IsAnyItemActive()
5610 return g.ActiveId != 0;
5613bool ImGui::IsAnyItemFocused()
5616 return g.NavId != 0 && !
g.NavDisableHighlight;
5619bool ImGui::IsItemVisible()
5622 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) != 0;
5625bool ImGui::IsItemEdited()
5628 return (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Edited) != 0;
5634void ImGui::SetNextItemAllowOverlap()
5637 g.NextItemData.ItemFlags |= ImGuiItemFlags_AllowOverlap;
5640#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
5643void ImGui::SetItemAllowOverlap()
5646 ImGuiID
id =
g.LastItemData.ID;
5647 if (
g.HoveredId ==
id)
5648 g.HoveredIdAllowOverlap =
true;
5649 if (
g.ActiveId ==
id)
5650 g.ActiveIdAllowOverlap =
true;
5655void ImGui::SetActiveIdUsingAllKeyboardKeys()
5658 IM_ASSERT(
g.ActiveId != 0);
5659 g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_COUNT) - 1;
5660 g.ActiveIdUsingAllKeyboardKeys =
true;
5661 NavMoveRequestCancel();
5664ImGuiID ImGui::GetItemID()
5667 return g.LastItemData.ID;
5670ImVec2 ImGui::GetItemRectMin()
5673 return g.LastItemData.Rect.Min;
5676ImVec2 ImGui::GetItemRectMax()
5679 return g.LastItemData.Rect.Max;
5682ImVec2 ImGui::GetItemRectSize()
5685 return g.LastItemData.Rect.GetSize();
5690bool ImGui::BeginChild(
const char* str_id,
const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags)
5692 ImGuiID
id = GetCurrentWindow()->GetID(str_id);
5693 return BeginChildEx(str_id,
id, size_arg, child_flags, window_flags);
5696bool ImGui::BeginChild(ImGuiID
id,
const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags)
5698 return BeginChildEx(NULL,
id, size_arg, child_flags, window_flags);
5701bool ImGui::BeginChildEx(
const char* name, ImGuiID
id,
const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags)
5704 ImGuiWindow* parent_window =
g.CurrentWindow;
5708 const ImGuiChildFlags ImGuiChildFlags_SupportedMask_ = ImGuiChildFlags_Border | ImGuiChildFlags_AlwaysUseWindowPadding | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_FrameStyle;
5709 IM_UNUSED(ImGuiChildFlags_SupportedMask_);
5710 IM_ASSERT((child_flags & ~ImGuiChildFlags_SupportedMask_) == 0 &&
"Illegal ImGuiChildFlags value. Did you pass ImGuiWindowFlags values instead of ImGuiChildFlags?");
5711 IM_ASSERT((window_flags & ImGuiWindowFlags_AlwaysAutoResize) == 0 &&
"Cannot specify ImGuiWindowFlags_AlwaysAutoResize for BeginChild(). Use ImGuiChildFlags_AlwaysAutoResize!");
5712 if (child_flags & ImGuiChildFlags_AlwaysAutoResize)
5714 IM_ASSERT((child_flags & (ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY)) == 0 &&
"Cannot use ImGuiChildFlags_ResizeX or ImGuiChildFlags_ResizeY with ImGuiChildFlags_AlwaysAutoResize!");
5715 IM_ASSERT((child_flags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY)) != 0 &&
"Must use ImGuiChildFlags_AutoResizeX or ImGuiChildFlags_AutoResizeY with ImGuiChildFlags_AlwaysAutoResize!");
5717#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
5718 if (window_flags & ImGuiWindowFlags_AlwaysUseWindowPadding)
5719 child_flags |= ImGuiChildFlags_AlwaysUseWindowPadding;
5721 if (child_flags & ImGuiChildFlags_AutoResizeX)
5722 child_flags &= ~ImGuiChildFlags_ResizeX;
5723 if (child_flags & ImGuiChildFlags_AutoResizeY)
5724 child_flags &= ~ImGuiChildFlags_ResizeY;
5727 window_flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDocking;
5728 window_flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove);
5729 if (child_flags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize))
5730 window_flags |= ImGuiWindowFlags_AlwaysAutoResize;
5731 if ((child_flags & (ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY)) == 0)
5732 window_flags |= ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings;
5735 if (child_flags & ImGuiChildFlags_FrameStyle)
5737 PushStyleColor(ImGuiCol_ChildBg,
g.Style.Colors[ImGuiCol_FrameBg]);
5738 PushStyleVar(ImGuiStyleVar_ChildRounding,
g.Style.FrameRounding);
5739 PushStyleVar(ImGuiStyleVar_ChildBorderSize,
g.Style.FrameBorderSize);
5740 PushStyleVar(ImGuiStyleVar_WindowPadding,
g.Style.FramePadding);
5741 child_flags |= ImGuiChildFlags_Border | ImGuiChildFlags_AlwaysUseWindowPadding;
5742 window_flags |= ImGuiWindowFlags_NoMove;
5746 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags;
5747 g.NextWindowData.ChildFlags = child_flags;
5752 const ImVec2 size_avail = GetContentRegionAvail();
5753 const ImVec2 size_default((child_flags & ImGuiChildFlags_AutoResizeX) ? 0.0f : size_avail.x, (child_flags & ImGuiChildFlags_AutoResizeY) ? 0.0f : size_avail.y);
5754 const ImVec2
size = CalcItemSize(size_arg, size_default.x, size_default.y);
5755 SetNextWindowSize(size);
5760 const char* temp_window_name;
5770 const float backup_border_size =
g.Style.ChildBorderSize;
5771 if ((child_flags & ImGuiChildFlags_Border) == 0)
5772 g.Style.ChildBorderSize = 0.0f;
5775 const bool ret = Begin(temp_window_name, NULL, window_flags);
5778 g.Style.ChildBorderSize = backup_border_size;
5779 if (child_flags & ImGuiChildFlags_FrameStyle)
5785 ImGuiWindow* child_window =
g.CurrentWindow;
5786 child_window->ChildId =
id;
5790 if (child_window->BeginCount == 1)
5791 parent_window->DC.CursorPos = child_window->Pos;
5795 const ImGuiID temp_id_for_activation =
ImHashStr(
"##Child", 0,
id);
5796 if (
g.ActiveId == temp_id_for_activation)
5798 if (
g.NavActivateId ==
id && !(window_flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY))
5800 FocusWindow(child_window);
5801 NavInitWindow(child_window,
false);
5802 SetActiveID(temp_id_for_activation, child_window);
5803 g.ActiveIdSource =
g.NavInputSource;
5808void ImGui::EndChild()
5811 ImGuiWindow* child_window =
g.CurrentWindow;
5813 IM_ASSERT(
g.WithinEndChild ==
false);
5814 IM_ASSERT(child_window->Flags & ImGuiWindowFlags_ChildWindow);
5816 g.WithinEndChild =
true;
5817 ImVec2 child_size = child_window->Size;
5819 if (child_window->BeginCount == 1)
5821 ImGuiWindow* parent_window =
g.CurrentWindow;
5822 ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + child_size);
5823 ItemSize(child_size);
5824 if ((child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY) && !(child_window->Flags & ImGuiWindowFlags_NavFlattened))
5826 ItemAdd(bb, child_window->ChildId);
5827 RenderNavHighlight(bb, child_window->ChildId);
5830 if (child_window->DC.NavLayersActiveMask == 0 && child_window ==
g.NavWindow)
5831 RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)),
g.NavId, ImGuiNavHighlightFlags_Compact);
5839 if (child_window->Flags & ImGuiWindowFlags_NavFlattened)
5840 parent_window->DC.NavLayersActiveMaskNext |= child_window->DC.NavLayersActiveMaskNext;
5842 if (
g.HoveredWindow == child_window)
5843 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
5845 g.WithinEndChild =
false;
5846 g.LogLinePosY = -FLT_MAX;
5849static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags,
bool enabled)
5851 window->SetWindowPosAllowFlags = enabled ? (window->SetWindowPosAllowFlags | flags) : (window->SetWindowPosAllowFlags & ~flags);
5852 window->SetWindowSizeAllowFlags = enabled ? (window->SetWindowSizeAllowFlags | flags) : (window->SetWindowSizeAllowFlags & ~flags);
5853 window->SetWindowCollapsedAllowFlags = enabled ? (window->SetWindowCollapsedAllowFlags | flags) : (window->SetWindowCollapsedAllowFlags & ~flags);
5854 window->SetWindowDockAllowFlags = enabled ? (window->SetWindowDockAllowFlags | flags) : (window->SetWindowDockAllowFlags & ~flags);
5857ImGuiWindow* ImGui::FindWindowByID(ImGuiID
id)
5860 return (ImGuiWindow*)
g.WindowsById.GetVoidPtr(
id);
5863ImGuiWindow* ImGui::FindWindowByName(
const char* name)
5866 return FindWindowByID(
id);
5869static void ApplyWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
5871 const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
5872 window->ViewportPos = main_viewport->Pos;
5873 if (settings->ViewportId)
5875 window->ViewportId = settings->ViewportId;
5876 window->ViewportPos = ImVec2(settings->ViewportPos.x, settings->ViewportPos.y);
5878 window->Pos = ImTrunc(ImVec2(settings->Pos.x + window->ViewportPos.x, settings->Pos.y + window->ViewportPos.y));
5879 if (settings->Size.x > 0 && settings->Size.y > 0)
5880 window->Size = window->SizeFull = ImTrunc(ImVec2(settings->Size.x, settings->Size.y));
5881 window->Collapsed = settings->Collapsed;
5882 window->DockId = settings->DockId;
5883 window->DockOrder = settings->DockOrder;
5886static void UpdateWindowInFocusOrderList(ImGuiWindow* window,
bool just_created, ImGuiWindowFlags new_flags)
5890 const bool new_is_explicit_child = (new_flags & ImGuiWindowFlags_ChildWindow) != 0 && ((new_flags & ImGuiWindowFlags_Popup) == 0 || (new_flags & ImGuiWindowFlags_ChildMenu) != 0);
5891 const bool child_flag_changed = new_is_explicit_child != window->IsExplicitChild;
5892 if ((just_created || child_flag_changed) && !new_is_explicit_child)
5894 IM_ASSERT(!
g.WindowsFocusOrder.contains(window));
5895 g.WindowsFocusOrder.push_back(window);
5896 window->FocusOrder = (short)(
g.WindowsFocusOrder.Size - 1);
5898 else if (!just_created && child_flag_changed && new_is_explicit_child)
5900 IM_ASSERT(
g.WindowsFocusOrder[window->FocusOrder] == window);
5901 for (
int n = window->FocusOrder + 1; n <
g.WindowsFocusOrder.Size; n++)
5902 g.WindowsFocusOrder[n]->FocusOrder--;
5903 g.WindowsFocusOrder.erase(
g.WindowsFocusOrder.Data + window->FocusOrder);
5904 window->FocusOrder = -1;
5906 window->IsExplicitChild = new_is_explicit_child;
5909static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
5913 const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
5914 window->Pos = main_viewport->Pos + ImVec2(60, 60);
5915 window->Size = window->SizeFull = ImVec2(0, 0);
5916 window->ViewportPos = main_viewport->Pos;
5917 window->SetWindowPosAllowFlags = window->SetWindowSizeAllowFlags = window->SetWindowCollapsedAllowFlags = window->SetWindowDockAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
5919 if (settings != NULL)
5921 SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver,
false);
5922 ApplyWindowSettings(window, settings);
5924 window->DC.CursorStartPos = window->DC.CursorMaxPos = window->DC.IdealMaxPos = window->Pos;
5926 if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
5928 window->AutoFitFramesX = window->AutoFitFramesY = 2;
5929 window->AutoFitOnlyGrows =
false;
5933 if (window->Size.x <= 0.0f)
5934 window->AutoFitFramesX = 2;
5935 if (window->Size.y <= 0.0f)
5936 window->AutoFitFramesY = 2;
5937 window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
5941static ImGuiWindow* CreateNewWindow(
const char* name, ImGuiWindowFlags flags)
5946 ImGuiWindow* window = IM_NEW(ImGuiWindow)(&
g, name);
5947 window->Flags = flags;
5948 g.WindowsById.SetVoidPtr(window->ID, window);
5950 ImGuiWindowSettings* settings = NULL;
5951 if (!(flags & ImGuiWindowFlags_NoSavedSettings))
5952 if ((settings = ImGui::FindWindowSettingsByWindow(window)) != 0)
5953 window->SettingsOffset =
g.SettingsWindows.offset_from_ptr(settings);
5955 InitOrLoadWindowSettings(window, settings);
5957 if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus)
5958 g.Windows.push_front(window);
5960 g.Windows.push_back(window);
5965static ImGuiWindow* GetWindowForTitleDisplay(ImGuiWindow* window)
5967 return window->DockNodeAsHost ? window->DockNodeAsHost->VisibleWindow : window;
5970static ImGuiWindow* GetWindowForTitleAndMenuHeight(ImGuiWindow* window)
5972 return (window->DockNodeAsHost && window->DockNodeAsHost->VisibleWindow) ? window->DockNodeAsHost->VisibleWindow : window;
5975static inline ImVec2 CalcWindowMinSize(ImGuiWindow* window)
5982 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_Popup))
5984 size_min.x = (window->ChildFlags & ImGuiChildFlags_ResizeX) ?
g.Style.WindowMinSize.x : 4.0f;
5985 size_min.y = (window->ChildFlags & ImGuiChildFlags_ResizeY) ?
g.Style.WindowMinSize.y : 4.0f;
5989 size_min.x = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ?
g.Style.WindowMinSize.x : 4.0f;
5990 size_min.y = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ?
g.Style.WindowMinSize.y : 4.0f;
5994 ImGuiWindow* window_for_height = GetWindowForTitleAndMenuHeight(window);
5995 size_min.y = ImMax(size_min.y, window_for_height->TitleBarHeight() + window_for_height->MenuBarHeight() + ImMax(0.0f,
g.Style.WindowRounding - 1.0f));
5999static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window,
const ImVec2& size_desired)
6002 ImVec2 new_size = size_desired;
6003 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)
6006 ImRect cr =
g.NextWindowData.SizeConstraintRect;
6007 new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x;
6008 new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y;
6009 if (
g.NextWindowData.SizeCallback)
6011 ImGuiSizeCallbackData data;
6012 data.UserData =
g.NextWindowData.SizeCallbackUserData;
6013 data.Pos = window->Pos;
6014 data.CurrentSize = window->SizeFull;
6015 data.DesiredSize = new_size;
6016 g.NextWindowData.SizeCallback(&data);
6017 new_size = data.DesiredSize;
6019 new_size.x = IM_TRUNC(new_size.x);
6020 new_size.y = IM_TRUNC(new_size.y);
6024 ImVec2 size_min = CalcWindowMinSize(window);
6025 return ImMax(new_size, size_min);
6028static void CalcWindowContentSizes(ImGuiWindow* window, ImVec2* content_size_current, ImVec2* content_size_ideal)
6030 bool preserve_old_content_sizes =
false;
6031 if (window->Collapsed && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
6032 preserve_old_content_sizes =
true;
6033 else if (window->Hidden && window->HiddenFramesCannotSkipItems == 0 && window->HiddenFramesCanSkipItems > 0)
6034 preserve_old_content_sizes =
true;
6035 if (preserve_old_content_sizes)
6037 *content_size_current = window->ContentSize;
6038 *content_size_ideal = window->ContentSizeIdeal;
6042 content_size_current->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : IM_TRUNC(window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x);
6043 content_size_current->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : IM_TRUNC(window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y);
6044 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);
6045 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);
6048static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window,
const ImVec2& size_contents)
6051 ImGuiStyle& style =
g.Style;
6052 const float decoration_w_without_scrollbars = window->DecoOuterSizeX1 + window->DecoOuterSizeX2 - window->ScrollbarSizes.x;
6053 const float decoration_h_without_scrollbars = window->DecoOuterSizeY1 + window->DecoOuterSizeY2 - window->ScrollbarSizes.y;
6054 ImVec2 size_pad = window->WindowPadding * 2.0f;
6055 ImVec2 size_desired = size_contents + size_pad + ImVec2(decoration_w_without_scrollbars, decoration_h_without_scrollbars);
6056 if (window->Flags & ImGuiWindowFlags_Tooltip)
6059 return size_desired;
6064 ImVec2 size_min = CalcWindowMinSize(window);
6065 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;
6066 const int monitor_idx = window->ViewportAllowPlatformMonitorExtend;
6067 if (monitor_idx >= 0 && monitor_idx <
g.PlatformIO.Monitors.Size && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0)
6068 size_max =
g.PlatformIO.Monitors[monitor_idx].WorkSize - style.DisplaySafeAreaPadding * 2.0f;
6069 ImVec2 size_auto_fit = ImClamp(size_desired, size_min, ImMax(size_min, size_max));
6073 ImVec2 size_auto_fit_after_constraint = CalcWindowSizeAfterConstraint(window, size_auto_fit);
6074 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);
6075 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);
6076 if (will_have_scrollbar_x)
6077 size_auto_fit.y += style.ScrollbarSize;
6078 if (will_have_scrollbar_y)
6079 size_auto_fit.x += style.ScrollbarSize;
6080 return size_auto_fit;
6084ImVec2 ImGui::CalcWindowNextAutoFitSize(ImGuiWindow* window)
6086 ImVec2 size_contents_current;
6087 ImVec2 size_contents_ideal;
6088 CalcWindowContentSizes(window, &size_contents_current, &size_contents_ideal);
6089 ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, size_contents_ideal);
6090 ImVec2 size_final = CalcWindowSizeAfterConstraint(window, size_auto_fit);
6094static ImGuiCol GetWindowBgColorIdx(ImGuiWindow* window)
6096 if (window->Flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
6097 return ImGuiCol_PopupBg;
6098 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !window->DockIsActive)
6099 return ImGuiCol_ChildBg;
6100 return ImGuiCol_WindowBg;
6103static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window,
const ImVec2& corner_target,
const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size)
6105 ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm);
6106 ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm);
6107 ImVec2 size_expected = pos_max - pos_min;
6108 ImVec2 size_constrained = CalcWindowSizeAfterConstraint(window, size_expected);
6110 if (corner_norm.x == 0.0f)
6111 out_pos->x -= (size_constrained.x - size_expected.x);
6112 if (corner_norm.y == 0.0f)
6113 out_pos->y -= (size_constrained.y - size_expected.y);
6114 *out_size = size_constrained;
6126 { ImVec2(1, 1), ImVec2(-1, -1), 0, 3 },
6127 { ImVec2(0, 1), ImVec2(+1, -1), 3, 6 },
6128 { ImVec2(0, 0), ImVec2(+1, +1), 6, 9 },
6129 { ImVec2(1, 0), ImVec2(-1, +1), 9, 12 }
6141 { ImVec2(+1, 0), ImVec2(0, 1), ImVec2(0, 0), IM_PI * 1.00f },
6142 { ImVec2(-1, 0), ImVec2(1, 0), ImVec2(1, 1), IM_PI * 0.00f },
6143 { ImVec2(0, +1), ImVec2(0, 0), ImVec2(1, 0), IM_PI * 1.50f },
6144 { ImVec2(0, -1), ImVec2(1, 1), ImVec2(0, 1), IM_PI * 0.50f }
6147static ImRect GetResizeBorderRect(ImGuiWindow* window,
int border_n,
float perp_padding,
float thickness)
6149 ImRect rect = window->Rect();
6150 if (thickness == 0.0f)
6151 rect.Max -= ImVec2(1, 1);
6152 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); }
6153 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); }
6154 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); }
6155 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); }
6161ImGuiID ImGui::GetWindowResizeCornerID(ImGuiWindow* window,
int n)
6163 IM_ASSERT(n >= 0 && n < 4);
6164 ImGuiID
id = window->DockIsActive ? window->DockNode->HostWindow->ID : window->ID;
6171ImGuiID ImGui::GetWindowResizeBorderID(ImGuiWindow* window, ImGuiDir dir)
6173 IM_ASSERT(dir >= 0 && dir < 4);
6174 int n = (int)dir + 4;
6175 ImGuiID
id = window->DockIsActive ? window->DockNode->HostWindow->ID : window->ID;
6183static 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)
6186 ImGuiWindowFlags flags = window->Flags;
6188 if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
6190 if (window->WasActive ==
false)
6193 int ret_auto_fit_mask = 0x00;
6194 const float grip_draw_size = IM_TRUNC(ImMax(
g.FontSize * 1.35f, window->WindowRounding + 1.0f +
g.FontSize * 0.2f));
6195 const float grip_hover_inner_size = IM_TRUNC(grip_draw_size * 0.75f);
6196 const float grip_hover_outer_size =
g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_HOVER_PADDING : 0.0f;
6198 ImRect clamp_rect = visibility_rect;
6199 const bool window_move_from_title_bar =
g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar);
6200 if (window_move_from_title_bar)
6201 clamp_rect.Min.y -= window->TitleBarHeight();
6203 ImVec2 pos_target(FLT_MAX, FLT_MAX);
6204 ImVec2 size_target(FLT_MAX, FLT_MAX);
6212 const bool clip_with_viewport_rect = !(
g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport) || (
g.IO.MouseHoveredViewport != window->ViewportId) || !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration);
6213 if (clip_with_viewport_rect)
6214 window->ClipRect = window->Viewport->GetMainRect();
6217 window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
6221 for (
int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
6224 const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, def.
CornerPosN);
6228 ImRect resize_rect(corner - def.
InnerDir * grip_hover_outer_size, corner + def.
InnerDir * grip_hover_inner_size);
6229 if (resize_rect.Min.x > resize_rect.Max.x) ImSwap(resize_rect.Min.x, resize_rect.Max.x);
6230 if (resize_rect.Min.y > resize_rect.Max.y) ImSwap(resize_rect.Min.y, resize_rect.Max.y);
6231 ImGuiID resize_grip_id = window->GetID(resize_grip_n);
6232 ItemAdd(resize_rect, resize_grip_id, NULL, ImGuiItemFlags_NoNav);
6233 ButtonBehavior(resize_rect, resize_grip_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
6235 if (hovered || held)
6236 g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;
6238 if (held &&
g.IO.MouseDoubleClicked[0])
6241 size_target = CalcWindowSizeAfterConstraint(window, size_auto_fit);
6242 ret_auto_fit_mask = 0x03;
6249 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);
6250 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);
6251 ImVec2 corner_target =
g.IO.MousePos -
g.ActiveIdClickOffset + ImLerp(def.
InnerDir * grip_hover_outer_size, def.
InnerDir * -grip_hover_inner_size, def.
CornerPosN);
6252 corner_target = ImClamp(corner_target, clamp_min, clamp_max);
6253 CalcResizePosSizeFromAnyCorner(window, corner_target, def.
CornerPosN, &pos_target, &size_target);
6257 if (resize_grip_n == 0 || held || hovered)
6258 resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
6261 int resize_border_mask = 0x00;
6262 if (window->Flags & ImGuiWindowFlags_ChildWindow)
6263 resize_border_mask |= ((window->ChildFlags & ImGuiChildFlags_ResizeX) ? 0x02 : 0) | ((window->ChildFlags & ImGuiChildFlags_ResizeY) ? 0x08 : 0);
6265 resize_border_mask =
g.IO.ConfigWindowsResizeFromEdges ? 0x0F : 0x00;
6266 for (
int border_n = 0; border_n < 4; border_n++)
6268 if ((resize_border_mask & (1 << border_n)) == 0)
6271 const ImGuiAxis axis = (border_n == ImGuiDir_Left || border_n == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
6274 ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_HOVER_PADDING);
6275 ImGuiID border_id = window->GetID(border_n + 4);
6276 ItemAdd(border_rect, border_id, NULL, ImGuiItemFlags_NoNav);
6277 ButtonBehavior(border_rect, border_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
6279 if (hovered &&
g.HoveredIdTimer <= WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER)
6281 if (hovered || held)
6282 g.MouseCursor = (axis == ImGuiAxis_X) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS;
6283 if (held &&
g.IO.MouseDoubleClicked[0])
6287 if (border_n == 1 || border_n == 3)
6289 size_target[axis] = CalcWindowSizeAfterConstraint(window, size_auto_fit)[axis];
6290 ret_auto_fit_mask |= (1 << axis);
6291 hovered = held =
false;
6300 const bool just_scrolled_manually_while_resizing = (
g.WheelingWindow != NULL &&
g.WheelingWindowScrolledFrame ==
g.FrameCount && IsWindowChildOf(window,
g.WheelingWindow,
false,
true));
6301 if (
g.ActiveIdIsJustActivated || just_scrolled_manually_while_resizing)
6303 g.WindowResizeBorderExpectedRect = border_rect;
6304 g.WindowResizeRelativeMode =
false;
6306 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && memcmp(&
g.WindowResizeBorderExpectedRect, &border_rect,
sizeof(ImRect)) != 0)
6307 g.WindowResizeRelativeMode =
true;
6309 const ImVec2 border_curr = (window->Pos + ImMin(def.
SegmentN1, def.
SegmentN2) * window->Size);
6310 const float border_target_rel_mode_for_axis = border_curr[axis] +
g.IO.MouseDelta[axis];
6311 const float border_target_abs_mode_for_axis =
g.IO.MousePos[axis] -
g.ActiveIdClickOffset[axis] + WINDOWS_HOVER_PADDING;
6314 ImVec2 border_target = window->Pos;
6315 border_target[axis] = border_target_abs_mode_for_axis;
6318 bool ignore_resize =
false;
6319 if (
g.WindowResizeRelativeMode)
6322 border_target[axis] = border_target_rel_mode_for_axis;
6323 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))
6324 ignore_resize =
true;
6328 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);
6329 ImVec2 clamp_max(border_n == ImGuiDir_Left ? clamp_rect.Max.x : +FLT_MAX, border_n == ImGuiDir_Up ? clamp_rect.Max.y : +FLT_MAX);
6330 border_target = ImClamp(border_target, clamp_min, clamp_max);
6331 if (flags & ImGuiWindowFlags_ChildWindow)
6333 if ((flags & (ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar)) == 0 || (flags & ImGuiWindowFlags_NoScrollbar))
6334 border_target.x = ImClamp(border_target.x, window->ParentWindow->InnerClipRect.Min.x, window->ParentWindow->InnerClipRect.Max.x);
6335 if (flags & ImGuiWindowFlags_NoScrollbar)
6336 border_target.y = ImClamp(border_target.y, window->ParentWindow->InnerClipRect.Min.y, window->ParentWindow->InnerClipRect.Max.y);
6339 CalcResizePosSizeFromAnyCorner(window, border_target, ImMin(def.
SegmentN1, def.
SegmentN2), &pos_target, &size_target);
6342 *border_hovered = border_n;
6344 *border_held = border_n;
6349 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
6354 if (
g.NavWindowingTarget &&
g.NavWindowingTarget->RootWindowDockTree == window)
6356 ImVec2 nav_resize_dir;
6357 if (
g.NavInputSource == ImGuiInputSource_Keyboard &&
g.IO.KeyShift)
6358 nav_resize_dir = GetKeyMagnitude2d(ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow);
6359 if (
g.NavInputSource == ImGuiInputSource_Gamepad)
6360 nav_resize_dir = GetKeyMagnitude2d(ImGuiKey_GamepadDpadLeft, ImGuiKey_GamepadDpadRight, ImGuiKey_GamepadDpadUp, ImGuiKey_GamepadDpadDown);
6361 if (nav_resize_dir.x != 0.0f || nav_resize_dir.y != 0.0f)
6363 const float NAV_RESIZE_SPEED = 600.0f;
6364 const float resize_step = NAV_RESIZE_SPEED *
g.IO.DeltaTime * ImMin(
g.IO.DisplayFramebufferScale.x,
g.IO.DisplayFramebufferScale.y);
6365 g.NavWindowingAccumDeltaSize += nav_resize_dir * resize_step;
6366 g.NavWindowingAccumDeltaSize = ImMax(
g.NavWindowingAccumDeltaSize, clamp_rect.Min - window->Pos - window->Size);
6367 g.NavWindowingToggleLayer =
false;
6368 g.NavDisableMouseHover =
true;
6369 resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive);
6370 ImVec2 accum_floored = ImTrunc(
g.NavWindowingAccumDeltaSize);
6371 if (accum_floored.x != 0.0f || accum_floored.y != 0.0f)
6374 size_target = CalcWindowSizeAfterConstraint(window, window->SizeFull + accum_floored);
6375 g.NavWindowingAccumDeltaSize -= accum_floored;
6381 const ImVec2 curr_pos = window->Pos;
6382 const ImVec2 curr_size = window->SizeFull;
6383 if (size_target.x != FLT_MAX && (window->Size.x != size_target.x || window->SizeFull.x != size_target.x))
6384 window->Size.x = window->SizeFull.x = size_target.x;
6385 if (size_target.y != FLT_MAX && (window->Size.y != size_target.y || window->SizeFull.y != size_target.y))
6386 window->Size.y = window->SizeFull.y = size_target.y;
6387 if (pos_target.x != FLT_MAX && window->Pos.x != ImTrunc(pos_target.x))
6388 window->Pos.x = ImTrunc(pos_target.x);
6389 if (pos_target.y != FLT_MAX && window->Pos.y != ImTrunc(pos_target.y))
6390 window->Pos.y = ImTrunc(pos_target.y);
6391 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)
6392 MarkIniSettingsDirty(window);
6395 if (*border_held != -1)
6396 g.WindowResizeBorderExpectedRect = GetResizeBorderRect(window, *border_held, grip_hover_inner_size, WINDOWS_HOVER_PADDING);
6398 return ret_auto_fit_mask;
6401static inline void ClampWindowPos(ImGuiWindow* window,
const ImRect& visibility_rect)
6404 ImVec2 size_for_clamping = window->Size;
6405 if (
g.IO.ConfigWindowsMoveFromTitleBarOnly && (!(window->Flags & ImGuiWindowFlags_NoTitleBar) || window->DockNodeAsHost))
6406 size_for_clamping.y = ImGui::GetFrameHeight();
6407 window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max);
6410static void RenderWindowOuterSingleBorder(ImGuiWindow* window,
int border_n, ImU32 border_col,
float border_size)
6413 const float rounding = window->WindowRounding;
6414 const ImRect border_r = GetResizeBorderRect(window, border_n, rounding, 0.0f);
6415 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);
6416 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);
6417 window->DrawList->PathStroke(border_col, ImDrawFlags_None, border_size);
6420static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
6423 const float border_size = window->WindowBorderSize;
6424 const ImU32 border_col = GetColorU32(ImGuiCol_Border);
6425 if (border_size > 0.0f && (window->Flags & ImGuiWindowFlags_NoBackground) == 0)
6426 window->DrawList->AddRect(window->Pos, window->Pos + window->Size, border_col, window->WindowRounding, 0, window->WindowBorderSize);
6427 else if (border_size > 0.0f)
6429 if (window->ChildFlags & ImGuiChildFlags_ResizeX)
6430 RenderWindowOuterSingleBorder(window, 1, border_col, border_size);
6431 if (window->ChildFlags & ImGuiChildFlags_ResizeY)
6432 RenderWindowOuterSingleBorder(window, 3, border_col, border_size);
6434 if (window->ResizeBorderHovered != -1 || window->ResizeBorderHeld != -1)
6436 const int border_n = (window->ResizeBorderHeld != -1) ? window->ResizeBorderHeld : window->ResizeBorderHovered;
6437 const ImU32 border_col_resizing = GetColorU32((window->ResizeBorderHeld != -1) ? ImGuiCol_SeparatorActive : ImGuiCol_SeparatorHovered);
6438 RenderWindowOuterSingleBorder(window, border_n, border_col_resizing, ImMax(2.0f, window->WindowBorderSize));
6440 if (
g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
6442 float y = window->Pos.y + window->TitleBarHeight() - 1;
6443 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);
6449void 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)
6452 ImGuiStyle& style =
g.Style;
6453 ImGuiWindowFlags flags = window->Flags;
6456 IM_ASSERT(window->BeginCount == 0);
6457 window->SkipItems =
false;
6461 const float window_rounding = window->WindowRounding;
6462 const float window_border_size = window->WindowBorderSize;
6463 if (window->Collapsed)
6466 const float backup_border_size = style.FrameBorderSize;
6467 g.Style.FrameBorderSize = window->WindowBorderSize;
6468 ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !
g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed);
6469 if (window->ViewportOwned)
6470 title_bar_col |= IM_COL32_A_MASK;
6471 RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col,
true, window_rounding);
6472 g.Style.FrameBorderSize = backup_border_size;
6477 if (!(flags & ImGuiWindowFlags_NoBackground))
6479 bool is_docking_transparent_payload =
false;
6480 if (
g.DragDropActive && (
g.FrameCount -
g.DragDropAcceptFrameCount) <= 1 &&
g.IO.ConfigDockingTransparentPayload)
6481 if (
g.DragDropPayload.IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) && *(ImGuiWindow**)
g.DragDropPayload.Data == window)
6482 is_docking_transparent_payload =
true;
6484 ImU32 bg_col = GetColorU32(GetWindowBgColorIdx(window));
6485 if (window->ViewportOwned)
6487 bg_col |= IM_COL32_A_MASK;
6488 if (is_docking_transparent_payload)
6489 window->Viewport->Alpha *= DOCKING_TRANSPARENT_PAYLOAD_ALPHA;
6494 bool override_alpha =
false;
6496 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasBgAlpha)
6498 alpha =
g.NextWindowData.BgAlphaVal;
6499 override_alpha =
true;
6501 if (is_docking_transparent_payload)
6503 alpha *= DOCKING_TRANSPARENT_PAYLOAD_ALPHA;
6504 override_alpha =
true;
6507 bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT);
6511 if (window->DockIsActive)
6512 window->DockNode->LastBgColor = bg_col;
6513 ImDrawList* bg_draw_list = window->DockIsActive ? window->DockNode->HostWindow->DrawList : window->DrawList;
6514 if (window->DockIsActive || (flags & ImGuiWindowFlags_DockNodeHost))
6515 bg_draw_list->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
6516 bg_draw_list->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
6517 if (window->DockIsActive || (flags & ImGuiWindowFlags_DockNodeHost))
6518 bg_draw_list->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_FG);
6520 if (window->DockIsActive)
6521 window->DockNode->IsBgDrawnThisFrame =
true;
6526 if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
6528 ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
6529 if (window->ViewportOwned)
6530 title_bar_col |= IM_COL32_A_MASK;
6531 window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawFlags_RoundCornersTop);
6535 if (flags & ImGuiWindowFlags_MenuBar)
6537 ImRect menu_bar_rect = window->MenuBarRect();
6538 menu_bar_rect.ClipWith(window->Rect());
6539 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);
6540 if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
6541 window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
6545 ImGuiDockNode* node = window->DockNode;
6546 if (window->DockIsActive && node->IsHiddenTabBar() && !node->IsNoTabBar())
6548 float unhide_sz_draw = ImTrunc(
g.FontSize * 0.70f);
6549 float unhide_sz_hit = ImTrunc(
g.FontSize * 0.55f);
6550 ImVec2 p = node->Pos;
6551 ImRect r(p, p + ImVec2(unhide_sz_hit, unhide_sz_hit));
6552 ImGuiID unhide_id = window->GetID(
"#UNHIDE");
6553 KeepAliveID(unhide_id);
6555 if (ButtonBehavior(r, unhide_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren))
6556 node->WantHiddenTabBarToggle =
true;
6557 else if (held && IsMouseDragging(0))
6558 StartMouseMovingWindowOrNode(window, node,
true);
6561 ImU32 col = GetColorU32(((held && hovered) || (node->IsFocused && !hovered)) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
6562 window->DrawList->AddTriangleFilled(p, p + ImVec2(unhide_sz_draw, 0.0f), p + ImVec2(0.0f, unhide_sz_draw), col);
6566 if (window->ScrollbarX)
6567 Scrollbar(ImGuiAxis_X);
6568 if (window->ScrollbarY)
6569 Scrollbar(ImGuiAxis_Y);
6572 if (handle_borders_and_resize_grips && !(flags & ImGuiWindowFlags_NoResize))
6574 for (
int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
6576 const ImU32 col = resize_grip_col[resize_grip_n];
6577 if ((col & IM_COL32_A_MASK) == 0)
6580 const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.
CornerPosN);
6581 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)));
6582 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)));
6583 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);
6584 window->DrawList->PathFillConvex(col);
6589 if (handle_borders_and_resize_grips && !window->DockNodeAsHost)
6590 RenderWindowOuterBorders(window);
6596void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window,
const ImRect& title_bar_rect,
const char* name,
bool* p_open)
6599 ImGuiStyle& style =
g.Style;
6600 ImGuiWindowFlags flags = window->Flags;
6602 const bool has_close_button = (p_open != NULL);
6603 const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None);
6607 const ImGuiItemFlags item_flags_backup =
g.CurrentItemFlags;
6608 g.CurrentItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
6609 window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
6613 float pad_l = style.FramePadding.x;
6614 float pad_r = style.FramePadding.x;
6615 float button_sz =
g.FontSize;
6616 ImVec2 close_button_pos;
6617 ImVec2 collapse_button_pos;
6618 if (has_close_button)
6620 close_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - button_sz, title_bar_rect.Min.y + style.FramePadding.y);
6621 pad_r += button_sz + style.ItemInnerSpacing.x;
6623 if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Right)
6625 collapse_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - button_sz, title_bar_rect.Min.y + style.FramePadding.y);
6626 pad_r += button_sz + style.ItemInnerSpacing.x;
6628 if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Left)
6630 collapse_button_pos = ImVec2(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y + style.FramePadding.y);
6631 pad_l += button_sz + style.ItemInnerSpacing.x;
6635 if (has_collapse_button)
6636 if (CollapseButton(window->GetID(
"#COLLAPSE"), collapse_button_pos, NULL))
6637 window->WantCollapseToggle =
true;
6640 if (has_close_button)
6641 if (CloseButton(window->GetID(
"#CLOSE"), close_button_pos))
6644 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
6645 g.CurrentItemFlags = item_flags_backup;
6649 const float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? button_sz * 0.80f : 0.0f;
6650 const ImVec2 text_size =
CalcTextSize(name, NULL,
true) + ImVec2(marker_size_x, 0.0f);
6654 if (pad_l > style.FramePadding.x)
6655 pad_l +=
g.Style.ItemInnerSpacing.x;
6656 if (pad_r > style.FramePadding.x)
6657 pad_r +=
g.Style.ItemInnerSpacing.x;
6658 if (style.WindowTitleAlign.x > 0.0f && style.WindowTitleAlign.x < 1.0f)
6660 float centerness = ImSaturate(1.0f - ImFabs(style.WindowTitleAlign.x - 0.5f) * 2.0f);
6661 float pad_extend = ImMin(ImMax(pad_l, pad_r), title_bar_rect.GetWidth() - pad_l - pad_r - text_size.x);
6662 pad_l = ImMax(pad_l, pad_extend * centerness);
6663 pad_r = ImMax(pad_r, pad_extend * centerness);
6666 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);
6667 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);
6668 if (flags & ImGuiWindowFlags_UnsavedDocument)
6671 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);
6672 marker_pos.y = (layout_r.Min.y + layout_r.Max.y) * 0.5f;
6673 if (marker_pos.x > layout_r.Min.x)
6675 RenderBullet(window->DrawList, marker_pos, GetColorU32(ImGuiCol_Text));
6676 clip_r.Max.x = ImMin(clip_r.Max.x, marker_pos.x - (
int)(marker_size_x * 0.5f));
6681 RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r);
6684void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window)
6686 window->ParentWindow = parent_window;
6687 window->RootWindow = window->RootWindowPopupTree = window->RootWindowDockTree = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window;
6688 if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
6690 window->RootWindowDockTree = parent_window->RootWindowDockTree;
6691 if (!window->DockIsActive && !(parent_window->Flags & ImGuiWindowFlags_DockNodeHost))
6692 window->RootWindow = parent_window->RootWindow;
6694 if (parent_window && (flags & ImGuiWindowFlags_Popup))
6695 window->RootWindowPopupTree = parent_window->RootWindowPopupTree;
6696 if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)))
6697 window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight;
6698 while (window->RootWindowForNav->Flags & ImGuiWindowFlags_NavFlattened)
6700 IM_ASSERT(window->RootWindowForNav->ParentWindow != NULL);
6701 window->RootWindowForNav = window->RootWindowForNav->ParentWindow;
6718ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
6721 if (
g.OpenPopupStack.Size <= 0)
6725 for (ImGuiPopupData& popup_data :
g.OpenPopupStack)
6727 ImGuiWindow* popup_window = popup_data.Window;
6728 if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal))
6730 if (!popup_window->Active && !popup_window->WasActive)
6733 return popup_window;
6734 if (IsWindowWithinBeginStackOf(window, popup_window))
6736 return popup_window;
6748bool ImGui::Begin(
const char* name,
bool* p_open, ImGuiWindowFlags flags)
6751 const ImGuiStyle& style =
g.Style;
6752 IM_ASSERT(name != NULL && name[0] !=
'\0');
6753 IM_ASSERT(
g.WithinFrameScope);
6754 IM_ASSERT(
g.FrameCountEnded !=
g.FrameCount);
6757 ImGuiWindow* window = FindWindowByName(name);
6758 const bool window_just_created = (window == NULL);
6759 if (window_just_created)
6760 window = CreateNewWindow(name, flags);
6763 if (
g.DebugBreakInWindow == window->ID)
6767 if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs)
6768 flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
6770 if (flags & ImGuiWindowFlags_NavFlattened)
6771 IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow);
6773 const int current_frame =
g.FrameCount;
6774 const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame);
6775 window->IsFallbackWindow = (
g.CurrentWindowStack.Size == 0 &&
g.WithinFrameScopeWithImplicitWindow);
6778 bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1);
6779 if (flags & ImGuiWindowFlags_Popup)
6781 ImGuiPopupData& popup_ref =
g.OpenPopupStack[
g.BeginPopupStack.Size];
6782 window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId);
6783 window_just_activated_by_user |= (window != popup_ref.Window);
6787 const bool window_was_appearing = window->Appearing;
6788 if (first_begin_of_the_frame)
6790 UpdateWindowInFocusOrderList(window, window_just_created, flags);
6791 window->Appearing = window_just_activated_by_user;
6792 if (window->Appearing)
6793 SetWindowConditionAllowFlags(window, ImGuiCond_Appearing,
true);
6794 window->FlagsPreviousFrame = window->Flags;
6795 window->Flags = (ImGuiWindowFlags)flags;
6796 window->ChildFlags = (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasChildFlags) ?
g.NextWindowData.ChildFlags : 0;
6797 window->LastFrameActive = current_frame;
6798 window->LastTimeActive = (float)
g.Time;
6799 window->BeginOrderWithinParent = 0;
6800 window->BeginOrderWithinContext = (short)(
g.WindowsActiveCount++);
6804 flags = window->Flags;
6809 IM_ASSERT(window->DockNode == NULL || window->DockNodeAsHost == NULL);
6810 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasDock)
6811 SetWindowDock(window,
g.NextWindowData.DockId,
g.NextWindowData.DockCond);
6812 if (first_begin_of_the_frame)
6814 bool has_dock_node = (window->DockId != 0 || window->DockNode != NULL);
6815 bool new_auto_dock_node = !has_dock_node && GetWindowAlwaysWantOwnTabBar(window);
6816 bool dock_node_was_visible = window->DockNodeIsVisible;
6817 bool dock_tab_was_visible = window->DockTabIsVisible;
6818 if (has_dock_node || new_auto_dock_node)
6820 BeginDocked(window, p_open);
6821 flags = window->Flags;
6822 if (window->DockIsActive)
6824 IM_ASSERT(window->DockNode != NULL);
6825 g.NextWindowData.Flags &= ~ImGuiNextWindowDataFlags_HasSizeConstraint;
6829 if (window->DockTabIsVisible && !dock_tab_was_visible && dock_node_was_visible && !window->Appearing && !window_was_appearing)
6831 window->Appearing =
true;
6832 SetWindowConditionAllowFlags(window, ImGuiCond_Appearing,
true);
6837 window->DockIsActive = window->DockNodeIsVisible = window->DockTabIsVisible =
false;
6842 ImGuiWindow* parent_window_in_stack = (window->DockIsActive && window->DockNode->HostWindow) ? window->DockNode->HostWindow :
g.CurrentWindowStack.empty() ? NULL :
g.CurrentWindowStack.back().
Window;
6843 ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow;
6844 IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
6847 if (window->IDStack.Size == 0)
6848 window->IDStack.push_back(window->ID);
6851 g.CurrentWindow = window;
6852 ImGuiWindowStackData window_stack_data;
6853 window_stack_data.Window = window;
6854 window_stack_data.ParentLastItemDataBackup =
g.LastItemData;
6855 window_stack_data.StackSizesOnBegin.SetToContextState(&
g);
6856 g.CurrentWindowStack.push_back(window_stack_data);
6857 if (flags & ImGuiWindowFlags_ChildMenu)
6861 if (first_begin_of_the_frame)
6863 UpdateWindowParentAndRootLinks(window, flags, parent_window);
6864 window->ParentWindowInBeginStack = parent_window_in_stack;
6869 window->ParentWindowForFocusRoute = (window->RootWindow != window) ? parent_window_in_stack : NULL;
6870 if (window->ParentWindowForFocusRoute == NULL && window->DockNode != NULL)
6871 if (window->DockNode->MergedFlags & ImGuiDockNodeFlags_DockedWindowsInFocusRoute)
6872 window->ParentWindowForFocusRoute = window->DockNode->HostWindow;
6875 if (window->WindowClass.FocusRouteParentWindowId != 0)
6877 window->ParentWindowForFocusRoute = FindWindowByID(window->WindowClass.FocusRouteParentWindowId);
6878 IM_ASSERT(window->ParentWindowForFocusRoute != 0);
6883 PushFocusScope((flags & ImGuiWindowFlags_NavFlattened) ?
g.CurrentFocusScopeId : window->
ID);
6884 window->NavRootFocusScopeId =
g.CurrentFocusScopeId;
6887 if (flags & ImGuiWindowFlags_Popup)
6889 ImGuiPopupData& popup_ref =
g.OpenPopupStack[
g.BeginPopupStack.Size];
6890 popup_ref.Window = window;
6891 popup_ref.ParentNavLayer = parent_window_in_stack->DC.NavLayerCurrent;
6892 g.BeginPopupStack.push_back(popup_ref);
6893 window->PopupId = popup_ref.PopupId;
6898 bool window_pos_set_by_api =
false;
6899 bool window_size_x_set_by_api =
false, window_size_y_set_by_api =
false;
6900 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos)
6902 window_pos_set_by_api = (window->SetWindowPosAllowFlags &
g.NextWindowData.PosCond) != 0;
6903 if (window_pos_set_by_api && ImLengthSqr(
g.NextWindowData.PosPivotVal) > 0.00001f)
6907 window->SetWindowPosVal =
g.NextWindowData.PosVal;
6908 window->SetWindowPosPivot =
g.NextWindowData.PosPivotVal;
6909 window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
6913 SetWindowPos(window,
g.NextWindowData.PosVal,
g.NextWindowData.PosCond);
6916 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize)
6918 window_size_x_set_by_api = (window->SetWindowSizeAllowFlags &
g.NextWindowData.SizeCond) != 0 && (
g.NextWindowData.SizeVal.x > 0.0f);
6919 window_size_y_set_by_api = (window->SetWindowSizeAllowFlags &
g.NextWindowData.SizeCond) != 0 && (
g.NextWindowData.SizeVal.y > 0.0f);
6920 if ((window->ChildFlags & ImGuiChildFlags_ResizeX) && (window->SetWindowSizeAllowFlags & ImGuiCond_FirstUseEver) == 0)
6921 g.NextWindowData.SizeVal.x = window->SizeFull.x;
6922 if ((window->ChildFlags & ImGuiChildFlags_ResizeY) && (window->SetWindowSizeAllowFlags & ImGuiCond_FirstUseEver) == 0)
6923 g.NextWindowData.SizeVal.y = window->SizeFull.y;
6924 SetWindowSize(window,
g.NextWindowData.SizeVal,
g.NextWindowData.SizeCond);
6926 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasScroll)
6928 if (
g.NextWindowData.ScrollVal.x >= 0.0f)
6930 window->ScrollTarget.x =
g.NextWindowData.ScrollVal.x;
6931 window->ScrollTargetCenterRatio.x = 0.0f;
6933 if (
g.NextWindowData.ScrollVal.y >= 0.0f)
6935 window->ScrollTarget.y =
g.NextWindowData.ScrollVal.y;
6936 window->ScrollTargetCenterRatio.y = 0.0f;
6939 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasContentSize)
6940 window->ContentSizeExplicit =
g.NextWindowData.ContentSizeVal;
6941 else if (first_begin_of_the_frame)
6942 window->ContentSizeExplicit = ImVec2(0.0f, 0.0f);
6943 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasWindowClass)
6944 window->WindowClass =
g.NextWindowData.WindowClass;
6945 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasCollapsed)
6946 SetWindowCollapsed(window,
g.NextWindowData.CollapsedVal,
g.NextWindowData.CollapsedCond);
6947 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasFocus)
6948 FocusWindow(window);
6949 if (window->Appearing)
6950 SetWindowConditionAllowFlags(window, ImGuiCond_Appearing,
false);
6953 g.CurrentWindow = NULL;
6956 if (first_begin_of_the_frame)
6959 const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip);
6960 const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesCannotSkipItems > 0);
6961 window->Active =
true;
6962 window->HasCloseButton = (p_open != NULL);
6963 window->ClipRect = ImVec4(-FLT_MAX, -FLT_MAX, +FLT_MAX, +FLT_MAX);
6964 window->IDStack.resize(1);
6965 window->DrawList->_ResetForNewFrame();
6966 window->DC.CurrentTableIdx = -1;
6967 if (flags & ImGuiWindowFlags_DockNodeHost)
6969 window->DrawList->ChannelsSplit(2);
6970 window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_FG);
6974 if (window->MemoryCompacted)
6975 GcAwakeTransientWindowBuffers(window);
6979 bool window_title_visible_elsewhere =
false;
6980 if ((window->Viewport && window->Viewport->Window == window) || (window->DockIsActive))
6981 window_title_visible_elsewhere =
true;
6982 else if (
g.NavWindowingListWindow != NULL && (window->Flags & ImGuiWindowFlags_NoNavFocus) == 0)
6983 window_title_visible_elsewhere =
true;
6984 if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0)
6986 size_t buf_len = (size_t)window->NameBufLen;
6987 window->Name =
ImStrdupcpy(window->Name, &buf_len, name);
6988 window->NameBufLen = (int)buf_len;
6994 CalcWindowContentSizes(window, &window->ContentSize, &window->ContentSizeIdeal);
6999 if (window->HiddenFramesCanSkipItems > 0)
7000 window->HiddenFramesCanSkipItems--;
7001 if (window->HiddenFramesCannotSkipItems > 0)
7002 window->HiddenFramesCannotSkipItems--;
7003 if (window->HiddenFramesForRenderOnly > 0)
7004 window->HiddenFramesForRenderOnly--;
7007 if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api))
7008 window->HiddenFramesCannotSkipItems = 1;
7012 if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0)
7014 window->HiddenFramesCannotSkipItems = 1;
7015 if (flags & ImGuiWindowFlags_AlwaysAutoResize)
7017 if (!window_size_x_set_by_api)
7018 window->Size.x = window->SizeFull.x = 0.f;
7019 if (!window_size_y_set_by_api)
7020 window->Size.y = window->SizeFull.y = 0.f;
7021 window->ContentSize = window->ContentSizeIdeal = ImVec2(0.f, 0.f);
7028 WindowSelectViewport(window);
7029 SetCurrentViewport(window, window->Viewport);
7030 window->FontDpiScale = (
g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleFonts) ? window->Viewport->DpiScale : 1.0f;
7031 SetCurrentWindow(window);
7032 flags = window->Flags;
7037 if (!window->DockIsActive && (flags & ImGuiWindowFlags_ChildWindow))
7038 window->WindowBorderSize = style.ChildBorderSize;
7040 window->WindowBorderSize = ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize;
7041 window->WindowPadding = style.WindowPadding;
7042 if (!window->DockIsActive && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !(window->ChildFlags & ImGuiChildFlags_AlwaysUseWindowPadding) && window->WindowBorderSize == 0.0f)
7043 window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
7046 window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x),
g.NextWindowData.MenuBarOffsetMinVal.x);
7047 window->DC.MenuBarOffset.y =
g.NextWindowData.MenuBarOffsetMinVal.y;
7051 bool use_current_size_for_scrollbar_x = window_just_created;
7052 bool use_current_size_for_scrollbar_y = window_just_created;
7053 if (window_size_x_set_by_api && window->ContentSizeExplicit.x != 0.0f)
7054 use_current_size_for_scrollbar_x =
true;
7055 if (window_size_y_set_by_api && window->ContentSizeExplicit.y != 0.0f)
7056 use_current_size_for_scrollbar_y =
true;
7060 if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse) && !window->DockIsActive)
7063 ImRect title_bar_rect = window->TitleBarRect();
7064 if (
g.HoveredWindow == window &&
g.HoveredId == 0 &&
g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max))
7065 if (
g.IO.MouseClickedCount[0] == 2 && GetKeyOwner(ImGuiKey_MouseLeft) == ImGuiKeyOwner_None)
7066 window->WantCollapseToggle =
true;
7067 if (window->WantCollapseToggle)
7069 window->Collapsed = !window->Collapsed;
7070 if (!window->Collapsed)
7071 use_current_size_for_scrollbar_y =
true;
7072 MarkIniSettingsDirty(window);
7077 window->Collapsed =
false;
7079 window->WantCollapseToggle =
false;
7085 const ImVec2 scrollbar_sizes_from_last_frame = window->ScrollbarSizes;
7086 window->DecoOuterSizeX1 = 0.0f;
7087 window->DecoOuterSizeX2 = 0.0f;
7088 window->DecoOuterSizeY1 = window->TitleBarHeight() + window->MenuBarHeight();
7089 window->DecoOuterSizeY2 = 0.0f;
7090 window->ScrollbarSizes = ImVec2(0.0f, 0.0f);
7093 const ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, window->ContentSizeIdeal);
7094 if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed)
7097 if (!window_size_x_set_by_api)
7099 window->SizeFull.x = size_auto_fit.x;
7100 use_current_size_for_scrollbar_x =
true;
7102 if (!window_size_y_set_by_api)
7104 window->SizeFull.y = size_auto_fit.y;
7105 use_current_size_for_scrollbar_y =
true;
7108 else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
7112 if (!window_size_x_set_by_api && window->AutoFitFramesX > 0)
7114 window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
7115 use_current_size_for_scrollbar_x =
true;
7117 if (!window_size_y_set_by_api && window->AutoFitFramesY > 0)
7119 window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
7120 use_current_size_for_scrollbar_y =
true;
7122 if (!window->Collapsed)
7123 MarkIniSettingsDirty(window);
7127 window->SizeFull = CalcWindowSizeAfterConstraint(window, window->SizeFull);
7128 window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull;
7133 if (window_just_activated_by_user)
7135 window->AutoPosLastDirection = ImGuiDir_None;
7136 if ((flags & ImGuiWindowFlags_Popup) != 0 && !(flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api)
7137 window->Pos =
g.BeginPopupStack.back().OpenPopupPos;
7141 if (flags & ImGuiWindowFlags_ChildWindow)
7143 IM_ASSERT(parent_window && parent_window->Active);
7144 window->BeginOrderWithinParent = (short)parent_window->DC.ChildWindows.Size;
7145 parent_window->DC.ChildWindows.push_back(window);
7146 if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api && !window_is_child_tooltip)
7147 window->Pos = parent_window->DC.CursorPos;
7150 const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesCannotSkipItems == 0);
7151 if (window_pos_with_pivot)
7152 SetWindowPos(window, window->SetWindowPosVal - window->Size * window->SetWindowPosPivot, 0);
7153 else if ((flags & ImGuiWindowFlags_ChildMenu) != 0)
7154 window->Pos = FindBestWindowPosForPopup(window);
7155 else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize)
7156 window->Pos = FindBestWindowPosForPopup(window);
7157 else if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip)
7158 window->Pos = FindBestWindowPosForPopup(window);
7161 if (window->ViewportAllowPlatformMonitorExtend >= 0 && !window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_IsMinimized))
7162 if (!window->Viewport->GetMainRect().Contains(window->Rect()))
7166 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoFocusOnAppearing);
7170 SetCurrentViewport(window, window->Viewport);
7171 window->FontDpiScale = (
g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleFonts) ? window->Viewport->DpiScale : 1.0f;
7172 SetCurrentWindow(window);
7175 if (window->ViewportOwned)
7176 WindowSyncOwnedViewport(window, parent_window_in_stack);
7180 ImRect viewport_rect(window->Viewport->GetMainRect());
7181 ImRect viewport_work_rect(window->Viewport->GetWorkRect());
7182 ImVec2 visibility_padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
7183 ImRect visibility_rect(viewport_work_rect.Min + visibility_padding, viewport_work_rect.Max - visibility_padding);
7188 if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow))
7190 if (!window->ViewportOwned && viewport_rect.GetWidth() > 0 && viewport_rect.GetHeight() > 0.0f)
7192 ClampWindowPos(window, visibility_rect);
7194 else if (window->ViewportOwned &&
g.PlatformIO.Monitors.Size > 0)
7196 if (
g.MovingWindow != NULL && window->RootWindowDockTree ==
g.MovingWindow->RootWindowDockTree)
7199 visibility_rect =
g.PlatformMonitorsFullWorkRect;
7205 const ImGuiPlatformMonitor* monitor = GetViewportPlatformMonitor(window->Viewport);
7206 visibility_rect = ImRect(monitor->WorkPos, monitor->WorkPos + monitor->WorkSize);
7208 visibility_rect.Expand(-visibility_padding);
7209 ClampWindowPos(window, visibility_rect);
7212 window->Pos = ImTrunc(window->Pos);
7216 if (window->ViewportOwned || window->DockIsActive)
7217 window->WindowRounding = 0.0f;
7219 window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
7226 bool want_focus =
false;
7227 if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing))
7229 if (flags & ImGuiWindowFlags_Popup)
7231 else if ((window->DockIsActive || (flags & ImGuiWindowFlags_ChildWindow) == 0) && !(flags & ImGuiWindowFlags_Tooltip))
7236#ifdef IMGUI_ENABLE_TEST_ENGINE
7237 if (
g.TestEngineHookItems)
7239 IM_ASSERT(window->IDStack.Size == 1);
7240 window->IDStack.Size = 0;
7241 IMGUI_TEST_ENGINE_ITEM_ADD(window->ID, window->Rect(), NULL);
7242 IMGUI_TEST_ENGINE_ITEM_INFO(window->ID, window->Name, (
g.HoveredWindow == window) ? ImGuiItemStatusFlags_HoveredRect : 0);
7243 window->IDStack.Size = 1;
7248 const bool handle_borders_and_resize_grips = (window->DockNodeAsHost || !window->DockIsActive);
7251 int border_hovered = -1, border_held = -1;
7252 ImU32 resize_grip_col[4] = {};
7253 const int resize_grip_count = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) ? 0 :
g.IO.ConfigWindowsResizeFromEdges ? 2 : 1;
7254 const float resize_grip_draw_size = IM_TRUNC(ImMax(
g.FontSize * 1.10f, window->WindowRounding + 1.0f +
g.FontSize * 0.2f));
7255 if (handle_borders_and_resize_grips && !window->Collapsed)
7256 if (
int auto_fit_mask = UpdateWindowManualResize(window, size_auto_fit, &border_hovered, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect))
7258 if (auto_fit_mask & (1 << ImGuiAxis_X))
7259 use_current_size_for_scrollbar_x =
true;
7260 if (auto_fit_mask & (1 << ImGuiAxis_Y))
7261 use_current_size_for_scrollbar_y =
true;
7263 window->ResizeBorderHovered = (
signed char)border_hovered;
7264 window->ResizeBorderHeld = (
signed char)border_held;
7267 if (window->ViewportOwned)
7269 if (!window->Viewport->PlatformRequestMove)
7270 window->Viewport->Pos = window->Pos;
7271 if (!window->Viewport->PlatformRequestResize)
7272 window->Viewport->Size = window->Size;
7273 window->Viewport->UpdateWorkRect();
7274 viewport_rect = window->Viewport->GetMainRect();
7278 window->ViewportPos = window->Viewport->Pos;
7283 if (!window->Collapsed)
7288 ImVec2 avail_size_from_current_frame = ImVec2(window->SizeFull.x, window->SizeFull.y - (window->DecoOuterSizeY1 + window->DecoOuterSizeY2));
7289 ImVec2 avail_size_from_last_frame = window->InnerRect.GetSize() + scrollbar_sizes_from_last_frame;
7290 ImVec2 needed_size_from_last_frame = window_just_created ? ImVec2(0, 0) : window->ContentSize + window->WindowPadding * 2.0f;
7291 float size_x_for_scrollbars = use_current_size_for_scrollbar_x ? avail_size_from_current_frame.x : avail_size_from_last_frame.x;
7292 float size_y_for_scrollbars = use_current_size_for_scrollbar_y ? avail_size_from_current_frame.y : avail_size_from_last_frame.y;
7294 window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
7295 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));
7296 if (window->ScrollbarX && !window->ScrollbarY)
7297 window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar);
7298 window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
7301 window->DecoOuterSizeX2 += window->ScrollbarSizes.x;
7302 window->DecoOuterSizeY2 += window->ScrollbarSizes.y;
7314 const ImRect host_rect = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) ? parent_window->ClipRect : viewport_rect;
7315 const ImRect outer_rect = window->Rect();
7316 const ImRect title_bar_rect = window->TitleBarRect();
7317 window->OuterRectClipped = outer_rect;
7318 if (window->DockIsActive)
7319 window->OuterRectClipped.Min.y += window->TitleBarHeight();
7320 window->OuterRectClipped.ClipWith(host_rect);
7328 window->InnerRect.Min.x = window->Pos.x + window->DecoOuterSizeX1;
7329 window->InnerRect.Min.y = window->Pos.y + window->DecoOuterSizeY1;
7330 window->InnerRect.Max.x = window->Pos.x + window->Size.x - window->DecoOuterSizeX2;
7331 window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->DecoOuterSizeY2;
7340 float top_border_size = (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
7341 window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(ImTrunc(window->WindowPadding.x * 0.5f), window->WindowBorderSize));
7342 window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + top_border_size);
7343 window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(ImTrunc(window->WindowPadding.x * 0.5f), window->WindowBorderSize));
7344 window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y - window->WindowBorderSize);
7345 window->InnerClipRect.ClipWithFull(host_rect);
7348 if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))
7349 window->ItemWidthDefault = ImTrunc(window->Size.x * 0.65f);
7351 window->ItemWidthDefault = ImTrunc(
g.FontSize * 16.0f);
7358 window->ScrollMax.x = ImMax(0.0f, window->ContentSize.x + window->WindowPadding.x * 2.0f - window->InnerRect.GetWidth());
7359 window->ScrollMax.y = ImMax(0.0f, window->ContentSize.y + window->WindowPadding.y * 2.0f - window->InnerRect.GetHeight());
7362 window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window);
7363 window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
7364 window->DecoInnerSizeX1 = window->DecoInnerSizeY1 = 0.0f;
7369 IM_ASSERT(window->DrawList->CmdBuffer.Size == 1 && window->DrawList->CmdBuffer[0].ElemCount == 0);
7370 window->DrawList->PushTextureID(
g.Font->ContainerAtlas->TexID);
7371 PushClipRect(host_rect.Min, host_rect.Max,
false);
7376 const bool is_undocked_or_docked_visible = !window->DockIsActive || window->DockTabIsVisible;
7377 if (is_undocked_or_docked_visible)
7379 bool render_decorations_in_parent =
false;
7380 if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip)
7384 ImGuiWindow* previous_child = parent_window->DC.ChildWindows.Size >= 2 ? parent_window->DC.ChildWindows[parent_window->DC.ChildWindows.Size - 2] : NULL;
7385 bool previous_child_overlapping = previous_child ? previous_child->Rect().Overlaps(window->Rect()) :
false;
7386 bool parent_is_empty = (parent_window->DrawList->VtxBuffer.Size == 0);
7387 if (window->DrawList->CmdBuffer.back().ElemCount == 0 && !parent_is_empty && !previous_child_overlapping)
7388 render_decorations_in_parent =
true;
7390 if (render_decorations_in_parent)
7391 window->DrawList = parent_window->DrawList;
7394 const ImGuiWindow* window_to_highlight =
g.NavWindowingTarget ?
g.NavWindowingTarget :
g.NavWindow;
7395 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)));
7396 RenderWindowDecorations(window, title_bar_rect, title_bar_is_highlight, handle_borders_and_resize_grips, resize_grip_count, resize_grip_col, resize_grip_draw_size);
7398 if (render_decorations_in_parent)
7399 window->DrawList = &window->DrawListInst;
7409 const bool allow_scrollbar_x = !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar);
7410 const bool allow_scrollbar_y = !(flags & ImGuiWindowFlags_NoScrollbar);
7411 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)));
7412 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)));
7413 window->WorkRect.Min.x = ImTrunc(window->InnerRect.Min.x - window->Scroll.x + ImMax(window->WindowPadding.x, window->WindowBorderSize));
7414 window->WorkRect.Min.y = ImTrunc(window->InnerRect.Min.y - window->Scroll.y + ImMax(window->WindowPadding.y, window->WindowBorderSize));
7415 window->WorkRect.Max.x = window->WorkRect.Min.x + work_rect_size_x;
7416 window->WorkRect.Max.y = window->WorkRect.Min.y + work_rect_size_y;
7417 window->ParentWorkRect = window->WorkRect;
7424 window->ContentRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x + window->DecoOuterSizeX1;
7425 window->ContentRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->DecoOuterSizeY1;
7426 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)));
7427 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)));
7431 window->DC.Indent.x = window->DecoOuterSizeX1 + window->WindowPadding.x - window->Scroll.x;
7432 window->DC.GroupOffset.x = 0.0f;
7433 window->DC.ColumnsOffset.x = 0.0f;
7437 double start_pos_highp_x = (double)window->Pos.x + window->WindowPadding.x - (
double)window->Scroll.x + window->DecoOuterSizeX1 + window->DC.ColumnsOffset.x;
7438 double start_pos_highp_y = (double)window->Pos.y + window->WindowPadding.y - (
double)window->Scroll.y + window->DecoOuterSizeY1;
7439 window->DC.CursorStartPos = ImVec2((
float)start_pos_highp_x, (
float)start_pos_highp_y);
7440 window->DC.CursorStartPosLossyness = ImVec2((
float)(start_pos_highp_x - window->DC.CursorStartPos.x), (
float)(start_pos_highp_y - window->DC.CursorStartPos.y));
7441 window->DC.CursorPos = window->DC.CursorStartPos;
7442 window->DC.CursorPosPrevLine = window->DC.CursorPos;
7443 window->DC.CursorMaxPos = window->DC.CursorStartPos;
7444 window->DC.IdealMaxPos = window->DC.CursorStartPos;
7445 window->DC.CurrLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f);
7446 window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
7447 window->DC.IsSameLine = window->DC.IsSetPos =
false;
7449 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
7450 window->DC.NavLayersActiveMask = window->DC.NavLayersActiveMaskNext;
7451 window->DC.NavLayersActiveMaskNext = 0x00;
7452 window->DC.NavIsScrollPushableX =
true;
7453 window->DC.NavHideHighlightOneFrame =
false;
7454 window->DC.NavWindowHasScrollY = (window->ScrollMax.y > 0.0f);
7456 window->DC.MenuBarAppending =
false;
7457 window->DC.MenuColumns.Update(style.ItemSpacing.x, window_just_activated_by_user);
7458 window->DC.TreeDepth = 0;
7459 window->DC.TreeJumpToParentOnPopMask = 0x00;
7460 window->DC.ChildWindows.resize(0);
7461 window->DC.StateStorage = &window->StateStorage;
7462 window->DC.CurrentColumns = NULL;
7463 window->DC.LayoutType = ImGuiLayoutType_Vertical;
7464 window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
7466 window->DC.ItemWidth = window->ItemWidthDefault;
7467 window->DC.TextWrapPos = -1.0f;
7468 window->DC.ItemWidthStack.resize(0);
7469 window->DC.TextWrapPosStack.resize(0);
7470 if (flags & ImGuiWindowFlags_Modal)
7471 window->DC.ModalDimBgColor = ColorConvertFloat4ToU32(GetStyleColorVec4(ImGuiCol_ModalWindowDimBg));
7473 if (window->AutoFitFramesX > 0)
7474 window->AutoFitFramesX--;
7475 if (window->AutoFitFramesY > 0)
7476 window->AutoFitFramesY--;
7483 FocusWindow(window, ImGuiFocusRequestFlags_UnlessBelowModal);
7484 if (want_focus && window ==
g.NavWindow)
7485 NavInitWindow(window,
false);
7488 if (p_open != NULL && window->Viewport->PlatformRequestClose && window->Viewport != GetMainViewport())
7490 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Window '%s' closed by PlatformRequestClose\n", window->Name);
7492 g.NavWindowingToggleLayer =
false;
7496 if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
7497 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);
7500 window->HitTestHoleSize.x = window->HitTestHoleSize.y = 0;
7512 if (
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable)
7516 if (
g.MovingWindow == window && (window->RootWindowDockTree->Flags & ImGuiWindowFlags_NoDocking) == 0)
7517 BeginDockableDragDropSource(window);
7520 if (
g.DragDropActive && !(flags & ImGuiWindowFlags_NoDocking))
7521 if (
g.MovingWindow == NULL ||
g.MovingWindow->RootWindowDockTree != window)
7522 if ((window == window->RootWindowDockTree) && !(window->Flags & ImGuiWindowFlags_DockNodeHost))
7523 BeginDockableDragDropTarget(window);
7528 if (window->DockIsActive)
7529 SetLastItemData(window->MoveId,
g.CurrentItemFlags, window->DockTabItemStatusFlags, window->DockTabItemRect);
7531 SetLastItemData(window->MoveId,
g.CurrentItemFlags, IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max,
false) ? ImGuiItemStatusFlags_HoveredRect : 0, title_bar_rect);
7534#ifndef IMGUI_DISABLE_DEBUG_TOOLS
7535 if (
g.DebugLocateId != 0 && (window->ID ==
g.DebugLocateId || window->MoveId ==
g.DebugLocateId))
7536 DebugLocateItemResolveWithLastItem();
7540#ifdef IMGUI_ENABLE_TEST_ENGINE
7541 if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
7542 IMGUI_TEST_ENGINE_ITEM_ADD(
g.LastItemData.ID,
g.LastItemData.Rect, &
g.LastItemData);
7548 SetCurrentViewport(window, window->Viewport);
7549 SetCurrentWindow(window);
7552 if (!(flags & ImGuiWindowFlags_DockNodeHost))
7553 PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max,
true);
7556 window->WriteAccessed =
false;
7557 window->BeginCount++;
7558 g.NextWindowData.ClearFlags();
7561 if (first_begin_of_the_frame)
7567 if (window->DockIsActive && !window->DockTabIsVisible)
7569 if (window->LastFrameJustFocused ==
g.FrameCount)
7570 window->HiddenFramesCannotSkipItems = 1;
7572 window->HiddenFramesCanSkipItems = 1;
7575 if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ChildMenu))
7579 IM_ASSERT((flags& ImGuiWindowFlags_NoTitleBar) != 0 || window->DockIsActive);
7580 const bool nav_request = (flags & ImGuiWindowFlags_NavFlattened) && (
g.NavAnyRequest &&
g.NavWindow &&
g.NavWindow->RootWindowForNav == window->RootWindowForNav);
7581 if (!
g.LogEnabled && !nav_request)
7582 if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y)
7584 if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
7585 window->HiddenFramesCannotSkipItems = 1;
7587 window->HiddenFramesCanSkipItems = 1;
7591 if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCanSkipItems > 0))
7592 window->HiddenFramesCanSkipItems = 1;
7593 if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCannotSkipItems > 0))
7594 window->HiddenFramesCannotSkipItems = 1;
7598 if (style.Alpha <= 0.0f)
7599 window->HiddenFramesCanSkipItems = 1;
7602 bool hidden_regular = (window->HiddenFramesCanSkipItems > 0) || (window->HiddenFramesCannotSkipItems > 0);
7603 window->Hidden = hidden_regular || (window->HiddenFramesForRenderOnly > 0);
7606 if (window->DisableInputsFrames > 0)
7608 window->DisableInputsFrames--;
7609 window->Flags |= ImGuiWindowFlags_NoInputs;
7613 bool skip_items =
false;
7614 if (window->Collapsed || !window->Active || hidden_regular)
7615 if (window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesCannotSkipItems <= 0)
7617 window->SkipItems = skip_items;
7620 if (window->SkipItems)
7621 window->DC.NavLayersActiveMaskNext = window->DC.NavLayersActiveMask;
7626 if (window->SkipItems && !window->Appearing)
7627 IM_ASSERT(window->Appearing ==
false);
7632#ifndef IMGUI_DISABLE_DEBUG_TOOLS
7633 if (!window->IsFallbackWindow)
7634 if ((
g.IO.ConfigDebugBeginReturnValueOnce && window_just_created) || (
g.IO.ConfigDebugBeginReturnValueLoop &&
g.DebugBeginReturnValueCullDepth ==
g.CurrentWindowStack.Size))
7636 if (window->AutoFitFramesX > 0) { window->AutoFitFramesX++; }
7637 if (window->AutoFitFramesY > 0) { window->AutoFitFramesY++; }
7642 return !window->SkipItems;
7648 ImGuiWindow* window =
g.CurrentWindow;
7651 if (
g.CurrentWindowStack.Size <= 1 &&
g.WithinFrameScopeWithImplicitWindow)
7653 IM_ASSERT_USER_ERROR(
g.CurrentWindowStack.Size > 1,
"Calling End() too many times!");
7656 IM_ASSERT(
g.CurrentWindowStack.Size > 0);
7659 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_DockNodeHost) && !window->DockIsActive)
7660 IM_ASSERT_USER_ERROR(
g.WithinEndChild,
"Must call EndChild() and not End()!");
7663 if (window->DC.CurrentColumns)
7665 if (!(window->Flags & ImGuiWindowFlags_DockNodeHost))
7670 if (!(window->Flags & ImGuiWindowFlags_ChildWindow))
7673 if (window->DC.IsSetPos)
7674 ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
7677 if (window->DockNode && window->DockTabIsVisible)
7678 if (ImGuiWindow* host_window = window->DockNode->HostWindow)
7679 host_window->DC.CursorMaxPos = window->DC.CursorMaxPos + window->WindowPadding - host_window->WindowPadding;
7682 g.LastItemData =
g.CurrentWindowStack.back().ParentLastItemDataBackup;
7683 if (window->Flags & ImGuiWindowFlags_ChildMenu)
7685 if (window->Flags & ImGuiWindowFlags_Popup)
7686 g.BeginPopupStack.pop_back();
7687 g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithContextState(&
g);
7688 g.CurrentWindowStack.pop_back();
7689 SetCurrentWindow(
g.CurrentWindowStack.Size == 0 ? NULL :
g.CurrentWindowStack.back().
Window);
7690 if (
g.CurrentWindow)
7691 SetCurrentViewport(
g.CurrentWindow,
g.CurrentWindow->Viewport);
7694void ImGui::BringWindowToFocusFront(ImGuiWindow* window)
7697 IM_ASSERT(window == window->RootWindow);
7699 const int cur_order = window->FocusOrder;
7700 IM_ASSERT(
g.WindowsFocusOrder[cur_order] == window);
7701 if (
g.WindowsFocusOrder.back() == window)
7704 const int new_order =
g.WindowsFocusOrder.Size - 1;
7705 for (
int n = cur_order; n < new_order; n++)
7707 g.WindowsFocusOrder[n] =
g.WindowsFocusOrder[n + 1];
7708 g.WindowsFocusOrder[n]->FocusOrder--;
7709 IM_ASSERT(
g.WindowsFocusOrder[n]->FocusOrder == n);
7711 g.WindowsFocusOrder[new_order] = window;
7712 window->FocusOrder = (short)new_order;
7715void ImGui::BringWindowToDisplayFront(ImGuiWindow* window)
7718 ImGuiWindow* current_front_window =
g.Windows.back();
7719 if (current_front_window == window || current_front_window->RootWindowDockTree == window)
7721 for (
int i =
g.Windows.Size - 2; i >= 0; i--)
7722 if (
g.Windows[i] == window)
7724 memmove(&
g.Windows[i], &
g.Windows[i + 1], (
size_t)(
g.Windows.Size - i - 1) *
sizeof(ImGuiWindow*));
7725 g.Windows[
g.Windows.Size - 1] = window;
7730void ImGui::BringWindowToDisplayBack(ImGuiWindow* window)
7733 if (
g.Windows[0] == window)
7735 for (
int i = 0; i <
g.Windows.Size; i++)
7736 if (
g.Windows[i] == window)
7738 memmove(&
g.Windows[1], &
g.Windows[0], (
size_t)i *
sizeof(ImGuiWindow*));
7739 g.Windows[0] = window;
7744void ImGui::BringWindowToDisplayBehind(ImGuiWindow* window, ImGuiWindow* behind_window)
7746 IM_ASSERT(window != NULL && behind_window != NULL);
7748 window = window->RootWindow;
7749 behind_window = behind_window->RootWindow;
7750 int pos_wnd = FindWindowDisplayIndex(window);
7751 int pos_beh = FindWindowDisplayIndex(behind_window);
7752 if (pos_wnd < pos_beh)
7754 size_t copy_bytes = (pos_beh - pos_wnd - 1) *
sizeof(ImGuiWindow*);
7755 memmove(&
g.Windows.Data[pos_wnd], &
g.Windows.Data[pos_wnd + 1], copy_bytes);
7756 g.Windows[pos_beh - 1] = window;
7760 size_t copy_bytes = (pos_wnd - pos_beh) *
sizeof(ImGuiWindow*);
7761 memmove(&
g.Windows.Data[pos_beh + 1], &
g.Windows.Data[pos_beh], copy_bytes);
7762 g.Windows[pos_beh] = window;
7766int ImGui::FindWindowDisplayIndex(ImGuiWindow* window)
7769 return g.Windows.index_from_ptr(
g.Windows.find(window));
7773void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags)
7778 if ((flags & ImGuiFocusRequestFlags_UnlessBelowModal) && (
g.NavWindow != window))
7779 if (ImGuiWindow* blocking_modal = FindBlockingModal(window))
7781 IMGUI_DEBUG_LOG_FOCUS(
"[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n", window ? window->Name :
"<NULL>", blocking_modal->Name);
7782 if (window && window == window->RootWindow && (window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
7783 BringWindowToDisplayBehind(window, blocking_modal);
7788 if ((flags & ImGuiFocusRequestFlags_RestoreFocusedChild) && window != NULL)
7789 window = NavRestoreLastChildNavWindow(window);
7792 if (
g.NavWindow != window)
7794 SetNavWindow(window);
7795 if (window &&
g.NavDisableMouseHover)
7796 g.NavMousePosDirty =
true;
7797 g.NavId = window ? window->NavLastIds[0] : 0;
7798 g.NavLayer = ImGuiNavLayer_Main;
7799 SetNavFocusScope(window ? window->NavRootFocusScopeId : 0);
7800 g.NavIdIsAlive =
false;
7801 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
7804 ClosePopupsOverWindow(window,
false);
7808 IM_ASSERT(window == NULL || window->RootWindowDockTree != NULL);
7809 ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL;
7810 ImGuiWindow* display_front_window = window ? window->RootWindowDockTree : NULL;
7811 ImGuiDockNode* dock_node = window ? window->DockNode : NULL;
7812 bool active_id_window_is_dock_node_host = (
g.ActiveIdWindow && dock_node && dock_node->HostWindow ==
g.ActiveIdWindow);
7818 if (
g.ActiveId != 0 &&
g.ActiveIdWindow &&
g.ActiveIdWindow->RootWindow != focus_front_window)
7819 if (!
g.ActiveIdNoClearOnFocusLoss && !active_id_window_is_dock_node_host)
7825 window->LastFrameJustFocused =
g.FrameCount;
7833 BringWindowToFocusFront(focus_front_window);
7834 if (((window->Flags | focus_front_window->Flags | display_front_window->Flags) & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
7835 BringWindowToDisplayFront(display_front_window);
7838void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport, ImGuiFocusRequestFlags flags)
7841 int start_idx =
g.WindowsFocusOrder.Size - 1;
7842 if (under_this_window != NULL)
7846 while (under_this_window->Flags & ImGuiWindowFlags_ChildWindow)
7848 under_this_window = under_this_window->ParentWindow;
7851 start_idx = FindWindowFocusIndex(under_this_window) + offset;
7853 for (
int i = start_idx; i >= 0; i--)
7856 ImGuiWindow* window =
g.WindowsFocusOrder[i];
7857 if (window == ignore_window || !window->WasActive)
7859 if (filter_viewport != NULL && window->Viewport != filter_viewport)
7861 if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
7868 FocusWindow(window, flags);
7872 FocusWindow(NULL, flags);
7876void ImGui::SetCurrentFont(ImFont* font)
7879 IM_ASSERT(font && font->IsLoaded());
7880 IM_ASSERT(font->Scale > 0.0f);
7882 g.FontBaseSize = ImMax(1.0f,
g.IO.FontGlobalScale *
g.Font->FontSize *
g.Font->Scale);
7883 g.FontSize =
g.CurrentWindow ?
g.CurrentWindow->CalcFontSize() : 0.0f;
7885 ImFontAtlas* atlas =
g.Font->ContainerAtlas;
7886 g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel;
7887 g.DrawListSharedData.TexUvLines = atlas->TexUvLines;
7888 g.DrawListSharedData.Font =
g.Font;
7889 g.DrawListSharedData.FontSize =
g.FontSize;
7892void ImGui::PushFont(ImFont* font)
7896 font = GetDefaultFont();
7897 SetCurrentFont(font);
7898 g.FontStack.push_back(font);
7899 g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID);
7902void ImGui::PopFont()
7905 g.CurrentWindow->DrawList->PopTextureID();
7906 g.FontStack.pop_back();
7907 SetCurrentFont(
g.FontStack.empty() ? GetDefaultFont() :
g.FontStack.back());
7910void ImGui::PushItemFlag(ImGuiItemFlags option,
bool enabled)
7913 ImGuiItemFlags item_flags =
g.CurrentItemFlags;
7914 IM_ASSERT(item_flags ==
g.ItemFlagsStack.back());
7916 item_flags |= option;
7918 item_flags &= ~option;
7919 g.CurrentItemFlags = item_flags;
7920 g.ItemFlagsStack.push_back(item_flags);
7923void ImGui::PopItemFlag()
7926 IM_ASSERT(
g.ItemFlagsStack.Size > 1);
7927 g.ItemFlagsStack.pop_back();
7928 g.CurrentItemFlags =
g.ItemFlagsStack.back();
7937void ImGui::BeginDisabled(
bool disabled)
7940 bool was_disabled = (
g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
7941 if (!was_disabled && disabled)
7943 g.DisabledAlphaBackup =
g.Style.Alpha;
7944 g.Style.Alpha *=
g.Style.DisabledAlpha;
7946 if (was_disabled || disabled)
7947 g.CurrentItemFlags |= ImGuiItemFlags_Disabled;
7948 g.ItemFlagsStack.push_back(
g.CurrentItemFlags);
7949 g.DisabledStackSize++;
7952void ImGui::EndDisabled()
7955 IM_ASSERT(
g.DisabledStackSize > 0);
7956 g.DisabledStackSize--;
7957 bool was_disabled = (
g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
7959 g.ItemFlagsStack.pop_back();
7960 g.CurrentItemFlags =
g.ItemFlagsStack.back();
7961 if (was_disabled && (
g.CurrentItemFlags & ImGuiItemFlags_Disabled) == 0)
7962 g.Style.Alpha =
g.DisabledAlphaBackup;
7965void ImGui::PushTabStop(
bool tab_stop)
7967 PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop);
7970void ImGui::PopTabStop()
7975void ImGui::PushButtonRepeat(
bool repeat)
7977 PushItemFlag(ImGuiItemFlags_ButtonRepeat,
repeat);
7980void ImGui::PopButtonRepeat()
7985void ImGui::PushTextWrapPos(
float wrap_pos_x)
7987 ImGuiWindow* window = GetCurrentWindow();
7988 window->DC.TextWrapPosStack.push_back(window->DC.TextWrapPos);
7989 window->DC.TextWrapPos = wrap_pos_x;
7992void ImGui::PopTextWrapPos()
7994 ImGuiWindow* window = GetCurrentWindow();
7995 window->DC.TextWrapPos = window->DC.TextWrapPosStack.back();
7996 window->DC.TextWrapPosStack.pop_back();
7999static ImGuiWindow* GetCombinedRootWindow(ImGuiWindow* window,
bool popup_hierarchy,
bool dock_hierarchy)
8001 ImGuiWindow* last_window = NULL;
8002 while (last_window != window)
8004 last_window = window;
8005 window = window->RootWindow;
8006 if (popup_hierarchy)
8007 window = window->RootWindowPopupTree;
8009 window = window->RootWindowDockTree;
8014bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent,
bool popup_hierarchy,
bool dock_hierarchy)
8016 ImGuiWindow* window_root = GetCombinedRootWindow(window, popup_hierarchy, dock_hierarchy);
8017 if (window_root == potential_parent)
8019 while (window != NULL)
8021 if (window == potential_parent)
8023 if (window == window_root)
8025 window = window->ParentWindow;
8030bool ImGui::IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent)
8032 if (window->RootWindow == potential_parent)
8034 while (window != NULL)
8036 if (window == potential_parent)
8038 window = window->ParentWindowInBeginStack;
8043bool ImGui::IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below)
8048 const int display_layer_delta = GetWindowDisplayLayer(potential_above) - GetWindowDisplayLayer(potential_below);
8049 if (display_layer_delta != 0)
8050 return display_layer_delta > 0;
8052 for (
int i =
g.Windows.Size - 1; i >= 0; i--)
8054 ImGuiWindow* candidate_window =
g.Windows[i];
8055 if (candidate_window == potential_above)
8057 if (candidate_window == potential_below)
8067bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
8069 IM_ASSERT((flags & ~ImGuiHoveredFlags_AllowedMaskForIsWindowHovered) == 0 &&
"Invalid flags for IsWindowHovered()!");
8072 ImGuiWindow* ref_window =
g.HoveredWindow;
8073 ImGuiWindow* cur_window =
g.CurrentWindow;
8074 if (ref_window == NULL)
8077 if ((flags & ImGuiHoveredFlags_AnyWindow) == 0)
8079 IM_ASSERT(cur_window);
8080 const bool popup_hierarchy = (flags & ImGuiHoveredFlags_NoPopupHierarchy) == 0;
8081 const bool dock_hierarchy = (flags & ImGuiHoveredFlags_DockHierarchy) != 0;
8082 if (flags & ImGuiHoveredFlags_RootWindow)
8083 cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy, dock_hierarchy);
8086 if (flags & ImGuiHoveredFlags_ChildWindows)
8087 result = IsWindowChildOf(ref_window, cur_window, popup_hierarchy, dock_hierarchy);
8089 result = (ref_window == cur_window);
8094 if (!IsWindowContentHoverable(ref_window, flags))
8096 if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
8097 if (
g.ActiveId != 0 && !
g.ActiveIdAllowOverlap &&
g.ActiveId != ref_window->MoveId)
8105 if (flags & ImGuiHoveredFlags_ForTooltip)
8106 flags = ApplyHoverFlagsForTooltip(flags,
g.Style.HoverFlagsForTooltipMouse);
8107 if ((flags & ImGuiHoveredFlags_Stationary) != 0 &&
g.HoverWindowUnlockedStationaryId != ref_window->ID)
8113bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags)
8116 ImGuiWindow* ref_window =
g.NavWindow;
8117 ImGuiWindow* cur_window =
g.CurrentWindow;
8119 if (ref_window == NULL)
8121 if (flags & ImGuiFocusedFlags_AnyWindow)
8124 IM_ASSERT(cur_window);
8125 const bool popup_hierarchy = (flags & ImGuiFocusedFlags_NoPopupHierarchy) == 0;
8126 const bool dock_hierarchy = (flags & ImGuiFocusedFlags_DockHierarchy) != 0;
8127 if (flags & ImGuiHoveredFlags_RootWindow)
8128 cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy, dock_hierarchy);
8130 if (flags & ImGuiHoveredFlags_ChildWindows)
8131 return IsWindowChildOf(ref_window, cur_window, popup_hierarchy, dock_hierarchy);
8133 return (ref_window == cur_window);
8136ImGuiID ImGui::GetWindowDockID()
8139 return g.CurrentWindow->DockId;
8142bool ImGui::IsWindowDocked()
8145 return g.CurrentWindow->DockIsActive;
8151bool ImGui::IsWindowNavFocusable(ImGuiWindow* window)
8153 return window->WasActive && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
8156float ImGui::GetWindowWidth()
8158 ImGuiWindow* window =
GImGui->CurrentWindow;
8159 return window->Size.x;
8162float ImGui::GetWindowHeight()
8164 ImGuiWindow* window =
GImGui->CurrentWindow;
8165 return window->Size.y;
8168ImVec2 ImGui::GetWindowPos()
8171 ImGuiWindow* window =
g.CurrentWindow;
8175void ImGui::SetWindowPos(ImGuiWindow* window,
const ImVec2& pos, ImGuiCond cond)
8178 if (cond && (window->SetWindowPosAllowFlags & cond) == 0)
8181 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
8182 window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
8183 window->SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX);
8186 const ImVec2 old_pos = window->Pos;
8187 window->Pos = ImTrunc(pos);
8188 ImVec2 offset = window->Pos - old_pos;
8189 if (offset.x == 0.0f && offset.y == 0.0f)
8191 MarkIniSettingsDirty(window);
8193 window->DC.CursorPos += offset;
8194 window->DC.CursorMaxPos += offset;
8195 window->DC.IdealMaxPos += offset;
8196 window->DC.CursorStartPos += offset;
8199void ImGui::SetWindowPos(
const ImVec2& pos, ImGuiCond cond)
8201 ImGuiWindow* window = GetCurrentWindowRead();
8202 SetWindowPos(window, pos, cond);
8205void ImGui::SetWindowPos(
const char* name,
const ImVec2& pos, ImGuiCond cond)
8207 if (ImGuiWindow* window = FindWindowByName(name))
8208 SetWindowPos(window, pos, cond);
8211ImVec2 ImGui::GetWindowSize()
8213 ImGuiWindow* window = GetCurrentWindowRead();
8214 return window->Size;
8217void ImGui::SetWindowSize(ImGuiWindow* window,
const ImVec2& size, ImGuiCond cond)
8220 if (cond && (window->SetWindowSizeAllowFlags & cond) == 0)
8223 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
8224 window->SetWindowSizeAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
8227 if ((window->Flags & ImGuiWindowFlags_ChildWindow) == 0 || window->Appearing || (window->ChildFlags & ImGuiChildFlags_AlwaysAutoResize) != 0)
8228 window->AutoFitFramesX = (
size.x <= 0.0f) ? 2 : 0;
8229 if ((window->Flags & ImGuiWindowFlags_ChildWindow) == 0 || window->Appearing || (window->ChildFlags & ImGuiChildFlags_AlwaysAutoResize) != 0)
8230 window->AutoFitFramesY = (
size.y <= 0.0f) ? 2 : 0;
8233 ImVec2 old_size = window->SizeFull;
8235 window->AutoFitOnlyGrows =
false;
8237 window->SizeFull.x = IM_TRUNC(
size.x);
8239 window->AutoFitOnlyGrows =
false;
8241 window->SizeFull.y = IM_TRUNC(
size.y);
8242 if (old_size.x != window->SizeFull.x || old_size.y != window->SizeFull.y)
8243 MarkIniSettingsDirty(window);
8246void ImGui::SetWindowSize(
const ImVec2& size, ImGuiCond cond)
8248 SetWindowSize(
GImGui->CurrentWindow, size, cond);
8251void ImGui::SetWindowSize(
const char* name,
const ImVec2& size, ImGuiCond cond)
8253 if (ImGuiWindow* window = FindWindowByName(name))
8254 SetWindowSize(window, size, cond);
8257void ImGui::SetWindowCollapsed(ImGuiWindow* window,
bool collapsed, ImGuiCond cond)
8260 if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0)
8262 window->SetWindowCollapsedAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
8265 window->Collapsed = collapsed;
8268void ImGui::SetWindowHitTestHole(ImGuiWindow* window,
const ImVec2& pos,
const ImVec2& size)
8270 IM_ASSERT(window->HitTestHoleSize.x == 0);
8271 window->HitTestHoleSize = ImVec2ih(size);
8272 window->HitTestHoleOffset = ImVec2ih(pos - window->Pos);
8275void ImGui::SetWindowHiddenAndSkipItemsForCurrentFrame(ImGuiWindow* window)
8277 window->Hidden = window->SkipItems =
true;
8278 window->HiddenFramesCanSkipItems = 1;
8281void ImGui::SetWindowCollapsed(
bool collapsed, ImGuiCond cond)
8283 SetWindowCollapsed(
GImGui->CurrentWindow, collapsed, cond);
8286bool ImGui::IsWindowCollapsed()
8288 ImGuiWindow* window = GetCurrentWindowRead();
8289 return window->Collapsed;
8292bool ImGui::IsWindowAppearing()
8294 ImGuiWindow* window = GetCurrentWindowRead();
8295 return window->Appearing;
8298void ImGui::SetWindowCollapsed(
const char* name,
bool collapsed, ImGuiCond cond)
8300 if (ImGuiWindow* window = FindWindowByName(name))
8301 SetWindowCollapsed(window, collapsed, cond);
8304void ImGui::SetWindowFocus()
8306 FocusWindow(
GImGui->CurrentWindow);
8309void ImGui::SetWindowFocus(
const char* name)
8313 if (ImGuiWindow* window = FindWindowByName(name))
8314 FocusWindow(window);
8322void ImGui::SetNextWindowPos(
const ImVec2& pos, ImGuiCond cond,
const ImVec2& pivot)
8325 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
8326 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasPos;
8327 g.NextWindowData.PosVal = pos;
8328 g.NextWindowData.PosPivotVal = pivot;
8329 g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always;
8330 g.NextWindowData.PosUndock =
true;
8333void ImGui::SetNextWindowSize(
const ImVec2& size, ImGuiCond cond)
8336 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
8337 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSize;
8338 g.NextWindowData.SizeVal =
size;
8339 g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always;
8346void ImGui::SetNextWindowSizeConstraints(
const ImVec2& size_min,
const ImVec2& size_max, ImGuiSizeCallback custom_callback,
void* custom_callback_user_data)
8349 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint;
8350 g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max);
8351 g.NextWindowData.SizeCallback = custom_callback;
8352 g.NextWindowData.SizeCallbackUserData = custom_callback_user_data;
8357void ImGui::SetNextWindowContentSize(
const ImVec2& size)
8360 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasContentSize;
8361 g.NextWindowData.ContentSizeVal = ImTrunc(size);
8364void ImGui::SetNextWindowScroll(
const ImVec2& scroll)
8367 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasScroll;
8368 g.NextWindowData.ScrollVal = scroll;
8371void ImGui::SetNextWindowCollapsed(
bool collapsed, ImGuiCond cond)
8374 IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
8375 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasCollapsed;
8376 g.NextWindowData.CollapsedVal = collapsed;
8377 g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always;
8380void ImGui::SetNextWindowFocus()
8383 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus;
8386void ImGui::SetNextWindowBgAlpha(
float alpha)
8389 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasBgAlpha;
8390 g.NextWindowData.BgAlphaVal = alpha;
8393void ImGui::SetNextWindowViewport(ImGuiID
id)
8396 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasViewport;
8397 g.NextWindowData.ViewportId =
id;
8400void ImGui::SetNextWindowDockID(ImGuiID
id, ImGuiCond cond)
8403 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasDock;
8404 g.NextWindowData.DockCond = cond ? cond : ImGuiCond_Always;
8405 g.NextWindowData.DockId =
id;
8408void ImGui::SetNextWindowClass(
const ImGuiWindowClass* window_class)
8411 IM_ASSERT((window_class->ViewportFlagsOverrideSet & window_class->ViewportFlagsOverrideClear) == 0);
8412 g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasWindowClass;
8413 g.NextWindowData.WindowClass = *window_class;
8416ImDrawList* ImGui::GetWindowDrawList()
8418 ImGuiWindow* window = GetCurrentWindow();
8419 return window->DrawList;
8422float ImGui::GetWindowDpiScale()
8425 return g.CurrentDpiScale;
8428ImGuiViewport* ImGui::GetWindowViewport()
8431 IM_ASSERT(
g.CurrentViewport != NULL &&
g.CurrentViewport ==
g.CurrentWindow->Viewport);
8432 return g.CurrentViewport;
8435ImFont* ImGui::GetFont()
8440float ImGui::GetFontSize()
8445ImVec2 ImGui::GetFontTexUvWhitePixel()
8447 return GImGui->DrawListSharedData.TexUvWhitePixel;
8450void ImGui::SetWindowFontScale(
float scale)
8452 IM_ASSERT(scale > 0.0f);
8454 ImGuiWindow* window = GetCurrentWindow();
8455 window->FontWindowScale =
scale;
8456 g.FontSize =
g.DrawListSharedData.FontSize = window->CalcFontSize();
8459void ImGui::PushFocusScope(ImGuiID
id)
8462 ImGuiFocusScopeData data;
8464 data.WindowID =
g.CurrentWindow->ID;
8465 g.FocusScopeStack.push_back(data);
8466 g.CurrentFocusScopeId =
id;
8469void ImGui::PopFocusScope()
8472 if (
g.FocusScopeStack.Size == 0)
8474 IM_ASSERT_USER_ERROR(
g.FocusScopeStack.Size > 0,
"Calling PopFocusScope() too many times!");
8477 g.FocusScopeStack.pop_back();
8478 g.CurrentFocusScopeId =
g.FocusScopeStack.Size ?
g.FocusScopeStack.back().ID : 0;
8481void ImGui::SetNavFocusScope(ImGuiID focus_scope_id)
8484 g.NavFocusScopeId = focus_scope_id;
8485 g.NavFocusRoute.resize(0);
8486 if (focus_scope_id == 0)
8488 IM_ASSERT(
g.NavWindow != NULL);
8491 if (focus_scope_id ==
g.CurrentFocusScopeId)
8494 for (
int n =
g.FocusScopeStack.Size - 1; n >= 0 &&
g.FocusScopeStack.Data[n].WindowID ==
g.CurrentWindow->ID; n--)
8495 g.NavFocusRoute.push_back(
g.FocusScopeStack.Data[n]);
8497 else if (focus_scope_id ==
g.NavWindow->NavRootFocusScopeId)
8498 g.NavFocusRoute.push_back({ focus_scope_id,
g.NavWindow->ID });
8503 for (ImGuiWindow* window =
g.NavWindow->ParentWindowForFocusRoute; window != NULL; window = window->ParentWindowForFocusRoute)
8504 g.NavFocusRoute.push_back({ window->NavRootFocusScopeId, window->ID });
8505 IM_ASSERT(
g.NavFocusRoute.Size < 100);
8509void ImGui::FocusItem()
8512 ImGuiWindow* window =
g.CurrentWindow;
8513 IMGUI_DEBUG_LOG_FOCUS(
"FocusItem(0x%08x) in window \"%s\"\n",
g.LastItemData.ID, window->Name);
8514 if (
g.DragDropActive ||
g.MovingWindow != NULL)
8516 IMGUI_DEBUG_LOG_FOCUS(
"FocusItem() ignored while DragDropActive!\n");
8520 ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavHighlight | ImGuiNavMoveFlags_NoSelect;
8521 ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
8522 SetNavWindow(window);
8523 NavMoveRequestSubmit(ImGuiDir_None, ImGuiDir_Up, move_flags, scroll_flags);
8524 NavMoveRequestResolveWithLastItem(&
g.NavMoveResultLocal);
8527void ImGui::ActivateItemByID(ImGuiID
id)
8530 g.NavNextActivateId =
id;
8531 g.NavNextActivateFlags = ImGuiActivateFlags_None;
8536void ImGui::SetKeyboardFocusHere(
int offset)
8539 ImGuiWindow* window =
g.CurrentWindow;
8540 IM_ASSERT(offset >= -1);
8541 IMGUI_DEBUG_LOG_FOCUS(
"SetKeyboardFocusHere(%d) in window \"%s\"\n", offset, window->Name);
8547 if (
g.DragDropActive ||
g.MovingWindow != NULL)
8549 IMGUI_DEBUG_LOG_FOCUS(
"SetKeyboardFocusHere() ignored while DragDropActive!\n");
8553 SetNavWindow(window);
8555 ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavHighlight;
8556 ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
8557 NavMoveRequestSubmit(ImGuiDir_None, offset < 0 ? ImGuiDir_Up : ImGuiDir_Down, move_flags, scroll_flags);
8560 NavMoveRequestResolveWithLastItem(&
g.NavMoveResultLocal);
8564 g.NavTabbingDir = 1;
8565 g.NavTabbingCounter = offset + 1;
8569void ImGui::SetItemDefaultFocus()
8572 ImGuiWindow* window =
g.CurrentWindow;
8573 if (!window->Appearing)
8575 if (
g.NavWindow != window->RootWindowForNav || (!
g.NavInitRequest &&
g.NavInitResult.ID == 0) ||
g.NavLayer != window->DC.NavLayerCurrent)
8578 g.NavInitRequest =
false;
8579 NavApplyItemToResult(&
g.NavInitResult);
8580 NavUpdateAnyRequestFlag();
8583 if (!window->ClipRect.Contains(
g.LastItemData.Rect))
8584 ScrollToRectEx(window,
g.LastItemData.Rect, ImGuiScrollFlags_None);
8587void ImGui::SetStateStorage(ImGuiStorage* tree)
8589 ImGuiWindow* window =
GImGui->CurrentWindow;
8590 window->DC.StateStorage = tree ? tree : &window->StateStorage;
8593ImGuiStorage* ImGui::GetStateStorage()
8595 ImGuiWindow* window =
GImGui->CurrentWindow;
8596 return window->DC.StateStorage;
8599void ImGui::PushID(
const char* str_id)
8602 ImGuiWindow* window =
g.CurrentWindow;
8603 ImGuiID
id = window->GetID(str_id);
8604 window->IDStack.push_back(
id);
8607void ImGui::PushID(
const char* str_id_begin,
const char* str_id_end)
8610 ImGuiWindow* window =
g.CurrentWindow;
8611 ImGuiID
id = window->GetID(str_id_begin, str_id_end);
8612 window->IDStack.push_back(
id);
8615void ImGui::PushID(
const void* ptr_id)
8618 ImGuiWindow* window =
g.CurrentWindow;
8619 ImGuiID
id = window->GetID(ptr_id);
8620 window->IDStack.push_back(
id);
8623void ImGui::PushID(
int int_id)
8626 ImGuiWindow* window =
g.CurrentWindow;
8627 ImGuiID
id = window->GetID(int_id);
8628 window->IDStack.push_back(
id);
8632void ImGui::PushOverrideID(ImGuiID
id)
8635 ImGuiWindow* window =
g.CurrentWindow;
8636 if (
g.DebugHookIdInfo ==
id)
8637 DebugHookIdInfo(
id, ImGuiDataType_ID, NULL, NULL);
8638 window->IDStack.push_back(
id);
8644ImGuiID ImGui::GetIDWithSeed(
const char* str,
const char* str_end, ImGuiID seed)
8646 ImGuiID
id =
ImHashStr(str, str_end ? (str_end - str) : 0, seed);
8648 if (
g.DebugHookIdInfo ==
id)
8649 DebugHookIdInfo(
id, ImGuiDataType_String, str, str_end);
8653ImGuiID ImGui::GetIDWithSeed(
int n, ImGuiID seed)
8655 ImGuiID
id =
ImHashData(&n,
sizeof(n), seed);
8657 if (
g.DebugHookIdInfo ==
id)
8658 DebugHookIdInfo(
id, ImGuiDataType_S32, (
void*)(intptr_t)n, NULL);
8664 ImGuiWindow* window =
GImGui->CurrentWindow;
8665 IM_ASSERT(window->IDStack.Size > 1);
8666 window->IDStack.pop_back();
8669ImGuiID ImGui::GetID(
const char* str_id)
8671 ImGuiWindow* window =
GImGui->CurrentWindow;
8672 return window->GetID(str_id);
8675ImGuiID ImGui::GetID(
const char* str_id_begin,
const char* str_id_end)
8677 ImGuiWindow* window =
GImGui->CurrentWindow;
8678 return window->GetID(str_id_begin, str_id_end);
8681ImGuiID ImGui::GetID(
const void* ptr_id)
8683 ImGuiWindow* window =
GImGui->CurrentWindow;
8684 return window->GetID(ptr_id);
8687bool ImGui::IsRectVisible(
const ImVec2& size)
8689 ImGuiWindow* window =
GImGui->CurrentWindow;
8690 return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size));
8693bool ImGui::IsRectVisible(
const ImVec2& rect_min,
const ImVec2& rect_max)
8695 ImGuiWindow* window =
GImGui->CurrentWindow;
8696 return window->ClipRect.Overlaps(ImRect(rect_min, rect_max));
8764ImGuiKeyChord ImGui::FixupKeyChord(ImGuiContext* ctx, ImGuiKeyChord key_chord)
8767 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
8770 if (key == ImGuiKey_LeftCtrl || key == ImGuiKey_RightCtrl)
8771 key_chord |= ImGuiMod_Ctrl;
8772 if (key == ImGuiKey_LeftShift || key == ImGuiKey_RightShift)
8773 key_chord |= ImGuiMod_Shift;
8774 if (key == ImGuiKey_LeftAlt || key == ImGuiKey_RightAlt)
8775 key_chord |= ImGuiMod_Alt;
8776 if (key == ImGuiKey_LeftSuper || key == ImGuiKey_RightSuper)
8777 key_chord |= ImGuiMod_Super;
8779 if (key_chord & ImGuiMod_Shortcut)
8780 return (key_chord & ~ImGuiMod_Shortcut) | (ctx->IO.ConfigMacOSXBehaviors ? ImGuiMod_Super : ImGuiMod_Ctrl);
8784ImGuiKeyData* ImGui::GetKeyData(ImGuiContext* ctx, ImGuiKey key)
8786 ImGuiContext&
g = *ctx;
8789 if (key & ImGuiMod_Mask_)
8790 key = ConvertSingleModFlagToKey(ctx, key);
8792#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
8793 IM_ASSERT(key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_NamedKey_END);
8794 if (IsLegacyKey(key) &&
g.IO.KeyMap[key] != -1)
8795 key = (ImGuiKey)
g.IO.KeyMap[key];
8797 IM_ASSERT(IsNamedKey(key) &&
"Support for user key indices was dropped in favor of ImGuiKey. Please update backend & user code.");
8799 return &
g.IO.KeysData[key - ImGuiKey_KeysData_OFFSET];
8802#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
8803ImGuiKey ImGui::GetKeyIndex(ImGuiKey key)
8806 IM_ASSERT(IsNamedKey(key));
8807 const ImGuiKeyData* key_data = GetKeyData(key);
8808 return (ImGuiKey)(key_data -
g.IO.KeysData);
8813static const char*
const GKeyNames[] =
8815 "Tab",
"LeftArrow",
"RightArrow",
"UpArrow",
"DownArrow",
"PageUp",
"PageDown",
8816 "Home",
"End",
"Insert",
"Delete",
"Backspace",
"Space",
"Enter",
"Escape",
8817 "LeftCtrl",
"LeftShift",
"LeftAlt",
"LeftSuper",
"RightCtrl",
"RightShift",
"RightAlt",
"RightSuper",
"Menu",
8818 "0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
8819 "I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
8820 "F1",
"F2",
"F3",
"F4",
"F5",
"F6",
"F7",
"F8",
"F9",
"F10",
"F11",
"F12",
8821 "F13",
"F14",
"F15",
"F16",
"F17",
"F18",
"F19",
"F20",
"F21",
"F22",
"F23",
"F24",
8822 "Apostrophe",
"Comma",
"Minus",
"Period",
"Slash",
"Semicolon",
"Equal",
"LeftBracket",
8823 "Backslash",
"RightBracket",
"GraveAccent",
"CapsLock",
"ScrollLock",
"NumLock",
"PrintScreen",
8824 "Pause",
"Keypad0",
"Keypad1",
"Keypad2",
"Keypad3",
"Keypad4",
"Keypad5",
"Keypad6",
8825 "Keypad7",
"Keypad8",
"Keypad9",
"KeypadDecimal",
"KeypadDivide",
"KeypadMultiply",
8826 "KeypadSubtract",
"KeypadAdd",
"KeypadEnter",
"KeypadEqual",
8827 "AppBack",
"AppForward",
8828 "GamepadStart",
"GamepadBack",
8829 "GamepadFaceLeft",
"GamepadFaceRight",
"GamepadFaceUp",
"GamepadFaceDown",
8830 "GamepadDpadLeft",
"GamepadDpadRight",
"GamepadDpadUp",
"GamepadDpadDown",
8831 "GamepadL1",
"GamepadR1",
"GamepadL2",
"GamepadR2",
"GamepadL3",
"GamepadR3",
8832 "GamepadLStickLeft",
"GamepadLStickRight",
"GamepadLStickUp",
"GamepadLStickDown",
8833 "GamepadRStickLeft",
"GamepadRStickRight",
"GamepadRStickUp",
"GamepadRStickDown",
8834 "MouseLeft",
"MouseRight",
"MouseMiddle",
"MouseX1",
"MouseX2",
"MouseWheelX",
"MouseWheelY",
8835 "ModCtrl",
"ModShift",
"ModAlt",
"ModSuper",
8839const char* ImGui::GetKeyName(ImGuiKey key)
8842#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
8843 IM_ASSERT((IsNamedKeyOrModKey(key) || key == ImGuiKey_None) &&
"Support for user key indices was dropped in favor of ImGuiKey. Please update backend and user code.");
8845 if (IsLegacyKey(key))
8847 if (
g.IO.KeyMap[key] == -1)
8849 IM_ASSERT(IsNamedKey((ImGuiKey)
g.IO.KeyMap[key]));
8850 key = (ImGuiKey)
g.IO.KeyMap[key];
8853 if (key == ImGuiKey_None)
8855 if (key & ImGuiMod_Mask_)
8856 key = ConvertSingleModFlagToKey(&
g, key);
8857 if (!IsNamedKey(key))
8860 return GKeyNames[key - ImGuiKey_NamedKey_BEGIN];
8864const char* ImGui::GetKeyChordName(ImGuiKeyChord key_chord)
8867 key_chord = FixupKeyChord(&
g, key_chord);
8868 ImFormatString(
g.TempKeychordName, IM_ARRAYSIZE(
g.TempKeychordName),
"%s%s%s%s%s",
8869 (key_chord & ImGuiMod_Ctrl) ?
"Ctrl+" :
"",
8870 (key_chord & ImGuiMod_Shift) ?
"Shift+" :
"",
8871 (key_chord & ImGuiMod_Alt) ?
"Alt+" :
"",
8872 (key_chord & ImGuiMod_Super) ? (
g.IO.ConfigMacOSXBehaviors ?
"Cmd+" :
"Super+") :
"",
8873 GetKeyName((ImGuiKey)(key_chord & ~ImGuiMod_Mask_)));
8874 return g.TempKeychordName;
8881int ImGui::CalcTypematicRepeatAmount(
float t0,
float t1,
float repeat_delay,
float repeat_rate)
8887 if (repeat_rate <= 0.0f)
8888 return (t0 < repeat_delay) && (t1 >= repeat_delay);
8889 const int count_t0 = (t0 < repeat_delay) ? -1 : (int)((t0 - repeat_delay) / repeat_rate);
8890 const int count_t1 = (t1 < repeat_delay) ? -1 : (int)((t1 - repeat_delay) / repeat_rate);
8891 const int count = count_t1 - count_t0;
8895void ImGui::GetTypematicRepeatRate(ImGuiInputFlags flags,
float* repeat_delay,
float* repeat_rate)
8898 switch (flags & ImGuiInputFlags_RepeatRateMask_)
8900 case ImGuiInputFlags_RepeatRateNavMove: *repeat_delay =
g.IO.KeyRepeatDelay * 0.72f; *repeat_rate =
g.IO.KeyRepeatRate * 0.80f;
return;
8901 case ImGuiInputFlags_RepeatRateNavTweak: *repeat_delay =
g.IO.KeyRepeatDelay * 0.72f; *repeat_rate =
g.IO.KeyRepeatRate * 0.30f;
return;
8902 case ImGuiInputFlags_RepeatRateDefault:
default: *repeat_delay =
g.IO.KeyRepeatDelay * 1.00f; *repeat_rate =
g.IO.KeyRepeatRate * 1.00f;
return;
8908int ImGui::GetKeyPressedAmount(ImGuiKey key,
float repeat_delay,
float repeat_rate)
8911 const ImGuiKeyData* key_data = GetKeyData(key);
8912 if (!key_data->Down)
8914 const float t = key_data->DownDuration;
8915 return CalcTypematicRepeatAmount(
t -
g.IO.DeltaTime,
t, repeat_delay, repeat_rate);
8919ImVec2 ImGui::GetKeyMagnitude2d(ImGuiKey key_left, ImGuiKey key_right, ImGuiKey key_up, ImGuiKey key_down)
8922 GetKeyData(key_right)->AnalogValue - GetKeyData(key_left)->AnalogValue,
8923 GetKeyData(key_down)->AnalogValue - GetKeyData(key_up)->AnalogValue);
8930static void ImGui::UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt)
8933 rt->EntriesNext.resize(0);
8934 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
8936 const int new_routing_start_idx = rt->EntriesNext.Size;
8937 ImGuiKeyRoutingData* routing_entry;
8938 for (
int old_routing_idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; old_routing_idx != -1; old_routing_idx = routing_entry->NextEntryIndex)
8940 routing_entry = &rt->Entries[old_routing_idx];
8941 routing_entry->RoutingCurrScore = routing_entry->RoutingNextScore;
8942 routing_entry->RoutingCurr = routing_entry->RoutingNext;
8943 routing_entry->RoutingNext = ImGuiKeyOwner_None;
8944 routing_entry->RoutingNextScore = 255;
8945 if (routing_entry->RoutingCurr == ImGuiKeyOwner_None)
8947 rt->EntriesNext.push_back(*routing_entry);
8951 if (routing_entry->Mods ==
g.IO.KeyMods)
8953 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
8954 if (owner_data->OwnerCurr == ImGuiKeyOwner_None)
8956 owner_data->OwnerCurr = routing_entry->RoutingCurr;
8963 rt->Index[key - ImGuiKey_NamedKey_BEGIN] = (ImGuiKeyRoutingIndex)(new_routing_start_idx < rt->EntriesNext.Size ? new_routing_start_idx : -1);
8964 for (
int n = new_routing_start_idx; n < rt->EntriesNext.Size; n++)
8965 rt->EntriesNext[n].NextEntryIndex = (ImGuiKeyRoutingIndex)((n + 1 < rt->EntriesNext.Size) ? n + 1 : -1);
8967 rt->Entries.swap(rt->EntriesNext);
8971static inline ImGuiID GetRoutingIdFromOwnerId(ImGuiID owner_id)
8974 return (owner_id != ImGuiKeyOwner_None && owner_id != ImGuiKeyOwner_Any) ? owner_id :
g.CurrentFocusScopeId;
8977ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord)
8986 ImGuiKeyRoutingTable* rt = &
g.KeysRoutingTable;
8987 ImGuiKeyRoutingData* routing_data;
8988 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
8989 ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
8990 if (key == ImGuiKey_None)
8991 key = ConvertSingleModFlagToKey(&
g, mods);
8992 IM_ASSERT(IsNamedKey(key) && (key_chord & ImGuiMod_Shortcut) == 0);
8996 for (ImGuiKeyRoutingIndex idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; idx != -1; idx = routing_data->NextEntryIndex)
8998 routing_data = &rt->Entries[idx];
8999 if (routing_data->Mods == mods)
9000 return routing_data;
9004 ImGuiKeyRoutingIndex routing_data_idx = (ImGuiKeyRoutingIndex)rt->Entries.Size;
9005 rt->Entries.push_back(ImGuiKeyRoutingData());
9006 routing_data = &rt->Entries[routing_data_idx];
9007 routing_data->Mods = (ImU16)mods;
9008 routing_data->NextEntryIndex = rt->Index[key - ImGuiKey_NamedKey_BEGIN];
9009 rt->Index[key - ImGuiKey_NamedKey_BEGIN] = routing_data_idx;
9010 return routing_data;
9021static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInputFlags flags)
9023 if (flags & ImGuiInputFlags_RouteFocused)
9029 if (owner_id != 0 &&
g.ActiveId == owner_id)
9039 if (focus_scope_id == 0)
9041 for (
int index_in_focus_path = 0; index_in_focus_path <
g.NavFocusRoute.Size; index_in_focus_path++)
9042 if (
g.NavFocusRoute.Data[index_in_focus_path].ID == focus_scope_id)
9043 return 3 + index_in_focus_path;
9049 if (flags & ImGuiInputFlags_RouteGlobal)
9051 if (flags & ImGuiInputFlags_RouteGlobalLow)
9058static bool IsKeyChordPotentiallyCharInput(ImGuiKeyChord key_chord)
9064 ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
9065 const bool ignore_char_inputs = ((mods & ImGuiMod_Ctrl) && !(mods & ImGuiMod_Alt)) || (
g.IO.ConfigMacOSXBehaviors && (mods & ImGuiMod_Super));
9066 if (ignore_char_inputs)
9070 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
9071 return g.KeysMayBeCharInput.TestBit(key);
9079bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
9082 if ((flags & ImGuiInputFlags_RouteMask_) == 0)
9083 flags |= ImGuiInputFlags_RouteGlobalHigh;
9085 IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteMask_));
9086 IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_None);
9089 key_chord = FixupKeyChord(&
g, key_chord);
9092 if (
g.DebugBreakInShortcutRouting == key_chord)
9095 if (flags & ImGuiInputFlags_RouteUnlessBgFocused)
9096 if (
g.NavWindow == NULL)
9100 if (flags & ImGuiInputFlags_RouteAlways)
9102 IMGUI_DEBUG_LOG_INPUTROUTING(
"SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> always\n", GetKeyChordName(key_chord), owner_id, flags);
9107 if (
g.ActiveId != 0 &&
g.ActiveId != owner_id)
9114 if ((flags & ImGuiInputFlags_RouteFocused) &&
g.IO.WantTextInput && IsKeyChordPotentiallyCharInput(key_chord))
9116 IMGUI_DEBUG_LOG_INPUTROUTING(
"SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> filtered as potential char input\n", GetKeyChordName(key_chord), owner_id, flags);
9121 if ((flags & ImGuiInputFlags_RouteGlobalHigh) == 0 &&
g.ActiveIdUsingAllKeyboardKeys)
9123 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
9124 if (key == ImGuiKey_None)
9125 key = ConvertSingleModFlagToKey(&
g, (ImGuiKey)(key_chord & ImGuiMod_Mask_));
9126 if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END)
9132 const int score = CalcRoutingScore(
g.CurrentFocusScopeId, owner_id, flags);
9133 IMGUI_DEBUG_LOG_INPUTROUTING(
"SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> score %d\n", GetKeyChordName(key_chord), owner_id, flags, score);
9139 ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord);
9141 if (score < routing_data->RoutingNextScore)
9143 routing_data->RoutingNext = owner_id;
9144 routing_data->RoutingNextScore = (ImU8)score;
9148 if (routing_data->RoutingCurr == owner_id)
9149 IMGUI_DEBUG_LOG_INPUTROUTING(
"--> granting current route\n");
9150 return routing_data->RoutingCurr == owner_id;
9155bool ImGui::TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id)
9158 const ImGuiID routing_id = GetRoutingIdFromOwnerId(owner_id);
9159 key_chord = FixupKeyChord(&
g, key_chord);
9160 ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord);
9161 return routing_data->RoutingCurr == routing_id;
9166bool ImGui::IsKeyDown(ImGuiKey key)
9168 return IsKeyDown(key, ImGuiKeyOwner_Any);
9171bool ImGui::IsKeyDown(ImGuiKey key, ImGuiID owner_id)
9173 const ImGuiKeyData* key_data = GetKeyData(key);
9174 if (!key_data->Down)
9176 if (!TestKeyOwner(key, owner_id))
9181bool ImGui::IsKeyPressed(ImGuiKey key,
bool repeat)
9183 return IsKeyPressed(key, ImGuiKeyOwner_Any,
repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None);
9187bool ImGui::IsKeyPressed(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags)
9189 const ImGuiKeyData* key_data = GetKeyData(key);
9190 if (!key_data->Down)
9192 const float t = key_data->DownDuration;
9195 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsKeyPressed) == 0);
9196 if (flags & (ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_))
9197 flags |= ImGuiInputFlags_Repeat;
9199 bool pressed = (
t == 0.0f);
9200 if (!pressed && (flags & ImGuiInputFlags_Repeat) != 0)
9202 float repeat_delay, repeat_rate;
9203 GetTypematicRepeatRate(flags, &repeat_delay, &repeat_rate);
9204 pressed = (
t > repeat_delay) && GetKeyPressedAmount(key, repeat_delay, repeat_rate) > 0;
9205 if (pressed && (flags & ImGuiInputFlags_RepeatUntilMask_))
9210 double key_pressed_time =
g.Time -
t + 0.00001f;
9211 if ((flags & ImGuiInputFlags_RepeatUntilKeyModsChange) && (
g.LastKeyModsChangeTime > key_pressed_time))
9213 if ((flags & ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone) && (
g.LastKeyModsChangeFromNoneTime > key_pressed_time))
9215 if ((flags & ImGuiInputFlags_RepeatUntilOtherKeyPress) && (
g.LastKeyboardKeyPressTime > key_pressed_time))
9221 if (!TestKeyOwner(key, owner_id))
9226bool ImGui::IsKeyReleased(ImGuiKey key)
9228 return IsKeyReleased(key, ImGuiKeyOwner_Any);
9231bool ImGui::IsKeyReleased(ImGuiKey key, ImGuiID owner_id)
9233 const ImGuiKeyData* key_data = GetKeyData(key);
9234 if (key_data->DownDurationPrev < 0.0f || key_data->Down)
9236 if (!TestKeyOwner(key, owner_id))
9241bool ImGui::IsMouseDown(ImGuiMouseButton button)
9244 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9245 return g.IO.MouseDown[button] && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any);
9248bool ImGui::IsMouseDown(ImGuiMouseButton button, ImGuiID owner_id)
9251 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9252 return g.IO.MouseDown[button] && TestKeyOwner(MouseButtonToKey(button), owner_id);
9255bool ImGui::IsMouseClicked(ImGuiMouseButton button,
bool repeat)
9257 return IsMouseClicked(button, ImGuiKeyOwner_Any,
repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None);
9260bool ImGui::IsMouseClicked(ImGuiMouseButton button, ImGuiID owner_id, ImGuiInputFlags flags)
9263 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9264 if (!
g.IO.MouseDown[button])
9266 const float t =
g.IO.MouseDownDuration[button];
9269 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsMouseClicked) == 0);
9271 const bool repeat = (flags & ImGuiInputFlags_Repeat) != 0;
9272 const bool pressed = (
t == 0.0f) || (
repeat &&
t >
g.IO.KeyRepeatDelay && CalcTypematicRepeatAmount(
t -
g.IO.DeltaTime,
t,
g.IO.KeyRepeatDelay,
g.IO.KeyRepeatRate) > 0);
9276 if (!TestKeyOwner(MouseButtonToKey(button), owner_id))
9282bool ImGui::IsMouseReleased(ImGuiMouseButton button)
9285 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9286 return g.IO.MouseReleased[button] && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any);
9289bool ImGui::IsMouseReleased(ImGuiMouseButton button, ImGuiID owner_id)
9292 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9293 return g.IO.MouseReleased[button] && TestKeyOwner(MouseButtonToKey(button), owner_id);
9296bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button)
9299 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9300 return g.IO.MouseClickedCount[button] == 2 && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any);
9303bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button, ImGuiID owner_id)
9306 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9307 return g.IO.MouseClickedCount[button] == 2 && TestKeyOwner(MouseButtonToKey(button), owner_id);
9310int ImGui::GetMouseClickedCount(ImGuiMouseButton button)
9313 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9314 return g.IO.MouseClickedCount[button];
9320bool ImGui::IsMouseHoveringRect(
const ImVec2& r_min,
const ImVec2& r_max,
bool clip)
9325 ImRect rect_clipped(r_min, r_max);
9327 rect_clipped.ClipWith(
g.CurrentWindow->ClipRect);
9330 if (!rect_clipped.ContainsWithPad(
g.IO.MousePos,
g.Style.TouchExtraPadding))
9332 if (!
g.MouseViewport->GetMainRect().Overlaps(rect_clipped))
9339bool ImGui::IsMouseDragPastThreshold(ImGuiMouseButton button,
float lock_threshold)
9342 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9343 if (lock_threshold < 0.0f)
9344 lock_threshold =
g.IO.MouseDragThreshold;
9345 return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;
9348bool ImGui::IsMouseDragging(ImGuiMouseButton button,
float lock_threshold)
9351 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9352 if (!
g.IO.MouseDown[button])
9354 return IsMouseDragPastThreshold(button, lock_threshold);
9357ImVec2 ImGui::GetMousePos()
9360 return g.IO.MousePos;
9365void ImGui::TeleportMousePos(
const ImVec2& pos)
9368 g.IO.MousePos =
g.IO.MousePosPrev = pos;
9369 g.IO.MouseDelta = ImVec2(0.0f, 0.0f);
9370 g.IO.WantSetMousePos =
true;
9375ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
9378 if (
g.BeginPopupStack.Size > 0)
9379 return g.OpenPopupStack[
g.BeginPopupStack.Size - 1].OpenMousePos;
9380 return g.IO.MousePos;
9384bool ImGui::IsMousePosValid(
const ImVec2* mouse_pos)
9388 IM_ASSERT(
GImGui != NULL);
9389 const float MOUSE_INVALID = -256000.0f;
9390 ImVec2 p = mouse_pos ? *mouse_pos :
GImGui->IO.MousePos;
9391 return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID;
9395bool ImGui::IsAnyMouseDown()
9398 for (
int n = 0; n < IM_ARRAYSIZE(
g.IO.MouseDown); n++)
9399 if (
g.IO.MouseDown[n])
9407ImVec2 ImGui::GetMouseDragDelta(ImGuiMouseButton button,
float lock_threshold)
9410 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9411 if (lock_threshold < 0.0f)
9412 lock_threshold =
g.IO.MouseDragThreshold;
9413 if (
g.IO.MouseDown[button] ||
g.IO.MouseReleased[button])
9414 if (
g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold)
9415 if (IsMousePosValid(&
g.IO.MousePos) && IsMousePosValid(&
g.IO.MouseClickedPos[button]))
9416 return g.IO.MousePos -
g.IO.MouseClickedPos[button];
9417 return ImVec2(0.0f, 0.0f);
9420void ImGui::ResetMouseDragDelta(ImGuiMouseButton button)
9423 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(
g.IO.MouseDown));
9425 g.IO.MouseClickedPos[button] =
g.IO.MousePos;
9432ImGuiMouseCursor ImGui::GetMouseCursor()
9435 return g.MouseCursor;
9438void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)
9441 g.MouseCursor = cursor_type;
9444static void UpdateAliasKey(ImGuiKey key,
bool v,
float analog_value)
9446 IM_ASSERT(ImGui::IsAliasKey(key));
9447 ImGuiKeyData* key_data = ImGui::GetKeyData(key);
9449 key_data->AnalogValue = analog_value;
9453static ImGuiKeyChord GetMergedModsFromKeys()
9455 ImGuiKeyChord mods = 0;
9456 if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) { mods |= ImGuiMod_Ctrl; }
9457 if (ImGui::IsKeyDown(ImGuiMod_Shift)) { mods |= ImGuiMod_Shift; }
9458 if (ImGui::IsKeyDown(ImGuiMod_Alt)) { mods |= ImGuiMod_Alt; }
9459 if (ImGui::IsKeyDown(ImGuiMod_Super)) { mods |= ImGuiMod_Super; }
9463static void ImGui::UpdateKeyboardInputs()
9469#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
9470 if (io.BackendUsingLegacyKeyArrays == 0)
9473 for (
int n = 0; n < ImGuiKey_LegacyNativeKey_END; n++)
9474 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!");
9478 if (
g.FrameCount == 0)
9479 for (
int n = ImGuiKey_LegacyNativeKey_BEGIN; n < ImGuiKey_LegacyNativeKey_END; n++)
9480 IM_ASSERT(
g.IO.KeyMap[n] == -1 &&
"Backend is not allowed to write to io.KeyMap[0..511]!");
9483 for (
int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++)
9484 if (io.KeyMap[n] != -1)
9486 IM_ASSERT(IsLegacyKey((ImGuiKey)io.KeyMap[n]));
9487 io.KeyMap[io.KeyMap[n]] = n;
9491 for (
int n = ImGuiKey_LegacyNativeKey_BEGIN; n < ImGuiKey_LegacyNativeKey_END; n++)
9492 if (io.KeysDown[n] || io.BackendUsingLegacyKeyArrays == 1)
9494 const ImGuiKey key = (ImGuiKey)(io.KeyMap[n] != -1 ? io.KeyMap[n] : n);
9495 IM_ASSERT(io.KeyMap[n] == -1 || IsNamedKey(key));
9496 io.KeysData[key].Down = io.KeysDown[n];
9498 io.KeysDown[key] = io.KeysDown[n];
9499 io.BackendUsingLegacyKeyArrays = 1;
9501 if (io.BackendUsingLegacyKeyArrays == 1)
9503 GetKeyData(ImGuiMod_Ctrl)->Down = io.KeyCtrl;
9504 GetKeyData(ImGuiMod_Shift)->Down = io.KeyShift;
9505 GetKeyData(ImGuiMod_Alt)->Down = io.KeyAlt;
9506 GetKeyData(ImGuiMod_Super)->Down = io.KeySuper;
9512#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
9513 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
9514 if (io.BackendUsingLegacyNavInputArray && nav_gamepad_active)
9516 #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)
9517 #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)
9518 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceDown, ImGuiNavInput_Activate);
9519 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceRight, ImGuiNavInput_Cancel);
9520 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceLeft, ImGuiNavInput_Menu);
9521 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceUp, ImGuiNavInput_Input);
9522 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadLeft, ImGuiNavInput_DpadLeft);
9523 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadRight, ImGuiNavInput_DpadRight);
9524 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadUp, ImGuiNavInput_DpadUp);
9525 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadDown, ImGuiNavInput_DpadDown);
9526 MAP_LEGACY_NAV_INPUT_TO_KEY2(ImGuiKey_GamepadL1, ImGuiNavInput_FocusPrev, ImGuiNavInput_TweakSlow);
9527 MAP_LEGACY_NAV_INPUT_TO_KEY2(ImGuiKey_GamepadR1, ImGuiNavInput_FocusNext, ImGuiNavInput_TweakFast);
9528 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickLeft, ImGuiNavInput_LStickLeft);
9529 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickRight, ImGuiNavInput_LStickRight);
9530 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickUp, ImGuiNavInput_LStickUp);
9531 MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickDown, ImGuiNavInput_LStickDown);
9537 for (
int n = 0; n < ImGuiMouseButton_COUNT; n++)
9538 UpdateAliasKey(MouseButtonToKey(n), io.MouseDown[n], io.MouseDown[n] ? 1.0f : 0.0f);
9539 UpdateAliasKey(ImGuiKey_MouseWheelX, io.MouseWheelH != 0.0f, io.MouseWheelH);
9540 UpdateAliasKey(ImGuiKey_MouseWheelY, io.MouseWheel != 0.0f, io.MouseWheel);
9546 const ImGuiKeyChord prev_key_mods = io.KeyMods;
9547 io.KeyMods = GetMergedModsFromKeys();
9548 io.KeyCtrl = (io.KeyMods & ImGuiMod_Ctrl) != 0;
9549 io.KeyShift = (io.KeyMods & ImGuiMod_Shift) != 0;
9550 io.KeyAlt = (io.KeyMods & ImGuiMod_Alt) != 0;
9551 io.KeySuper = (io.KeyMods & ImGuiMod_Super) != 0;
9552 if (prev_key_mods != io.KeyMods)
9553 g.LastKeyModsChangeTime =
g.Time;
9554 if (prev_key_mods != io.KeyMods && prev_key_mods == 0)
9555 g.LastKeyModsChangeFromNoneTime =
g.Time;
9558 if ((io.BackendFlags & ImGuiBackendFlags_HasGamepad) == 0)
9559 for (
int i = ImGuiKey_Gamepad_BEGIN; i < ImGuiKey_Gamepad_END; i++)
9561 io.KeysData[i - ImGuiKey_KeysData_OFFSET].Down =
false;
9562 io.KeysData[i - ImGuiKey_KeysData_OFFSET].AnalogValue = 0.0f;
9566 for (
int i = 0; i < ImGuiKey_KeysData_SIZE; i++)
9568 ImGuiKeyData* key_data = &io.KeysData[i];
9569 key_data->DownDurationPrev = key_data->DownDuration;
9570 key_data->DownDuration = key_data->Down ? (key_data->DownDuration < 0.0f ? 0.0f : key_data->DownDuration + io.DeltaTime) : -1.0f;
9571 if (key_data->DownDuration == 0.0f)
9573 ImGuiKey key = (ImGuiKey)(ImGuiKey_KeysData_OFFSET + i);
9574 if (IsKeyboardKey(key))
9575 g.LastKeyboardKeyPressTime =
g.Time;
9576 else if (key == ImGuiKey_ReservedForModCtrl || key == ImGuiKey_ReservedForModShift || key == ImGuiKey_ReservedForModAlt || key == ImGuiKey_ReservedForModSuper)
9577 g.LastKeyboardKeyPressTime =
g.Time;
9582 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
9584 ImGuiKeyData* key_data = &io.KeysData[key - ImGuiKey_KeysData_OFFSET];
9585 ImGuiKeyOwnerData* owner_data = &
g.KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN];
9586 owner_data->OwnerCurr = owner_data->OwnerNext;
9587 if (!key_data->Down)
9588 owner_data->OwnerNext = ImGuiKeyOwner_None;
9589 owner_data->LockThisFrame = owner_data->LockUntilRelease = owner_data->LockUntilRelease && key_data->Down;
9593 UpdateKeyRoutingTable(&
g.KeysRoutingTable);
9596static void ImGui::UpdateMouseInputs()
9606 io.MouseWheelRequestAxisSwap = io.KeyShift && !io.ConfigMacOSXBehaviors;
9609 if (IsMousePosValid(&io.MousePos))
9610 io.MousePos =
g.MouseLastValidPos = ImFloor(io.MousePos);
9613 if (IsMousePosValid(&io.MousePos) && IsMousePosValid(&io.MousePosPrev))
9614 io.MouseDelta = io.MousePos - io.MousePosPrev;
9616 io.MouseDelta = ImVec2(0.0f, 0.0f);
9620 const float mouse_stationary_threshold = (io.MouseSource == ImGuiMouseSource_Mouse) ? 2.0f : 3.0f;
9621 const bool mouse_stationary = (ImLengthSqr(io.MouseDelta) <= mouse_stationary_threshold * mouse_stationary_threshold);
9622 g.MouseStationaryTimer = mouse_stationary ? (
g.MouseStationaryTimer + io.DeltaTime) : 0.0f;
9626 if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)
9627 g.NavDisableMouseHover =
false;
9629 for (
int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
9631 io.MouseClicked[i] = io.MouseDown[i] && io.MouseDownDuration[i] < 0.0f;
9632 io.MouseClickedCount[i] = 0;
9633 io.MouseReleased[i] = !io.MouseDown[i] && io.MouseDownDuration[i] >= 0.0f;
9634 io.MouseDownDurationPrev[i] = io.MouseDownDuration[i];
9635 io.MouseDownDuration[i] = io.MouseDown[i] ? (io.MouseDownDuration[i] < 0.0f ? 0.0f : io.MouseDownDuration[i] + io.DeltaTime) : -1.0f;
9636 if (io.MouseClicked[i])
9638 bool is_repeated_click =
false;
9639 if ((
float)(
g.Time - io.MouseClickedTime[i]) < io.MouseDoubleClickTime)
9641 ImVec2 delta_from_click_pos = IsMousePosValid(&io.MousePos) ? (io.MousePos - io.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
9642 if (ImLengthSqr(delta_from_click_pos) < io.MouseDoubleClickMaxDist * io.MouseDoubleClickMaxDist)
9643 is_repeated_click =
true;
9645 if (is_repeated_click)
9646 io.MouseClickedLastCount[i]++;
9648 io.MouseClickedLastCount[i] = 1;
9649 io.MouseClickedTime[i] =
g.Time;
9650 io.MouseClickedPos[i] = io.MousePos;
9651 io.MouseClickedCount[i] = io.MouseClickedLastCount[i];
9652 io.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f);
9653 io.MouseDragMaxDistanceSqr[i] = 0.0f;
9655 else if (io.MouseDown[i])
9658 ImVec2 delta_from_click_pos = IsMousePosValid(&io.MousePos) ? (io.MousePos - io.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
9659 io.MouseDragMaxDistanceSqr[i] = ImMax(io.MouseDragMaxDistanceSqr[i], ImLengthSqr(delta_from_click_pos));
9660 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);
9661 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);
9665 io.MouseDoubleClicked[i] = (io.MouseClickedCount[i] == 2);
9668 if (io.MouseClicked[i])
9669 g.NavDisableMouseHover =
false;
9673static void LockWheelingWindow(ImGuiWindow* window,
float wheel_amount)
9677 g.WheelingWindowReleaseTimer = ImMin(
g.WheelingWindowReleaseTimer + ImAbs(wheel_amount) * WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER, WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER);
9679 g.WheelingWindowReleaseTimer = 0.0f;
9680 if (
g.WheelingWindow == window)
9682 IMGUI_DEBUG_LOG_IO(
"[io] LockWheelingWindow() \"%s\"\n", window ? window->Name :
"NULL");
9683 g.WheelingWindow = window;
9684 g.WheelingWindowRefMousePos =
g.IO.MousePos;
9687 g.WheelingWindowStartFrame = -1;
9688 g.WheelingAxisAvg = ImVec2(0.0f, 0.0f);
9692static ImGuiWindow* FindBestWheelingWindow(
const ImVec2& wheel)
9696 ImGuiWindow* windows[2] = { NULL, NULL };
9697 for (
int axis = 0; axis < 2; axis++)
9698 if (wheel[axis] != 0.0f)
9699 for (ImGuiWindow* window = windows[axis] =
g.HoveredWindow; window->Flags & ImGuiWindowFlags_ChildWindow; window = windows[axis] = window->ParentWindow)
9705 const bool has_scrolling = (window->ScrollMax[axis] != 0.0f);
9706 const bool inputs_disabled = (window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs);
9708 if (has_scrolling && !inputs_disabled)
9711 if (windows[0] == NULL && windows[1] == NULL)
9715 if (windows[0] == windows[1] || windows[0] == NULL || windows[1] == NULL)
9716 return windows[1] ? windows[1] : windows[0];
9721 if (
g.WheelingWindowStartFrame == -1)
9722 g.WheelingWindowStartFrame =
g.FrameCount;
9723 if ((
g.WheelingWindowStartFrame ==
g.FrameCount && wheel.x != 0.0f && wheel.y != 0.0f) || (
g.WheelingAxisAvg.x ==
g.WheelingAxisAvg.y))
9725 g.WheelingWindowWheelRemainder = wheel;
9728 return (
g.WheelingAxisAvg.x >
g.WheelingAxisAvg.y) ? windows[0] : windows[1];
9732void ImGui::UpdateMouseWheel()
9737 if (
g.WheelingWindow != NULL)
9739 g.WheelingWindowReleaseTimer -=
g.IO.DeltaTime;
9740 if (IsMousePosValid() && ImLengthSqr(
g.IO.MousePos -
g.WheelingWindowRefMousePos) >
g.IO.MouseDragThreshold *
g.IO.MouseDragThreshold)
9741 g.WheelingWindowReleaseTimer = 0.0f;
9742 if (
g.WheelingWindowReleaseTimer <= 0.0f)
9743 LockWheelingWindow(NULL, 0.0f);
9747 wheel.x = TestKeyOwner(ImGuiKey_MouseWheelX, ImGuiKeyOwner_None) ?
g.IO.MouseWheelH : 0.0f;
9748 wheel.y = TestKeyOwner(ImGuiKey_MouseWheelY, ImGuiKeyOwner_None) ?
g.IO.MouseWheel : 0.0f;
9751 ImGuiWindow* mouse_window =
g.WheelingWindow ?
g.WheelingWindow :
g.HoveredWindow;
9752 if (!mouse_window || mouse_window->Collapsed)
9757 if (wheel.y != 0.0f &&
g.IO.KeyCtrl &&
g.IO.FontAllowUserScaling)
9759 LockWheelingWindow(mouse_window, wheel.y);
9760 ImGuiWindow* window = mouse_window;
9761 const float new_font_scale = ImClamp(window->FontWindowScale +
g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
9762 const float scale = new_font_scale / window->FontWindowScale;
9763 window->FontWindowScale = new_font_scale;
9764 if (window == window->RootWindow)
9766 const ImVec2 offset = window->Size * (1.0f -
scale) * (
g.IO.MousePos - window->Pos) / window->Size;
9767 SetWindowPos(window, window->Pos + offset, 0);
9768 window->Size = ImTrunc(window->Size * scale);
9769 window->SizeFull = ImTrunc(window->SizeFull * scale);
9778 if (
g.IO.MouseWheelRequestAxisSwap)
9779 wheel = ImVec2(wheel.y, 0.0f);
9783 g.WheelingAxisAvg.x = ImExponentialMovingAverage(
g.WheelingAxisAvg.x, ImAbs(wheel.x), 30);
9784 g.WheelingAxisAvg.y = ImExponentialMovingAverage(
g.WheelingAxisAvg.y, ImAbs(wheel.y), 30);
9787 wheel +=
g.WheelingWindowWheelRemainder;
9788 g.WheelingWindowWheelRemainder = ImVec2(0.0f, 0.0f);
9789 if (wheel.x == 0.0f && wheel.y == 0.0f)
9795 if (ImGuiWindow* window = (
g.WheelingWindow ?
g.WheelingWindow : FindBestWheelingWindow(wheel)))
9796 if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))
9798 bool do_scroll[2] = { wheel.x != 0.0f && window->ScrollMax.x != 0.0f, wheel.y != 0.0f && window->ScrollMax.y != 0.0f };
9799 if (do_scroll[ImGuiAxis_X] && do_scroll[ImGuiAxis_Y])
9800 do_scroll[(
g.WheelingAxisAvg.x >
g.WheelingAxisAvg.y) ? ImGuiAxis_Y : ImGuiAxis_X] = false;
9801 if (do_scroll[ImGuiAxis_X])
9803 LockWheelingWindow(window, wheel.x);
9804 float max_step = window->InnerRect.GetWidth() * 0.67f;
9805 float scroll_step = ImTrunc(ImMin(2 * window->CalcFontSize(), max_step));
9806 SetScrollX(window, window->Scroll.x - wheel.x * scroll_step);
9807 g.WheelingWindowScrolledFrame =
g.FrameCount;
9809 if (do_scroll[ImGuiAxis_Y])
9811 LockWheelingWindow(window, wheel.y);
9812 float max_step = window->InnerRect.GetHeight() * 0.67f;
9813 float scroll_step = ImTrunc(ImMin(5 * window->CalcFontSize(), max_step));
9814 SetScrollY(window, window->Scroll.y - wheel.y * scroll_step);
9815 g.WheelingWindowScrolledFrame =
g.FrameCount;
9820void ImGui::SetNextFrameWantCaptureKeyboard(
bool want_capture_keyboard)
9823 g.WantCaptureKeyboardNextFrame = want_capture_keyboard ? 1 : 0;
9826void ImGui::SetNextFrameWantCaptureMouse(
bool want_capture_mouse)
9829 g.WantCaptureMouseNextFrame = want_capture_mouse ? 1 : 0;
9832#ifndef IMGUI_DISABLE_DEBUG_TOOLS
9833static const char* GetInputSourceName(ImGuiInputSource source)
9835 const char* input_source_names[] = {
"None",
"Mouse",
"Keyboard",
"Gamepad",
"Clipboard" };
9836 IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT && source >= 0 && source < ImGuiInputSource_COUNT);
9837 return input_source_names[source];
9839static const char* GetMouseSourceName(ImGuiMouseSource source)
9841 const char* mouse_source_names[] = {
"Mouse",
"TouchScreen",
"Pen" };
9842 IM_ASSERT(IM_ARRAYSIZE(mouse_source_names) == ImGuiMouseSource_COUNT && source >= 0 && source < ImGuiMouseSource_COUNT);
9843 return mouse_source_names[source];
9845static void DebugPrintInputEvent(
const char* prefix,
const ImGuiInputEvent* e)
9848 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; }
9849 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; }
9850 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; }
9851 if (
e->Type == ImGuiInputEventType_MouseViewport){IMGUI_DEBUG_LOG_IO(
"[io] %s: MouseViewport (0x%08X)\n", prefix,
e->MouseViewport.HoveredViewportID);
return; }
9852 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; }
9853 if (
e->Type == ImGuiInputEventType_Text) { IMGUI_DEBUG_LOG_IO(
"[io] %s: Text: %c (U+%08X)\n", prefix,
e->Text.Char,
e->Text.Char);
return; }
9854 if (
e->Type == ImGuiInputEventType_Focus) { IMGUI_DEBUG_LOG_IO(
"[io] %s: AppFocused %d\n", prefix,
e->AppFocused.Focused);
return; }
9862void ImGui::UpdateInputEvents(
bool trickle_fast_inputs)
9870 const bool trickle_interleaved_keys_and_text = (trickle_fast_inputs &&
g.WantTextInputNextFrame == 1);
9872 bool mouse_moved =
false, mouse_wheeled =
false, key_changed =
false, text_inputted =
false;
9873 int mouse_button_changed = 0x00;
9874 ImBitArray<ImGuiKey_KeysData_SIZE> key_changed_mask;
9877 for (; event_n <
g.InputEventsQueue.Size; event_n++)
9879 ImGuiInputEvent*
e = &
g.InputEventsQueue[event_n];
9880 if (
e->Type == ImGuiInputEventType_MousePos)
9882 if (
g.IO.WantSetMousePos)
9885 ImVec2 event_pos(
e->MousePos.PosX,
e->MousePos.PosY);
9886 if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || text_inputted))
9888 io.MousePos = event_pos;
9889 io.MouseSource =
e->MousePos.MouseSource;
9892 else if (
e->Type == ImGuiInputEventType_MouseButton)
9895 const ImGuiMouseButton button =
e->MouseButton.Button;
9896 IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT);
9897 if (trickle_fast_inputs && ((mouse_button_changed & (1 << button)) || mouse_wheeled))
9899 if (trickle_fast_inputs &&
e->MouseButton.MouseSource == ImGuiMouseSource_TouchScreen && mouse_moved)
9901 io.MouseDown[button] =
e->MouseButton.Down;
9902 io.MouseSource =
e->MouseButton.MouseSource;
9903 mouse_button_changed |= (1 << button);
9905 else if (
e->Type == ImGuiInputEventType_MouseWheel)
9908 if (trickle_fast_inputs && (mouse_moved || mouse_button_changed != 0))
9910 io.MouseWheelH +=
e->MouseWheel.WheelX;
9911 io.MouseWheel +=
e->MouseWheel.WheelY;
9912 io.MouseSource =
e->MouseWheel.MouseSource;
9913 mouse_wheeled =
true;
9915 else if (
e->Type == ImGuiInputEventType_MouseViewport)
9917 io.MouseHoveredViewport =
e->MouseViewport.HoveredViewportID;
9919 else if (
e->Type == ImGuiInputEventType_Key)
9922 ImGuiKey key =
e->Key.Key;
9923 IM_ASSERT(key != ImGuiKey_None);
9924 ImGuiKeyData* key_data = GetKeyData(key);
9925 const int key_data_index = (int)(key_data -
g.IO.KeysData);
9926 if (trickle_fast_inputs && key_data->Down !=
e->Key.Down && (key_changed_mask.TestBit(key_data_index) || text_inputted || mouse_button_changed != 0))
9928 key_data->Down =
e->Key.Down;
9929 key_data->AnalogValue =
e->Key.AnalogValue;
9931 key_changed_mask.SetBit(key_data_index);
9934#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
9935 io.KeysDown[key_data_index] = key_data->Down;
9936 if (io.KeyMap[key_data_index] != -1)
9937 io.KeysDown[io.KeyMap[key_data_index]] = key_data->Down;
9940 else if (
e->Type == ImGuiInputEventType_Text)
9943 if (trickle_fast_inputs && ((key_changed && trickle_interleaved_keys_and_text) || mouse_button_changed != 0 || mouse_moved || mouse_wheeled))
9945 unsigned int c =
e->Text.Char;
9946 io.InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID);
9947 if (trickle_interleaved_keys_and_text)
9948 text_inputted =
true;
9950 else if (
e->Type == ImGuiInputEventType_Focus)
9954 const bool focus_lost = !
e->AppFocused.Focused;
9955 io.AppFocusLost = focus_lost;
9959 IM_ASSERT(0 &&
"Unknown event!");
9965 for (
int n = 0; n < event_n; n++)
9966 g.InputEventsTrail.push_back(
g.InputEventsQueue[n]);
9969#ifndef IMGUI_DISABLE_DEBUG_TOOLS
9970 if (event_n != 0 && (
g.DebugLogFlags & ImGuiDebugLogFlags_EventIO))
9971 for (
int n = 0; n <
g.InputEventsQueue.Size; n++)
9972 DebugPrintInputEvent(n < event_n ?
"Processed" :
"Remaining", &
g.InputEventsQueue[n]);
9976 if (event_n ==
g.InputEventsQueue.Size)
9977 g.InputEventsQueue.resize(0);
9979 g.InputEventsQueue.erase(
g.InputEventsQueue.Data,
g.InputEventsQueue.Data + event_n);
9985 if (
g.IO.AppFocusLost)
9986 g.IO.ClearInputKeys();
9989ImGuiID ImGui::GetKeyOwner(ImGuiKey key)
9991 if (!IsNamedKeyOrModKey(key))
9992 return ImGuiKeyOwner_None;
9995 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
9996 ImGuiID owner_id = owner_data->OwnerCurr;
9998 if (
g.ActiveIdUsingAllKeyboardKeys && owner_id !=
g.ActiveId && owner_id != ImGuiKeyOwner_Any)
9999 if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END)
10000 return ImGuiKeyOwner_None;
10009bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id)
10011 if (!IsNamedKeyOrModKey(key))
10015 if (
g.ActiveIdUsingAllKeyboardKeys && owner_id !=
g.ActiveId && owner_id != ImGuiKeyOwner_Any)
10016 if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END)
10019 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
10020 if (owner_id == ImGuiKeyOwner_Any)
10021 return (owner_data->LockThisFrame ==
false);
10026 if (owner_data->OwnerCurr != owner_id)
10028 if (owner_data->LockThisFrame)
10030 if (owner_data->OwnerCurr != ImGuiKeyOwner_None)
10042void ImGui::SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags)
10045 IM_ASSERT(IsNamedKeyOrModKey(key) && (owner_id != ImGuiKeyOwner_Any || (flags & (ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease))));
10046 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetKeyOwner) == 0);
10049 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
10050 owner_data->OwnerCurr = owner_data->OwnerNext = owner_id;
10054 owner_data->LockUntilRelease = (flags & ImGuiInputFlags_LockUntilRelease) != 0;
10055 owner_data->LockThisFrame = (flags & ImGuiInputFlags_LockThisFrame) != 0 || (owner_data->LockUntilRelease);
10059void ImGui::SetKeyOwnersForKeyChord(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
10061 if (key_chord & ImGuiMod_Ctrl) { SetKeyOwner(ImGuiMod_Ctrl, owner_id, flags); }
10062 if (key_chord & ImGuiMod_Shift) { SetKeyOwner(ImGuiMod_Shift, owner_id, flags); }
10063 if (key_chord & ImGuiMod_Alt) { SetKeyOwner(ImGuiMod_Alt, owner_id, flags); }
10064 if (key_chord & ImGuiMod_Super) { SetKeyOwner(ImGuiMod_Super, owner_id, flags); }
10065 if (key_chord & ImGuiMod_Shortcut) { SetKeyOwner(ImGuiMod_Shortcut, owner_id, flags); }
10066 if (key_chord & ~ImGuiMod_Mask_) { SetKeyOwner((ImGuiKey)(key_chord & ~ImGuiMod_Mask_), owner_id, flags); }
10075void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
10078 ImGuiID
id =
g.LastItemData.ID;
10079 if (
id == 0 || (
g.HoveredId !=
id &&
g.ActiveId !=
id))
10081 if ((flags & ImGuiInputFlags_CondMask_) == 0)
10082 flags |= ImGuiInputFlags_CondDefault_;
10083 if ((
g.HoveredId ==
id && (flags & ImGuiInputFlags_CondHovered)) || (
g.ActiveId ==
id && (flags & ImGuiInputFlags_CondActive)))
10085 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetItemKeyOwner) == 0);
10086 SetKeyOwner(key,
id, flags & ~ImGuiInputFlags_CondMask_);
10091bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord)
10093 return IsKeyChordPressed(key_chord, 0, ImGuiInputFlags_None);
10097bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
10100 key_chord = FixupKeyChord(&
g, key_chord);
10101 ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
10102 if (
g.IO.KeyMods != mods)
10106 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
10107 if (key == ImGuiKey_None)
10108 key = ConvertSingleModFlagToKey(&
g, mods);
10109 if (!IsKeyPressed(key, owner_id, (flags & ImGuiInputFlags_RepeatMask_)))
10114void ImGui::SetNextItemShortcut(ImGuiKeyChord key_chord)
10117 g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasShortcut;
10118 g.NextItemData.Shortcut = key_chord;
10121bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
10127 if ((flags & ImGuiInputFlags_RouteMask_) == 0)
10128 flags |= ImGuiInputFlags_RouteFocused;
10132 if (owner_id == ImGuiKeyOwner_Any || owner_id == ImGuiKeyOwner_None)
10133 owner_id = GetRoutingIdFromOwnerId(owner_id);
10136 if (!SetShortcutRouting(key_chord, owner_id, flags))
10141 if ((flags & ImGuiInputFlags_Repeat) != 0 && (flags & ImGuiInputFlags_RepeatUntilMask_) == 0)
10142 flags |= ImGuiInputFlags_RepeatUntilKeyModsChange;
10144 if (!IsKeyChordPressed(key_chord, owner_id, flags))
10146 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByShortcut) == 0);
10163bool 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)
10165 bool error =
false;
10166 if (strcmp(version, IMGUI_VERSION) != 0) { error =
true; IM_ASSERT(strcmp(version, IMGUI_VERSION) == 0 &&
"Mismatched version string!"); }
10167 if (sz_io !=
sizeof(ImGuiIO)) { error =
true; IM_ASSERT(sz_io ==
sizeof(ImGuiIO) &&
"Mismatched struct layout!"); }
10168 if (sz_style !=
sizeof(ImGuiStyle)) { error =
true; IM_ASSERT(sz_style ==
sizeof(ImGuiStyle) &&
"Mismatched struct layout!"); }
10169 if (sz_vec2 !=
sizeof(ImVec2)) { error =
true; IM_ASSERT(sz_vec2 ==
sizeof(ImVec2) &&
"Mismatched struct layout!"); }
10170 if (sz_vec4 !=
sizeof(ImVec4)) { error =
true; IM_ASSERT(sz_vec4 ==
sizeof(ImVec4) &&
"Mismatched struct layout!"); }
10171 if (sz_vert !=
sizeof(ImDrawVert)) { error =
true; IM_ASSERT(sz_vert ==
sizeof(ImDrawVert) &&
"Mismatched struct layout!"); }
10172 if (sz_idx !=
sizeof(ImDrawIdx)) { error =
true; IM_ASSERT(sz_idx ==
sizeof(ImDrawIdx) &&
"Mismatched struct layout!"); }
10191void ImGui::ErrorCheckUsingSetCursorPosToExtendParentBoundaries()
10194 ImGuiWindow* window =
g.CurrentWindow;
10195 IM_ASSERT(window->DC.IsSetPos);
10196 window->DC.IsSetPos =
false;
10197#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
10198 if (window->DC.CursorPos.x <= window->DC.CursorMaxPos.x && window->DC.CursorPos.y <= window->DC.CursorMaxPos.y)
10200 if (window->SkipItems)
10202 IM_ASSERT(0 &&
"Code uses SetCursorPos()/SetCursorScreenPos() to extend window/parent boundaries. Please submit an item e.g. Dummy() to validate extent.");
10204 window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
10208static void ImGui::ErrorCheckNewFrameSanityChecks()
10218 if (
true) IM_ASSERT(1);
else IM_ASSERT(0);
10222#ifdef __EMSCRIPTEN__
10223 if (
g.IO.DeltaTime <= 0.0f &&
g.FrameCount > 0)
10224 g.IO.DeltaTime = 0.00001f;
10229 IM_ASSERT(
g.Initialized);
10230 IM_ASSERT((
g.IO.DeltaTime > 0.0f ||
g.FrameCount == 0) &&
"Need a positive DeltaTime!");
10231 IM_ASSERT((
g.FrameCount == 0 ||
g.FrameCountEnded ==
g.FrameCount) &&
"Forgot to call Render() or EndFrame() at the end of the previous frame?");
10232 IM_ASSERT(
g.IO.DisplaySize.x >= 0.0f &&
g.IO.DisplaySize.y >= 0.0f &&
"Invalid DisplaySize value!");
10233 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()");
10234 IM_ASSERT(
g.Style.CurveTessellationTol > 0.0f &&
"Invalid style setting!");
10235 IM_ASSERT(
g.Style.CircleTessellationMaxError > 0.0f &&
"Invalid style setting!");
10236 IM_ASSERT(
g.Style.Alpha >= 0.0f &&
g.Style.Alpha <= 1.0f &&
"Invalid style setting!");
10237 IM_ASSERT(
g.Style.WindowMinSize.x >= 1.0f &&
g.Style.WindowMinSize.y >= 1.0f &&
"Invalid style setting.");
10238 IM_ASSERT(
g.Style.WindowMenuButtonPosition == ImGuiDir_None ||
g.Style.WindowMenuButtonPosition == ImGuiDir_Left ||
g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
10239 IM_ASSERT(
g.Style.ColorButtonPosition == ImGuiDir_Left ||
g.Style.ColorButtonPosition == ImGuiDir_Right);
10240#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
10241 for (
int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_COUNT; n++)
10242 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)");
10245 if ((
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) &&
g.IO.BackendUsingLegacyKeyArrays == 1)
10246 IM_ASSERT(
g.IO.KeyMap[ImGuiKey_Space] != -1 &&
"ImGuiKey_Space is not mapped, required for keyboard navigation.");
10250 if (
g.IO.ConfigWindowsResizeFromEdges && !(
g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors))
10251 g.IO.ConfigWindowsResizeFromEdges =
false;
10254 if (
g.FrameCount == 1 && (
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable) && (
g.ConfigFlagsLastFrame & ImGuiConfigFlags_DockingEnable) == 0)
10255 IM_ASSERT(0 &&
"Please set DockingEnable before the first call to NewFrame()! Otherwise you will lose your .ini settings!");
10256 if (
g.FrameCount == 1 && (
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) && (
g.ConfigFlagsLastFrame & ImGuiConfigFlags_ViewportsEnable) == 0)
10257 IM_ASSERT(0 &&
"Please set ViewportsEnable before the first call to NewFrame()! Otherwise you will lose your .ini settings!");
10260 if (
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
10262 if ((
g.IO.BackendFlags & ImGuiBackendFlags_PlatformHasViewports) && (
g.IO.BackendFlags & ImGuiBackendFlags_RendererHasViewports))
10264 IM_ASSERT((
g.FrameCount == 0 ||
g.FrameCount ==
g.FrameCountPlatformEnded) &&
"Forgot to call UpdatePlatformWindows() in main loop after EndFrame()? Check examples/ applications for reference.");
10265 IM_ASSERT(
g.PlatformIO.Platform_CreateWindow != NULL &&
"Platform init didn't install handlers?");
10266 IM_ASSERT(
g.PlatformIO.Platform_DestroyWindow != NULL &&
"Platform init didn't install handlers?");
10267 IM_ASSERT(
g.PlatformIO.Platform_GetWindowPos != NULL &&
"Platform init didn't install handlers?");
10268 IM_ASSERT(
g.PlatformIO.Platform_SetWindowPos != NULL &&
"Platform init didn't install handlers?");
10269 IM_ASSERT(
g.PlatformIO.Platform_GetWindowSize != NULL &&
"Platform init didn't install handlers?");
10270 IM_ASSERT(
g.PlatformIO.Platform_SetWindowSize != NULL &&
"Platform init didn't install handlers?");
10271 IM_ASSERT(
g.PlatformIO.Monitors.Size > 0 &&
"Platform init didn't setup Monitors list?");
10272 IM_ASSERT((
g.Viewports[0]->PlatformUserData != NULL ||
g.Viewports[0]->PlatformHandle != NULL) &&
"Platform init didn't setup main viewport.");
10273 if (
g.IO.ConfigDockingTransparentPayload && (
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
10274 IM_ASSERT(
g.PlatformIO.Platform_SetWindowAlpha != NULL &&
"Platform_SetWindowAlpha handler is required to use io.ConfigDockingTransparent!");
10279 g.IO.ConfigFlags &= ~ImGuiConfigFlags_ViewportsEnable;
10283 for (ImGuiPlatformMonitor& mon :
g.PlatformIO.Monitors)
10286 IM_ASSERT(mon.MainSize.x > 0.0f && mon.MainSize.y > 0.0f &&
"Monitor main bounds not setup properly.");
10287 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.");
10288 IM_ASSERT(mon.DpiScale != 0.0f);
10293static void ImGui::ErrorCheckEndFrameSanityChecks()
10303 const ImGuiKeyChord key_mods = GetMergedModsFromKeys();
10304 IM_ASSERT((key_mods == 0 ||
g.IO.KeyMods == key_mods) &&
"Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
10305 IM_UNUSED(key_mods);
10312 if (
g.CurrentWindowStack.Size != 1)
10314 if (
g.CurrentWindowStack.Size > 1)
10316 ImGuiWindow* window =
g.CurrentWindowStack.back().Window;
10317 IM_ASSERT_USER_ERROR(
g.CurrentWindowStack.Size == 1,
"Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?");
10319 while (
g.CurrentWindowStack.Size > 1)
10324 IM_ASSERT_USER_ERROR(
g.CurrentWindowStack.Size == 1,
"Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?");
10328 IM_ASSERT_USER_ERROR(
g.GroupStack.Size == 0,
"Missing EndGroup call!");
10336void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback,
void* user_data)
10340 while (
g.CurrentWindowStack.Size > 0)
10342 ErrorCheckEndWindowRecover(log_callback, user_data);
10343 ImGuiWindow* window =
g.CurrentWindow;
10344 if (
g.CurrentWindowStack.Size == 1)
10346 IM_ASSERT(window->IsFallbackWindow);
10349 if (window->Flags & ImGuiWindowFlags_ChildWindow)
10351 if (log_callback) log_callback(user_data,
"Recovered from missing EndChild() for '%s'", window->Name);
10356 if (log_callback) log_callback(user_data,
"Recovered from missing End() for '%s'", window->Name);
10363void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback,
void* user_data)
10366 while (
g.CurrentTable && (
g.CurrentTable->OuterWindow ==
g.CurrentWindow ||
g.CurrentTable->InnerWindow ==
g.CurrentWindow))
10368 if (log_callback) log_callback(user_data,
"Recovered from missing EndTable() in '%s'",
g.CurrentTable->OuterWindow->Name);
10372 ImGuiWindow* window =
g.CurrentWindow;
10373 ImGuiStackSizes* stack_sizes = &
g.CurrentWindowStack.back().StackSizesOnBegin;
10374 IM_ASSERT(window != NULL);
10375 while (
g.CurrentTabBar != NULL)
10377 if (log_callback) log_callback(user_data,
"Recovered from missing EndTabBar() in '%s'", window->Name);
10380 while (window->DC.TreeDepth > 0)
10382 if (log_callback) log_callback(user_data,
"Recovered from missing TreePop() in '%s'", window->Name);
10385 while (
g.GroupStack.Size > stack_sizes->SizeOfGroupStack)
10387 if (log_callback) log_callback(user_data,
"Recovered from missing EndGroup() in '%s'", window->Name);
10390 while (window->IDStack.Size > 1)
10392 if (log_callback) log_callback(user_data,
"Recovered from missing PopID() in '%s'", window->Name);
10395 while (
g.DisabledStackSize > stack_sizes->SizeOfDisabledStack)
10397 if (log_callback) log_callback(user_data,
"Recovered from missing EndDisabled() in '%s'", window->Name);
10400 while (
g.ColorStack.Size > stack_sizes->SizeOfColorStack)
10402 if (log_callback) log_callback(user_data,
"Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s", window->Name, GetStyleColorName(
g.ColorStack.back().Col));
10405 while (
g.ItemFlagsStack.Size > stack_sizes->SizeOfItemFlagsStack)
10407 if (log_callback) log_callback(user_data,
"Recovered from missing PopItemFlag() in '%s'", window->Name);
10410 while (
g.StyleVarStack.Size > stack_sizes->SizeOfStyleVarStack)
10412 if (log_callback) log_callback(user_data,
"Recovered from missing PopStyleVar() in '%s'", window->Name);
10415 while (
g.FontStack.Size > stack_sizes->SizeOfFontStack)
10417 if (log_callback) log_callback(user_data,
"Recovered from missing PopFont() in '%s'", window->Name);
10420 while (
g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack + 1)
10422 if (log_callback) log_callback(user_data,
"Recovered from missing PopFocusScope() in '%s'", window->Name);
10428void ImGuiStackSizes::SetToContextState(ImGuiContext* ctx)
10430 ImGuiContext&
g = *ctx;
10431 ImGuiWindow* window =
g.CurrentWindow;
10432 SizeOfIDStack = (short)window->IDStack.Size;
10433 SizeOfColorStack = (short)
g.ColorStack.Size;
10434 SizeOfStyleVarStack = (short)
g.StyleVarStack.Size;
10435 SizeOfFontStack = (short)
g.FontStack.Size;
10436 SizeOfFocusScopeStack = (short)
g.FocusScopeStack.Size;
10437 SizeOfGroupStack = (short)
g.GroupStack.Size;
10438 SizeOfItemFlagsStack = (short)
g.ItemFlagsStack.Size;
10439 SizeOfBeginPopupStack = (short)
g.BeginPopupStack.Size;
10440 SizeOfDisabledStack = (short)
g.DisabledStackSize;
10444void ImGuiStackSizes::CompareWithContextState(ImGuiContext* ctx)
10446 ImGuiContext&
g = *ctx;
10447 ImGuiWindow* window =
g.CurrentWindow;
10452 IM_ASSERT(SizeOfIDStack == window->IDStack.Size &&
"PushID/PopID or TreeNode/TreePop Mismatch!");
10456 IM_ASSERT(SizeOfGroupStack ==
g.GroupStack.Size &&
"BeginGroup/EndGroup Mismatch!");
10457 IM_ASSERT(SizeOfBeginPopupStack ==
g.BeginPopupStack.Size &&
"BeginPopup/EndPopup or BeginMenu/EndMenu Mismatch!");
10458 IM_ASSERT(SizeOfDisabledStack ==
g.DisabledStackSize &&
"BeginDisabled/EndDisabled Mismatch!");
10459 IM_ASSERT(SizeOfItemFlagsStack >=
g.ItemFlagsStack.Size &&
"PushItemFlag/PopItemFlag Mismatch!");
10460 IM_ASSERT(SizeOfColorStack >=
g.ColorStack.Size &&
"PushStyleColor/PopStyleColor Mismatch!");
10461 IM_ASSERT(SizeOfStyleVarStack >=
g.StyleVarStack.Size &&
"PushStyleVar/PopStyleVar Mismatch!");
10462 IM_ASSERT(SizeOfFontStack >=
g.FontStack.Size &&
"PushFont/PopFont Mismatch!");
10463 IM_ASSERT(SizeOfFocusScopeStack ==
g.FocusScopeStack.Size &&
"PushFocusScope/PopFocusScope Mismatch!");
10475void ImGui::KeepAliveID(ImGuiID
id)
10478 if (
g.ActiveId ==
id)
10479 g.ActiveIdIsAlive =
id;
10480 if (
g.ActiveIdPreviousFrame ==
id)
10481 g.ActiveIdPreviousFrameIsAlive =
true;
10484static void ItemHandleShortcut(ImGuiID
id)
10488 if (ImGui::Shortcut(
g.NextItemData.Shortcut,
id, ImGuiInputFlags_None) &&
g.NavActivateId == 0)
10490 g.NavActivateId =
id;
10491 g.NavActivateFlags = ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_FromShortcut;
10492 if (
g.ActiveId == 0 ||
g.ActiveId ==
id)
10493 g.NavActivateDownId =
g.NavActivatePressedId =
id;
10494 ImGui::NavHighlightActivated(
id);
10502bool ImGui::ItemAdd(
const ImRect& bb, ImGuiID
id,
const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags)
10505 ImGuiWindow* window =
g.CurrentWindow;
10509 g.LastItemData.ID =
id;
10510 g.LastItemData.Rect = bb;
10511 g.LastItemData.NavRect = nav_bb_arg ? *nav_bb_arg : bb;
10512 g.LastItemData.InFlags =
g.CurrentItemFlags |
g.NextItemData.ItemFlags | extra_flags;
10513 g.LastItemData.StatusFlags = ImGuiItemStatusFlags_None;
10530 if (!(
g.LastItemData.InFlags & ImGuiItemFlags_NoNav))
10533 window->DC.NavLayersActiveMaskNext |= (1 << window->DC.NavLayerCurrent);
10534 if (
g.NavId ==
id ||
g.NavAnyRequest)
10535 if (
g.NavWindow->RootWindowForNav == window->RootWindowForNav)
10536 if (window ==
g.NavWindow || ((window->Flags |
g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened))
10540 if (
g.NextItemData.Flags & ImGuiNextItemDataFlags_HasShortcut)
10541 ItemHandleShortcut(
id);
10545 g.NextItemData.Flags = ImGuiNextItemDataFlags_None;
10546 g.NextItemData.ItemFlags = ImGuiItemFlags_None;
10548#ifdef IMGUI_ENABLE_TEST_ENGINE
10550 IMGUI_TEST_ENGINE_ITEM_ADD(
id,
g.LastItemData.NavRect, &
g.LastItemData);
10559 const bool is_rect_visible = bb.Overlaps(window->ClipRect);
10560 if (!is_rect_visible)
10561 if (
id == 0 || (
id !=
g.ActiveId &&
id !=
g.ActiveIdPreviousFrame &&
id !=
g.NavId &&
id !=
g.NavActivateId))
10566#ifndef IMGUI_DISABLE_DEBUG_TOOLS
10569 if (
id ==
g.DebugLocateId)
10570 DebugLocateItemResolveWithLastItem();
10575 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!");
10583 if (is_rect_visible)
10584 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Visible;
10585 if (IsMouseHoveringRect(bb.Min, bb.Max))
10586 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect;
10626void ImGui::ItemSize(
const ImVec2& size,
float text_baseline_y)
10629 ImGuiWindow* window =
g.CurrentWindow;
10630 if (window->SkipItems)
10636 const float offset_to_match_baseline_y = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f;
10638 const float line_y1 = window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y;
10639 const float line_height = ImMax(window->DC.CurrLineSize.y, window->DC.CursorPos.y - line_y1 +
size.y + offset_to_match_baseline_y);
10643 window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x +
size.x;
10644 window->DC.CursorPosPrevLine.y = line_y1;
10645 window->DC.CursorPos.x = IM_TRUNC(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
10646 window->DC.CursorPos.y = IM_TRUNC(line_y1 + line_height +
g.Style.ItemSpacing.y);
10647 window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
10648 window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y -
g.Style.ItemSpacing.y);
10651 window->DC.PrevLineSize.y = line_height;
10652 window->DC.CurrLineSize.y = 0.0f;
10653 window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y);
10654 window->DC.CurrLineTextBaseOffset = 0.0f;
10655 window->DC.IsSameLine = window->DC.IsSetPos =
false;
10658 if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
10667void ImGui::SameLine(
float offset_from_start_x,
float spacing_w)
10670 ImGuiWindow* window =
g.CurrentWindow;
10671 if (window->SkipItems)
10674 if (offset_from_start_x != 0.0f)
10676 if (spacing_w < 0.0f)
10678 window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + offset_from_start_x + spacing_w + window->DC.GroupOffset.x + window->DC.ColumnsOffset.x;
10679 window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
10683 if (spacing_w < 0.0f)
10684 spacing_w =
g.Style.ItemSpacing.x;
10685 window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w;
10686 window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
10688 window->DC.CurrLineSize = window->DC.PrevLineSize;
10689 window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
10690 window->DC.IsSameLine =
true;
10693ImVec2 ImGui::GetCursorScreenPos()
10695 ImGuiWindow* window = GetCurrentWindowRead();
10696 return window->DC.CursorPos;
10699void ImGui::SetCursorScreenPos(
const ImVec2& pos)
10701 ImGuiWindow* window = GetCurrentWindow();
10702 window->DC.CursorPos = pos;
10704 window->DC.IsSetPos =
true;
10709ImVec2 ImGui::GetCursorPos()
10711 ImGuiWindow* window = GetCurrentWindowRead();
10712 return window->DC.CursorPos - window->Pos + window->Scroll;
10715float ImGui::GetCursorPosX()
10717 ImGuiWindow* window = GetCurrentWindowRead();
10718 return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x;
10721float ImGui::GetCursorPosY()
10723 ImGuiWindow* window = GetCurrentWindowRead();
10724 return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y;
10727void ImGui::SetCursorPos(
const ImVec2& local_pos)
10729 ImGuiWindow* window = GetCurrentWindow();
10730 window->DC.CursorPos = window->Pos - window->Scroll + local_pos;
10732 window->DC.IsSetPos =
true;
10735void ImGui::SetCursorPosX(
float x)
10737 ImGuiWindow* window = GetCurrentWindow();
10738 window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x;
10740 window->DC.IsSetPos =
true;
10743void ImGui::SetCursorPosY(
float y)
10745 ImGuiWindow* window = GetCurrentWindow();
10746 window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y;
10748 window->DC.IsSetPos =
true;
10751ImVec2 ImGui::GetCursorStartPos()
10753 ImGuiWindow* window = GetCurrentWindowRead();
10754 return window->DC.CursorStartPos - window->Pos;
10757void ImGui::Indent(
float indent_w)
10760 ImGuiWindow* window = GetCurrentWindow();
10761 window->DC.Indent.x += (indent_w != 0.0f) ? indent_w :
g.Style.IndentSpacing;
10762 window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
10765void ImGui::Unindent(
float indent_w)
10768 ImGuiWindow* window = GetCurrentWindow();
10769 window->DC.Indent.x -= (indent_w != 0.0f) ? indent_w :
g.Style.IndentSpacing;
10770 window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
10774void ImGui::SetNextItemWidth(
float item_width)
10777 g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasWidth;
10778 g.NextItemData.Width = item_width;
10782void ImGui::PushItemWidth(
float item_width)
10785 ImGuiWindow* window =
g.CurrentWindow;
10786 window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);
10787 window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);
10788 g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
10791void ImGui::PushMultiItemsWidths(
int components,
float w_full)
10794 ImGuiWindow* window =
g.CurrentWindow;
10795 IM_ASSERT(components > 0);
10796 const ImGuiStyle& style =
g.Style;
10797 window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);
10798 float w_items = w_full - style.ItemInnerSpacing.x * (components - 1);
10799 float prev_split = w_items;
10800 for (
int i = components - 1; i > 0; i--)
10802 float next_split = IM_TRUNC(w_items * i / components);
10803 window->DC.ItemWidthStack.push_back(ImMax(prev_split - next_split, 1.0f));
10804 prev_split = next_split;
10806 window->DC.ItemWidth = ImMax(prev_split, 1.0f);
10807 g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
10810void ImGui::PopItemWidth()
10812 ImGuiWindow* window = GetCurrentWindow();
10813 window->DC.ItemWidth = window->DC.ItemWidthStack.back();
10814 window->DC.ItemWidthStack.pop_back();
10819float ImGui::CalcItemWidth()
10822 ImGuiWindow* window =
g.CurrentWindow;
10824 if (
g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth)
10825 w =
g.NextItemData.Width;
10827 w = window->DC.ItemWidth;
10830 float region_max_x = GetContentRegionMaxAbs().x;
10831 w = ImMax(1.0f, region_max_x - window->DC.CursorPos.x + w);
10841ImVec2 ImGui::CalcItemSize(ImVec2 size,
float default_w,
float default_h)
10844 ImGuiWindow* window =
g.CurrentWindow;
10847 if (
size.x < 0.0f ||
size.y < 0.0f)
10848 region_max = GetContentRegionMaxAbs();
10850 if (
size.x == 0.0f)
10851 size.x = default_w;
10852 else if (
size.x < 0.0f)
10853 size.x = ImMax(4.0f, region_max.x - window->DC.CursorPos.x +
size.x);
10855 if (
size.y == 0.0f)
10856 size.y = default_h;
10857 else if (
size.y < 0.0f)
10858 size.y = ImMax(4.0f, region_max.y - window->DC.CursorPos.y +
size.y);
10863float ImGui::GetTextLineHeight()
10869float ImGui::GetTextLineHeightWithSpacing()
10872 return g.FontSize +
g.Style.ItemSpacing.y;
10875float ImGui::GetFrameHeight()
10878 return g.FontSize +
g.Style.FramePadding.y * 2.0f;
10881float ImGui::GetFrameHeightWithSpacing()
10884 return g.FontSize +
g.Style.FramePadding.y * 2.0f +
g.Style.ItemSpacing.y;
10890ImVec2 ImGui::GetContentRegionMax()
10893 ImGuiWindow* window =
g.CurrentWindow;
10894 ImVec2 mx = (window->DC.CurrentColumns ||
g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max;
10895 return mx - window->Pos;
10899ImVec2 ImGui::GetContentRegionMaxAbs()
10902 ImGuiWindow* window =
g.CurrentWindow;
10903 ImVec2 mx = (window->DC.CurrentColumns ||
g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max;
10907ImVec2 ImGui::GetContentRegionAvail()
10909 ImGuiWindow* window =
GImGui->CurrentWindow;
10910 return GetContentRegionMaxAbs() - window->DC.CursorPos;
10914ImVec2 ImGui::GetWindowContentRegionMin()
10916 ImGuiWindow* window =
GImGui->CurrentWindow;
10917 return window->ContentRegionRect.Min - window->Pos;
10920ImVec2 ImGui::GetWindowContentRegionMax()
10922 ImGuiWindow* window =
GImGui->CurrentWindow;
10923 return window->ContentRegionRect.Max - window->Pos;
10929void ImGui::BeginGroup()
10932 ImGuiWindow* window =
g.CurrentWindow;
10934 g.GroupStack.resize(
g.GroupStack.Size + 1);
10935 ImGuiGroupData& group_data =
g.GroupStack.back();
10936 group_data.WindowID = window->ID;
10937 group_data.BackupCursorPos = window->DC.CursorPos;
10938 group_data.BackupCursorPosPrevLine = window->DC.CursorPosPrevLine;
10939 group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
10940 group_data.BackupIndent = window->DC.Indent;
10941 group_data.BackupGroupOffset = window->DC.GroupOffset;
10942 group_data.BackupCurrLineSize = window->DC.CurrLineSize;
10943 group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset;
10944 group_data.BackupActiveIdIsAlive =
g.ActiveIdIsAlive;
10945 group_data.BackupHoveredIdIsAlive =
g.HoveredId != 0;
10946 group_data.BackupIsSameLine = window->DC.IsSameLine;
10947 group_data.BackupActiveIdPreviousFrameIsAlive =
g.ActiveIdPreviousFrameIsAlive;
10948 group_data.EmitItem =
true;
10950 window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
10951 window->DC.Indent = window->DC.GroupOffset;
10952 window->DC.CursorMaxPos = window->DC.CursorPos;
10953 window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
10955 g.LogLinePosY = -FLT_MAX;
10958void ImGui::EndGroup()
10961 ImGuiWindow* window =
g.CurrentWindow;
10962 IM_ASSERT(
g.GroupStack.Size > 0);
10964 ImGuiGroupData& group_data =
g.GroupStack.back();
10965 IM_ASSERT(group_data.WindowID == window->ID);
10967 if (window->DC.IsSetPos)
10968 ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
10970 ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos));
10972 window->DC.CursorPos = group_data.BackupCursorPos;
10973 window->DC.CursorPosPrevLine = group_data.BackupCursorPosPrevLine;
10974 window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos);
10975 window->DC.Indent = group_data.BackupIndent;
10976 window->DC.GroupOffset = group_data.BackupGroupOffset;
10977 window->DC.CurrLineSize = group_data.BackupCurrLineSize;
10978 window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset;
10979 window->DC.IsSameLine = group_data.BackupIsSameLine;
10981 g.LogLinePosY = -FLT_MAX;
10983 if (!group_data.EmitItem)
10985 g.GroupStack.pop_back();
10989 window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset);
10990 ItemSize(group_bb.GetSize());
10991 ItemAdd(group_bb, 0, NULL, ImGuiItemFlags_NoTabStop);
10997 const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive !=
g.ActiveId) && (
g.ActiveIdIsAlive ==
g.ActiveId) &&
g.ActiveId;
10998 const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive ==
false) && (
g.ActiveIdPreviousFrameIsAlive ==
true);
10999 if (group_contains_curr_active_id)
11000 g.LastItemData.ID =
g.ActiveId;
11001 else if (group_contains_prev_active_id)
11002 g.LastItemData.ID =
g.ActiveIdPreviousFrame;
11003 g.LastItemData.Rect = group_bb;
11006 const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive ==
false) &&
g.HoveredId != 0;
11007 if (group_contains_curr_hovered_id)
11008 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
11011 if (group_contains_curr_active_id &&
g.ActiveIdHasBeenEditedThisFrame)
11012 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
11015 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated;
11016 if (group_contains_prev_active_id &&
g.ActiveId !=
g.ActiveIdPreviousFrame)
11017 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated;
11019 g.GroupStack.pop_back();
11020 if (
g.DebugShowGroupRects)
11021 window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255));
11033static float CalcScrollEdgeSnap(
float target,
float snap_min,
float snap_max,
float snap_threshold,
float center_ratio)
11035 if (target <= snap_min + snap_threshold)
11036 return ImLerp(snap_min, target, center_ratio);
11037 if (target >= snap_max - snap_threshold)
11038 return ImLerp(target, snap_max, center_ratio);
11042static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window)
11044 ImVec2 scroll = window->Scroll;
11045 ImVec2 decoration_size(window->DecoOuterSizeX1 + window->DecoInnerSizeX1 + window->DecoOuterSizeX2, window->DecoOuterSizeY1 + window->DecoInnerSizeY1 + window->DecoOuterSizeY2);
11046 for (
int axis = 0; axis < 2; axis++)
11048 if (window->ScrollTarget[axis] < FLT_MAX)
11050 float center_ratio = window->ScrollTargetCenterRatio[axis];
11051 float scroll_target = window->ScrollTarget[axis];
11052 if (window->ScrollTargetEdgeSnapDist[axis] > 0.0f)
11054 float snap_min = 0.0f;
11055 float snap_max = window->ScrollMax[axis] + window->SizeFull[axis] - decoration_size[axis];
11056 scroll_target = CalcScrollEdgeSnap(scroll_target, snap_min, snap_max, window->ScrollTargetEdgeSnapDist[axis], center_ratio);
11058 scroll[axis] = scroll_target - center_ratio * (window->SizeFull[axis] - decoration_size[axis]);
11060 scroll[axis] = IM_ROUND(ImMax(scroll[axis], 0.0f));
11061 if (!window->Collapsed && !window->SkipItems)
11062 scroll[axis] = ImMin(scroll[axis], window->ScrollMax[axis]);
11067void ImGui::ScrollToItem(ImGuiScrollFlags flags)
11070 ImGuiWindow* window =
g.CurrentWindow;
11071 ScrollToRectEx(window,
g.LastItemData.NavRect, flags);
11074void ImGui::ScrollToRect(ImGuiWindow* window,
const ImRect& item_rect, ImGuiScrollFlags flags)
11076 ScrollToRectEx(window, item_rect, flags);
11080ImVec2 ImGui::ScrollToRectEx(ImGuiWindow* window,
const ImRect& item_rect, ImGuiScrollFlags flags)
11083 ImRect scroll_rect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1));
11084 scroll_rect.Min.x = ImMin(scroll_rect.Min.x + window->DecoInnerSizeX1, scroll_rect.Max.x);
11085 scroll_rect.Min.y = ImMin(scroll_rect.Min.y + window->DecoInnerSizeY1, scroll_rect.Max.y);
11090 IM_ASSERT((flags & ImGuiScrollFlags_MaskX_) == 0 || ImIsPowerOfTwo(flags & ImGuiScrollFlags_MaskX_));
11091 IM_ASSERT((flags & ImGuiScrollFlags_MaskY_) == 0 || ImIsPowerOfTwo(flags & ImGuiScrollFlags_MaskY_));
11094 ImGuiScrollFlags in_flags = flags;
11095 if ((flags & ImGuiScrollFlags_MaskX_) == 0 && window->ScrollbarX)
11096 flags |= ImGuiScrollFlags_KeepVisibleEdgeX;
11097 if ((flags & ImGuiScrollFlags_MaskY_) == 0)
11098 flags |= window->Appearing ? ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeY;
11100 const bool fully_visible_x = item_rect.Min.x >= scroll_rect.Min.x && item_rect.Max.x <= scroll_rect.Max.x;
11101 const bool fully_visible_y = item_rect.Min.y >= scroll_rect.Min.y && item_rect.Max.y <= scroll_rect.Max.y;
11102 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;
11103 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;
11105 if ((flags & ImGuiScrollFlags_KeepVisibleEdgeX) && !fully_visible_x)
11107 if (item_rect.Min.x < scroll_rect.Min.x || !can_be_fully_visible_x)
11108 SetScrollFromPosX(window, item_rect.Min.x -
g.Style.ItemSpacing.x - window->Pos.x, 0.0f);
11109 else if (item_rect.Max.x >= scroll_rect.Max.x)
11110 SetScrollFromPosX(window, item_rect.Max.x +
g.Style.ItemSpacing.x - window->Pos.x, 1.0f);
11112 else if (((flags & ImGuiScrollFlags_KeepVisibleCenterX) && !fully_visible_x) || (flags & ImGuiScrollFlags_AlwaysCenterX))
11114 if (can_be_fully_visible_x)
11115 SetScrollFromPosX(window, ImTrunc((item_rect.Min.x + item_rect.Max.x) * 0.5f) - window->Pos.x, 0.5f);
11117 SetScrollFromPosX(window, item_rect.Min.x - window->Pos.x, 0.0f);
11120 if ((flags & ImGuiScrollFlags_KeepVisibleEdgeY) && !fully_visible_y)
11122 if (item_rect.Min.y < scroll_rect.Min.y || !can_be_fully_visible_y)
11123 SetScrollFromPosY(window, item_rect.Min.y -
g.Style.ItemSpacing.y - window->Pos.y, 0.0f);
11124 else if (item_rect.Max.y >= scroll_rect.Max.y)
11125 SetScrollFromPosY(window, item_rect.Max.y +
g.Style.ItemSpacing.y - window->Pos.y, 1.0f);
11127 else if (((flags & ImGuiScrollFlags_KeepVisibleCenterY) && !fully_visible_y) || (flags & ImGuiScrollFlags_AlwaysCenterY))
11129 if (can_be_fully_visible_y)
11130 SetScrollFromPosY(window, ImTrunc((item_rect.Min.y + item_rect.Max.y) * 0.5f) - window->Pos.y, 0.5f);
11132 SetScrollFromPosY(window, item_rect.Min.y - window->Pos.y, 0.0f);
11135 ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
11136 ImVec2 delta_scroll = next_scroll - window->Scroll;
11139 if (!(flags & ImGuiScrollFlags_NoScrollParent) && (window->Flags & ImGuiWindowFlags_ChildWindow))
11142 if ((in_flags & (ImGuiScrollFlags_AlwaysCenterX | ImGuiScrollFlags_KeepVisibleCenterX)) != 0)
11143 in_flags = (in_flags & ~ImGuiScrollFlags_MaskX_) | ImGuiScrollFlags_KeepVisibleEdgeX;
11144 if ((in_flags & (ImGuiScrollFlags_AlwaysCenterY | ImGuiScrollFlags_KeepVisibleCenterY)) != 0)
11145 in_flags = (in_flags & ~ImGuiScrollFlags_MaskY_) | ImGuiScrollFlags_KeepVisibleEdgeY;
11146 delta_scroll += ScrollToRectEx(window->ParentWindow, ImRect(item_rect.Min - delta_scroll, item_rect.Max - delta_scroll), in_flags);
11149 return delta_scroll;
11152float ImGui::GetScrollX()
11154 ImGuiWindow* window =
GImGui->CurrentWindow;
11155 return window->Scroll.x;
11158float ImGui::GetScrollY()
11160 ImGuiWindow* window =
GImGui->CurrentWindow;
11161 return window->Scroll.y;
11164float ImGui::GetScrollMaxX()
11166 ImGuiWindow* window =
GImGui->CurrentWindow;
11167 return window->ScrollMax.x;
11170float ImGui::GetScrollMaxY()
11172 ImGuiWindow* window =
GImGui->CurrentWindow;
11173 return window->ScrollMax.y;
11176void ImGui::SetScrollX(ImGuiWindow* window,
float scroll_x)
11178 window->ScrollTarget.x = scroll_x;
11179 window->ScrollTargetCenterRatio.x = 0.0f;
11180 window->ScrollTargetEdgeSnapDist.x = 0.0f;
11183void ImGui::SetScrollY(ImGuiWindow* window,
float scroll_y)
11185 window->ScrollTarget.y = scroll_y;
11186 window->ScrollTargetCenterRatio.y = 0.0f;
11187 window->ScrollTargetEdgeSnapDist.y = 0.0f;
11190void ImGui::SetScrollX(
float scroll_x)
11193 SetScrollX(
g.CurrentWindow, scroll_x);
11196void ImGui::SetScrollY(
float scroll_y)
11199 SetScrollY(
g.CurrentWindow, scroll_y);
11212void ImGui::SetScrollFromPosX(ImGuiWindow* window,
float local_x,
float center_x_ratio)
11214 IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f);
11215 window->ScrollTarget.x = IM_TRUNC(local_x - window->DecoOuterSizeX1 - window->DecoInnerSizeX1 + window->Scroll.x);
11216 window->ScrollTargetCenterRatio.x = center_x_ratio;
11217 window->ScrollTargetEdgeSnapDist.x = 0.0f;
11220void ImGui::SetScrollFromPosY(ImGuiWindow* window,
float local_y,
float center_y_ratio)
11222 IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f);
11223 window->ScrollTarget.y = IM_TRUNC(local_y - window->DecoOuterSizeY1 - window->DecoInnerSizeY1 + window->Scroll.y);
11224 window->ScrollTargetCenterRatio.y = center_y_ratio;
11225 window->ScrollTargetEdgeSnapDist.y = 0.0f;
11228void ImGui::SetScrollFromPosX(
float local_x,
float center_x_ratio)
11231 SetScrollFromPosX(
g.CurrentWindow, local_x, center_x_ratio);
11234void ImGui::SetScrollFromPosY(
float local_y,
float center_y_ratio)
11237 SetScrollFromPosY(
g.CurrentWindow, local_y, center_y_ratio);
11241void ImGui::SetScrollHereX(
float center_x_ratio)
11244 ImGuiWindow* window =
g.CurrentWindow;
11245 float spacing_x = ImMax(window->WindowPadding.x,
g.Style.ItemSpacing.x);
11246 float target_pos_x = ImLerp(
g.LastItemData.Rect.Min.x - spacing_x,
g.LastItemData.Rect.Max.x + spacing_x, center_x_ratio);
11247 SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio);
11250 window->ScrollTargetEdgeSnapDist.x = ImMax(0.0f, window->WindowPadding.x - spacing_x);
11254void ImGui::SetScrollHereY(
float center_y_ratio)
11257 ImGuiWindow* window =
g.CurrentWindow;
11258 float spacing_y = ImMax(window->WindowPadding.y,
g.Style.ItemSpacing.y);
11259 float target_pos_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y, window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y, center_y_ratio);
11260 SetScrollFromPosY(window, target_pos_y - window->Pos.y, center_y_ratio);
11263 window->ScrollTargetEdgeSnapDist.y = ImMax(0.0f, window->WindowPadding.y - spacing_y);
11270bool ImGui::BeginTooltip()
11272 return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None);
11275bool ImGui::BeginItemTooltip()
11277 if (!IsItemHovered(ImGuiHoveredFlags_ForTooltip))
11279 return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None);
11282bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags)
11286 if (
g.DragDropWithinSource ||
g.DragDropWithinTarget)
11294 ImVec2 tooltip_pos =
g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET *
g.Style.MouseCursorScale;
11295 SetNextWindowPos(tooltip_pos);
11296 SetNextWindowBgAlpha(
g.Style.Colors[ImGuiCol_PopupBg].w * 0.60f);
11298 tooltip_flags |= ImGuiTooltipFlags_OverridePrevious;
11301 char window_name[16];
11302 ImFormatString(window_name, IM_ARRAYSIZE(window_name),
"##Tooltip_%02d",
g.TooltipOverrideCount);
11303 if (tooltip_flags & ImGuiTooltipFlags_OverridePrevious)
11304 if (ImGuiWindow* window = FindWindowByName(window_name))
11305 if (window->Active)
11308 SetWindowHiddenAndSkipItemsForCurrentFrame(window);
11309 ImFormatString(window_name, IM_ARRAYSIZE(window_name),
"##Tooltip_%02d", ++
g.TooltipOverrideCount);
11311 ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDocking;
11312 Begin(window_name, NULL, flags | extra_window_flags);
11321void ImGui::EndTooltip()
11323 IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip);
11327void ImGui::SetTooltip(
const char* fmt, ...)
11330 va_start(args, fmt);
11331 SetTooltipV(fmt, args);
11335void ImGui::SetTooltipV(
const char* fmt, va_list args)
11337 if (!BeginTooltipEx(ImGuiTooltipFlags_OverridePrevious, ImGuiWindowFlags_None))
11345void ImGui::SetItemTooltip(
const char* fmt, ...)
11348 va_start(args, fmt);
11349 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip))
11350 SetTooltipV(fmt, args);
11354void ImGui::SetItemTooltipV(
const char* fmt, va_list args)
11356 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip))
11357 SetTooltipV(fmt, args);
11366bool ImGui::IsPopupOpen(ImGuiID
id, ImGuiPopupFlags popup_flags)
11369 if (popup_flags & ImGuiPopupFlags_AnyPopupId)
11373 IM_ASSERT(
id == 0);
11374 if (popup_flags & ImGuiPopupFlags_AnyPopupLevel)
11375 return g.OpenPopupStack.Size > 0;
11377 return g.OpenPopupStack.Size >
g.BeginPopupStack.Size;
11381 if (popup_flags & ImGuiPopupFlags_AnyPopupLevel)
11384 for (ImGuiPopupData& popup_data :
g.OpenPopupStack)
11385 if (popup_data.PopupId ==
id)
11392 return g.OpenPopupStack.Size >
g.BeginPopupStack.Size &&
g.OpenPopupStack[
g.BeginPopupStack.Size].PopupId ==
id;
11397bool ImGui::IsPopupOpen(
const char* str_id, ImGuiPopupFlags popup_flags)
11400 ImGuiID
id = (popup_flags & ImGuiPopupFlags_AnyPopupId) ? 0 :
g.CurrentWindow->GetID(str_id);
11401 if ((popup_flags & ImGuiPopupFlags_AnyPopupLevel) &&
id != 0)
11402 IM_ASSERT(0 &&
"Cannot use IsPopupOpen() with a string id and ImGuiPopupFlags_AnyPopupLevel.");
11403 return IsPopupOpen(
id, popup_flags);
11407ImGuiWindow* ImGui::GetTopMostPopupModal()
11410 for (
int n =
g.OpenPopupStack.Size - 1; n >= 0; n--)
11411 if (ImGuiWindow* popup =
g.OpenPopupStack.Data[n].Window)
11412 if (popup->Flags & ImGuiWindowFlags_Modal)
11418ImGuiWindow* ImGui::GetTopMostAndVisiblePopupModal()
11421 for (
int n =
g.OpenPopupStack.Size - 1; n >= 0; n--)
11422 if (ImGuiWindow* popup =
g.OpenPopupStack.Data[n].Window)
11423 if ((popup->Flags & ImGuiWindowFlags_Modal) && IsWindowActiveAndVisible(popup))
11428void ImGui::OpenPopup(
const char* str_id, ImGuiPopupFlags popup_flags)
11431 ImGuiID
id =
g.CurrentWindow->GetID(str_id);
11432 IMGUI_DEBUG_LOG_POPUP(
"[popup] OpenPopup(\"%s\" -> 0x%08X)\n", str_id,
id);
11433 OpenPopupEx(
id, popup_flags);
11436void ImGui::OpenPopup(ImGuiID
id, ImGuiPopupFlags popup_flags)
11438 OpenPopupEx(
id, popup_flags);
11445void ImGui::OpenPopupEx(ImGuiID
id, ImGuiPopupFlags popup_flags)
11448 ImGuiWindow* parent_window =
g.CurrentWindow;
11449 const int current_stack_size =
g.BeginPopupStack.Size;
11451 if (popup_flags & ImGuiPopupFlags_NoOpenOverExistingPopup)
11452 if (IsPopupOpen((ImGuiID)0, ImGuiPopupFlags_AnyPopupId))
11455 ImGuiPopupData popup_ref;
11456 popup_ref.PopupId =
id;
11457 popup_ref.Window = NULL;
11458 popup_ref.RestoreNavWindow =
g.NavWindow;
11459 popup_ref.OpenFrameCount =
g.FrameCount;
11460 popup_ref.OpenParentId = parent_window->IDStack.back();
11461 popup_ref.OpenPopupPos = NavCalcPreferredRefPos();
11462 popup_ref.OpenMousePos = IsMousePosValid(&
g.IO.MousePos) ?
g.IO.MousePos : popup_ref.OpenPopupPos;
11464 IMGUI_DEBUG_LOG_POPUP(
"[popup] OpenPopupEx(0x%08X)\n",
id);
11465 if (
g.OpenPopupStack.Size < current_stack_size + 1)
11467 g.OpenPopupStack.push_back(popup_ref);
11475 bool keep_existing =
false;
11476 if (
g.OpenPopupStack[current_stack_size].PopupId ==
id)
11477 if ((
g.OpenPopupStack[current_stack_size].OpenFrameCount ==
g.FrameCount - 1) || (popup_flags & ImGuiPopupFlags_NoReopen))
11478 keep_existing =
true;
11482 g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount;
11487 ClosePopupToLevel(current_stack_size,
true);
11488 g.OpenPopupStack.push_back(popup_ref);
11500void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window,
bool restore_focus_to_window_under_popup)
11503 if (
g.OpenPopupStack.Size == 0)
11508 int popup_count_to_keep = 0;
11512 for (; popup_count_to_keep <
g.OpenPopupStack.Size; popup_count_to_keep++)
11514 ImGuiPopupData& popup =
g.OpenPopupStack[popup_count_to_keep];
11517 IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0);
11527 bool ref_window_is_descendent_of_popup =
false;
11528 for (
int n = popup_count_to_keep; n <
g.OpenPopupStack.Size; n++)
11529 if (ImGuiWindow* popup_window =
g.OpenPopupStack[n].Window)
11531 if (IsWindowWithinBeginStackOf(ref_window, popup_window))
11533 ref_window_is_descendent_of_popup =
true;
11536 if (!ref_window_is_descendent_of_popup)
11540 if (popup_count_to_keep <
g.OpenPopupStack.Size)
11542 IMGUI_DEBUG_LOG_POPUP(
"[popup] ClosePopupsOverWindow(\"%s\")\n", ref_window ? ref_window->Name :
"<NULL>");
11543 ClosePopupToLevel(popup_count_to_keep, restore_focus_to_window_under_popup);
11547void ImGui::ClosePopupsExceptModals()
11551 int popup_count_to_keep;
11552 for (popup_count_to_keep =
g.OpenPopupStack.Size; popup_count_to_keep > 0; popup_count_to_keep--)
11554 ImGuiWindow* window =
g.OpenPopupStack[popup_count_to_keep - 1].Window;
11555 if (!window || (window->Flags & ImGuiWindowFlags_Modal))
11558 if (popup_count_to_keep <
g.OpenPopupStack.Size)
11559 ClosePopupToLevel(popup_count_to_keep,
true);
11562void ImGui::ClosePopupToLevel(
int remaining,
bool restore_focus_to_window_under_popup)
11565 IMGUI_DEBUG_LOG_POPUP(
"[popup] ClosePopupToLevel(%d), restore_under=%d\n", remaining, restore_focus_to_window_under_popup);
11566 IM_ASSERT(remaining >= 0 && remaining <
g.OpenPopupStack.Size);
11569 ImGuiPopupData prev_popup =
g.OpenPopupStack[remaining];
11570 g.OpenPopupStack.resize(remaining);
11573 if (restore_focus_to_window_under_popup && prev_popup.Window)
11575 ImGuiWindow* popup_window = prev_popup.Window;
11576 ImGuiWindow* focus_window = (popup_window->Flags & ImGuiWindowFlags_ChildMenu) ? popup_window->ParentWindow : prev_popup.RestoreNavWindow;
11577 if (focus_window && !focus_window->WasActive)
11578 FocusTopMostWindowUnderOne(popup_window, NULL, NULL, ImGuiFocusRequestFlags_RestoreFocusedChild);
11580 FocusWindow(focus_window, (
g.NavLayer == ImGuiNavLayer_Main) ? ImGuiFocusRequestFlags_RestoreFocusedChild : ImGuiFocusRequestFlags_None);
11585void ImGui::CloseCurrentPopup()
11588 int popup_idx =
g.BeginPopupStack.Size - 1;
11589 if (popup_idx < 0 || popup_idx >=
g.OpenPopupStack.Size ||
g.BeginPopupStack[popup_idx].PopupId !=
g.OpenPopupStack[popup_idx].PopupId)
11593 while (popup_idx > 0)
11595 ImGuiWindow* popup_window =
g.OpenPopupStack[popup_idx].Window;
11596 ImGuiWindow* parent_popup_window =
g.OpenPopupStack[popup_idx - 1].Window;
11597 bool close_parent =
false;
11598 if (popup_window && (popup_window->Flags & ImGuiWindowFlags_ChildMenu))
11599 if (parent_popup_window && !(parent_popup_window->Flags & ImGuiWindowFlags_MenuBar))
11600 close_parent =
true;
11605 IMGUI_DEBUG_LOG_POPUP(
"[popup] CloseCurrentPopup %d -> %d\n",
g.BeginPopupStack.Size - 1, popup_idx);
11606 ClosePopupToLevel(popup_idx,
true);
11611 if (ImGuiWindow* window =
g.NavWindow)
11612 window->DC.NavHideHighlightOneFrame =
true;
11616bool ImGui::BeginPopupEx(ImGuiID
id, ImGuiWindowFlags flags)
11619 if (!IsPopupOpen(
id, ImGuiPopupFlags_None))
11621 g.NextWindowData.ClearFlags();
11626 if (flags & ImGuiWindowFlags_ChildMenu)
11627 ImFormatString(name, IM_ARRAYSIZE(name),
"##Menu_%02d",
g.BeginMenuDepth);
11631 flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoDocking;
11632 bool is_open = Begin(name, NULL, flags);
11641bool ImGui::BeginPopup(
const char* str_id, ImGuiWindowFlags flags)
11644 if (
g.OpenPopupStack.Size <=
g.BeginPopupStack.Size)
11646 g.NextWindowData.ClearFlags();
11649 flags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings;
11650 ImGuiID
id =
g.CurrentWindow->GetID(str_id);
11651 return BeginPopupEx(
id, flags);
11658bool ImGui::BeginPopupModal(
const char* name,
bool* p_open, ImGuiWindowFlags flags)
11661 ImGuiWindow* window =
g.CurrentWindow;
11662 const ImGuiID
id = window->GetID(name);
11663 if (!IsPopupOpen(
id, ImGuiPopupFlags_None))
11665 g.NextWindowData.ClearFlags();
11666 if (p_open && *p_open)
11674 if ((
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0)
11676 const ImGuiViewport* viewport = window->WasActive ? window->Viewport : GetMainViewport();
11677 SetNextWindowPos(viewport->GetCenter(), ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f));
11680 flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDocking;
11681 const bool is_open = Begin(name, p_open, flags);
11682 if (!is_open || (p_open && !*p_open))
11686 ClosePopupToLevel(
g.BeginPopupStack.Size,
true);
11692void ImGui::EndPopup()
11695 ImGuiWindow* window =
g.CurrentWindow;
11696 IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup);
11697 IM_ASSERT(
g.BeginPopupStack.Size > 0);
11700 if (
g.NavWindow == window)
11701 NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY);
11704 IM_ASSERT(
g.WithinEndChild ==
false);
11705 if (window->Flags & ImGuiWindowFlags_ChildWindow)
11706 g.WithinEndChild =
true;
11708 g.WithinEndChild =
false;
11713void ImGui::OpenPopupOnItemClick(
const char* str_id, ImGuiPopupFlags popup_flags)
11716 ImGuiWindow* window =
g.CurrentWindow;
11717 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
11718 if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
11720 ImGuiID
id = str_id ? window->GetID(str_id) :
g.LastItemData.ID;
11721 IM_ASSERT(
id != 0);
11722 OpenPopupEx(
id, popup_flags);
11742bool ImGui::BeginPopupContextItem(
const char* str_id, ImGuiPopupFlags popup_flags)
11745 ImGuiWindow* window =
g.CurrentWindow;
11746 if (window->SkipItems)
11748 ImGuiID
id = str_id ? window->GetID(str_id) :
g.LastItemData.ID;
11749 IM_ASSERT(
id != 0);
11750 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
11751 if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
11752 OpenPopupEx(
id, popup_flags);
11753 return BeginPopupEx(
id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
11756bool ImGui::BeginPopupContextWindow(
const char* str_id, ImGuiPopupFlags popup_flags)
11759 ImGuiWindow* window =
g.CurrentWindow;
11761 str_id =
"window_context";
11762 ImGuiID
id = window->GetID(str_id);
11763 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
11764 if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
11765 if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
11766 OpenPopupEx(
id, popup_flags);
11767 return BeginPopupEx(
id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
11770bool ImGui::BeginPopupContextVoid(
const char* str_id, ImGuiPopupFlags popup_flags)
11773 ImGuiWindow* window =
g.CurrentWindow;
11775 str_id =
"void_context";
11776 ImGuiID
id = window->GetID(str_id);
11777 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
11778 if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
11779 if (GetTopMostPopupModal() == NULL)
11780 OpenPopupEx(
id, popup_flags);
11781 return BeginPopupEx(
id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
11789ImVec2 ImGui::FindBestWindowPosForPopupEx(
const ImVec2& ref_pos,
const ImVec2& size, ImGuiDir* last_dir,
const ImRect& r_outer,
const ImRect& r_avoid, ImGuiPopupPositionPolicy policy)
11791 ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size);
11796 if (policy == ImGuiPopupPositionPolicy_ComboBox)
11798 const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Down, ImGuiDir_Right, ImGuiDir_Left, ImGuiDir_Up };
11799 for (
int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
11801 const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
11802 if (n != -1 && dir == *last_dir)
11805 if (dir == ImGuiDir_Down) pos = ImVec2(r_avoid.Min.x, r_avoid.Max.y);
11806 if (dir == ImGuiDir_Right) pos = ImVec2(r_avoid.Min.x, r_avoid.Min.y -
size.y);
11807 if (dir == ImGuiDir_Left) pos = ImVec2(r_avoid.Max.x -
size.x, r_avoid.Max.y);
11808 if (dir == ImGuiDir_Up) pos = ImVec2(r_avoid.Max.x -
size.x, r_avoid.Min.y -
size.y);
11809 if (!r_outer.Contains(ImRect(pos, pos + size)))
11818 if (policy == ImGuiPopupPositionPolicy_Tooltip || policy == ImGuiPopupPositionPolicy_Default)
11820 const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left };
11821 for (
int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
11823 const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
11824 if (n != -1 && dir == *last_dir)
11827 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);
11828 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);
11831 if (avail_w <
size.x && (dir == ImGuiDir_Left || dir == ImGuiDir_Right))
11833 if (avail_h <
size.y && (dir == ImGuiDir_Up || dir == ImGuiDir_Down))
11837 pos.x = (dir == ImGuiDir_Left) ? r_avoid.Min.x -
size.x : (dir == ImGuiDir_Right) ? r_avoid.Max.x : base_pos_clamped.x;
11838 pos.y = (dir == ImGuiDir_Up) ? r_avoid.Min.y -
size.y : (dir == ImGuiDir_Down) ? r_avoid.Max.y : base_pos_clamped.y;
11841 pos.x = ImMax(pos.x, r_outer.Min.x);
11842 pos.y = ImMax(pos.y, r_outer.Min.y);
11850 *last_dir = ImGuiDir_None;
11853 if (policy == ImGuiPopupPositionPolicy_Tooltip)
11854 return ref_pos + ImVec2(2, 2);
11857 ImVec2 pos = ref_pos;
11858 pos.x = ImMax(ImMin(pos.x +
size.x, r_outer.Max.x) -
size.x, r_outer.Min.x);
11859 pos.y = ImMax(ImMin(pos.y +
size.y, r_outer.Max.y) -
size.y, r_outer.Min.y);
11864ImRect ImGui::GetPopupAllowedExtentRect(ImGuiWindow* window)
11868 if (window->ViewportAllowPlatformMonitorExtend >= 0)
11871 const ImGuiPlatformMonitor& monitor =
g.PlatformIO.Monitors[window->ViewportAllowPlatformMonitorExtend];
11872 r_screen.Min = monitor.WorkPos;
11873 r_screen.Max = monitor.WorkPos + monitor.WorkSize;
11878 r_screen = window->Viewport->GetMainRect();
11880 ImVec2 padding =
g.Style.DisplaySafeAreaPadding;
11881 r_screen.Expand(ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f, (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f));
11885ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
11889 ImRect r_outer = GetPopupAllowedExtentRect(window);
11890 if (window->Flags & ImGuiWindowFlags_ChildMenu)
11894 ImGuiWindow* parent_window = window->ParentWindow;
11895 float horizontal_overlap =
g.Style.ItemInnerSpacing.x;
11897 if (parent_window->DC.MenuBarAppending)
11898 r_avoid = ImRect(-FLT_MAX, parent_window->ClipRect.Min.y, FLT_MAX, parent_window->ClipRect.Max.y);
11900 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);
11901 return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Default);
11903 if (window->Flags & ImGuiWindowFlags_Popup)
11905 return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, ImRect(window->Pos, window->Pos), ImGuiPopupPositionPolicy_Default);
11907 if (window->Flags & ImGuiWindowFlags_Tooltip)
11912 IM_ASSERT(
g.CurrentWindow == window);
11913 const float scale =
g.Style.MouseCursorScale;
11914 const ImVec2 ref_pos = NavCalcPreferredRefPos();
11915 const ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET *
scale;
11917 if (!
g.NavDisableHighlight &&
g.NavDisableMouseHover && !(
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos))
11918 r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
11920 r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * scale, ref_pos.y + 24 * scale);
11922 return FindBestWindowPosForPopupEx(tooltip_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Tooltip);
11925 return window->Pos;
11936void ImGui::SetNavWindow(ImGuiWindow* window)
11939 if (
g.NavWindow != window)
11941 IMGUI_DEBUG_LOG_FOCUS(
"[focus] SetNavWindow(\"%s\")\n", window ? window->Name :
"<NULL>");
11942 g.NavWindow = window;
11943 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
11945 g.NavInitRequest =
g.NavMoveSubmitted =
g.NavMoveScoringItems =
false;
11946 NavUpdateAnyRequestFlag();
11949void ImGui::NavHighlightActivated(ImGuiID
id)
11952 g.NavHighlightActivatedId =
id;
11953 g.NavHighlightActivatedTimer = NAV_ACTIVATE_HIGHLIGHT_TIMER;
11956void ImGui::NavClearPreferredPosForAxis(ImGuiAxis axis)
11959 g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[
g.NavLayer][axis] = FLT_MAX;
11962void ImGui::SetNavID(ImGuiID
id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id,
const ImRect& rect_rel)
11965 IM_ASSERT(
g.NavWindow != NULL);
11966 IM_ASSERT(nav_layer == ImGuiNavLayer_Main || nav_layer == ImGuiNavLayer_Menu);
11968 g.NavLayer = nav_layer;
11969 SetNavFocusScope(focus_scope_id);
11970 g.NavWindow->NavLastIds[nav_layer] =
id;
11971 g.NavWindow->NavRectRel[nav_layer] = rect_rel;
11974 NavClearPreferredPosForAxis(ImGuiAxis_X);
11975 NavClearPreferredPosForAxis(ImGuiAxis_Y);
11978void ImGui::SetFocusID(ImGuiID
id, ImGuiWindow* window)
11981 IM_ASSERT(
id != 0);
11983 if (
g.NavWindow != window)
11984 SetNavWindow(window);
11988 const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent;
11990 g.NavLayer = nav_layer;
11991 SetNavFocusScope(
g.CurrentFocusScopeId);
11992 window->NavLastIds[nav_layer] =
id;
11993 if (
g.LastItemData.ID ==
id)
11994 window->NavRectRel[nav_layer] = WindowRectAbsToRel(window,
g.LastItemData.NavRect);
11996 if (
g.ActiveIdSource == ImGuiInputSource_Keyboard ||
g.ActiveIdSource == ImGuiInputSource_Gamepad)
11997 g.NavDisableMouseHover =
true;
11999 g.NavDisableHighlight =
true;
12002 NavClearPreferredPosForAxis(ImGuiAxis_X);
12003 NavClearPreferredPosForAxis(ImGuiAxis_Y);
12006static ImGuiDir ImGetDirQuadrantFromDelta(
float dx,
float dy)
12008 if (ImFabs(dx) > ImFabs(dy))
12009 return (dx > 0.0f) ? ImGuiDir_Right : ImGuiDir_Left;
12010 return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up;
12013static float inline NavScoreItemDistInterval(
float cand_min,
float cand_max,
float curr_min,
float curr_max)
12015 if (cand_max < curr_min)
12016 return cand_max - curr_min;
12017 if (curr_max < cand_min)
12018 return cand_min - curr_max;
12023static bool ImGui::NavScoreItem(ImGuiNavItemData* result)
12026 ImGuiWindow* window =
g.CurrentWindow;
12027 if (
g.NavLayer != window->DC.NavLayerCurrent)
12031 ImRect cand =
g.LastItemData.NavRect;
12032 const ImRect curr =
g.NavScoringRect;
12033 g.NavScoringDebugCount++;
12036 if (window->ParentWindow ==
g.NavWindow)
12038 IM_ASSERT((window->Flags |
g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened);
12039 if (!window->ClipRect.Overlaps(cand))
12041 cand.ClipWithFull(window->ClipRect);
12046 float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x);
12047 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));
12048 if (dby != 0.0f && dbx != 0.0f)
12049 dbx = (dbx / 1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f);
12050 float dist_box = ImFabs(dbx) + ImFabs(dby);
12053 float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x);
12054 float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y);
12055 float dist_center = ImFabs(dcx) + ImFabs(dcy);
12059 float dax = 0.0f, day = 0.0f, dist_axial = 0.0f;
12060 if (dbx != 0.0f || dby != 0.0f)
12065 dist_axial = dist_box;
12066 quadrant = ImGetDirQuadrantFromDelta(dbx, dby);
12068 else if (dcx != 0.0f || dcy != 0.0f)
12073 dist_axial = dist_center;
12074 quadrant = ImGetDirQuadrantFromDelta(dcx, dcy);
12079 quadrant = (
g.LastItemData.ID <
g.NavId) ? ImGuiDir_Left : ImGuiDir_Right;
12082 const ImGuiDir move_dir =
g.NavMoveDir;
12083#if IMGUI_DEBUG_NAV_SCORING
12087 if (quadrant == move_dir)
12089 ImFormatString(buf, IM_ARRAYSIZE(buf),
"%.0f/%.0f", dist_box, dist_center);
12090 ImDrawList* draw_list = GetForegroundDrawList(window);
12091 draw_list->AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 80));
12092 draw_list->AddRectFilled(cand.Min, cand.Min +
CalcTextSize(buf), IM_COL32(255, 0, 0, 200));
12093 draw_list->AddText(cand.Min, IM_COL32(255, 255, 255, 255), buf);
12096 const bool debug_hovering = IsMouseHoveringRect(cand.Min, cand.Max);
12097 const bool debug_tty = (
g.IO.KeyCtrl && IsKeyPressed(ImGuiKey_Space));
12098 if (debug_hovering || debug_tty)
12101 "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",
12102 dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial,
"-WENS"[move_dir+1],
"-WENS"[quadrant+1]);
12103 if (debug_hovering)
12105 ImDrawList* draw_list = GetForegroundDrawList(window);
12106 draw_list->AddRect(curr.Min, curr.Max, IM_COL32(255, 200, 0, 100));
12107 draw_list->AddRect(cand.Min, cand.Max, IM_COL32(255, 255, 0, 200));
12108 draw_list->AddRectFilled(cand.Max - ImVec2(4, 4), cand.Max +
CalcTextSize(buf) + ImVec2(4, 4), IM_COL32(40, 0, 0, 200));
12109 draw_list->AddText(cand.Max, ~0U, buf);
12111 if (debug_tty) { IMGUI_DEBUG_LOG_NAV(
"id 0x%08X\n%s\n",
g.LastItemData.ID, buf); }
12116 bool new_best =
false;
12117 if (quadrant == move_dir)
12120 if (dist_box < result->DistBox)
12122 result->DistBox = dist_box;
12123 result->DistCenter = dist_center;
12126 if (dist_box == result->DistBox)
12129 if (dist_center < result->DistCenter)
12131 result->DistCenter = dist_center;
12134 else if (dist_center == result->DistCenter)
12139 if (((move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) ? dby : dbx) < 0.0f)
12150 if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial)
12151 if (
g.NavLayer == ImGuiNavLayer_Menu && !(
g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
12152 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))
12154 result->DistAxial = dist_axial;
12161static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result)
12164 ImGuiWindow* window =
g.CurrentWindow;
12165 result->Window = window;
12166 result->ID =
g.LastItemData.ID;
12167 result->FocusScopeId =
g.CurrentFocusScopeId;
12168 result->InFlags =
g.LastItemData.InFlags;
12169 result->RectRel = WindowRectAbsToRel(window,
g.LastItemData.NavRect);
12170 if (result->InFlags & ImGuiItemFlags_HasSelectionUserData)
12172 IM_ASSERT(
g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
12173 result->SelectionUserData =
g.NextItemData.SelectionUserData;
12179void ImGui::NavUpdateCurrentWindowIsScrollPushableX()
12182 ImGuiWindow* window =
g.CurrentWindow;
12183 window->DC.NavIsScrollPushableX = (
g.CurrentTable == NULL && window->DC.CurrentColumns == NULL);
12188static void ImGui::NavProcessItem()
12191 ImGuiWindow* window =
g.CurrentWindow;
12192 const ImGuiID
id =
g.LastItemData.ID;
12193 const ImGuiItemFlags item_flags =
g.LastItemData.InFlags;
12196 if (window->DC.NavIsScrollPushableX ==
false)
12198 g.LastItemData.NavRect.Min.x = ImClamp(
g.LastItemData.NavRect.Min.x, window->ClipRect.Min.x, window->ClipRect.Max.x);
12199 g.LastItemData.NavRect.Max.x = ImClamp(
g.LastItemData.NavRect.Max.x, window->ClipRect.Min.x, window->ClipRect.Max.x);
12201 const ImRect nav_bb =
g.LastItemData.NavRect;
12204 if (
g.NavInitRequest &&
g.NavLayer == window->DC.NavLayerCurrent && (item_flags & ImGuiItemFlags_Disabled) == 0)
12207 const bool candidate_for_nav_default_focus = (item_flags & ImGuiItemFlags_NoNavDefaultFocus) == 0;
12208 if (candidate_for_nav_default_focus ||
g.NavInitResult.ID == 0)
12210 NavApplyItemToResult(&
g.NavInitResult);
12212 if (candidate_for_nav_default_focus)
12214 g.NavInitRequest =
false;
12215 NavUpdateAnyRequestFlag();
12221 if (
g.NavMoveScoringItems && (item_flags & ImGuiItemFlags_Disabled) == 0)
12223 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_FocusApi) || (window->Flags & ImGuiWindowFlags_NoNavInputs) == 0)
12225 const bool is_tabbing = (
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0;
12228 NavProcessItemForTabbingRequest(
id, item_flags,
g.NavMoveFlags);
12230 else if (
g.NavId !=
id || (
g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId))
12232 ImGuiNavItemData* result = (window ==
g.NavWindow) ? &
g.NavMoveResultLocal : &
g.NavMoveResultOther;
12233 if (NavScoreItem(result))
12234 NavApplyItemToResult(result);
12237 const float VISIBLE_RATIO = 0.70f;
12238 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb))
12239 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)
12240 if (NavScoreItem(&
g.NavMoveResultLocalVisible))
12241 NavApplyItemToResult(&
g.NavMoveResultLocalVisible);
12249 if (
g.NavWindow != window)
12250 SetNavWindow(window);
12251 g.NavLayer = window->DC.NavLayerCurrent;
12252 SetNavFocusScope(
g.CurrentFocusScopeId);
12253 g.NavFocusScopeId =
g.CurrentFocusScopeId;
12254 g.NavIdIsAlive =
true;
12255 if (
g.LastItemData.InFlags & ImGuiItemFlags_HasSelectionUserData)
12257 IM_ASSERT(
g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
12258 g.NavLastValidSelectionUserData =
g.NextItemData.SelectionUserData;
12260 window->NavRectRel[window->DC.NavLayerCurrent] = WindowRectAbsToRel(window, nav_bb);
12271void ImGui::NavProcessItemForTabbingRequest(ImGuiID
id, ImGuiItemFlags item_flags, ImGuiNavMoveFlags move_flags)
12275 if ((move_flags & ImGuiNavMoveFlags_FocusApi) == 0)
12277 if (
g.NavLayer !=
g.CurrentWindow->DC.NavLayerCurrent)
12279 if (
g.NavFocusScopeId !=
g.CurrentFocusScopeId)
12287 if (move_flags & ImGuiNavMoveFlags_FocusApi)
12290 can_stop = (item_flags & ImGuiItemFlags_NoTabStop) == 0 && ((
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) || (item_flags & ImGuiItemFlags_Inputable));
12293 ImGuiNavItemData* result = &
g.NavMoveResultLocal;
12294 if (
g.NavTabbingDir == +1)
12297 if (can_stop &&
g.NavTabbingResultFirst.ID == 0)
12298 NavApplyItemToResult(&
g.NavTabbingResultFirst);
12299 if (can_stop &&
g.NavTabbingCounter > 0 && --
g.NavTabbingCounter == 0)
12300 NavMoveRequestResolveWithLastItem(result);
12301 else if (
g.NavId ==
id)
12302 g.NavTabbingCounter = 1;
12304 else if (
g.NavTabbingDir == -1)
12311 g.NavMoveScoringItems =
false;
12312 NavUpdateAnyRequestFlag();
12318 NavApplyItemToResult(result);
12321 else if (
g.NavTabbingDir == 0)
12323 if (can_stop &&
g.NavId ==
id)
12324 NavMoveRequestResolveWithLastItem(result);
12325 if (can_stop &&
g.NavTabbingResultFirst.ID == 0)
12326 NavApplyItemToResult(&
g.NavTabbingResultFirst);
12330bool ImGui::NavMoveRequestButNoResultYet()
12333 return g.NavMoveScoringItems &&
g.NavMoveResultLocal.ID == 0 &&
g.NavMoveResultOther.ID == 0;
12337void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags)
12340 IM_ASSERT(
g.NavWindow != NULL);
12342 if (move_flags & ImGuiNavMoveFlags_IsTabbing)
12343 move_flags |= ImGuiNavMoveFlags_AllowCurrentNavId;
12345 g.NavMoveSubmitted =
g.NavMoveScoringItems =
true;
12346 g.NavMoveDir = move_dir;
12347 g.NavMoveDirForDebug = move_dir;
12348 g.NavMoveClipDir = clip_dir;
12349 g.NavMoveFlags = move_flags;
12350 g.NavMoveScrollFlags = scroll_flags;
12351 g.NavMoveForwardToNextFrame =
false;
12352 g.NavMoveKeyMods = (move_flags & ImGuiNavMoveFlags_FocusApi) ? 0 :
g.IO.KeyMods;
12353 g.NavMoveResultLocal.Clear();
12354 g.NavMoveResultLocalVisible.Clear();
12355 g.NavMoveResultOther.Clear();
12356 g.NavTabbingCounter = 0;
12357 g.NavTabbingResultFirst.Clear();
12358 NavUpdateAnyRequestFlag();
12361void ImGui::NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result)
12364 g.NavMoveScoringItems =
false;
12365 NavApplyItemToResult(result);
12366 NavUpdateAnyRequestFlag();
12370void ImGui::NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiNavTreeNodeData* tree_node_data)
12373 g.NavMoveScoringItems =
false;
12374 g.LastItemData.ID = tree_node_data->ID;
12375 g.LastItemData.InFlags = tree_node_data->InFlags & ~ImGuiItemFlags_HasSelectionUserData;
12376 g.LastItemData.NavRect = tree_node_data->NavRect;
12377 NavApplyItemToResult(result);
12378 NavClearPreferredPosForAxis(ImGuiAxis_Y);
12379 NavUpdateAnyRequestFlag();
12382void ImGui::NavMoveRequestCancel()
12385 g.NavMoveSubmitted =
g.NavMoveScoringItems =
false;
12386 NavUpdateAnyRequestFlag();
12390void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags)
12393 IM_ASSERT(
g.NavMoveForwardToNextFrame ==
false);
12394 NavMoveRequestCancel();
12395 g.NavMoveForwardToNextFrame =
true;
12396 g.NavMoveDir = move_dir;
12397 g.NavMoveClipDir = clip_dir;
12398 g.NavMoveFlags = move_flags | ImGuiNavMoveFlags_Forwarded;
12399 g.NavMoveScrollFlags = scroll_flags;
12404void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags wrap_flags)
12407 IM_ASSERT((wrap_flags & ImGuiNavMoveFlags_WrapMask_ ) != 0 && (wrap_flags & ~ImGuiNavMoveFlags_WrapMask_) == 0);
12411 if (
g.NavWindow == window &&
g.NavMoveScoringItems &&
g.NavLayer == ImGuiNavLayer_Main)
12412 g.NavMoveFlags = (
g.NavMoveFlags & ~ImGuiNavMoveFlags_WrapMask_) | wrap_flags;
12417static void ImGui::NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window)
12419 ImGuiWindow* parent = nav_window;
12420 while (parent && parent->RootWindow != parent && (parent->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
12421 parent = parent->ParentWindow;
12422 if (parent && parent != nav_window)
12423 parent->NavLastChildNavWindow = nav_window;
12428static ImGuiWindow* ImGui::NavRestoreLastChildNavWindow(ImGuiWindow* window)
12430 if (window->NavLastChildNavWindow && window->NavLastChildNavWindow->WasActive)
12431 return window->NavLastChildNavWindow;
12432 if (window->DockNodeAsHost && window->DockNodeAsHost->TabBar)
12433 if (ImGuiTabItem* tab = TabBarFindMostRecentlySelectedTabForActiveWindow(window->DockNodeAsHost->TabBar))
12434 return tab->Window;
12438void ImGui::NavRestoreLayer(ImGuiNavLayer layer)
12441 if (layer == ImGuiNavLayer_Main)
12443 ImGuiWindow* prev_nav_window =
g.NavWindow;
12444 g.NavWindow = NavRestoreLastChildNavWindow(
g.NavWindow);
12445 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
12446 if (prev_nav_window)
12447 IMGUI_DEBUG_LOG_FOCUS(
"[focus] NavRestoreLayer: from \"%s\" to SetNavWindow(\"%s\")\n", prev_nav_window->Name,
g.NavWindow->Name);
12449 ImGuiWindow* window =
g.NavWindow;
12450 if (window->NavLastIds[layer] != 0)
12452 SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
12456 g.NavLayer = layer;
12457 NavInitWindow(window,
true);
12461void ImGui::NavRestoreHighlightAfterMove()
12464 g.NavDisableHighlight =
false;
12465 g.NavDisableMouseHover =
g.NavMousePosDirty =
true;
12468static inline void ImGui::NavUpdateAnyRequestFlag()
12472 if (
g.NavAnyRequest)
12473 IM_ASSERT(
g.NavWindow != NULL);
12477void ImGui::NavInitWindow(ImGuiWindow* window,
bool force_reinit)
12481 IM_ASSERT(window ==
g.NavWindow);
12483 if (window->Flags & ImGuiWindowFlags_NoNavInputs)
12486 SetNavFocusScope(window->NavRootFocusScopeId);
12490 bool init_for_nav =
false;
12491 if (window == window->RootWindow || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
12492 init_for_nav =
true;
12493 IMGUI_DEBUG_LOG_NAV(
"[nav] NavInitRequest: from NavInitWindow(), init_for_nav=%d, window=\"%s\", layer=%d\n", init_for_nav, window->Name,
g.NavLayer);
12496 SetNavID(0,
g.NavLayer, window->NavRootFocusScopeId, ImRect());
12497 g.NavInitRequest =
true;
12498 g.NavInitRequestFromMove =
false;
12499 g.NavInitResult.ID = 0;
12500 NavUpdateAnyRequestFlag();
12504 g.NavId = window->NavLastIds[0];
12505 SetNavFocusScope(window->NavRootFocusScopeId);
12509static ImVec2 ImGui::NavCalcPreferredRefPos()
12512 ImGuiWindow* window =
g.NavWindow;
12513 if (
g.NavDisableHighlight || !
g.NavDisableMouseHover || !window)
12518 ImVec2 p = IsMousePosValid(&
g.IO.MousePos) ?
g.IO.MousePos :
g.MouseLastValidPos;
12519 return ImVec2(p.x + 1.0f, p.y);
12525 ImRect rect_rel = WindowRectRelToAbs(window, window->NavRectRel[
g.NavLayer]);
12526 if (window->LastFrameActive !=
g.FrameCount && (window->ScrollTarget.x != FLT_MAX || window->ScrollTarget.y != FLT_MAX))
12528 ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
12529 rect_rel.Translate(window->Scroll - next_scroll);
12531 ImVec2 pos = ImVec2(rect_rel.Min.x + ImMin(
g.Style.FramePadding.x * 4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(
g.Style.FramePadding.y, rect_rel.GetHeight()));
12532 ImGuiViewport* viewport = window->Viewport;
12533 return ImTrunc(ImClamp(pos, viewport->Pos, viewport->Pos + viewport->Size));
12537float ImGui::GetNavTweakPressedAmount(ImGuiAxis axis)
12540 float repeat_delay, repeat_rate;
12541 GetTypematicRepeatRate(ImGuiInputFlags_RepeatRateNavTweak, &repeat_delay, &repeat_rate);
12543 ImGuiKey key_less, key_more;
12544 if (
g.NavInputSource == ImGuiInputSource_Gamepad)
12546 key_less = (axis == ImGuiAxis_X) ? ImGuiKey_GamepadDpadLeft : ImGuiKey_GamepadDpadUp;
12547 key_more = (axis == ImGuiAxis_X) ? ImGuiKey_GamepadDpadRight : ImGuiKey_GamepadDpadDown;
12551 key_less = (axis == ImGuiAxis_X) ? ImGuiKey_LeftArrow : ImGuiKey_UpArrow;
12552 key_more = (axis == ImGuiAxis_X) ? ImGuiKey_RightArrow : ImGuiKey_DownArrow;
12554 float amount = (float)GetKeyPressedAmount(key_more, repeat_delay, repeat_rate) - (float)GetKeyPressedAmount(key_less, repeat_delay, repeat_rate);
12555 if (amount != 0.0f && IsKeyDown(key_less) && IsKeyDown(key_more))
12560static void ImGui::NavUpdate()
12563 ImGuiIO& io =
g.IO;
12565 io.WantSetMousePos =
false;
12570 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
12571 const ImGuiKey nav_gamepad_keys_to_change_source[] = { ImGuiKey_GamepadFaceRight, ImGuiKey_GamepadFaceLeft, ImGuiKey_GamepadFaceUp, ImGuiKey_GamepadFaceDown, ImGuiKey_GamepadDpadRight, ImGuiKey_GamepadDpadLeft, ImGuiKey_GamepadDpadUp, ImGuiKey_GamepadDpadDown };
12572 if (nav_gamepad_active)
12573 for (ImGuiKey key : nav_gamepad_keys_to_change_source)
12574 if (IsKeyDown(key))
12575 g.NavInputSource = ImGuiInputSource_Gamepad;
12576 const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
12577 const ImGuiKey nav_keyboard_keys_to_change_source[] = { ImGuiKey_Space, ImGuiKey_Enter, ImGuiKey_Escape, ImGuiKey_RightArrow, ImGuiKey_LeftArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow };
12578 if (nav_keyboard_active)
12579 for (ImGuiKey key : nav_keyboard_keys_to_change_source)
12580 if (IsKeyDown(key))
12581 g.NavInputSource = ImGuiInputSource_Keyboard;
12584 g.NavJustMovedToId = 0;
12585 if (
g.NavInitResult.ID != 0)
12586 NavInitRequestApplyResult();
12587 g.NavInitRequest =
false;
12588 g.NavInitRequestFromMove =
false;
12589 g.NavInitResult.ID = 0;
12592 if (
g.NavMoveSubmitted)
12593 NavMoveRequestApplyResult();
12594 g.NavTabbingCounter = 0;
12595 g.NavMoveSubmitted =
g.NavMoveScoringItems =
false;
12598 bool set_mouse_pos =
false;
12599 if (
g.NavMousePosDirty &&
g.NavIdIsAlive)
12600 if (!
g.NavDisableHighlight &&
g.NavDisableMouseHover &&
g.NavWindow)
12601 set_mouse_pos =
true;
12602 g.NavMousePosDirty =
false;
12603 IM_ASSERT(
g.NavLayer == ImGuiNavLayer_Main ||
g.NavLayer == ImGuiNavLayer_Menu);
12607 NavSaveLastChildNavWindowIntoParent(
g.NavWindow);
12608 if (
g.NavWindow &&
g.NavWindow->NavLastChildNavWindow != NULL &&
g.NavLayer == ImGuiNavLayer_Main)
12609 g.NavWindow->NavLastChildNavWindow = NULL;
12612 NavUpdateWindowing();
12615 io.NavActive = (nav_keyboard_active || nav_gamepad_active) &&
g.NavWindow && !(
g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs);
12616 io.NavVisible = (io.NavActive &&
g.NavId != 0 && !
g.NavDisableHighlight) || (
g.NavWindowingTarget != NULL);
12619 NavUpdateCancelRequest();
12622 g.NavActivateId =
g.NavActivateDownId =
g.NavActivatePressedId = 0;
12623 g.NavActivateFlags = ImGuiActivateFlags_None;
12624 if (
g.NavId != 0 && !
g.NavDisableHighlight && !
g.NavWindowingTarget &&
g.NavWindow && !(
g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
12626 const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space, ImGuiKeyOwner_None)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_None));
12627 const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, ImGuiKeyOwner_None)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_None)));
12628 const bool input_down = (nav_keyboard_active && (IsKeyDown(ImGuiKey_Enter, ImGuiKeyOwner_None) || IsKeyDown(ImGuiKey_KeypadEnter, ImGuiKeyOwner_None))) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput, ImGuiKeyOwner_None));
12629 const bool input_pressed = input_down && ((nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, ImGuiKeyOwner_None) || IsKeyPressed(ImGuiKey_KeypadEnter, ImGuiKeyOwner_None))) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, ImGuiKeyOwner_None)));
12630 if (
g.ActiveId == 0 && activate_pressed)
12632 g.NavActivateId =
g.NavId;
12633 g.NavActivateFlags = ImGuiActivateFlags_PreferTweak;
12635 if ((
g.ActiveId == 0 ||
g.ActiveId ==
g.NavId) && input_pressed)
12637 g.NavActivateId =
g.NavId;
12638 g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
12640 if ((
g.ActiveId == 0 ||
g.ActiveId ==
g.NavId) && (activate_down || input_down))
12641 g.NavActivateDownId =
g.NavId;
12642 if ((
g.ActiveId == 0 ||
g.ActiveId ==
g.NavId) && (activate_pressed || input_pressed))
12644 g.NavActivatePressedId =
g.NavId;
12645 NavHighlightActivated(
g.NavId);
12648 if (
g.NavWindow && (
g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
12649 g.NavDisableHighlight =
true;
12650 if (
g.NavActivateId != 0)
12651 IM_ASSERT(
g.NavActivateDownId ==
g.NavActivateId);
12654 if (
g.NavHighlightActivatedTimer > 0.0f)
12655 g.NavHighlightActivatedTimer = ImMax(0.0f,
g.NavHighlightActivatedTimer - io.DeltaTime);
12656 if (
g.NavHighlightActivatedTimer == 0.0f)
12657 g.NavHighlightActivatedId = 0;
12661 if (
g.NavNextActivateId != 0)
12663 g.NavActivateId =
g.NavActivateDownId =
g.NavActivatePressedId =
g.NavNextActivateId;
12664 g.NavActivateFlags =
g.NavNextActivateFlags;
12666 g.NavNextActivateId = 0;
12669 NavUpdateCreateMoveRequest();
12670 if (
g.NavMoveDir == ImGuiDir_None)
12671 NavUpdateCreateTabbingRequest();
12672 NavUpdateAnyRequestFlag();
12673 g.NavIdIsAlive =
false;
12676 if (
g.NavWindow && !(
g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !
g.NavWindowingTarget)
12679 ImGuiWindow* window =
g.NavWindow;
12680 const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * io.DeltaTime);
12681 const ImGuiDir move_dir =
g.NavMoveDir;
12682 if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavWindowHasScrollY && move_dir != ImGuiDir_None)
12684 if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right)
12685 SetScrollX(window, ImTrunc(window->Scroll.x + ((move_dir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
12686 if (move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down)
12687 SetScrollY(window, ImTrunc(window->Scroll.y + ((move_dir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed));
12692 if (nav_gamepad_active)
12694 const ImVec2 scroll_dir = GetKeyMagnitude2d(ImGuiKey_GamepadLStickLeft, ImGuiKey_GamepadLStickRight, ImGuiKey_GamepadLStickUp, ImGuiKey_GamepadLStickDown);
12695 const float tweak_factor = IsKeyDown(ImGuiKey_NavGamepadTweakSlow) ? 1.0f / 10.0f : IsKeyDown(ImGuiKey_NavGamepadTweakFast) ? 10.0f : 1.0f;
12696 if (scroll_dir.x != 0.0f && window->ScrollbarX)
12697 SetScrollX(window, ImTrunc(window->Scroll.x + scroll_dir.x * scroll_speed * tweak_factor));
12698 if (scroll_dir.y != 0.0f)
12699 SetScrollY(window, ImTrunc(window->Scroll.y + scroll_dir.y * scroll_speed * tweak_factor));
12704 if (!nav_keyboard_active && !nav_gamepad_active)
12706 g.NavDisableHighlight =
true;
12707 g.NavDisableMouseHover = set_mouse_pos =
false;
12712 if (set_mouse_pos && (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
12713 TeleportMousePos(NavCalcPreferredRefPos());
12716 g.NavScoringDebugCount = 0;
12717#if IMGUI_DEBUG_NAV_RECTS
12718 if (ImGuiWindow* debug_window =
g.NavWindow)
12720 ImDrawList* draw_list = GetForegroundDrawList(debug_window);
12721 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)); }
12727void ImGui::NavInitRequestApplyResult()
12734 ImGuiNavItemData* result = &
g.NavInitResult;
12735 if (
g.NavId != result->ID)
12737 g.NavJustMovedToId = result->ID;
12738 g.NavJustMovedToFocusScopeId = result->FocusScopeId;
12739 g.NavJustMovedToKeyMods = 0;
12744 IMGUI_DEBUG_LOG_NAV(
"[nav] NavInitRequest: ApplyResult: NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID,
g.NavLayer,
g.NavWindow->Name);
12745 SetNavID(result->ID,
g.NavLayer, result->FocusScopeId, result->RectRel);
12746 g.NavIdIsAlive =
true;
12747 if (result->SelectionUserData != ImGuiSelectionUserData_Invalid)
12748 g.NavLastValidSelectionUserData = result->SelectionUserData;
12749 if (
g.NavInitRequestFromMove)
12750 NavRestoreHighlightAfterMove();
12754static void NavBiasScoringRect(ImRect& r, ImVec2& preferred_pos_rel, ImGuiDir move_dir, ImGuiNavMoveFlags move_flags)
12758 const ImVec2 rel_to_abs_offset =
g.NavWindow->DC.CursorStartPos;
12763 if ((move_flags & ImGuiNavMoveFlags_Forwarded) == 0)
12765 if (preferred_pos_rel.x == FLT_MAX)
12766 preferred_pos_rel.x = ImMin(r.Min.x + 1.0f, r.Max.x) - rel_to_abs_offset.x;
12767 if (preferred_pos_rel.y == FLT_MAX)
12768 preferred_pos_rel.y = r.GetCenter().y - rel_to_abs_offset.y;
12772 if ((move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) && preferred_pos_rel.x != FLT_MAX)
12773 r.Min.x = r.Max.x = preferred_pos_rel.x + rel_to_abs_offset.x;
12774 else if ((move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right) && preferred_pos_rel.y != FLT_MAX)
12775 r.Min.y = r.Max.y = preferred_pos_rel.y + rel_to_abs_offset.y;
12778void ImGui::NavUpdateCreateMoveRequest()
12781 ImGuiIO& io =
g.IO;
12782 ImGuiWindow* window =
g.NavWindow;
12783 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
12784 const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
12786 if (
g.NavMoveForwardToNextFrame && window != NULL)
12790 IM_ASSERT(
g.NavMoveDir != ImGuiDir_None &&
g.NavMoveClipDir != ImGuiDir_None);
12791 IM_ASSERT(
g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded);
12792 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveRequestForward %d\n",
g.NavMoveDir);
12797 g.NavMoveDir = ImGuiDir_None;
12798 g.NavMoveFlags = ImGuiNavMoveFlags_None;
12799 g.NavMoveScrollFlags = ImGuiScrollFlags_None;
12800 if (window && !
g.NavWindowingTarget && !(window->Flags & ImGuiWindowFlags_NoNavInputs))
12802 const ImGuiInputFlags repeat_mode = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateNavMove;
12803 if (!IsActiveIdUsingNavDir(ImGuiDir_Left) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadLeft, ImGuiKeyOwner_None, repeat_mode)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_LeftArrow, ImGuiKeyOwner_None, repeat_mode)))) {
g.NavMoveDir = ImGuiDir_Left; }
12804 if (!IsActiveIdUsingNavDir(ImGuiDir_Right) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadRight, ImGuiKeyOwner_None, repeat_mode)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_RightArrow, ImGuiKeyOwner_None, repeat_mode)))) {
g.NavMoveDir = ImGuiDir_Right; }
12805 if (!IsActiveIdUsingNavDir(ImGuiDir_Up) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadUp, ImGuiKeyOwner_None, repeat_mode)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_UpArrow, ImGuiKeyOwner_None, repeat_mode)))) {
g.NavMoveDir = ImGuiDir_Up; }
12806 if (!IsActiveIdUsingNavDir(ImGuiDir_Down) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadDown, ImGuiKeyOwner_None, repeat_mode)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_DownArrow, ImGuiKeyOwner_None, repeat_mode)))) {
g.NavMoveDir = ImGuiDir_Down; }
12808 g.NavMoveClipDir =
g.NavMoveDir;
12809 g.NavScoringNoClipRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
12814 float scoring_rect_offset_y = 0.0f;
12815 if (window &&
g.NavMoveDir == ImGuiDir_None && nav_keyboard_active)
12816 scoring_rect_offset_y = NavUpdatePageUpPageDown();
12817 if (scoring_rect_offset_y != 0.0f)
12819 g.NavScoringNoClipRect = window->InnerRect;
12820 g.NavScoringNoClipRect.TranslateY(scoring_rect_offset_y);
12824#if IMGUI_DEBUG_NAV_SCORING
12829 if (
g.NavMoveDir == ImGuiDir_None)
12830 g.NavMoveDir =
g.NavMoveDirForDebug;
12831 g.NavMoveClipDir =
g.NavMoveDir;
12832 g.NavMoveFlags |= ImGuiNavMoveFlags_DebugNoResult;
12837 g.NavMoveForwardToNextFrame =
false;
12838 if (
g.NavMoveDir != ImGuiDir_None)
12839 NavMoveRequestSubmit(
g.NavMoveDir,
g.NavMoveClipDir,
g.NavMoveFlags,
g.NavMoveScrollFlags);
12842 if (
g.NavMoveSubmitted &&
g.NavId == 0)
12844 IMGUI_DEBUG_LOG_NAV(
"[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", window ? window->Name :
"<NULL>",
g.NavLayer);
12845 g.NavInitRequest =
g.NavInitRequestFromMove =
true;
12846 g.NavInitResult.ID = 0;
12847 g.NavDisableHighlight =
false;
12853 if (
g.NavMoveSubmitted &&
g.NavInputSource == ImGuiInputSource_Gamepad &&
g.NavLayer == ImGuiNavLayer_Main && window != NULL)
12855 bool clamp_x = (
g.NavMoveFlags & (ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_WrapX)) == 0;
12856 bool clamp_y = (
g.NavMoveFlags & (ImGuiNavMoveFlags_LoopY | ImGuiNavMoveFlags_WrapY)) == 0;
12857 ImRect inner_rect_rel = WindowRectAbsToRel(window, ImRect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1)));
12861 inner_rect_rel.Translate(CalcNextScrollFromScrollTargetAndClamp(window) - window->Scroll);
12863 if ((clamp_x || clamp_y) && !inner_rect_rel.Contains(window->NavRectRel[
g.NavLayer]))
12865 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveRequest: clamp NavRectRel for gamepad move\n");
12866 float pad_x = ImMin(inner_rect_rel.GetWidth(), window->CalcFontSize() * 0.5f);
12867 float pad_y = ImMin(inner_rect_rel.GetHeight(), window->CalcFontSize() * 0.5f);
12868 inner_rect_rel.Min.x = clamp_x ? (inner_rect_rel.Min.x + pad_x) : -FLT_MAX;
12869 inner_rect_rel.Max.x = clamp_x ? (inner_rect_rel.Max.x - pad_x) : +FLT_MAX;
12870 inner_rect_rel.Min.y = clamp_y ? (inner_rect_rel.Min.y + pad_y) : -FLT_MAX;
12871 inner_rect_rel.Max.y = clamp_y ? (inner_rect_rel.Max.y - pad_y) : +FLT_MAX;
12872 window->NavRectRel[
g.NavLayer].ClipWithFull(inner_rect_rel);
12878 ImRect scoring_rect;
12879 if (window != NULL)
12881 ImRect nav_rect_rel = !window->NavRectRel[
g.NavLayer].IsInverted() ? window->NavRectRel[
g.NavLayer] : ImRect(0, 0, 0, 0);
12882 scoring_rect = WindowRectRelToAbs(window, nav_rect_rel);
12883 scoring_rect.TranslateY(scoring_rect_offset_y);
12884 if (
g.NavMoveSubmitted)
12885 NavBiasScoringRect(scoring_rect, window->RootWindowForNav->NavPreferredScoringPosRel[
g.NavLayer],
g.NavMoveDir,
g.NavMoveFlags);
12886 IM_ASSERT(!scoring_rect.IsInverted());
12890 g.NavScoringRect = scoring_rect;
12891 g.NavScoringNoClipRect.Add(scoring_rect);
12894void ImGui::NavUpdateCreateTabbingRequest()
12897 ImGuiWindow* window =
g.NavWindow;
12898 IM_ASSERT(
g.NavMoveDir == ImGuiDir_None);
12899 if (window == NULL ||
g.NavWindowingTarget != NULL || (window->Flags & ImGuiWindowFlags_NoNavInputs))
12902 const bool tab_pressed = IsKeyPressed(ImGuiKey_Tab, ImGuiKeyOwner_None, ImGuiInputFlags_Repeat) && !
g.IO.KeyCtrl && !
g.IO.KeyAlt;
12909 const bool nav_keyboard_active = (
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
12910 if (nav_keyboard_active)
12911 g.NavTabbingDir =
g.IO.KeyShift ? -1 : (
g.NavDisableHighlight ==
true &&
g.ActiveId == 0) ? 0 : +1;
12913 g.NavTabbingDir =
g.IO.KeyShift ? -1 : (
g.ActiveId == 0) ? 0 : +1;
12914 ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate;
12915 ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
12916 ImGuiDir clip_dir = (
g.NavTabbingDir < 0) ? ImGuiDir_Up : ImGuiDir_Down;
12917 NavMoveRequestSubmit(ImGuiDir_None, clip_dir, move_flags, scroll_flags);
12918 g.NavTabbingCounter = -1;
12922void ImGui::NavMoveRequestApplyResult()
12925#if IMGUI_DEBUG_NAV_SCORING
12926 if (
g.NavMoveFlags & ImGuiNavMoveFlags_DebugNoResult)
12931 ImGuiNavItemData* result = (
g.NavMoveResultLocal.ID != 0) ? &
g.NavMoveResultLocal : (
g.NavMoveResultOther.
ID != 0) ? &
g.NavMoveResultOther : NULL;
12934 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && result == NULL)
12935 if ((
g.NavTabbingCounter == 1 ||
g.NavTabbingDir == 0) &&
g.NavTabbingResultFirst.ID)
12936 result = &
g.NavTabbingResultFirst;
12939 const ImGuiAxis axis = (
g.NavMoveDir == ImGuiDir_Up ||
g.NavMoveDir == ImGuiDir_Down) ? ImGuiAxis_Y : ImGuiAxis_X;
12940 if (result == NULL)
12942 if (
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing)
12943 g.NavMoveFlags |= ImGuiNavMoveFlags_NoSetNavHighlight;
12944 if (
g.NavId != 0 && (
g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavHighlight) == 0)
12945 NavRestoreHighlightAfterMove();
12946 NavClearPreferredPosForAxis(axis);
12947 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveSubmitted but not led to a result!\n");
12952 if (
g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet)
12953 if (
g.NavMoveResultLocalVisible.ID != 0 &&
g.NavMoveResultLocalVisible.ID !=
g.NavId)
12954 result = &
g.NavMoveResultLocalVisible;
12957 if (result != &
g.NavMoveResultOther &&
g.NavMoveResultOther.ID != 0 &&
g.NavMoveResultOther.Window->ParentWindow ==
g.NavWindow)
12958 if ((
g.NavMoveResultOther.DistBox < result->DistBox) || (
g.NavMoveResultOther.DistBox == result->DistBox &&
g.NavMoveResultOther.DistCenter < result->DistCenter))
12959 result = &
g.NavMoveResultOther;
12960 IM_ASSERT(
g.NavWindow && result->Window);
12963 if (
g.NavLayer == ImGuiNavLayer_Main)
12965 ImRect rect_abs = WindowRectRelToAbs(result->Window, result->RectRel);
12966 ScrollToRectEx(result->Window, rect_abs,
g.NavMoveScrollFlags);
12968 if (
g.NavMoveFlags & ImGuiNavMoveFlags_ScrollToEdgeY)
12971 float scroll_target = (
g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f;
12972 SetScrollY(result->Window, scroll_target);
12976 if (
g.NavWindow != result->Window)
12978 IMGUI_DEBUG_LOG_FOCUS(
"[focus] NavMoveRequest: SetNavWindow(\"%s\")\n", result->Window->Name);
12979 g.NavWindow = result->Window;
12980 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
12984 if (
g.ActiveId != result->ID)
12989 if ((
g.NavId != result->ID || (
g.NavMoveFlags & ImGuiNavMoveFlags_IsPageMove)) && (
g.NavMoveFlags & ImGuiNavMoveFlags_NoSelect) == 0)
12991 g.NavJustMovedToId = result->ID;
12992 g.NavJustMovedToFocusScopeId = result->FocusScopeId;
12993 g.NavJustMovedToKeyMods =
g.NavMoveKeyMods;
12997 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID,
g.NavLayer,
g.NavWindow->Name);
12998 ImVec2 preferred_scoring_pos_rel =
g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[
g.NavLayer];
12999 SetNavID(result->ID,
g.NavLayer, result->FocusScopeId, result->RectRel);
13000 if (result->SelectionUserData != ImGuiSelectionUserData_Invalid)
13001 g.NavLastValidSelectionUserData = result->SelectionUserData;
13005 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) == 0)
13007 preferred_scoring_pos_rel[axis] = result->RectRel.GetCenter()[axis];
13008 g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[
g.NavLayer] = preferred_scoring_pos_rel;
13012 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && (result->InFlags & ImGuiItemFlags_Inputable) == 0)
13013 g.NavMoveFlags &= ~ImGuiNavMoveFlags_Activate;
13016 if (
g.NavMoveFlags & ImGuiNavMoveFlags_Activate)
13018 g.NavNextActivateId = result->ID;
13019 g.NavNextActivateFlags = ImGuiActivateFlags_None;
13020 if (
g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing)
13021 g.NavNextActivateFlags |= ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState | ImGuiActivateFlags_FromTabbing;
13025 if ((
g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavHighlight) == 0)
13026 NavRestoreHighlightAfterMove();
13033static void ImGui::NavUpdateCancelRequest()
13036 const bool nav_gamepad_active = (
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (
g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
13037 const bool nav_keyboard_active = (
g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
13038 if (!(nav_keyboard_active && IsKeyPressed(ImGuiKey_Escape, ImGuiKeyOwner_None)) && !(nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadCancel, ImGuiKeyOwner_None)))
13041 IMGUI_DEBUG_LOG_NAV(
"[nav] NavUpdateCancelRequest()\n");
13042 if (
g.ActiveId != 0)
13046 else if (
g.NavLayer != ImGuiNavLayer_Main)
13049 NavRestoreLayer(ImGuiNavLayer_Main);
13050 NavRestoreHighlightAfterMove();
13052 else if (
g.NavWindow &&
g.NavWindow !=
g.NavWindow->RootWindow && !(
g.NavWindow->RootWindowForNav->Flags & ImGuiWindowFlags_Popup) &&
g.NavWindow->RootWindowForNav->ParentWindow)
13055 ImGuiWindow* child_window =
g.NavWindow->RootWindowForNav;
13056 ImGuiWindow* parent_window = child_window->ParentWindow;
13057 IM_ASSERT(child_window->ChildId != 0);
13058 FocusWindow(parent_window);
13059 SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, WindowRectAbsToRel(parent_window, child_window->Rect()));
13060 NavRestoreHighlightAfterMove();
13062 else if (
g.OpenPopupStack.Size > 0 &&
g.OpenPopupStack.back().Window != NULL && !(
g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal))
13065 ClosePopupToLevel(
g.OpenPopupStack.Size - 1,
true);
13070 if (
g.NavWindow && ((
g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(
g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow)))
13071 g.NavWindow->NavLastIds[0] = 0;
13080static float ImGui::NavUpdatePageUpPageDown()
13083 ImGuiWindow* window =
g.NavWindow;
13084 if ((window->Flags & ImGuiWindowFlags_NoNavInputs) ||
g.NavWindowingTarget != NULL)
13087 const bool page_up_held = IsKeyDown(ImGuiKey_PageUp, ImGuiKeyOwner_None);
13088 const bool page_down_held = IsKeyDown(ImGuiKey_PageDown, ImGuiKeyOwner_None);
13089 const bool home_pressed = IsKeyPressed(ImGuiKey_Home, ImGuiKeyOwner_None, ImGuiInputFlags_Repeat);
13090 const bool end_pressed = IsKeyPressed(ImGuiKey_End, ImGuiKeyOwner_None, ImGuiInputFlags_Repeat);
13091 if (page_up_held == page_down_held && home_pressed == end_pressed)
13094 if (
g.NavLayer != ImGuiNavLayer_Main)
13095 NavRestoreLayer(ImGuiNavLayer_Main);
13097 if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavWindowHasScrollY)
13100 if (IsKeyPressed(ImGuiKey_PageUp, ImGuiKeyOwner_None, ImGuiInputFlags_Repeat))
13101 SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight());
13102 else if (IsKeyPressed(ImGuiKey_PageDown, ImGuiKeyOwner_None, ImGuiInputFlags_Repeat))
13103 SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight());
13104 else if (home_pressed)
13105 SetScrollY(window, 0.0f);
13106 else if (end_pressed)
13107 SetScrollY(window, window->ScrollMax.y);
13111 ImRect& nav_rect_rel = window->NavRectRel[
g.NavLayer];
13112 const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
13113 float nav_scoring_rect_offset_y = 0.0f;
13114 if (IsKeyPressed(ImGuiKey_PageUp,
true))
13116 nav_scoring_rect_offset_y = -page_offset_y;
13117 g.NavMoveDir = ImGuiDir_Down;
13118 g.NavMoveClipDir = ImGuiDir_Up;
13119 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet | ImGuiNavMoveFlags_IsPageMove;
13121 else if (IsKeyPressed(ImGuiKey_PageDown,
true))
13123 nav_scoring_rect_offset_y = +page_offset_y;
13124 g.NavMoveDir = ImGuiDir_Up;
13125 g.NavMoveClipDir = ImGuiDir_Down;
13126 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet | ImGuiNavMoveFlags_IsPageMove;
13128 else if (home_pressed)
13133 nav_rect_rel.Min.y = nav_rect_rel.Max.y = 0.0f;
13134 if (nav_rect_rel.IsInverted())
13135 nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
13136 g.NavMoveDir = ImGuiDir_Down;
13137 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdgeY;
13140 else if (end_pressed)
13142 nav_rect_rel.Min.y = nav_rect_rel.Max.y = window->ContentSize.y;
13143 if (nav_rect_rel.IsInverted())
13144 nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
13145 g.NavMoveDir = ImGuiDir_Up;
13146 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdgeY;
13149 return nav_scoring_rect_offset_y;
13154static void ImGui::NavEndFrame()
13159 if (
g.NavWindowingTarget != NULL)
13160 NavUpdateWindowingOverlay();
13165 if (
g.NavWindow && NavMoveRequestButNoResultYet() && (
g.NavMoveFlags & ImGuiNavMoveFlags_WrapMask_) && (
g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0)
13166 NavUpdateCreateWrappingRequest();
13169static void ImGui::NavUpdateCreateWrappingRequest()
13172 ImGuiWindow* window =
g.NavWindow;
13174 bool do_forward =
false;
13175 ImRect bb_rel = window->NavRectRel[
g.NavLayer];
13176 ImGuiDir clip_dir =
g.NavMoveDir;
13178 const ImGuiNavMoveFlags move_flags =
g.NavMoveFlags;
13180 if (
g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
13182 bb_rel.Min.x = bb_rel.Max.x = window->ContentSize.x + window->WindowPadding.x;
13183 if (move_flags & ImGuiNavMoveFlags_WrapX)
13185 bb_rel.TranslateY(-bb_rel.GetHeight());
13186 clip_dir = ImGuiDir_Up;
13190 if (
g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
13192 bb_rel.Min.x = bb_rel.Max.x = -window->WindowPadding.x;
13193 if (move_flags & ImGuiNavMoveFlags_WrapX)
13195 bb_rel.TranslateY(+bb_rel.GetHeight());
13196 clip_dir = ImGuiDir_Down;
13200 if (
g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
13202 bb_rel.Min.y = bb_rel.Max.y = window->ContentSize.y + window->WindowPadding.y;
13203 if (move_flags & ImGuiNavMoveFlags_WrapY)
13205 bb_rel.TranslateX(-bb_rel.GetWidth());
13206 clip_dir = ImGuiDir_Left;
13210 if (
g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
13212 bb_rel.Min.y = bb_rel.Max.y = -window->WindowPadding.y;
13213 if (move_flags & ImGuiNavMoveFlags_WrapY)
13215 bb_rel.TranslateX(+bb_rel.GetWidth());
13216 clip_dir = ImGuiDir_Right;
13222 window->NavRectRel[
g.NavLayer] = bb_rel;
13223 NavClearPreferredPosForAxis(ImGuiAxis_X);
13224 NavClearPreferredPosForAxis(ImGuiAxis_Y);
13225 NavMoveRequestForward(
g.NavMoveDir, clip_dir, move_flags,
g.NavMoveScrollFlags);
13228static int ImGui::FindWindowFocusIndex(ImGuiWindow* window)
13232 int order = window->FocusOrder;
13233 IM_ASSERT(window->RootWindow == window);
13234 IM_ASSERT(
g.WindowsFocusOrder[order] == window);
13238static ImGuiWindow* FindWindowNavFocusable(
int i_start,
int i_stop,
int dir)
13241 for (
int i = i_start; i >= 0 && i <
g.WindowsFocusOrder.Size && i != i_stop; i += dir)
13242 if (ImGui::IsWindowNavFocusable(
g.WindowsFocusOrder[i]))
13243 return g.WindowsFocusOrder[i];
13247static void NavUpdateWindowingHighlightWindow(
int focus_change_dir)
13250 IM_ASSERT(
g.NavWindowingTarget);
13251 if (
g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)
13254 const int i_current = ImGui::FindWindowFocusIndex(
g.NavWindowingTarget);
13255 ImGuiWindow* window_target = FindWindowNavFocusable(i_current + focus_change_dir, -INT_MAX, focus_change_dir);
13256 if (!window_target)
13257 window_target = FindWindowNavFocusable((focus_change_dir < 0) ? (
g.WindowsFocusOrder.Size - 1) : 0, i_current, focus_change_dir);
13260 g.NavWindowingTarget =
g.NavWindowingTargetAnim = window_target;
13261 g.NavWindowingAccumDeltaPos =
g.NavWindowingAccumDeltaSize = ImVec2(0.0f, 0.0f);
13263 g.NavWindowingToggleLayer =
false;
13269static void ImGui::NavUpdateWindowing()
13272 ImGuiIO& io =
g.IO;
13274 ImGuiWindow* apply_focus_window = NULL;
13275 bool apply_toggle_layer =
false;
13277 ImGuiWindow* modal_window = GetTopMostPopupModal();
13278 bool allow_windowing = (modal_window == NULL);
13279 if (!allow_windowing)
13280 g.NavWindowingTarget = NULL;
13283 if (
g.NavWindowingTargetAnim &&
g.NavWindowingTarget == NULL)
13285 g.NavWindowingHighlightAlpha = ImMax(
g.NavWindowingHighlightAlpha - io.DeltaTime * 10.0f, 0.0f);
13286 if (
g.DimBgRatio <= 0.0f &&
g.NavWindowingHighlightAlpha <= 0.0f)
13287 g.NavWindowingTargetAnim = NULL;
13292 const ImGuiID owner_id =
ImHashStr(
"###NavUpdateWindowing");
13293 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
13294 const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
13295 const bool keyboard_next_window = allow_windowing &&
g.ConfigNavWindowingKeyNext && Shortcut(
g.ConfigNavWindowingKeyNext, owner_id, ImGuiInputFlags_Repeat | ImGuiInputFlags_RouteAlways);
13296 const bool keyboard_prev_window = allow_windowing &&
g.ConfigNavWindowingKeyPrev && Shortcut(
g.ConfigNavWindowingKeyPrev, owner_id, ImGuiInputFlags_Repeat | ImGuiInputFlags_RouteAlways);
13297 const bool start_windowing_with_gamepad = allow_windowing && nav_gamepad_active && !
g.NavWindowingTarget && IsKeyPressed(ImGuiKey_NavGamepadMenu, 0, ImGuiInputFlags_None);
13298 const bool start_windowing_with_keyboard = allow_windowing && !
g.NavWindowingTarget && (keyboard_next_window || keyboard_prev_window);
13299 if (start_windowing_with_gamepad || start_windowing_with_keyboard)
13300 if (ImGuiWindow* window =
g.NavWindow ?
g.NavWindow : FindWindowNavFocusable(
g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
13302 g.NavWindowingTarget =
g.NavWindowingTargetAnim = window->RootWindow;
13303 g.NavWindowingTimer =
g.NavWindowingHighlightAlpha = 0.0f;
13304 g.NavWindowingAccumDeltaPos =
g.NavWindowingAccumDeltaSize = ImVec2(0.0f, 0.0f);
13305 g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true :
false;
13306 g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad;
13309 if (keyboard_next_window || keyboard_prev_window)
13310 SetKeyOwnersForKeyChord((
g.ConfigNavWindowingKeyNext |
g.ConfigNavWindowingKeyPrev) & ImGuiMod_Mask_, owner_id);
13314 g.NavWindowingTimer += io.DeltaTime;
13315 if (
g.NavWindowingTarget &&
g.NavInputSource == ImGuiInputSource_Gamepad)
13318 g.NavWindowingHighlightAlpha = ImMax(
g.NavWindowingHighlightAlpha, ImSaturate((
g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
13321 const int focus_change_dir = (int)IsKeyPressed(ImGuiKey_GamepadL1) - (int)IsKeyPressed(ImGuiKey_GamepadR1);
13322 if (focus_change_dir != 0)
13324 NavUpdateWindowingHighlightWindow(focus_change_dir);
13325 g.NavWindowingHighlightAlpha = 1.0f;
13329 if (!IsKeyDown(ImGuiKey_NavGamepadMenu))
13331 g.NavWindowingToggleLayer &= (
g.NavWindowingHighlightAlpha < 1.0f);
13332 if (
g.NavWindowingToggleLayer &&
g.NavWindow)
13333 apply_toggle_layer =
true;
13334 else if (!
g.NavWindowingToggleLayer)
13335 apply_focus_window =
g.NavWindowingTarget;
13336 g.NavWindowingTarget = NULL;
13341 if (
g.NavWindowingTarget &&
g.NavInputSource == ImGuiInputSource_Keyboard)
13344 ImGuiKeyChord shared_mods = ((
g.ConfigNavWindowingKeyNext ?
g.ConfigNavWindowingKeyNext : ImGuiMod_Mask_) & (
g.ConfigNavWindowingKeyPrev ?
g.ConfigNavWindowingKeyPrev : ImGuiMod_Mask_)) & ImGuiMod_Mask_;
13345 IM_ASSERT(shared_mods != 0);
13346 g.NavWindowingHighlightAlpha = ImMax(
g.NavWindowingHighlightAlpha, ImSaturate((
g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
13347 if (keyboard_next_window || keyboard_prev_window)
13348 NavUpdateWindowingHighlightWindow(keyboard_next_window ? -1 : +1);
13349 else if ((io.KeyMods & shared_mods) != shared_mods)
13350 apply_focus_window =
g.NavWindowingTarget;
13354 const ImGuiKey windowing_toggle_keys[] = { ImGuiKey_LeftAlt, ImGuiKey_RightAlt };
13355 for (ImGuiKey windowing_toggle_key : windowing_toggle_keys)
13356 if (nav_keyboard_active && IsKeyPressed(windowing_toggle_key, ImGuiKeyOwner_None))
13358 g.NavWindowingToggleLayer =
true;
13359 g.NavWindowingToggleKey = windowing_toggle_key;
13360 g.NavInputSource = ImGuiInputSource_Keyboard;
13363 if (
g.NavWindowingToggleLayer &&
g.NavInputSource == ImGuiInputSource_Keyboard)
13369 if (io.InputQueueCharacters.Size > 0 || io.KeyCtrl || io.KeyShift || io.KeySuper)
13370 g.NavWindowingToggleLayer =
false;
13371 if (TestKeyOwner(
g.NavWindowingToggleKey, ImGuiKeyOwner_None) ==
false || TestKeyOwner(ImGuiMod_Alt, ImGuiKeyOwner_None) ==
false)
13372 g.NavWindowingToggleLayer =
false;
13376 if (IsKeyReleased(
g.NavWindowingToggleKey) &&
g.NavWindowingToggleLayer)
13377 if (
g.ActiveId == 0 ||
g.ActiveIdAllowOverlap)
13378 if (IsMousePosValid(&io.MousePos) == IsMousePosValid(&io.MousePosPrev))
13379 apply_toggle_layer =
true;
13380 if (!IsKeyDown(
g.NavWindowingToggleKey))
13381 g.NavWindowingToggleLayer =
false;
13385 if (
g.NavWindowingTarget && !(
g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove))
13387 ImVec2 nav_move_dir;
13388 if (
g.NavInputSource == ImGuiInputSource_Keyboard && !io.KeyShift)
13389 nav_move_dir = GetKeyMagnitude2d(ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow);
13390 if (
g.NavInputSource == ImGuiInputSource_Gamepad)
13391 nav_move_dir = GetKeyMagnitude2d(ImGuiKey_GamepadLStickLeft, ImGuiKey_GamepadLStickRight, ImGuiKey_GamepadLStickUp, ImGuiKey_GamepadLStickDown);
13392 if (nav_move_dir.x != 0.0f || nav_move_dir.y != 0.0f)
13394 const float NAV_MOVE_SPEED = 800.0f;
13395 const float move_step = NAV_MOVE_SPEED * io.DeltaTime * ImMin(io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
13396 g.NavWindowingAccumDeltaPos += nav_move_dir * move_step;
13397 g.NavDisableMouseHover =
true;
13398 ImVec2 accum_floored = ImTrunc(
g.NavWindowingAccumDeltaPos);
13399 if (accum_floored.x != 0.0f || accum_floored.y != 0.0f)
13401 ImGuiWindow* moving_window =
g.NavWindowingTarget->RootWindowDockTree;
13402 SetWindowPos(moving_window, moving_window->Pos + accum_floored, ImGuiCond_Always);
13403 g.NavWindowingAccumDeltaPos -= accum_floored;
13409 if (apply_focus_window && (
g.NavWindow == NULL || apply_focus_window !=
g.NavWindow->RootWindow))
13413 ImGuiViewport* previous_viewport =
g.NavWindow ?
g.NavWindow->Viewport : NULL;
13415 NavRestoreHighlightAfterMove();
13416 ClosePopupsOverWindow(apply_focus_window,
false);
13417 FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild);
13418 apply_focus_window =
g.NavWindow;
13419 if (apply_focus_window->NavLastIds[0] == 0)
13420 NavInitWindow(apply_focus_window,
false);
13429 if (apply_focus_window->DC.NavLayersActiveMaskNext == (1 << ImGuiNavLayer_Menu))
13430 g.NavLayer = ImGuiNavLayer_Menu;
13433 if (apply_focus_window->Viewport != previous_viewport &&
g.PlatformIO.Platform_SetWindowFocus)
13434 g.PlatformIO.Platform_SetWindowFocus(apply_focus_window->Viewport);
13436 if (apply_focus_window)
13437 g.NavWindowingTarget = NULL;
13440 if (apply_toggle_layer &&
g.NavWindow)
13445 ImGuiWindow* new_nav_window =
g.NavWindow;
13446 while (new_nav_window->ParentWindow
13447 && (new_nav_window->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) == 0
13448 && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0
13449 && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
13450 new_nav_window = new_nav_window->ParentWindow;
13451 if (new_nav_window !=
g.NavWindow)
13453 ImGuiWindow* old_nav_window =
g.NavWindow;
13454 FocusWindow(new_nav_window);
13455 new_nav_window->NavLastChildNavWindow = old_nav_window;
13459 const ImGuiNavLayer new_nav_layer = (
g.NavWindow->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((
int)
g.NavLayer ^ 1) : ImGuiNavLayer_Main;
13460 if (new_nav_layer !=
g.NavLayer)
13463 const bool preserve_layer_1_nav_id = (new_nav_window->DockNodeAsHost != NULL);
13464 if (new_nav_layer == ImGuiNavLayer_Menu && !preserve_layer_1_nav_id)
13465 g.NavWindow->NavLastIds[new_nav_layer] = 0;
13466 NavRestoreLayer(new_nav_layer);
13467 NavRestoreHighlightAfterMove();
13473static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window)
13475 if (window->Flags & ImGuiWindowFlags_Popup)
13476 return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingPopup);
13477 if ((window->Flags & ImGuiWindowFlags_MenuBar) && strcmp(window->Name,
"##MainMenuBar") == 0)
13478 return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingMainMenuBar);
13479 if (window->DockNodeAsHost)
13480 return "(Dock node)";
13481 return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingUntitled);
13485void ImGui::NavUpdateWindowingOverlay()
13488 IM_ASSERT(
g.NavWindowingTarget != NULL);
13490 if (
g.NavWindowingTimer < NAV_WINDOWING_LIST_APPEAR_DELAY)
13493 if (
g.NavWindowingListWindow == NULL)
13494 g.NavWindowingListWindow = FindWindowByName(
"###NavWindowingList");
13495 const ImGuiViewport* viewport = GetMainViewport();
13496 SetNextWindowSizeConstraints(ImVec2(viewport->Size.x * 0.20f, viewport->Size.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX));
13497 SetNextWindowPos(viewport->GetCenter(), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
13498 PushStyleVar(ImGuiStyleVar_WindowPadding,
g.Style.WindowPadding * 2.0f);
13499 Begin(
"###NavWindowingList", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings);
13500 for (
int n =
g.WindowsFocusOrder.Size - 1; n >= 0; n--)
13502 ImGuiWindow* window =
g.WindowsFocusOrder[n];
13503 IM_ASSERT(window != NULL);
13504 if (!IsWindowNavFocusable(window))
13506 const char* label = window->Name;
13507 if (label == FindRenderedTextEnd(label))
13508 label = GetFallbackWindowNameForWindowingList(window);
13509 Selectable(label,
g.NavWindowingTarget == window);
13520bool ImGui::IsDragDropActive()
13523 return g.DragDropActive;
13526void ImGui::ClearDragDrop()
13529 g.DragDropActive =
false;
13530 g.DragDropPayload.Clear();
13531 g.DragDropAcceptFlags = ImGuiDragDropFlags_None;
13532 g.DragDropAcceptIdCurr =
g.DragDropAcceptIdPrev = 0;
13533 g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
13534 g.DragDropAcceptFrameCount = -1;
13536 g.DragDropPayloadBufHeap.clear();
13537 memset(&
g.DragDropPayloadBufLocal, 0,
sizeof(
g.DragDropPayloadBufLocal));
13540bool ImGui::BeginTooltipHidden()
13543 bool ret = Begin(
"##Tooltip_Hidden", NULL, ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize);
13544 SetWindowHiddenAndSkipItemsForCurrentFrame(
g.CurrentWindow);
13555bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
13558 ImGuiWindow* window =
g.CurrentWindow;
13562 ImGuiMouseButton mouse_button = ImGuiMouseButton_Left;
13564 bool source_drag_active =
false;
13565 ImGuiID source_id = 0;
13566 ImGuiID source_parent_id = 0;
13567 if (!(flags & ImGuiDragDropFlags_SourceExtern))
13569 source_id =
g.LastItemData.ID;
13570 if (source_id != 0)
13573 if (
g.ActiveId != source_id)
13575 if (
g.ActiveIdMouseButton != -1)
13576 mouse_button =
g.ActiveIdMouseButton;
13577 if (
g.IO.MouseDown[mouse_button] ==
false || window->SkipItems)
13579 g.ActiveIdAllowOverlap =
false;
13584 if (
g.IO.MouseDown[mouse_button] ==
false || window->SkipItems)
13586 if ((
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) == 0 && (
g.ActiveId == 0 ||
g.ActiveIdWindow != window))
13591 if (!(flags & ImGuiDragDropFlags_SourceAllowNullID))
13602 source_id =
g.LastItemData.ID = window->GetIDFromRectangle(
g.LastItemData.Rect);
13603 KeepAliveID(source_id);
13604 bool is_hovered = ItemHoverable(
g.LastItemData.Rect, source_id,
g.LastItemData.InFlags);
13605 if (is_hovered &&
g.IO.MouseClicked[mouse_button])
13607 SetActiveID(source_id, window);
13608 FocusWindow(window);
13610 if (
g.ActiveId == source_id)
13611 g.ActiveIdAllowOverlap = is_hovered;
13613 if (
g.ActiveId != source_id)
13615 source_parent_id = window->IDStack.back();
13616 source_drag_active = IsMouseDragging(mouse_button);
13619 SetActiveIdUsingAllKeyboardKeys();
13624 source_id =
ImHashStr(
"#SourceExtern");
13625 source_drag_active =
true;
13628 if (source_drag_active)
13630 if (!
g.DragDropActive)
13632 IM_ASSERT(source_id != 0);
13634 ImGuiPayload& payload =
g.DragDropPayload;
13635 payload.SourceId = source_id;
13636 payload.SourceParentId = source_parent_id;
13637 g.DragDropActive =
true;
13638 g.DragDropSourceFlags = flags;
13639 g.DragDropMouseButton = mouse_button;
13640 if (payload.SourceId ==
g.ActiveId)
13641 g.ActiveIdNoClearOnFocusLoss =
true;
13643 g.DragDropSourceFrameCount =
g.FrameCount;
13644 g.DragDropWithinSource =
true;
13646 if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
13651 if (
g.DragDropAcceptIdPrev && (
g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
13652 ret = BeginTooltipHidden();
13654 ret = BeginTooltip();
13659 if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
13660 g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
13667void ImGui::EndDragDropSource()
13670 IM_ASSERT(
g.DragDropActive);
13671 IM_ASSERT(
g.DragDropWithinSource &&
"Not after a BeginDragDropSource()?");
13673 if (!(
g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
13677 if (
g.DragDropPayload.DataFrameCount == -1)
13679 g.DragDropWithinSource =
false;
13683bool ImGui::SetDragDropPayload(
const char* type,
const void* data,
size_t data_size, ImGuiCond cond)
13686 ImGuiPayload& payload =
g.DragDropPayload;
13688 cond = ImGuiCond_Always;
13690 IM_ASSERT(type != NULL);
13691 IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType) &&
"Payload type can be at most 32 characters long");
13692 IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0));
13693 IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once);
13694 IM_ASSERT(payload.SourceId != 0);
13696 if (cond == ImGuiCond_Always || payload.DataFrameCount == -1)
13699 ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType));
13700 g.DragDropPayloadBufHeap.resize(0);
13701 if (data_size >
sizeof(
g.DragDropPayloadBufLocal))
13704 g.DragDropPayloadBufHeap.resize((
int)data_size);
13705 payload.Data =
g.DragDropPayloadBufHeap.Data;
13706 memcpy(payload.Data, data, data_size);
13708 else if (data_size > 0)
13711 memset(&
g.DragDropPayloadBufLocal, 0,
sizeof(
g.DragDropPayloadBufLocal));
13712 payload.Data =
g.DragDropPayloadBufLocal;
13713 memcpy(payload.Data, data, data_size);
13717 payload.Data = NULL;
13719 payload.DataSize = (int)data_size;
13721 payload.DataFrameCount =
g.FrameCount;
13724 return (
g.DragDropAcceptFrameCount ==
g.FrameCount) || (
g.DragDropAcceptFrameCount ==
g.FrameCount - 1);
13727bool ImGui::BeginDragDropTargetCustom(
const ImRect& bb, ImGuiID
id)
13730 if (!
g.DragDropActive)
13733 ImGuiWindow* window =
g.CurrentWindow;
13734 ImGuiWindow* hovered_window =
g.HoveredWindowUnderMovingWindow;
13735 if (hovered_window == NULL || window->RootWindowDockTree != hovered_window->RootWindowDockTree)
13737 IM_ASSERT(
id != 0);
13738 if (!IsMouseHoveringRect(bb.Min, bb.Max) || (
id ==
g.DragDropPayload.SourceId))
13740 if (window->SkipItems)
13743 IM_ASSERT(
g.DragDropWithinTarget ==
false);
13744 g.DragDropTargetRect = bb;
13745 g.DragDropTargetClipRect = window->ClipRect;
13746 g.DragDropTargetId =
id;
13747 g.DragDropWithinTarget =
true;
13755bool ImGui::BeginDragDropTarget()
13758 if (!
g.DragDropActive)
13761 ImGuiWindow* window =
g.CurrentWindow;
13762 if (!(
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect))
13764 ImGuiWindow* hovered_window =
g.HoveredWindowUnderMovingWindow;
13765 if (hovered_window == NULL || window->RootWindowDockTree != hovered_window->RootWindowDockTree || window->SkipItems)
13768 const ImRect& display_rect = (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ?
g.LastItemData.DisplayRect :
g.LastItemData.Rect;
13769 ImGuiID
id =
g.LastItemData.ID;
13772 id = window->GetIDFromRectangle(display_rect);
13775 if (
g.DragDropPayload.SourceId ==
id)
13778 IM_ASSERT(
g.DragDropWithinTarget ==
false);
13779 g.DragDropTargetRect = display_rect;
13780 g.DragDropTargetClipRect = (
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasClipRect) ?
g.LastItemData.ClipRect : window->ClipRect;
13781 g.DragDropTargetId =
id;
13782 g.DragDropWithinTarget =
true;
13786bool ImGui::IsDragDropPayloadBeingAccepted()
13789 return g.DragDropActive &&
g.DragDropAcceptIdPrev != 0;
13792const ImGuiPayload* ImGui::AcceptDragDropPayload(
const char* type, ImGuiDragDropFlags flags)
13795 ImGuiPayload& payload =
g.DragDropPayload;
13796 IM_ASSERT(
g.DragDropActive);
13797 IM_ASSERT(payload.DataFrameCount != -1);
13798 if (type != NULL && !payload.IsDataType(type))
13803 const bool was_accepted_previously = (
g.DragDropAcceptIdPrev ==
g.DragDropTargetId);
13804 ImRect r =
g.DragDropTargetRect;
13805 float r_surface = r.GetWidth() * r.GetHeight();
13806 if (r_surface >
g.DragDropAcceptIdCurrRectSurface)
13809 g.DragDropAcceptFlags = flags;
13810 g.DragDropAcceptIdCurr =
g.DragDropTargetId;
13811 g.DragDropAcceptIdCurrRectSurface = r_surface;
13815 payload.Preview = was_accepted_previously;
13816 flags |= (
g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect);
13817 if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview)
13818 RenderDragDropTargetRect(r,
g.DragDropTargetClipRect);
13820 g.DragDropAcceptFrameCount =
g.FrameCount;
13821 payload.Delivery = was_accepted_previously && !IsMouseDown(
g.DragDropMouseButton);
13822 if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery))
13830void ImGui::RenderDragDropTargetRect(
const ImRect& bb,
const ImRect& item_clip_rect)
13833 ImGuiWindow* window =
g.CurrentWindow;
13834 ImRect bb_display = bb;
13835 bb_display.ClipWith(item_clip_rect);
13836 bb_display.Expand(3.5f);
13837 bool push_clip_rect = !window->ClipRect.Contains(bb_display);
13838 if (push_clip_rect)
13839 window->DrawList->PushClipRectFullScreen();
13840 window->DrawList->AddRect(bb_display.Min, bb_display.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f);
13841 if (push_clip_rect)
13842 window->DrawList->PopClipRect();
13845const ImGuiPayload* ImGui::GetDragDropPayload()
13848 return (
g.DragDropActive &&
g.DragDropPayload.DataFrameCount != -1) ? &
g.DragDropPayload : NULL;
13851void ImGui::EndDragDropTarget()
13854 IM_ASSERT(
g.DragDropActive);
13855 IM_ASSERT(
g.DragDropWithinTarget);
13856 g.DragDropWithinTarget =
false;
13859 if (
g.DragDropPayload.Delivery)
13871static inline void LogTextV(ImGuiContext&
g,
const char* fmt, va_list args)
13875 g.LogBuffer.Buf.resize(0);
13876 g.LogBuffer.appendfv(fmt, args);
13877 ImFileWrite(
g.LogBuffer.c_str(),
sizeof(
char), (ImU64)
g.LogBuffer.size(),
g.LogFile);
13881 g.LogBuffer.appendfv(fmt, args);
13885void ImGui::LogText(
const char* fmt, ...)
13892 va_start(args, fmt);
13893 LogTextV(
g, fmt, args);
13897void ImGui::LogTextV(
const char* fmt, va_list args)
13903 LogTextV(
g, fmt, args);
13909void ImGui::LogRenderedText(
const ImVec2* ref_pos,
const char* text,
const char* text_end)
13912 ImGuiWindow* window =
g.CurrentWindow;
13914 const char* prefix =
g.LogNextPrefix;
13915 const char* suffix =
g.LogNextSuffix;
13916 g.LogNextPrefix =
g.LogNextSuffix = NULL;
13919 text_end = FindRenderedTextEnd(text, text_end);
13921 const bool log_new_line = ref_pos && (ref_pos->y >
g.LogLinePosY +
g.Style.FramePadding.y + 1);
13923 g.LogLinePosY = ref_pos->y;
13927 g.LogLineFirstItem =
true;
13931 LogRenderedText(ref_pos, prefix, prefix + strlen(prefix));
13934 if (
g.LogDepthRef > window->DC.TreeDepth)
13935 g.LogDepthRef = window->DC.TreeDepth;
13936 const int tree_depth = (window->DC.TreeDepth -
g.LogDepthRef);
13938 const char* text_remaining = text;
13943 const char* line_start = text_remaining;
13944 const char* line_end =
ImStreolRange(line_start, text_end);
13945 const bool is_last_line = (line_end == text_end);
13946 if (line_start != line_end || !is_last_line)
13948 const int line_length = (int)(line_end - line_start);
13949 const int indentation =
g.LogLineFirstItem ? tree_depth * 4 : 1;
13950 LogText(
"%*s%.*s", indentation,
"", line_length, line_start);
13951 g.LogLineFirstItem =
false;
13952 if (*line_end ==
'\n')
13955 g.LogLineFirstItem =
true;
13960 text_remaining = line_end + 1;
13964 LogRenderedText(ref_pos, suffix, suffix + strlen(suffix));
13968void ImGui::LogBegin(ImGuiLogType type,
int auto_open_depth)
13971 ImGuiWindow* window =
g.CurrentWindow;
13972 IM_ASSERT(
g.LogEnabled ==
false);
13973 IM_ASSERT(
g.LogFile == NULL);
13974 IM_ASSERT(
g.LogBuffer.empty());
13975 g.LogEnabled =
true;
13977 g.LogNextPrefix =
g.LogNextSuffix = NULL;
13978 g.LogDepthRef = window->DC.TreeDepth;
13979 g.LogDepthToExpand = ((auto_open_depth >= 0) ? auto_open_depth :
g.LogDepthToExpandDefault);
13980 g.LogLinePosY = FLT_MAX;
13981 g.LogLineFirstItem =
true;
13985void ImGui::LogSetNextTextDecoration(
const char* prefix,
const char* suffix)
13988 g.LogNextPrefix = prefix;
13989 g.LogNextSuffix = suffix;
13992void ImGui::LogToTTY(
int auto_open_depth)
13997 IM_UNUSED(auto_open_depth);
13998#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
13999 LogBegin(ImGuiLogType_TTY, auto_open_depth);
14000 g.LogFile = stdout;
14005void ImGui::LogToFile(
int auto_open_depth,
const char* filename)
14015 filename =
g.IO.LogFilename;
14016 if (!filename || !filename[0])
14018 ImFileHandle f =
ImFileOpen(filename,
"ab");
14025 LogBegin(ImGuiLogType_File, auto_open_depth);
14030void ImGui::LogToClipboard(
int auto_open_depth)
14035 LogBegin(ImGuiLogType_Clipboard, auto_open_depth);
14038void ImGui::LogToBuffer(
int auto_open_depth)
14043 LogBegin(ImGuiLogType_Buffer, auto_open_depth);
14046void ImGui::LogFinish()
14055 case ImGuiLogType_TTY:
14056#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
14060 case ImGuiLogType_File:
14063 case ImGuiLogType_Buffer:
14065 case ImGuiLogType_Clipboard:
14066 if (!
g.LogBuffer.empty())
14067 SetClipboardText(
g.LogBuffer.begin());
14069 case ImGuiLogType_None:
14074 g.LogEnabled =
false;
14075 g.LogType = ImGuiLogType_None;
14077 g.LogBuffer.clear();
14082void ImGui::LogButtons()
14086 PushID(
"LogButtons");
14087#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
14088 const bool log_to_tty = Button(
"Log To TTY"); SameLine();
14090 const bool log_to_tty =
false;
14092 const bool log_to_file = Button(
"Log To File"); SameLine();
14093 const bool log_to_clipboard = Button(
"Log To Clipboard"); SameLine();
14094 PushTabStop(
false);
14095 SetNextItemWidth(80.0f);
14096 SliderInt(
"Default Depth", &
g.LogDepthToExpandDefault, 0, 9, NULL);
14105 if (log_to_clipboard)
14130void ImGui::UpdateSettings()
14134 if (!
g.SettingsLoaded)
14136 IM_ASSERT(
g.SettingsWindows.empty());
14137 if (
g.IO.IniFilename)
14138 LoadIniSettingsFromDisk(
g.IO.IniFilename);
14139 g.SettingsLoaded =
true;
14143 if (
g.SettingsDirtyTimer > 0.0f)
14145 g.SettingsDirtyTimer -=
g.IO.DeltaTime;
14146 if (
g.SettingsDirtyTimer <= 0.0f)
14148 if (
g.IO.IniFilename != NULL)
14149 SaveIniSettingsToDisk(
g.IO.IniFilename);
14151 g.IO.WantSaveIniSettings =
true;
14152 g.SettingsDirtyTimer = 0.0f;
14157void ImGui::MarkIniSettingsDirty()
14160 if (
g.SettingsDirtyTimer <= 0.0f)
14161 g.SettingsDirtyTimer =
g.IO.IniSavingRate;
14164void ImGui::MarkIniSettingsDirty(ImGuiWindow* window)
14167 if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
14168 if (
g.SettingsDirtyTimer <= 0.0f)
14169 g.SettingsDirtyTimer =
g.IO.IniSavingRate;
14172void ImGui::AddSettingsHandler(
const ImGuiSettingsHandler* handler)
14175 IM_ASSERT(FindSettingsHandler(handler->TypeName) == NULL);
14176 g.SettingsHandlers.push_back(*handler);
14179void ImGui::RemoveSettingsHandler(
const char* type_name)
14182 if (ImGuiSettingsHandler* handler = FindSettingsHandler(type_name))
14183 g.SettingsHandlers.erase(handler);
14186ImGuiSettingsHandler* ImGui::FindSettingsHandler(
const char* type_name)
14189 const ImGuiID type_hash =
ImHashStr(type_name);
14190 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
14191 if (handler.TypeHash == type_hash)
14197void ImGui::ClearIniSettings()
14200 g.SettingsIniData.clear();
14201 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
14202 if (handler.ClearAllFn != NULL)
14203 handler.ClearAllFn(&
g, &handler);
14206void ImGui::LoadIniSettingsFromDisk(
const char* ini_filename)
14208 size_t file_data_size = 0;
14212 if (file_data_size > 0)
14213 LoadIniSettingsFromMemory(file_data, (
size_t)file_data_size);
14214 IM_FREE(file_data);
14219void ImGui::LoadIniSettingsFromMemory(
const char* ini_data,
size_t ini_size)
14222 IM_ASSERT(
g.Initialized);
14229 ini_size = strlen(ini_data);
14230 g.SettingsIniData.Buf.resize((
int)ini_size + 1);
14231 char*
const buf =
g.SettingsIniData.Buf.Data;
14232 char*
const buf_end = buf + ini_size;
14233 memcpy(buf, ini_data, ini_size);
14238 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
14239 if (handler.ReadInitFn != NULL)
14240 handler.ReadInitFn(&
g, &handler);
14242 void* entry_data = NULL;
14243 ImGuiSettingsHandler* entry_handler = NULL;
14245 char* line_end = NULL;
14246 for (
char* line = buf; line < buf_end; line = line_end + 1)
14249 while (*line ==
'\n' || *line ==
'\r')
14252 while (line_end < buf_end && *line_end !=
'\n' && *line_end !=
'\r')
14255 if (line[0] ==
';')
14257 if (line[0] ==
'[' && line_end > line && line_end[-1] ==
']')
14261 const char* name_end = line_end - 1;
14262 const char* type_start = line + 1;
14263 char* type_end = (
char*)(
void*)
ImStrchrRange(type_start, name_end,
']');
14264 const char* name_start = type_end ?
ImStrchrRange(type_end + 1, name_end,
'[') : NULL;
14265 if (!type_end || !name_start)
14269 entry_handler = FindSettingsHandler(type_start);
14270 entry_data = entry_handler ? entry_handler->ReadOpenFn(&
g, entry_handler, name_start) : NULL;
14272 else if (entry_handler != NULL && entry_data != NULL)
14275 entry_handler->ReadLineFn(&
g, entry_handler, entry_data, line);
14278 g.SettingsLoaded =
true;
14281 memcpy(buf, ini_data, ini_size);
14284 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
14285 if (handler.ApplyAllFn != NULL)
14286 handler.ApplyAllFn(&
g, &handler);
14289void ImGui::SaveIniSettingsToDisk(
const char* ini_filename)
14292 g.SettingsDirtyTimer = 0.0f;
14296 size_t ini_data_size = 0;
14297 const char* ini_data = SaveIniSettingsToMemory(&ini_data_size);
14298 ImFileHandle f =
ImFileOpen(ini_filename,
"wt");
14301 ImFileWrite(ini_data,
sizeof(
char), ini_data_size, f);
14306const char* ImGui::SaveIniSettingsToMemory(
size_t* out_size)
14309 g.SettingsDirtyTimer = 0.0f;
14310 g.SettingsIniData.Buf.resize(0);
14311 g.SettingsIniData.Buf.push_back(0);
14312 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
14313 handler.WriteAllFn(&
g, &handler, &
g.SettingsIniData);
14315 *out_size = (size_t)
g.SettingsIniData.size();
14316 return g.SettingsIniData.c_str();
14319ImGuiWindowSettings* ImGui::CreateNewWindowSettings(
const char* name)
14323 if (
g.IO.ConfigDebugIniSettings ==
false)
14327 if (
const char* p = strstr(name,
"###"))
14330 const size_t name_len = strlen(name);
14333 const size_t chunk_size =
sizeof(ImGuiWindowSettings) + name_len + 1;
14334 ImGuiWindowSettings* settings =
g.SettingsWindows.alloc_chunk(chunk_size);
14335 IM_PLACEMENT_NEW(settings) ImGuiWindowSettings();
14336 settings->ID =
ImHashStr(name, name_len);
14337 memcpy(settings->GetName(), name, name_len + 1);
14344ImGuiWindowSettings* ImGui::FindWindowSettingsByID(ImGuiID
id)
14347 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
14348 if (settings->ID ==
id && !settings->WantDelete)
14354ImGuiWindowSettings* ImGui::FindWindowSettingsByWindow(ImGuiWindow* window)
14357 if (window->SettingsOffset != -1)
14358 return g.SettingsWindows.ptr_from_offset(window->SettingsOffset);
14359 return FindWindowSettingsByID(window->ID);
14363void ImGui::ClearWindowSettings(
const char* name)
14367 ImGuiWindow* window = FindWindowByName(name);
14368 if (window != NULL)
14370 window->Flags |= ImGuiWindowFlags_NoSavedSettings;
14371 InitOrLoadWindowSettings(window, NULL);
14372 if (window->DockId != 0)
14373 DockContextProcessUndockWindow(&
g, window,
true);
14375 if (ImGuiWindowSettings* settings = window ? FindWindowSettingsByWindow(window) : FindWindowSettingsByID(
ImHashStr(name)))
14376 settings->WantDelete = true;
14379static void WindowSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
14381 ImGuiContext&
g = *ctx;
14382 for (ImGuiWindow* window :
g.Windows)
14383 window->SettingsOffset = -1;
14384 g.SettingsWindows.clear();
14387static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*,
const char* name)
14390 ImGuiWindowSettings* settings = ImGui::FindWindowSettingsByID(
id);
14392 *settings = ImGuiWindowSettings();
14394 settings = ImGui::CreateNewWindowSettings(name);
14396 settings->WantApply =
true;
14397 return (
void*)settings;
14400static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
void* entry,
const char* line)
14402 ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry;
14406 if (sscanf(line,
"Pos=%i,%i", &x, &y) == 2) { settings->Pos = ImVec2ih((
short)x, (
short)y); }
14407 else if (sscanf(line,
"Size=%i,%i", &x, &y) == 2) { settings->Size = ImVec2ih((
short)x, (
short)y); }
14408 else if (sscanf(line,
"ViewportId=0x%08X", &u1) == 1) { settings->ViewportId = u1; }
14409 else if (sscanf(line,
"ViewportPos=%i,%i", &x, &y) == 2){ settings->ViewportPos = ImVec2ih((
short)x, (
short)y); }
14410 else if (sscanf(line,
"Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); }
14411 else if (sscanf(line,
"IsChild=%d", &i) == 1) { settings->IsChild = (i != 0); }
14412 else if (sscanf(line,
"DockId=0x%X,%d", &u1, &i) == 2) { settings->DockId = u1; settings->DockOrder = (short)i; }
14413 else if (sscanf(line,
"DockId=0x%X", &u1) == 1) { settings->DockId = u1; settings->DockOrder = -1; }
14414 else if (sscanf(line,
"ClassId=0x%X", &u1) == 1) { settings->ClassId = u1; }
14418static void WindowSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
14420 ImGuiContext&
g = *ctx;
14421 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
14422 if (settings->WantApply)
14424 if (ImGuiWindow* window = ImGui::FindWindowByID(settings->ID))
14425 ApplyWindowSettings(window, settings);
14426 settings->WantApply =
false;
14430static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
14434 ImGuiContext&
g = *ctx;
14435 for (ImGuiWindow* window :
g.Windows)
14437 if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
14440 ImGuiWindowSettings* settings = ImGui::FindWindowSettingsByWindow(window);
14443 settings = ImGui::CreateNewWindowSettings(window->Name);
14444 window->SettingsOffset =
g.SettingsWindows.offset_from_ptr(settings);
14446 IM_ASSERT(settings->ID == window->ID);
14447 settings->Pos = ImVec2ih(window->Pos - window->ViewportPos);
14448 settings->Size = ImVec2ih(window->SizeFull);
14449 settings->ViewportId = window->ViewportId;
14450 settings->ViewportPos = ImVec2ih(window->ViewportPos);
14451 IM_ASSERT(window->DockNode == NULL || window->DockNode->ID == window->DockId);
14452 settings->DockId = window->DockId;
14453 settings->ClassId = window->WindowClass.ClassId;
14454 settings->DockOrder = window->DockOrder;
14455 settings->Collapsed = window->Collapsed;
14456 settings->IsChild = (window->RootWindow != window);
14457 settings->WantDelete =
false;
14461 buf->reserve(buf->size() +
g.SettingsWindows.size() * 6);
14462 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
14464 if (settings->WantDelete)
14466 const char* settings_name = settings->GetName();
14467 buf->appendf(
"[%s][%s]\n", handler->TypeName, settings_name);
14468 if (settings->IsChild)
14470 buf->appendf(
"IsChild=1\n");
14471 buf->appendf(
"Size=%d,%d\n", settings->Size.x, settings->Size.y);
14477 buf->appendf(
"ViewportPos=%d,%d\n", settings->ViewportPos.x, settings->ViewportPos.y);
14478 buf->appendf(
"ViewportId=0x%08X\n", settings->ViewportId);
14481 buf->appendf(
"Pos=%d,%d\n", settings->Pos.x, settings->Pos.y);
14482 if (settings->Size.x != 0 || settings->Size.y != 0)
14483 buf->appendf(
"Size=%d,%d\n", settings->Size.x, settings->Size.y);
14484 buf->appendf(
"Collapsed=%d\n", settings->Collapsed);
14485 if (settings->DockId != 0)
14488 if (settings->DockOrder == -1)
14489 buf->appendf(
"DockId=0x%08X\n", settings->DockId);
14491 buf->appendf(
"DockId=0x%08X,%d\n", settings->DockId, settings->DockOrder);
14492 if (settings->ClassId != 0)
14493 buf->appendf(
"ClassId=0x%08X\n", settings->ClassId);
14505void ImGui::LocalizeRegisterEntries(
const ImGuiLocEntry* entries,
int count)
14508 for (
int n = 0; n <
count; n++)
14509 g.LocalizationTable[entries[n].Key] = entries[n].Text;
14541ImGuiViewport* ImGui::GetMainViewport()
14544 return g.Viewports[0];
14548ImGuiViewport* ImGui::FindViewportByID(ImGuiID
id)
14551 for (ImGuiViewportP* viewport :
g.Viewports)
14552 if (viewport->
ID ==
id)
14557ImGuiViewport* ImGui::FindViewportByPlatformHandle(
void* platform_handle)
14560 for (ImGuiViewportP* viewport :
g.Viewports)
14561 if (viewport->PlatformHandle == platform_handle)
14566void ImGui::SetCurrentViewport(ImGuiWindow* current_window, ImGuiViewportP* viewport)
14569 (void)current_window;
14572 viewport->LastFrameActive =
g.FrameCount;
14573 if (
g.CurrentViewport == viewport)
14575 g.CurrentDpiScale = viewport ? viewport->DpiScale : 1.0f;
14576 g.CurrentViewport = viewport;
14581 if (
g.CurrentViewport &&
g.PlatformIO.Platform_OnChangedViewport)
14582 g.PlatformIO.Platform_OnChangedViewport(
g.CurrentViewport);
14585void ImGui::SetWindowViewport(ImGuiWindow* window, ImGuiViewportP* viewport)
14588 if (window->ViewportOwned && window->Viewport->Window == window)
14589 window->Viewport->Size = ImVec2(0.0f, 0.0f);
14591 window->Viewport = viewport;
14592 window->ViewportId = viewport->ID;
14593 window->ViewportOwned = (viewport->Window == window);
14596static bool ImGui::GetWindowAlwaysWantOwnViewport(ImGuiWindow* window)
14600 if (
g.IO.ConfigViewportsNoAutoMerge || (window->WindowClass.ViewportFlagsOverrideSet & ImGuiViewportFlags_NoAutoMerge))
14601 if (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
14602 if (!window->DockIsActive)
14603 if ((window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip)) == 0)
14604 if ((window->Flags & ImGuiWindowFlags_Popup) == 0 || (window->Flags & ImGuiWindowFlags_Modal) != 0)
14609static bool ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* viewport)
14612 if (window->Viewport == viewport)
14614 if ((viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) == 0)
14616 if ((viewport->Flags & ImGuiViewportFlags_IsMinimized) != 0)
14618 if (!viewport->GetMainRect().Contains(window->Rect()))
14620 if (GetWindowAlwaysWantOwnViewport(window))
14624 for (ImGuiWindow* window_behind :
g.Windows)
14626 if (window_behind == window)
14628 if (window_behind->WasActive && window_behind->ViewportOwned && !(window_behind->Flags & ImGuiWindowFlags_ChildWindow))
14629 if (window_behind->Viewport->GetMainRect().Overlaps(window->Rect()))
14634 ImGuiViewportP* old_viewport = window->Viewport;
14635 if (window->ViewportOwned)
14636 for (
int n = 0; n <
g.Windows.Size; n++)
14637 if (
g.Windows[n]->Viewport == old_viewport)
14638 SetWindowViewport(
g.Windows[n], viewport);
14639 SetWindowViewport(window, viewport);
14640 BringWindowToDisplayFront(window);
14646static bool ImGui::UpdateTryMergeWindowIntoHostViewports(ImGuiWindow* window)
14649 return UpdateTryMergeWindowIntoHostViewport(window,
g.Viewports[0]);
14654void ImGui::TranslateWindowsInViewport(ImGuiViewportP* viewport,
const ImVec2& old_pos,
const ImVec2& new_pos)
14657 IM_ASSERT(viewport->Window == NULL && (viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows));
14664 const bool translate_all_windows = (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable) != (
g.ConfigFlagsLastFrame & ImGuiConfigFlags_ViewportsEnable);
14665 ImRect test_still_fit_rect(old_pos, old_pos + viewport->Size);
14666 ImVec2 delta_pos = new_pos - old_pos;
14667 for (ImGuiWindow* window :
g.Windows)
14668 if (translate_all_windows || (window->Viewport == viewport && test_still_fit_rect.Contains(window->Rect())))
14669 TranslateWindow(window, delta_pos);
14673void ImGui::ScaleWindowsInViewport(ImGuiViewportP* viewport,
float scale)
14676 if (viewport->Window)
14678 ScaleWindow(viewport->Window, scale);
14682 for (ImGuiWindow* window :
g.Windows)
14683 if (window->Viewport == viewport)
14684 ScaleWindow(window,
scale);
14691ImGuiViewportP* ImGui::FindHoveredViewportFromPlatformWindowStack(
const ImVec2& mouse_platform_pos)
14694 ImGuiViewportP* best_candidate = NULL;
14695 for (ImGuiViewportP* viewport :
g.Viewports)
14696 if (!(viewport->Flags & (ImGuiViewportFlags_NoInputs | ImGuiViewportFlags_IsMinimized)) && viewport->GetMainRect().Contains(mouse_platform_pos))
14697 if (best_candidate == NULL || best_candidate->LastFocusedStampCount < viewport->LastFocusedStampCount)
14698 best_candidate = viewport;
14699 return best_candidate;
14704static void ImGui::UpdateViewportsNewFrame()
14707 IM_ASSERT(
g.PlatformIO.Viewports.Size <=
g.Viewports.Size);
14711 const bool viewports_enabled = (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable) != 0;
14712 if (viewports_enabled)
14714 ImGuiViewportP* focused_viewport = NULL;
14715 for (ImGuiViewportP* viewport :
g.Viewports)
14717 const bool platform_funcs_available = viewport->PlatformWindowCreated;
14718 if (
g.PlatformIO.Platform_GetWindowMinimized && platform_funcs_available)
14720 bool is_minimized =
g.PlatformIO.Platform_GetWindowMinimized(viewport);
14722 viewport->Flags |= ImGuiViewportFlags_IsMinimized;
14724 viewport->Flags &= ~ImGuiViewportFlags_IsMinimized;
14729 if (
g.PlatformIO.Platform_GetWindowFocus && platform_funcs_available)
14731 bool is_focused =
g.PlatformIO.Platform_GetWindowFocus(viewport);
14733 viewport->Flags |= ImGuiViewportFlags_IsFocused;
14735 viewport->Flags &= ~ImGuiViewportFlags_IsFocused;
14737 focused_viewport = viewport;
14742 if (focused_viewport &&
g.PlatformLastFocusedViewportId != focused_viewport->ID)
14744 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Focused viewport changed %08X -> %08X, attempting to apply our focus.\n",
g.PlatformLastFocusedViewportId, focused_viewport->ID);
14745 const ImGuiViewport* prev_focused_viewport = FindViewportByID(
g.PlatformLastFocusedViewportId);
14746 const bool prev_focused_has_been_destroyed = (prev_focused_viewport == NULL) || (prev_focused_viewport->PlatformWindowCreated ==
false);
14751 if (focused_viewport->LastFocusedStampCount !=
g.ViewportFocusedStampCount)
14752 focused_viewport->LastFocusedStampCount = ++
g.ViewportFocusedStampCount;
14753 g.PlatformLastFocusedViewportId = focused_viewport->ID;
14759 const bool apply_imgui_focus_on_focused_viewport = !IsAnyMouseDown() && !prev_focused_has_been_destroyed;
14760 if (apply_imgui_focus_on_focused_viewport)
14762 focused_viewport->LastFocusedHadNavWindow |= (
g.NavWindow != NULL) && (
g.NavWindow->Viewport == focused_viewport);
14763 ImGuiFocusRequestFlags focus_request_flags = ImGuiFocusRequestFlags_UnlessBelowModal | ImGuiFocusRequestFlags_RestoreFocusedChild;
14764 if (focused_viewport->Window != NULL)
14765 FocusWindow(focused_viewport->Window, focus_request_flags);
14766 else if (focused_viewport->LastFocusedHadNavWindow)
14767 FocusTopMostWindowUnderOne(NULL, NULL, focused_viewport, focus_request_flags);
14769 FocusWindow(NULL, focus_request_flags);
14772 if (focused_viewport)
14773 focused_viewport->LastFocusedHadNavWindow = (
g.NavWindow != NULL) && (
g.NavWindow->Viewport == focused_viewport);
14778 ImGuiViewportP* main_viewport =
g.Viewports[0];
14779 IM_ASSERT(main_viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID);
14780 IM_ASSERT(main_viewport->Window == NULL);
14781 ImVec2 main_viewport_pos = viewports_enabled ?
g.PlatformIO.Platform_GetWindowPos(main_viewport) : ImVec2(0.0f, 0.0f);
14782 ImVec2 main_viewport_size =
g.IO.DisplaySize;
14783 if (viewports_enabled && (main_viewport->Flags & ImGuiViewportFlags_IsMinimized))
14785 main_viewport_pos = main_viewport->Pos;
14786 main_viewport_size = main_viewport->Size;
14788 AddUpdateViewport(NULL, IMGUI_VIEWPORT_DEFAULT_ID, main_viewport_pos, main_viewport_size, ImGuiViewportFlags_OwnedByApp | ImGuiViewportFlags_CanHostOtherWindows);
14790 g.CurrentDpiScale = 0.0f;
14791 g.CurrentViewport = NULL;
14792 g.MouseViewport = NULL;
14793 for (
int n = 0; n <
g.Viewports.Size; n++)
14795 ImGuiViewportP* viewport =
g.Viewports[n];
14799 if (n > 0 && viewport->LastFrameActive <
g.FrameCount - 2)
14801 DestroyViewport(viewport);
14806 const bool platform_funcs_available = viewport->PlatformWindowCreated;
14807 if (viewports_enabled)
14811 if (!(viewport->Flags & ImGuiViewportFlags_IsMinimized) && platform_funcs_available)
14814 if (viewport->PlatformRequestMove)
14815 viewport->Pos = viewport->LastPlatformPos =
g.PlatformIO.Platform_GetWindowPos(viewport);
14816 if (viewport->PlatformRequestResize)
14817 viewport->Size = viewport->LastPlatformSize =
g.PlatformIO.Platform_GetWindowSize(viewport);
14822 UpdateViewportPlatformMonitor(viewport);
14825 viewport->WorkOffsetMin = viewport->BuildWorkOffsetMin;
14826 viewport->WorkOffsetMax = viewport->BuildWorkOffsetMax;
14827 viewport->BuildWorkOffsetMin = viewport->BuildWorkOffsetMax = ImVec2(0.0f, 0.0f);
14828 viewport->UpdateWorkRect();
14831 viewport->Alpha = 1.0f;
14835 const ImVec2 viewport_delta_pos = viewport->Pos - viewport->LastPos;
14836 if ((viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) && (viewport_delta_pos.x != 0.0f || viewport_delta_pos.y != 0.0f))
14837 TranslateWindowsInViewport(viewport, viewport->LastPos, viewport->Pos);
14840 float new_dpi_scale;
14841 if (
g.PlatformIO.Platform_GetWindowDpiScale && platform_funcs_available)
14842 new_dpi_scale =
g.PlatformIO.Platform_GetWindowDpiScale(viewport);
14843 else if (viewport->PlatformMonitor != -1)
14844 new_dpi_scale =
g.PlatformIO.Monitors[viewport->PlatformMonitor].DpiScale;
14846 new_dpi_scale = (viewport->DpiScale != 0.0f) ? viewport->DpiScale : 1.0f;
14847 if (viewport->DpiScale != 0.0f && new_dpi_scale != viewport->DpiScale)
14849 float scale_factor = new_dpi_scale / viewport->DpiScale;
14850 if (
g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports)
14851 ScaleWindowsInViewport(viewport, scale_factor);
14861 viewport->DpiScale = new_dpi_scale;
14865 g.PlatformMonitorsFullWorkRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
14866 if (
g.PlatformIO.Monitors.Size == 0)
14868 ImGuiPlatformMonitor* monitor = &
g.FallbackMonitor;
14869 monitor->MainPos = main_viewport->Pos;
14870 monitor->MainSize = main_viewport->Size;
14871 monitor->WorkPos = main_viewport->WorkPos;
14872 monitor->WorkSize = main_viewport->WorkSize;
14873 monitor->DpiScale = main_viewport->DpiScale;
14874 g.PlatformMonitorsFullWorkRect.Add(monitor->WorkPos);
14875 g.PlatformMonitorsFullWorkRect.Add(monitor->WorkPos + monitor->WorkSize);
14877 for (ImGuiPlatformMonitor& monitor :
g.PlatformIO.Monitors)
14879 g.PlatformMonitorsFullWorkRect.Add(monitor.WorkPos);
14880 g.PlatformMonitorsFullWorkRect.Add(monitor.WorkPos + monitor.WorkSize);
14883 if (!viewports_enabled)
14885 g.MouseViewport = main_viewport;
14891 ImGuiViewportP* viewport_hovered = NULL;
14892 if (
g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport)
14894 viewport_hovered =
g.IO.MouseHoveredViewport ? (ImGuiViewportP*)FindViewportByID(
g.IO.MouseHoveredViewport) : NULL;
14895 if (viewport_hovered && (viewport_hovered->Flags & ImGuiViewportFlags_NoInputs))
14896 viewport_hovered = FindHoveredViewportFromPlatformWindowStack(
g.IO.MousePos);
14904 viewport_hovered = FindHoveredViewportFromPlatformWindowStack(
g.IO.MousePos);
14906 if (viewport_hovered != NULL)
14907 g.MouseLastHoveredViewport = viewport_hovered;
14908 else if (
g.MouseLastHoveredViewport == NULL)
14909 g.MouseLastHoveredViewport =
g.Viewports[0];
14914 if (
g.MovingWindow &&
g.MovingWindow->Viewport)
14915 g.MouseViewport =
g.MovingWindow->Viewport;
14917 g.MouseViewport =
g.MouseLastHoveredViewport;
14924 const bool is_mouse_dragging_with_an_expected_destination =
g.DragDropActive;
14925 if (is_mouse_dragging_with_an_expected_destination && viewport_hovered == NULL)
14926 viewport_hovered =
g.MouseLastHoveredViewport;
14927 if (is_mouse_dragging_with_an_expected_destination ||
g.ActiveId == 0 || !IsAnyMouseDown())
14928 if (viewport_hovered != NULL && viewport_hovered !=
g.MouseViewport && !(viewport_hovered->Flags & ImGuiViewportFlags_NoInputs))
14929 g.MouseViewport = viewport_hovered;
14931 IM_ASSERT(
g.MouseViewport != NULL);
14935static void ImGui::UpdateViewportsEndFrame()
14938 g.PlatformIO.Viewports.resize(0);
14939 for (
int i = 0; i <
g.Viewports.Size; i++)
14941 ImGuiViewportP* viewport =
g.Viewports[i];
14942 viewport->LastPos = viewport->Pos;
14943 if (viewport->LastFrameActive <
g.FrameCount || viewport->Size.x <= 0.0f || viewport->Size.y <= 0.0f)
14946 if (viewport->Window && !IsWindowActiveAndVisible(viewport->Window))
14949 IM_ASSERT(viewport->Window != NULL);
14950 g.PlatformIO.Viewports.push_back(viewport);
14952 g.Viewports[0]->ClearRequestFlags();
14956ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID
id,
const ImVec2& pos,
const ImVec2& size, ImGuiViewportFlags flags)
14959 IM_ASSERT(
id != 0);
14961 flags |= ImGuiViewportFlags_IsPlatformWindow;
14962 if (window != NULL)
14964 if (
g.MovingWindow &&
g.MovingWindow->RootWindowDockTree == window)
14965 flags |= ImGuiViewportFlags_NoInputs | ImGuiViewportFlags_NoFocusOnAppearing;
14966 if ((window->Flags & ImGuiWindowFlags_NoMouseInputs) && (window->Flags & ImGuiWindowFlags_NoNavInputs))
14967 flags |= ImGuiViewportFlags_NoInputs;
14968 if (window->Flags & ImGuiWindowFlags_NoFocusOnAppearing)
14969 flags |= ImGuiViewportFlags_NoFocusOnAppearing;
14972 ImGuiViewportP* viewport = (ImGuiViewportP*)FindViewportByID(
id);
14976 if (!viewport->PlatformRequestMove || viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID)
14977 viewport->Pos = pos;
14978 if (!viewport->PlatformRequestResize || viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID)
14979 viewport->Size =
size;
14980 viewport->Flags = flags | (viewport->Flags & (ImGuiViewportFlags_IsMinimized | ImGuiViewportFlags_IsFocused));
14985 viewport = IM_NEW(ImGuiViewportP)();
14987 viewport->Idx =
g.Viewports.Size;
14988 viewport->Pos = viewport->LastPos = pos;
14989 viewport->Size =
size;
14990 viewport->Flags = flags;
14991 UpdateViewportPlatformMonitor(viewport);
14992 g.Viewports.push_back(viewport);
14993 g.ViewportCreatedCount++;
14994 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Add Viewport %08X '%s'\n",
id, window ? window->Name :
"<NULL>");
14998 g.DrawListSharedData.ClipRectFullscreen.x = ImMin(
g.DrawListSharedData.ClipRectFullscreen.x, viewport->Pos.x);
14999 g.DrawListSharedData.ClipRectFullscreen.y = ImMin(
g.DrawListSharedData.ClipRectFullscreen.y, viewport->Pos.y);
15000 g.DrawListSharedData.ClipRectFullscreen.z = ImMax(
g.DrawListSharedData.ClipRectFullscreen.z, viewport->Pos.x + viewport->Size.x);
15001 g.DrawListSharedData.ClipRectFullscreen.w = ImMax(
g.DrawListSharedData.ClipRectFullscreen.w, viewport->Pos.y + viewport->Size.y);
15005 if (viewport->PlatformMonitor != -1)
15006 viewport->DpiScale =
g.PlatformIO.Monitors[viewport->PlatformMonitor].DpiScale;
15009 viewport->Window = window;
15010 viewport->LastFrameActive =
g.FrameCount;
15011 viewport->UpdateWorkRect();
15012 IM_ASSERT(window == NULL || viewport->ID == window->ID);
15014 if (window != NULL)
15015 window->ViewportOwned =
true;
15020static void ImGui::DestroyViewport(ImGuiViewportP* viewport)
15024 for (ImGuiWindow* window :
g.Windows)
15026 if (window->Viewport != viewport)
15028 window->Viewport = NULL;
15029 window->ViewportOwned =
false;
15031 if (viewport ==
g.MouseLastHoveredViewport)
15032 g.MouseLastHoveredViewport = NULL;
15035 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Delete Viewport %08X '%s'\n", viewport->ID, viewport->Window ? viewport->Window->Name :
"n/a");
15036 DestroyPlatformWindow(viewport);
15037 IM_ASSERT(
g.PlatformIO.Viewports.contains(viewport) ==
false);
15038 IM_ASSERT(
g.Viewports[viewport->Idx] == viewport);
15039 g.Viewports.erase(
g.Viewports.Data + viewport->Idx);
15040 IM_DELETE(viewport);
15044static void ImGui::WindowSelectViewport(ImGuiWindow* window)
15047 ImGuiWindowFlags flags = window->Flags;
15048 window->ViewportAllowPlatformMonitorExtend = -1;
15051 ImGuiViewportP* main_viewport = (ImGuiViewportP*)(
void*)GetMainViewport();
15052 if (!(
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable))
15054 SetWindowViewport(window, main_viewport);
15057 window->ViewportOwned =
false;
15060 if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && window->Appearing)
15062 window->Viewport = NULL;
15063 window->ViewportId = 0;
15066 if ((
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasViewport) == 0)
15069 if (window->Viewport == NULL && window->ParentWindow && (!window->ParentWindow->IsFallbackWindow || window->ParentWindow->WasActive))
15070 window->Viewport = window->ParentWindow->Viewport;
15073 if (window->Viewport == NULL && window->ViewportId != 0)
15075 window->Viewport = (ImGuiViewportP*)FindViewportByID(window->ViewportId);
15076 if (window->Viewport == NULL && window->ViewportPos.x != FLT_MAX && window->ViewportPos.y != FLT_MAX)
15077 window->Viewport = AddUpdateViewport(window, window->ID, window->ViewportPos, window->Size, ImGuiViewportFlags_None);
15081 bool lock_viewport =
false;
15082 if (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasViewport)
15085 window->Viewport = (ImGuiViewportP*)FindViewportByID(
g.NextWindowData.ViewportId);
15086 window->ViewportId =
g.NextWindowData.ViewportId;
15087 if (window->Viewport && (window->Flags & ImGuiWindowFlags_DockNodeHost) != 0 && window->Viewport->Window != NULL)
15089 window->Viewport->Window = window;
15090 window->Viewport->ID = window->ViewportId = window->ID;
15092 lock_viewport =
true;
15094 else if ((flags & ImGuiWindowFlags_ChildWindow) || (flags & ImGuiWindowFlags_ChildMenu))
15097 if (window->DockNode && window->DockNode->HostWindow)
15098 IM_ASSERT(window->DockNode->HostWindow->Viewport == window->ParentWindow->Viewport);
15099 window->Viewport = window->ParentWindow->Viewport;
15101 else if (window->DockNode && window->DockNode->HostWindow)
15104 window->Viewport = window->DockNode->HostWindow->Viewport;
15106 else if (flags & ImGuiWindowFlags_Tooltip)
15108 window->Viewport =
g.MouseViewport;
15110 else if (GetWindowAlwaysWantOwnViewport(window))
15112 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
15114 else if (
g.MovingWindow &&
g.MovingWindow->RootWindowDockTree == window && IsMousePosValid())
15116 if (window->Viewport != NULL && window->Viewport->Window == window)
15117 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
15124 bool try_to_merge_into_host_viewport = (window->Viewport && window == window->Viewport->Window && (
g.ActiveId == 0 ||
g.ActiveIdAllowOverlap));
15125 if (try_to_merge_into_host_viewport)
15126 UpdateTryMergeWindowIntoHostViewports(window);
15130 if (window->Viewport == NULL)
15131 if (!UpdateTryMergeWindowIntoHostViewport(window, main_viewport))
15132 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
15135 if (!lock_viewport)
15137 if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
15141 ImVec2 mouse_ref = (flags & ImGuiWindowFlags_Tooltip) ?
g.IO.MousePos :
g.BeginPopupStack.back().OpenMousePos;
15142 bool use_mouse_ref = (
g.NavDisableHighlight || !
g.NavDisableMouseHover || !
g.NavWindow);
15143 bool mouse_valid = IsMousePosValid(&mouse_ref);
15144 if ((window->Appearing || (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_ChildMenu))) && (!use_mouse_ref || mouse_valid))
15145 window->ViewportAllowPlatformMonitorExtend = FindPlatformMonitorForPos((use_mouse_ref && mouse_valid) ? mouse_ref : NavCalcPreferredRefPos());
15147 window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor;
15149 else if (window->Viewport && window != window->Viewport->Window && window->Viewport->Window && !(flags & ImGuiWindowFlags_ChildWindow) && window->DockNode == NULL)
15152 const bool will_be_visible = (window->DockIsActive && !window->DockTabIsVisible) ?
false : true;
15153 if ((window->Flags & ImGuiWindowFlags_DockNodeHost) && window->Viewport->LastFrameActive <
g.FrameCount && will_be_visible)
15156 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Window '%s' steal Viewport %08X from Window '%s'\n", window->Name, window->Viewport->ID, window->Viewport->Window->Name);
15157 window->Viewport->Window = window;
15158 window->Viewport->ID = window->ID;
15159 window->Viewport->LastNameHash = 0;
15161 else if (!UpdateTryMergeWindowIntoHostViewports(window))
15164 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoFocusOnAppearing);
15167 else if (window->ViewportAllowPlatformMonitorExtend < 0 && (flags & ImGuiWindowFlags_ChildWindow) == 0)
15171 window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor;
15176 window->ViewportOwned = (window == window->Viewport->Window);
15177 window->ViewportId = window->Viewport->ID;
15184void ImGui::WindowSyncOwnedViewport(ImGuiWindow* window, ImGuiWindow* parent_window_in_stack)
15188 bool viewport_rect_changed =
false;
15192 if (window->Viewport->PlatformRequestMove)
15194 window->Pos = window->Viewport->Pos;
15195 MarkIniSettingsDirty(window);
15197 else if (memcmp(&window->Viewport->Pos, &window->Pos,
sizeof(window->Pos)) != 0)
15199 viewport_rect_changed =
true;
15200 window->Viewport->Pos = window->Pos;
15203 if (window->Viewport->PlatformRequestResize)
15205 window->Size = window->SizeFull = window->Viewport->Size;
15206 MarkIniSettingsDirty(window);
15208 else if (memcmp(&window->Viewport->Size, &window->Size,
sizeof(window->Size)) != 0)
15210 viewport_rect_changed =
true;
15211 window->Viewport->Size = window->Size;
15213 window->Viewport->UpdateWorkRect();
15217 if (viewport_rect_changed)
15218 UpdateViewportPlatformMonitor(window->Viewport);
15221 const ImGuiViewportFlags viewport_flags_to_clear = ImGuiViewportFlags_TopMost | ImGuiViewportFlags_NoTaskBarIcon | ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoRendererClear;
15222 ImGuiViewportFlags viewport_flags = window->Viewport->Flags & ~viewport_flags_to_clear;
15223 ImGuiWindowFlags window_flags = window->Flags;
15224 const bool is_modal = (window_flags & ImGuiWindowFlags_Modal) != 0;
15225 const bool is_short_lived_floating_window = (window_flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0;
15226 if (window_flags & ImGuiWindowFlags_Tooltip)
15227 viewport_flags |= ImGuiViewportFlags_TopMost;
15228 if ((
g.IO.ConfigViewportsNoTaskBarIcon || is_short_lived_floating_window) && !is_modal)
15229 viewport_flags |= ImGuiViewportFlags_NoTaskBarIcon;
15230 if (
g.IO.ConfigViewportsNoDecoration || is_short_lived_floating_window)
15231 viewport_flags |= ImGuiViewportFlags_NoDecoration;
15243 if (is_short_lived_floating_window && !is_modal)
15244 viewport_flags |= ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoFocusOnClick;
15247 if (window->WindowClass.ViewportFlagsOverrideSet)
15248 viewport_flags |= window->WindowClass.ViewportFlagsOverrideSet;
15249 if (window->WindowClass.ViewportFlagsOverrideClear)
15250 viewport_flags &= ~window->WindowClass.ViewportFlagsOverrideClear;
15255 if (!(window_flags & ImGuiWindowFlags_NoBackground))
15256 viewport_flags |= ImGuiViewportFlags_NoRendererClear;
15258 window->Viewport->Flags = viewport_flags;
15262 if (window->WindowClass.ParentViewportId != (ImGuiID)-1)
15263 window->Viewport->ParentViewportId = window->WindowClass.ParentViewportId;
15264 else if ((window_flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && parent_window_in_stack && (!parent_window_in_stack->IsFallbackWindow || parent_window_in_stack->WasActive))
15265 window->Viewport->ParentViewportId = parent_window_in_stack->Viewport->ID;
15272void ImGui::UpdatePlatformWindows()
15275 IM_ASSERT(
g.FrameCountEnded ==
g.FrameCount &&
"Forgot to call Render() or EndFrame() before UpdatePlatformWindows()?");
15276 IM_ASSERT(
g.FrameCountPlatformEnded <
g.FrameCount);
15277 g.FrameCountPlatformEnded =
g.FrameCount;
15278 if (!(
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable))
15283 for (
int i = 1; i <
g.Viewports.Size; i++)
15285 ImGuiViewportP* viewport =
g.Viewports[i];
15289 bool destroy_platform_window =
false;
15290 destroy_platform_window |= (viewport->LastFrameActive <
g.FrameCount - 1);
15291 destroy_platform_window |= (viewport->Window && !IsWindowActiveAndVisible(viewport->Window));
15292 if (destroy_platform_window)
15294 DestroyPlatformWindow(viewport);
15299 if (viewport->LastFrameActive <
g.FrameCount || viewport->Size.x <= 0 || viewport->Size.y <= 0)
15303 const bool is_new_platform_window = (viewport->PlatformWindowCreated ==
false);
15304 if (is_new_platform_window)
15306 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Create Platform Window %08X '%s'\n", viewport->ID, viewport->Window ? viewport->Window->Name :
"n/a");
15307 g.PlatformIO.Platform_CreateWindow(viewport);
15308 if (
g.PlatformIO.Renderer_CreateWindow != NULL)
15309 g.PlatformIO.Renderer_CreateWindow(viewport);
15310 g.PlatformWindowsCreatedCount++;
15311 viewport->LastNameHash = 0;
15312 viewport->LastPlatformPos = viewport->LastPlatformSize = ImVec2(FLT_MAX, FLT_MAX);
15313 viewport->LastRendererSize = viewport->Size;
15314 viewport->PlatformWindowCreated =
true;
15318 if ((viewport->LastPlatformPos.x != viewport->Pos.x || viewport->LastPlatformPos.y != viewport->Pos.y) && !viewport->PlatformRequestMove)
15319 g.PlatformIO.Platform_SetWindowPos(viewport, viewport->Pos);
15320 if ((viewport->LastPlatformSize.x != viewport->Size.x || viewport->LastPlatformSize.y != viewport->Size.y) && !viewport->PlatformRequestResize)
15321 g.PlatformIO.Platform_SetWindowSize(viewport, viewport->Size);
15322 if ((viewport->LastRendererSize.x != viewport->Size.x || viewport->LastRendererSize.y != viewport->Size.y) &&
g.PlatformIO.Renderer_SetWindowSize)
15323 g.PlatformIO.Renderer_SetWindowSize(viewport, viewport->Size);
15324 viewport->LastPlatformPos = viewport->Pos;
15325 viewport->LastPlatformSize = viewport->LastRendererSize = viewport->Size;
15328 if (ImGuiWindow* window_for_title = GetWindowForTitleDisplay(viewport->Window))
15330 const char* title_begin = window_for_title->Name;
15331 char* title_end = (
char*)(intptr_t)FindRenderedTextEnd(title_begin);
15332 const ImGuiID title_hash =
ImHashStr(title_begin, title_end - title_begin);
15333 if (viewport->LastNameHash != title_hash)
15335 char title_end_backup_c = *title_end;
15337 g.PlatformIO.Platform_SetWindowTitle(viewport, title_begin);
15338 *title_end = title_end_backup_c;
15339 viewport->LastNameHash = title_hash;
15344 if (viewport->LastAlpha != viewport->Alpha &&
g.PlatformIO.Platform_SetWindowAlpha)
15345 g.PlatformIO.Platform_SetWindowAlpha(viewport, viewport->Alpha);
15346 viewport->LastAlpha = viewport->Alpha;
15349 if (
g.PlatformIO.Platform_UpdateWindow)
15350 g.PlatformIO.Platform_UpdateWindow(viewport);
15352 if (is_new_platform_window)
15355 if (
g.FrameCount < 3)
15356 viewport->Flags |= ImGuiViewportFlags_NoFocusOnAppearing;
15359 g.PlatformIO.Platform_ShowWindow(viewport);
15363 if (viewport->LastFocusedStampCount !=
g.ViewportFocusedStampCount)
15364 viewport->LastFocusedStampCount = ++
g.ViewportFocusedStampCount;
15368 viewport->ClearRequestFlags();
15384void ImGui::RenderPlatformWindowsDefault(
void* platform_render_arg,
void* renderer_render_arg)
15387 ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
15388 for (
int i = 1; i < platform_io.Viewports.Size; i++)
15390 ImGuiViewport* viewport = platform_io.Viewports[i];
15391 if (viewport->Flags & ImGuiViewportFlags_IsMinimized)
15393 if (platform_io.Platform_RenderWindow) platform_io.Platform_RenderWindow(viewport, platform_render_arg);
15394 if (platform_io.Renderer_RenderWindow) platform_io.Renderer_RenderWindow(viewport, renderer_render_arg);
15396 for (
int i = 1; i < platform_io.Viewports.Size; i++)
15398 ImGuiViewport* viewport = platform_io.Viewports[i];
15399 if (viewport->Flags & ImGuiViewportFlags_IsMinimized)
15401 if (platform_io.Platform_SwapBuffers) platform_io.Platform_SwapBuffers(viewport, platform_render_arg);
15402 if (platform_io.Renderer_SwapBuffers) platform_io.Renderer_SwapBuffers(viewport, renderer_render_arg);
15406static int ImGui::FindPlatformMonitorForPos(
const ImVec2& pos)
15409 for (
int monitor_n = 0; monitor_n <
g.PlatformIO.Monitors.Size; monitor_n++)
15411 const ImGuiPlatformMonitor& monitor =
g.PlatformIO.Monitors[monitor_n];
15412 if (ImRect(monitor.MainPos, monitor.MainPos + monitor.MainSize).Contains(pos))
15421static int ImGui::FindPlatformMonitorForRect(
const ImRect& rect)
15425 const int monitor_count =
g.PlatformIO.Monitors.Size;
15426 if (monitor_count <= 1)
15427 return monitor_count - 1;
15431 const float surface_threshold = ImMax(rect.GetWidth() * rect.GetHeight() * 0.5f, 1.0f);
15432 int best_monitor_n = -1;
15433 float best_monitor_surface = 0.001f;
15435 for (
int monitor_n = 0; monitor_n <
g.PlatformIO.Monitors.Size && best_monitor_surface < surface_threshold; monitor_n++)
15437 const ImGuiPlatformMonitor& monitor =
g.PlatformIO.Monitors[monitor_n];
15438 const ImRect monitor_rect = ImRect(monitor.MainPos, monitor.MainPos + monitor.MainSize);
15439 if (monitor_rect.Contains(rect))
15441 ImRect overlapping_rect = rect;
15442 overlapping_rect.ClipWithFull(monitor_rect);
15443 float overlapping_surface = overlapping_rect.GetWidth() * overlapping_rect.GetHeight();
15444 if (overlapping_surface < best_monitor_surface)
15446 best_monitor_surface = overlapping_surface;
15447 best_monitor_n = monitor_n;
15449 return best_monitor_n;
15453static void ImGui::UpdateViewportPlatformMonitor(ImGuiViewportP* viewport)
15455 viewport->PlatformMonitor = (short)FindPlatformMonitorForRect(viewport->GetMainRect());
15459const ImGuiPlatformMonitor* ImGui::GetViewportPlatformMonitor(ImGuiViewport* viewport_p)
15462 ImGuiViewportP* viewport = (ImGuiViewportP*)(
void*)viewport_p;
15463 int monitor_idx = viewport->PlatformMonitor;
15464 if (monitor_idx >= 0 && monitor_idx <
g.PlatformIO.Monitors.Size)
15465 return &
g.PlatformIO.Monitors[monitor_idx];
15466 return &
g.FallbackMonitor;
15469void ImGui::DestroyPlatformWindow(ImGuiViewportP* viewport)
15472 if (viewport->PlatformWindowCreated)
15474 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Destroy Platform Window %08X '%s'\n", viewport->ID, viewport->Window ? viewport->Window->Name :
"n/a");
15475 if (
g.PlatformIO.Renderer_DestroyWindow)
15476 g.PlatformIO.Renderer_DestroyWindow(viewport);
15477 if (
g.PlatformIO.Platform_DestroyWindow)
15478 g.PlatformIO.Platform_DestroyWindow(viewport);
15479 IM_ASSERT(viewport->RendererUserData == NULL && viewport->PlatformUserData == NULL);
15483 if (viewport->ID != IMGUI_VIEWPORT_DEFAULT_ID)
15484 viewport->PlatformWindowCreated =
false;
15488 IM_ASSERT(viewport->RendererUserData == NULL && viewport->PlatformUserData == NULL && viewport->PlatformHandle == NULL);
15490 viewport->RendererUserData = viewport->PlatformUserData = viewport->PlatformHandle = NULL;
15491 viewport->ClearRequestFlags();
15494void ImGui::DestroyPlatformWindows()
15503 for (ImGuiViewportP* viewport :
g.Viewports)
15504 DestroyPlatformWindow(viewport);
15649 static ImGuiDockNode* DockContextAddNode(ImGuiContext* ctx, ImGuiID
id);
15650 static void DockContextRemoveNode(ImGuiContext* ctx, ImGuiDockNode* node,
bool merge_sibling_into_parent_node);
15651 static void DockContextQueueNotifyRemovedNode(ImGuiContext* ctx, ImGuiDockNode* node);
15652 static void DockContextProcessDock(ImGuiContext* ctx,
ImGuiDockRequest* req);
15653 static void DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx);
15654 static ImGuiDockNode* DockContextBindNodeToWindow(ImGuiContext* ctx, ImGuiWindow* window);
15655 static void DockContextBuildNodesFromSettings(ImGuiContext* ctx,
ImGuiDockNodeSettings* node_settings_array,
int node_settings_count);
15656 static void DockContextBuildAddWindowsToNodes(ImGuiContext* ctx, ImGuiID root_id);
15659 static void DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window,
bool add_to_tab_bar);
15660 static void DockNodeMoveWindows(ImGuiDockNode* dst_node, ImGuiDockNode* src_node);
15661 static void DockNodeMoveChildNodes(ImGuiDockNode* dst_node, ImGuiDockNode* src_node);
15662 static ImGuiWindow* DockNodeFindWindowByID(ImGuiDockNode* node, ImGuiID
id);
15663 static void DockNodeApplyPosSizeToWindows(ImGuiDockNode* node);
15664 static void DockNodeRemoveWindow(ImGuiDockNode* node, ImGuiWindow* window, ImGuiID save_dock_id);
15665 static void DockNodeHideHostWindow(ImGuiDockNode* node);
15666 static void DockNodeUpdate(ImGuiDockNode* node);
15667 static void DockNodeUpdateForRootNode(ImGuiDockNode* node);
15668 static void DockNodeUpdateFlagsAndCollapse(ImGuiDockNode* node);
15669 static void DockNodeUpdateHasCentralNodeChild(ImGuiDockNode* node);
15670 static void DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_window);
15671 static void DockNodeAddTabBar(ImGuiDockNode* node);
15672 static void DockNodeRemoveTabBar(ImGuiDockNode* node);
15673 static void DockNodeWindowMenuUpdate(ImGuiDockNode* node, ImGuiTabBar* tab_bar);
15674 static void DockNodeUpdateVisibleFlag(ImGuiDockNode* node);
15675 static void DockNodeStartMouseMovingWindow(ImGuiDockNode* node, ImGuiWindow* window);
15676 static bool DockNodeIsDropAllowed(ImGuiWindow* host_window, ImGuiWindow* payload_window);
15677 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);
15678 static void DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window,
const ImGuiDockPreviewData* preview_data);
15679 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);
15680 static void DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& pos_new, ImVec2& size_new, ImGuiDir dir, ImVec2 size_new_desired);
15681 static bool DockNodeCalcDropRectsAndTestMousePos(
const ImRect& parent, ImGuiDir dir, ImRect& out_draw,
bool outer_docking, ImVec2* test_mouse_pos);
15682 static const char* DockNodeGetHostWindowTitle(ImGuiDockNode* node,
char* buf,
int buf_size) {
ImFormatString(buf, buf_size,
"##DockNode_%02X", node->ID);
return buf; }
15683 static int DockNodeGetTabOrder(ImGuiWindow* window);
15686 static void DockNodeTreeSplit(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiAxis split_axis,
int split_first_child,
float split_ratio, ImGuiDockNode* new_node);
15687 static void DockNodeTreeMerge(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiDockNode* merge_lead_child);
15688 static void DockNodeTreeUpdatePosSize(ImGuiDockNode* node, ImVec2 pos, ImVec2 size, ImGuiDockNode* only_write_to_single_node = NULL);
15689 static void DockNodeTreeUpdateSplitter(ImGuiDockNode* node);
15690 static ImGuiDockNode* DockNodeTreeFindVisibleNodeByPos(ImGuiDockNode* node, ImVec2 pos);
15691 static ImGuiDockNode* DockNodeTreeFindFallbackLeafNode(ImGuiDockNode* node);
15694 static void DockSettingsRenameNodeReferences(ImGuiID old_node_id, ImGuiID new_node_id);
15695 static void DockSettingsRemoveNodeReferences(ImGuiID* node_ids,
int node_ids_count);
15697 static void DockSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*);
15698 static void DockSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*);
15699 static void* DockSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*,
const char* name);
15700 static void DockSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
void* entry,
const char* line);
15701 static void DockSettingsHandler_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf);
15732void ImGui::DockContextInitialize(ImGuiContext* ctx)
15734 ImGuiContext&
g = *ctx;
15737 ImGuiSettingsHandler ini_handler;
15738 ini_handler.TypeName =
"Docking";
15739 ini_handler.TypeHash =
ImHashStr(
"Docking");
15740 ini_handler.ClearAllFn = DockSettingsHandler_ClearAll;
15741 ini_handler.ReadInitFn = DockSettingsHandler_ClearAll;
15742 ini_handler.ReadOpenFn = DockSettingsHandler_ReadOpen;
15743 ini_handler.ReadLineFn = DockSettingsHandler_ReadLine;
15744 ini_handler.ApplyAllFn = DockSettingsHandler_ApplyAll;
15745 ini_handler.WriteAllFn = DockSettingsHandler_WriteAll;
15746 g.SettingsHandlers.push_back(ini_handler);
15748 g.DockNodeWindowMenuHandler = &DockNodeWindowMenuHandler_Default;
15751void ImGui::DockContextShutdown(ImGuiContext* ctx)
15753 ImGuiDockContext* dc = &ctx->DockContext;
15754 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
15755 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
15759void ImGui::DockContextClearNodes(ImGuiContext* ctx, ImGuiID root_id,
bool clear_settings_refs)
15762 IM_ASSERT(ctx ==
GImGui);
15763 DockBuilderRemoveNodeDockedWindows(root_id, clear_settings_refs);
15764 DockBuilderRemoveNodeChildNodes(root_id);
15769void ImGui::DockContextRebuildNodes(ImGuiContext* ctx)
15771 ImGuiContext&
g = *ctx;
15772 ImGuiDockContext* dc = &ctx->DockContext;
15773 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextRebuildNodes\n");
15774 SaveIniSettingsToMemory();
15775 ImGuiID root_id = 0;
15776 DockContextClearNodes(ctx, root_id,
false);
15777 DockContextBuildNodesFromSettings(ctx, dc->NodesSettings.Data, dc->NodesSettings.Size);
15778 DockContextBuildAddWindowsToNodes(ctx, root_id);
15782void ImGui::DockContextNewFrameUpdateUndocking(ImGuiContext* ctx)
15784 ImGuiContext&
g = *ctx;
15785 ImGuiDockContext* dc = &ctx->DockContext;
15786 if (!(
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
15788 if (dc->Nodes.Data.Size > 0 || dc->Requests.Size > 0)
15789 DockContextClearNodes(ctx, 0,
true);
15794 if (
g.IO.ConfigDockingNoSplit)
15795 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
15796 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
15797 if (node->IsRootNode() && node->IsSplitNode())
15799 DockBuilderRemoveNodeChildNodes(node->ID);
15805 if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_C)))
15806 dc->WantFullRebuild =
true;
15808 if (dc->WantFullRebuild)
15810 DockContextRebuildNodes(ctx);
15811 dc->WantFullRebuild =
false;
15818 DockContextProcessUndockWindow(ctx, req.UndockTargetWindow);
15820 DockContextProcessUndockNode(ctx, req.UndockTargetNode);
15825void ImGui::DockContextNewFrameUpdateDocking(ImGuiContext* ctx)
15827 ImGuiContext&
g = *ctx;
15828 ImGuiDockContext* dc = &ctx->DockContext;
15829 if (!(
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
15835 g.DebugHoveredDockNode = NULL;
15836 if (ImGuiWindow* hovered_window =
g.HoveredWindowUnderMovingWindow)
15838 if (hovered_window->DockNodeAsHost)
15839 g.DebugHoveredDockNode = DockNodeTreeFindVisibleNodeByPos(hovered_window->DockNodeAsHost,
g.IO.MousePos);
15840 else if (hovered_window->RootWindow->DockNode)
15841 g.DebugHoveredDockNode = hovered_window->RootWindow->DockNode;
15847 DockContextProcessDock(ctx, &req);
15848 dc->Requests.resize(0);
15852 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
15853 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
15854 if (node->IsFloatingNode())
15855 DockNodeUpdate(node);
15858void ImGui::DockContextEndFrame(ImGuiContext* ctx)
15861 ImGuiContext&
g = *ctx;
15862 ImGuiDockContext* dc = &
g.DockContext;
15863 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
15864 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
15865 if (node->LastFrameActive ==
g.FrameCount && node->IsVisible && node->HostWindow && node->IsLeafNode() && !node->IsBgDrawnThisFrame)
15867 ImRect bg_rect(node->Pos + ImVec2(0.0f, GetFrameHeight()), node->Pos + node->Size);
15868 ImDrawFlags bg_rounding_flags = CalcRoundingFlagsForRectInRect(bg_rect, node->HostWindow->Rect(),
g.Style.DockingSeparatorSize);
15869 node->HostWindow->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
15870 node->HostWindow->DrawList->AddRectFilled(bg_rect.Min, bg_rect.Max, node->LastBgColor, node->HostWindow->WindowRounding, bg_rounding_flags);
15874ImGuiDockNode* ImGui::DockContextFindNodeByID(ImGuiContext* ctx, ImGuiID
id)
15876 return (ImGuiDockNode*)ctx->DockContext.Nodes.GetVoidPtr(
id);
15879ImGuiID ImGui::DockContextGenNodeID(ImGuiContext* ctx)
15884 ImGuiID
id = 0x0001;
15885 while (DockContextFindNodeByID(ctx,
id) != NULL)
15890static ImGuiDockNode* ImGui::DockContextAddNode(ImGuiContext* ctx, ImGuiID
id)
15893 ImGuiContext&
g = *ctx;
15895 id = DockContextGenNodeID(ctx);
15897 IM_ASSERT(DockContextFindNodeByID(ctx,
id) == NULL);
15900 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextAddNode 0x%08X\n",
id);
15901 ImGuiDockNode* node = IM_NEW(ImGuiDockNode)(
id);
15902 ctx->DockContext.Nodes.SetVoidPtr(node->ID, node);
15906static void ImGui::DockContextRemoveNode(ImGuiContext* ctx, ImGuiDockNode* node,
bool merge_sibling_into_parent_node)
15908 ImGuiContext&
g = *ctx;
15909 ImGuiDockContext* dc = &ctx->DockContext;
15911 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextRemoveNode 0x%08X\n", node->ID);
15912 IM_ASSERT(DockContextFindNodeByID(ctx, node->ID) == node);
15913 IM_ASSERT(node->ChildNodes[0] == NULL && node->ChildNodes[1] == NULL);
15914 IM_ASSERT(node->Windows.Size == 0);
15916 if (node->HostWindow)
15917 node->HostWindow->DockNodeAsHost = NULL;
15919 ImGuiDockNode* parent_node = node->ParentNode;
15920 const bool merge = (merge_sibling_into_parent_node && parent_node != NULL);
15923 IM_ASSERT(parent_node->ChildNodes[0] == node || parent_node->ChildNodes[1] == node);
15924 ImGuiDockNode* sibling_node = (parent_node->ChildNodes[0] == node ? parent_node->ChildNodes[1] : parent_node->ChildNodes[0]);
15925 DockNodeTreeMerge(&
g, parent_node, sibling_node);
15929 for (
int n = 0; parent_node && n < IM_ARRAYSIZE(parent_node->ChildNodes); n++)
15930 if (parent_node->ChildNodes[n] == node)
15931 node->ParentNode->ChildNodes[n] = NULL;
15932 dc->Nodes.SetVoidPtr(node->ID, NULL);
15937static int IMGUI_CDECL DockNodeComparerDepthMostFirst(
const void* lhs,
const void* rhs)
15939 const ImGuiDockNode* a = *(
const ImGuiDockNode*
const*)lhs;
15940 const ImGuiDockNode* b = *(
const ImGuiDockNode*
const*)rhs;
15941 return ImGui::DockNodeGetDepth(b) - ImGui::DockNodeGetDepth(a);
15953static void ImGui::DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx)
15955 ImGuiContext&
g = *ctx;
15956 ImGuiDockContext* dc = &ctx->DockContext;
15957 IM_ASSERT(
g.Windows.Size == 0);
15959 ImPool<ImGuiDockContextPruneNodeData> pool;
15960 pool.Reserve(dc->NodesSettings.Size);
15963 for (
int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
15967 pool.GetOrAddByKey(settings->
ID)->RootId = parent_data ? parent_data->
RootId : settings->
ID;
15969 pool.GetOrAddByKey(settings->
ParentNodeId)->CountChildNodes++;
15974 for (
int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
15978 if (ImGuiWindowSettings* window_settings = FindWindowSettingsByID(settings->
ParentWindowId))
15979 if (window_settings->DockId)
15981 data->CountChildNodes++;
15986 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
15987 if (ImGuiID dock_id = settings->DockId)
15990 data->CountWindows++;
15992 data_root->CountChildWindows++;
15996 for (
int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
16010 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextPruneUnusedSettingsNodes: Prune 0x%08X\n", settings->
ID);
16011 DockSettingsRemoveNodeReferences(&settings->
ID, 1);
16017static void ImGui::DockContextBuildNodesFromSettings(ImGuiContext* ctx,
ImGuiDockNodeSettings* node_settings_array,
int node_settings_count)
16020 for (
int node_n = 0; node_n < node_settings_count; node_n++)
16023 if (settings->
ID == 0)
16025 ImGuiDockNode* node = DockContextAddNode(ctx, settings->
ID);
16027 node->Pos = ImVec2(settings->
Pos.x, settings->
Pos.y);
16028 node->Size = ImVec2(settings->
Size.x, settings->
Size.y);
16029 node->SizeRef = ImVec2(settings->
SizeRef.x, settings->
SizeRef.y);
16030 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_DockNode;
16031 if (node->ParentNode && node->ParentNode->ChildNodes[0] == NULL)
16032 node->ParentNode->ChildNodes[0] = node;
16033 else if (node->ParentNode && node->ParentNode->ChildNodes[1] == NULL)
16034 node->ParentNode->ChildNodes[1] = node;
16036 node->SplitAxis = (ImGuiAxis)settings->
SplitAxis;
16037 node->SetLocalFlags(settings->
Flags & ImGuiDockNodeFlags_SavedFlagsMask_);
16041 char host_window_title[20];
16042 ImGuiDockNode* root_node = DockNodeGetRootNode(node);
16043 node->HostWindow = FindWindowByName(DockNodeGetHostWindowTitle(root_node, host_window_title, IM_ARRAYSIZE(host_window_title)));
16047void ImGui::DockContextBuildAddWindowsToNodes(ImGuiContext* ctx, ImGuiID root_id)
16050 ImGuiContext&
g = *ctx;
16051 for (ImGuiWindow* window :
g.Windows)
16053 if (window->DockId == 0 || window->LastFrameActive <
g.FrameCount - 1)
16055 if (window->DockNode != NULL)
16058 ImGuiDockNode* node = DockContextFindNodeByID(ctx, window->DockId);
16059 IM_ASSERT(node != NULL);
16060 if (root_id == 0 || DockNodeGetRootNode(node)->ID == root_id)
16061 DockNodeAddWindow(node, window,
true);
16078void ImGui::DockContextQueueDock(ImGuiContext* ctx, ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload, ImGuiDir split_dir,
float split_ratio,
bool split_outer)
16080 IM_ASSERT(target != payload);
16089 ctx->DockContext.Requests.push_back(req);
16092void ImGui::DockContextQueueUndockWindow(ImGuiContext* ctx, ImGuiWindow* window)
16097 ctx->DockContext.Requests.push_back(req);
16100void ImGui::DockContextQueueUndockNode(ImGuiContext* ctx, ImGuiDockNode* node)
16105 ctx->DockContext.Requests.push_back(req);
16108void ImGui::DockContextQueueNotifyRemovedNode(ImGuiContext* ctx, ImGuiDockNode* node)
16110 ImGuiDockContext* dc = &ctx->DockContext;
16112 if (req.DockTargetNode == node)
16116void ImGui::DockContextProcessDock(ImGuiContext* ctx,
ImGuiDockRequest* req)
16121 ImGuiContext&
g = *ctx;
16127 if (payload_window)
16128 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);
16130 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextProcessDock node 0x%08X, split_dir %d\n", node ? node->ID : 0, req->DockSplitDir);
16133 ImGuiID next_selected_id = 0;
16134 ImGuiDockNode* payload_node = NULL;
16135 if (payload_window)
16137 payload_node = payload_window->DockNodeAsHost;
16138 payload_window->DockNodeAsHost = NULL;
16139 if (payload_node && payload_node->IsLeafNode())
16140 next_selected_id = payload_node->TabBar->NextSelectedTabId ? payload_node->TabBar->NextSelectedTabId : payload_node->TabBar->SelectedTabId;
16141 if (payload_node == NULL)
16142 next_selected_id = payload_window->TabId;
16148 IM_ASSERT(node->LastFrameAlive <=
g.FrameCount);
16149 if (node && target_window && node == target_window->DockNodeAsHost)
16150 IM_ASSERT(node->Windows.Size > 0 || node->IsSplitNode() || node->IsCentralNode());
16155 node = DockContextAddNode(ctx, 0);
16156 node->Pos = target_window->Pos;
16157 node->Size = target_window->Size;
16158 if (target_window->DockNodeAsHost == NULL)
16160 DockNodeAddWindow(node, target_window,
true);
16161 node->TabBar->Tabs[0].Flags &= ~ImGuiTabItemFlags_Unsorted;
16162 target_window->DockIsActive =
true;
16167 if (split_dir != ImGuiDir_None)
16170 const ImGuiAxis split_axis = (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
16171 const int split_inheritor_child_idx = (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up) ? 1 : 0;
16173 DockNodeTreeSplit(ctx, node, split_axis, split_inheritor_child_idx, split_ratio, payload_node);
16174 ImGuiDockNode* new_node = node->ChildNodes[split_inheritor_child_idx ^ 1];
16175 new_node->HostWindow = node->HostWindow;
16178 node->SetLocalFlags(node->LocalFlags & ~ImGuiDockNodeFlags_HiddenTabBar);
16180 if (node != payload_node)
16183 if (node->Windows.Size > 0 && node->TabBar == NULL)
16185 DockNodeAddTabBar(node);
16186 for (
int n = 0; n < node->Windows.Size; n++)
16187 TabBarAddTab(node->TabBar, ImGuiTabItemFlags_None, node->Windows[n]);
16190 if (payload_node != NULL)
16193 if (payload_node->IsSplitNode())
16195 if (node->Windows.Size > 0)
16200 IM_ASSERT(payload_node->OnlyNodeWithWindows != NULL);
16201 ImGuiDockNode* visible_node = payload_node->OnlyNodeWithWindows;
16202 if (visible_node->TabBar)
16203 IM_ASSERT(visible_node->TabBar->Tabs.Size > 0);
16204 DockNodeMoveWindows(node, visible_node);
16205 DockNodeMoveWindows(visible_node, node);
16206 DockSettingsRenameNodeReferences(node->ID, visible_node->ID);
16208 if (node->IsCentralNode())
16212 ImGuiDockNode* last_focused_node = DockContextFindNodeByID(ctx, payload_node->LastFocusedNodeId);
16213 IM_ASSERT(last_focused_node != NULL);
16214 ImGuiDockNode* last_focused_root_node = DockNodeGetRootNode(last_focused_node);
16215 IM_ASSERT(last_focused_root_node == DockNodeGetRootNode(payload_node));
16216 last_focused_node->SetLocalFlags(last_focused_node->LocalFlags | ImGuiDockNodeFlags_CentralNode);
16217 node->SetLocalFlags(node->LocalFlags & ~ImGuiDockNodeFlags_CentralNode);
16218 last_focused_root_node->CentralNode = last_focused_node;
16221 IM_ASSERT(node->Windows.Size == 0);
16222 DockNodeMoveChildNodes(node, payload_node);
16226 const ImGuiID payload_dock_id = payload_node->ID;
16227 DockNodeMoveWindows(node, payload_node);
16228 DockSettingsRenameNodeReferences(payload_dock_id, node->ID);
16230 DockContextRemoveNode(ctx, payload_node,
true);
16232 else if (payload_window)
16235 const ImGuiID payload_dock_id = payload_window->DockId;
16236 node->VisibleWindow = payload_window;
16237 DockNodeAddWindow(node, payload_window,
true);
16238 if (payload_dock_id != 0)
16239 DockSettingsRenameNodeReferences(payload_dock_id, node->ID);
16245 node->WantHiddenTabBarUpdate =
true;
16249 if (ImGuiTabBar* tab_bar = node->TabBar)
16250 tab_bar->NextSelectedTabId = next_selected_id;
16251 MarkIniSettingsDirty();
16262static ImVec2 FixLargeWindowsWhenUndocking(
const ImVec2& size, ImGuiViewport* ref_viewport)
16264 if (ref_viewport == NULL)
16268 ImVec2 max_size = ImTrunc(ref_viewport->WorkSize * 0.90f);
16269 if (
g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
16271 const ImGuiPlatformMonitor* monitor = ImGui::GetViewportPlatformMonitor(ref_viewport);
16272 max_size = ImTrunc(monitor->WorkSize * 0.90f);
16274 return ImMin(size, max_size);
16277void ImGui::DockContextProcessUndockWindow(ImGuiContext* ctx, ImGuiWindow* window,
bool clear_persistent_docking_ref)
16279 ImGuiContext&
g = *ctx;
16280 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextProcessUndockWindow window '%s', clear_persistent_docking_ref = %d\n", window->Name, clear_persistent_docking_ref);
16281 if (window->DockNode)
16282 DockNodeRemoveWindow(window->DockNode, window, clear_persistent_docking_ref ? 0 : window->DockId);
16284 window->DockId = 0;
16285 window->Collapsed =
false;
16286 window->DockIsActive =
false;
16287 window->DockNodeIsVisible = window->DockTabIsVisible =
false;
16288 window->Size = window->SizeFull = FixLargeWindowsWhenUndocking(window->SizeFull, window->Viewport);
16290 MarkIniSettingsDirty();
16293void ImGui::DockContextProcessUndockNode(ImGuiContext* ctx, ImGuiDockNode* node)
16295 ImGuiContext&
g = *ctx;
16296 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextProcessUndockNode node %08X\n", node->ID);
16297 IM_ASSERT(node->IsLeafNode());
16298 IM_ASSERT(node->Windows.Size >= 1);
16300 if (node->IsRootNode() || node->IsCentralNode())
16303 ImGuiDockNode* new_node = DockContextAddNode(ctx, 0);
16304 new_node->Pos = node->Pos;
16305 new_node->Size = node->Size;
16306 new_node->SizeRef = node->SizeRef;
16307 DockNodeMoveWindows(new_node, node);
16308 DockSettingsRenameNodeReferences(node->ID, new_node->ID);
16314 IM_ASSERT(node->ParentNode->ChildNodes[0] == node || node->ParentNode->ChildNodes[1] == node);
16315 int index_in_parent = (node->ParentNode->ChildNodes[0] == node) ? 0 : 1;
16316 node->ParentNode->ChildNodes[index_in_parent] = NULL;
16317 DockNodeTreeMerge(ctx, node->ParentNode, node->ParentNode->ChildNodes[index_in_parent ^ 1]);
16318 node->ParentNode->AuthorityForViewport = ImGuiDataAuthority_Window;
16319 node->ParentNode = NULL;
16321 for (ImGuiWindow* window : node->Windows)
16323 window->Flags &= ~ImGuiWindowFlags_ChildWindow;
16324 if (window->ParentWindow)
16325 window->ParentWindow->DC.ChildWindows.find_erase(window);
16326 UpdateWindowParentAndRootLinks(window, window->Flags, NULL);
16328 node->AuthorityForPos = node->AuthorityForSize = ImGuiDataAuthority_DockNode;
16329 node->Size = FixLargeWindowsWhenUndocking(node->Size, node->Windows[0]->Viewport);
16330 node->WantMouseMove =
true;
16331 MarkIniSettingsDirty();
16335bool ImGui::DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload_window, ImGuiDockNode* payload_node, ImGuiDir split_dir,
bool split_outer, ImVec2* out_pos)
16337 if (target != NULL && target_node == NULL)
16338 target_node = target->DockNode;
16342 if (target_node && target_node->ParentNode == NULL && target_node->IsCentralNode() && split_dir != ImGuiDir_None)
16343 split_outer =
true;
16345 DockNodePreviewDockSetup(target, target_node, payload_window, payload_node, &split_data,
false, split_outer);
16348 *out_pos = split_data.
DropRectsDraw[split_dir+1].GetCenter();
16385ImGuiDockNode::ImGuiDockNode(ImGuiID
id)
16388 SharedFlags = LocalFlags = LocalFlagsInWindows = MergedFlags = ImGuiDockNodeFlags_None;
16389 ParentNode = ChildNodes[0] = ChildNodes[1] = NULL;
16391 SplitAxis = ImGuiAxis_None;
16393 State = ImGuiDockNodeState_Unknown;
16394 LastBgColor = IM_COL32_WHITE;
16395 HostWindow = VisibleWindow = NULL;
16396 CentralNode = OnlyNodeWithWindows = NULL;
16397 CountNodeWithWindows = 0;
16398 LastFrameAlive = LastFrameActive = LastFrameFocused = -1;
16399 LastFocusedNodeId = 0;
16401 WantCloseTabId = 0;
16403 AuthorityForPos = AuthorityForSize = ImGuiDataAuthority_DockNode;
16404 AuthorityForViewport = ImGuiDataAuthority_Auto;
16406 IsFocused = HasCloseButton = HasWindowMenuButton = HasCentralNodeChild =
false;
16407 IsBgDrawnThisFrame =
false;
16408 WantCloseAll = WantLockSizeOnce = WantMouseMove = WantHiddenTabBarUpdate = WantHiddenTabBarToggle =
false;
16411ImGuiDockNode::~ImGuiDockNode()
16415 ChildNodes[0] = ChildNodes[1] = NULL;
16418int ImGui::DockNodeGetTabOrder(ImGuiWindow* window)
16420 ImGuiTabBar* tab_bar = window->DockNode->TabBar;
16421 if (tab_bar == NULL)
16423 ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, window->TabId);
16424 return tab ? TabBarGetTabOrder(tab_bar, tab) : -1;
16427static void DockNodeHideWindowDuringHostWindowCreation(ImGuiWindow* window)
16429 window->Hidden =
true;
16430 window->HiddenFramesCanSkipItems = window->Active ? 1 : 2;
16433static void ImGui::DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window,
bool add_to_tab_bar)
16435 ImGuiContext&
g = *
GImGui; (void)
g;
16436 if (window->DockNode)
16439 IM_ASSERT(window->DockNode->ID != node->ID);
16440 DockNodeRemoveWindow(window->DockNode, window, 0);
16442 IM_ASSERT(window->DockNode == NULL || window->DockNodeAsHost == NULL);
16443 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockNodeAddWindow node 0x%08X window '%s'\n", node->ID, window->Name);
16448 if (node->HostWindow == NULL && node->Windows.Size == 1 && node->Windows[0]->WasActive ==
false)
16449 DockNodeHideWindowDuringHostWindowCreation(node->Windows[0]);
16451 node->Windows.push_back(window);
16452 node->WantHiddenTabBarUpdate =
true;
16453 window->DockNode = node;
16454 window->DockId = node->ID;
16455 window->DockIsActive = (node->Windows.Size > 1);
16456 window->DockTabWantClose =
false;
16460 if (node->HostWindow == NULL && node->IsFloatingNode())
16462 if (node->AuthorityForPos == ImGuiDataAuthority_Auto)
16463 node->AuthorityForPos = ImGuiDataAuthority_Window;
16464 if (node->AuthorityForSize == ImGuiDataAuthority_Auto)
16465 node->AuthorityForSize = ImGuiDataAuthority_Window;
16466 if (node->AuthorityForViewport == ImGuiDataAuthority_Auto)
16467 node->AuthorityForViewport = ImGuiDataAuthority_Window;
16471 if (add_to_tab_bar)
16473 if (node->TabBar == NULL)
16475 DockNodeAddTabBar(node);
16476 node->TabBar->SelectedTabId = node->TabBar->NextSelectedTabId = node->SelectedTabId;
16479 for (
int n = 0; n < node->Windows.Size - 1; n++)
16480 TabBarAddTab(node->TabBar, ImGuiTabItemFlags_None, node->Windows[n]);
16482 TabBarAddTab(node->TabBar, ImGuiTabItemFlags_Unsorted, window);
16485 DockNodeUpdateVisibleFlag(node);
16488 if (node->HostWindow)
16489 UpdateWindowParentAndRootLinks(window, window->Flags | ImGuiWindowFlags_ChildWindow, node->HostWindow);
16492static void ImGui::DockNodeRemoveWindow(ImGuiDockNode* node, ImGuiWindow* window, ImGuiID save_dock_id)
16495 IM_ASSERT(window->DockNode == node);
16498 IM_ASSERT(save_dock_id == 0 || save_dock_id == node->ID);
16499 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockNodeRemoveWindow node 0x%08X window '%s'\n", node->ID, window->Name);
16501 window->DockNode = NULL;
16502 window->DockIsActive = window->DockTabWantClose =
false;
16503 window->DockId = save_dock_id;
16504 window->Flags &= ~ImGuiWindowFlags_ChildWindow;
16505 if (window->ParentWindow)
16506 window->ParentWindow->DC.ChildWindows.find_erase(window);
16507 UpdateWindowParentAndRootLinks(window, window->Flags, NULL);
16509 if (node->HostWindow && node->HostWindow->ViewportOwned)
16513 window->Viewport = NULL;
16514 window->ViewportId = 0;
16515 window->ViewportOwned =
false;
16516 window->Hidden =
true;
16520 bool erased =
false;
16521 for (
int n = 0; n < node->Windows.Size; n++)
16522 if (node->Windows[n] == window)
16524 node->Windows.erase(node->Windows.Data + n);
16530 if (node->VisibleWindow == window)
16531 node->VisibleWindow = NULL;
16534 node->WantHiddenTabBarUpdate =
true;
16537 TabBarRemoveTab(node->TabBar, window->TabId);
16538 const int tab_count_threshold_for_tab_bar = node->IsCentralNode() ? 1 : 2;
16539 if (node->Windows.Size < tab_count_threshold_for_tab_bar)
16540 DockNodeRemoveTabBar(node);
16543 if (node->Windows.Size == 0 && !node->IsCentralNode() && !node->IsDockSpace() && window->DockId != node->ID)
16546 DockContextRemoveNode(&
g, node,
true);
16550 if (node->Windows.Size == 1 && !node->IsCentralNode() && node->HostWindow)
16552 ImGuiWindow* remaining_window = node->Windows[0];
16554 remaining_window->Collapsed = node->HostWindow->Collapsed;
16558 DockNodeUpdateVisibleFlag(node);
16561static void ImGui::DockNodeMoveChildNodes(ImGuiDockNode* dst_node, ImGuiDockNode* src_node)
16563 IM_ASSERT(dst_node->Windows.Size == 0);
16564 dst_node->ChildNodes[0] = src_node->ChildNodes[0];
16565 dst_node->ChildNodes[1] = src_node->ChildNodes[1];
16566 if (dst_node->ChildNodes[0])
16567 dst_node->ChildNodes[0]->ParentNode = dst_node;
16568 if (dst_node->ChildNodes[1])
16569 dst_node->ChildNodes[1]->ParentNode = dst_node;
16570 dst_node->SplitAxis = src_node->SplitAxis;
16571 dst_node->SizeRef = src_node->SizeRef;
16572 src_node->ChildNodes[0] = src_node->ChildNodes[1] = NULL;
16575static void ImGui::DockNodeMoveWindows(ImGuiDockNode* dst_node, ImGuiDockNode* src_node)
16578 IM_ASSERT(src_node && dst_node && dst_node != src_node);
16579 ImGuiTabBar* src_tab_bar = src_node->TabBar;
16580 if (src_tab_bar != NULL)
16581 IM_ASSERT(src_node->Windows.Size <= src_node->TabBar->Tabs.Size);
16584 bool move_tab_bar = (src_tab_bar != NULL) && (dst_node->TabBar == NULL);
16587 dst_node->TabBar = src_node->TabBar;
16588 src_node->TabBar = NULL;
16592 for (ImGuiWindow* window : src_node->Windows)
16594 window->DockNode = NULL;
16595 window->DockIsActive =
false;
16596 DockNodeAddWindow(dst_node, window, !move_tab_bar);
16598 src_node->Windows.clear();
16600 if (!move_tab_bar && src_node->TabBar)
16602 if (dst_node->TabBar)
16603 dst_node->TabBar->SelectedTabId = src_node->TabBar->SelectedTabId;
16604 DockNodeRemoveTabBar(src_node);
16608static void ImGui::DockNodeApplyPosSizeToWindows(ImGuiDockNode* node)
16610 for (ImGuiWindow* window : node->Windows)
16612 SetWindowPos(window, node->Pos, ImGuiCond_Always);
16613 SetWindowSize(window, node->Size, ImGuiCond_Always);
16617static void ImGui::DockNodeHideHostWindow(ImGuiDockNode* node)
16619 if (node->HostWindow)
16621 if (node->HostWindow->DockNodeAsHost == node)
16622 node->HostWindow->DockNodeAsHost = NULL;
16623 node->HostWindow = NULL;
16626 if (node->Windows.Size == 1)
16628 node->VisibleWindow = node->Windows[0];
16629 node->Windows[0]->DockIsActive =
false;
16633 DockNodeRemoveTabBar(node);
16649 if (node->Windows.Size > 0)
16655 if (node->IsCentralNode())
16658 IM_ASSERT(node->IsLeafNode() &&
"If you get this assert: please submit .ini file + repro of actions leading to this.");
16663 if (node->ChildNodes[0])
16664 DockNodeFindInfo(node->ChildNodes[0], info);
16665 if (node->ChildNodes[1])
16666 DockNodeFindInfo(node->ChildNodes[1], info);
16669static ImGuiWindow* ImGui::DockNodeFindWindowByID(ImGuiDockNode* node, ImGuiID
id)
16671 IM_ASSERT(
id != 0);
16672 for (ImGuiWindow* window : node->Windows)
16673 if (window->
ID ==
id)
16680static void ImGui::DockNodeUpdateFlagsAndCollapse(ImGuiDockNode* node)
16683 IM_ASSERT(node->ParentNode == NULL || node->ParentNode->ChildNodes[0] == node || node->ParentNode->ChildNodes[1] == node);
16686 if (node->ParentNode)
16687 node->SharedFlags = node->ParentNode->SharedFlags & ImGuiDockNodeFlags_SharedFlagsInheritMask_;
16693 node->HasCentralNodeChild =
false;
16694 if (node->ChildNodes[0])
16695 DockNodeUpdateFlagsAndCollapse(node->ChildNodes[0]);
16696 if (node->ChildNodes[1])
16697 DockNodeUpdateFlagsAndCollapse(node->ChildNodes[1]);
16701 node->LocalFlagsInWindows = ImGuiDockNodeFlags_None;
16702 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
16704 ImGuiWindow* window = node->Windows[window_n];
16705 IM_ASSERT(window->DockNode == node);
16707 bool node_was_active = (node->LastFrameActive + 1 ==
g.FrameCount);
16709 remove |= node_was_active && (window->LastFrameActive + 1 <
g.FrameCount);
16710 remove |= node_was_active && (node->WantCloseAll || node->WantCloseTabId == window->TabId) && window->HasCloseButton && !(window->Flags & ImGuiWindowFlags_UnsavedDocument);
16711 remove |= (window->DockTabWantClose);
16714 window->DockTabWantClose =
false;
16715 if (node->Windows.Size == 1 && !node->IsCentralNode())
16717 DockNodeHideHostWindow(node);
16718 node->State = ImGuiDockNodeState_HostWindowHiddenBecauseSingleWindow;
16719 DockNodeRemoveWindow(node, window, node->ID);
16722 DockNodeRemoveWindow(node, window, node->ID);
16729 node->LocalFlagsInWindows |= window->WindowClass.DockNodeFlagsOverrideSet;
16731 node->UpdateMergedFlags();
16734 ImGuiDockNodeFlags node_flags = node->MergedFlags;
16735 if (node->WantHiddenTabBarUpdate && node->Windows.Size == 1 && (node_flags & ImGuiDockNodeFlags_AutoHideTabBar) && !node->IsHiddenTabBar())
16736 node->WantHiddenTabBarToggle =
true;
16737 node->WantHiddenTabBarUpdate =
false;
16740 if (node->WantHiddenTabBarToggle && node->VisibleWindow && (node->VisibleWindow->WindowClass.DockNodeFlagsOverrideSet & ImGuiDockNodeFlags_HiddenTabBar))
16741 node->WantHiddenTabBarToggle =
false;
16744 if (node->Windows.Size > 1)
16745 node->SetLocalFlags(node->LocalFlags & ~ImGuiDockNodeFlags_HiddenTabBar);
16746 else if (node->WantHiddenTabBarToggle)
16747 node->SetLocalFlags(node->LocalFlags ^ ImGuiDockNodeFlags_HiddenTabBar);
16748 node->WantHiddenTabBarToggle =
false;
16750 DockNodeUpdateVisibleFlag(node);
16754static void ImGui::DockNodeUpdateHasCentralNodeChild(ImGuiDockNode* node)
16756 node->HasCentralNodeChild =
false;
16757 if (node->ChildNodes[0])
16758 DockNodeUpdateHasCentralNodeChild(node->ChildNodes[0]);
16759 if (node->ChildNodes[1])
16760 DockNodeUpdateHasCentralNodeChild(node->ChildNodes[1]);
16761 if (node->IsRootNode())
16763 ImGuiDockNode* mark_node = node->CentralNode;
16766 mark_node->HasCentralNodeChild =
true;
16767 mark_node = mark_node->ParentNode;
16772static void ImGui::DockNodeUpdateVisibleFlag(ImGuiDockNode* node)
16775 bool is_visible = (node->ParentNode == NULL) ? node->IsDockSpace() : node->IsCentralNode();
16776 is_visible |= (node->Windows.Size > 0);
16777 is_visible |= (node->ChildNodes[0] && node->ChildNodes[0]->IsVisible);
16778 is_visible |= (node->ChildNodes[1] && node->ChildNodes[1]->IsVisible);
16779 node->IsVisible = is_visible;
16782static void ImGui::DockNodeStartMouseMovingWindow(ImGuiDockNode* node, ImGuiWindow* window)
16785 IM_ASSERT(node->WantMouseMove ==
true);
16786 StartMouseMovingWindow(window);
16787 g.ActiveIdClickOffset =
g.IO.MouseClickedPos[0] - node->Pos;
16788 g.MovingWindow = window;
16789 node->WantMouseMove =
false;
16793static void ImGui::DockNodeUpdateForRootNode(ImGuiDockNode* node)
16795 DockNodeUpdateFlagsAndCollapse(node);
16801 DockNodeFindInfo(node, &info);
16813 node->WindowClass = first_node_with_windows->Windows[0]->WindowClass;
16814 for (
int n = 1; n < first_node_with_windows->Windows.Size; n++)
16815 if (first_node_with_windows->Windows[n]->WindowClass.DockingAllowUnclassed ==
false)
16817 node->WindowClass = first_node_with_windows->Windows[n]->WindowClass;
16822 ImGuiDockNode* mark_node = node->CentralNode;
16825 mark_node->HasCentralNodeChild =
true;
16826 mark_node = mark_node->ParentNode;
16830static void DockNodeSetupHostWindow(ImGuiDockNode* node, ImGuiWindow* host_window)
16837 if (node->HostWindow && node->HostWindow != host_window && node->HostWindow->DockNodeAsHost == node)
16838 node->HostWindow->DockNodeAsHost = NULL;
16840 host_window->DockNodeAsHost = node;
16841 node->HostWindow = host_window;
16844static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
16847 IM_ASSERT(node->LastFrameActive !=
g.FrameCount);
16848 node->LastFrameAlive =
g.FrameCount;
16849 node->IsBgDrawnThisFrame =
false;
16851 node->CentralNode = node->OnlyNodeWithWindows = NULL;
16852 if (node->IsRootNode())
16853 DockNodeUpdateForRootNode(node);
16856 if (node->TabBar && node->IsNoTabBar())
16857 DockNodeRemoveTabBar(node);
16860 bool want_to_hide_host_window =
false;
16861 if (node->IsFloatingNode())
16863 if (node->Windows.Size <= 1 && node->IsLeafNode())
16864 if (!
g.IO.ConfigDockingAlwaysTabBar && (node->Windows.Size == 0 || !node->Windows[0]->WindowClass.DockingAlwaysTabBar))
16865 want_to_hide_host_window =
true;
16866 if (node->CountNodeWithWindows == 0)
16867 want_to_hide_host_window =
true;
16869 if (want_to_hide_host_window)
16871 if (node->Windows.Size == 1)
16874 ImGuiWindow* single_window = node->Windows[0];
16875 node->Pos = single_window->Pos;
16876 node->Size = single_window->SizeFull;
16877 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Window;
16880 if (node->HostWindow &&
g.NavWindow == node->HostWindow)
16881 FocusWindow(single_window);
16882 if (node->HostWindow)
16884 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);
16885 single_window->Viewport = node->HostWindow->Viewport;
16886 single_window->ViewportId = node->HostWindow->ViewportId;
16887 if (node->HostWindow->ViewportOwned)
16889 single_window->Viewport->ID = single_window->ID;
16890 single_window->Viewport->Window = single_window;
16891 single_window->ViewportOwned =
true;
16894 node->RefViewportId = single_window->ViewportId;
16897 DockNodeHideHostWindow(node);
16898 node->State = ImGuiDockNodeState_HostWindowHiddenBecauseSingleWindow;
16899 node->WantCloseAll =
false;
16900 node->WantCloseTabId = 0;
16901 node->HasCloseButton = node->HasWindowMenuButton =
false;
16902 node->LastFrameActive =
g.FrameCount;
16904 if (node->WantMouseMove && node->Windows.Size == 1)
16905 DockNodeStartMouseMovingWindow(node, node->Windows[0]);
16919 if (node->IsVisible && node->HostWindow == NULL && node->IsFloatingNode() && node->IsLeafNode())
16921 IM_ASSERT(node->Windows.Size > 0);
16922 ImGuiWindow* ref_window = NULL;
16923 if (node->SelectedTabId != 0)
16924 ref_window = DockNodeFindWindowByID(node, node->SelectedTabId);
16925 if (ref_window == NULL)
16926 ref_window = node->Windows[0];
16927 if (ref_window->AutoFitFramesX > 0 || ref_window->AutoFitFramesY > 0)
16929 node->State = ImGuiDockNodeState_HostWindowHiddenBecauseWindowsAreResizing;
16934 const ImGuiDockNodeFlags node_flags = node->MergedFlags;
16937 node->HasWindowMenuButton = (node->Windows.Size > 0) && (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0;
16938 node->HasCloseButton =
false;
16939 for (ImGuiWindow* window : node->Windows)
16942 node->HasCloseButton |= window->HasCloseButton;
16943 window->DockIsActive = (node->Windows.Size > 1);
16945 if (node_flags & ImGuiDockNodeFlags_NoCloseButton)
16946 node->HasCloseButton =
false;
16949 ImGuiWindow* host_window = NULL;
16950 bool beginned_into_host_window =
false;
16951 if (node->IsDockSpace())
16954 IM_ASSERT(node->HostWindow);
16955 host_window = node->HostWindow;
16960 if (node->IsRootNode() && node->IsVisible)
16962 ImGuiWindow* ref_window = (node->Windows.Size > 0) ? node->Windows[0] : NULL;
16965 if (node->AuthorityForPos == ImGuiDataAuthority_Window && ref_window)
16966 SetNextWindowPos(ref_window->Pos);
16967 else if (node->AuthorityForPos == ImGuiDataAuthority_DockNode)
16968 SetNextWindowPos(node->Pos);
16971 if (node->AuthorityForSize == ImGuiDataAuthority_Window && ref_window)
16972 SetNextWindowSize(ref_window->SizeFull);
16973 else if (node->AuthorityForSize == ImGuiDataAuthority_DockNode)
16974 SetNextWindowSize(node->Size);
16977 if (node->AuthorityForSize == ImGuiDataAuthority_Window && ref_window)
16978 SetNextWindowCollapsed(ref_window->Collapsed);
16981 if (node->AuthorityForViewport == ImGuiDataAuthority_Window && ref_window)
16982 SetNextWindowViewport(ref_window->ViewportId);
16983 else if (node->AuthorityForViewport == ImGuiDataAuthority_Window && node->RefViewportId != 0)
16984 SetNextWindowViewport(node->RefViewportId);
16986 SetNextWindowClass(&node->WindowClass);
16989 char window_label[20];
16990 DockNodeGetHostWindowTitle(node, window_label, IM_ARRAYSIZE(window_label));
16991 ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_DockNodeHost;
16992 window_flags |= ImGuiWindowFlags_NoFocusOnAppearing;
16993 window_flags |= ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoCollapse;
16994 window_flags |= ImGuiWindowFlags_NoTitleBar;
16996 SetNextWindowBgAlpha(0.0f);
16997 PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
16998 Begin(window_label, NULL, window_flags);
17000 beginned_into_host_window =
true;
17002 host_window =
g.CurrentWindow;
17003 DockNodeSetupHostWindow(node, host_window);
17004 host_window->DC.CursorPos = host_window->Pos;
17005 node->Pos = host_window->Pos;
17006 node->Size = host_window->Size;
17014 if (node->HostWindow->Appearing)
17015 BringWindowToDisplayFront(node->HostWindow);
17017 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Auto;
17019 else if (node->ParentNode)
17021 node->HostWindow = host_window = node->ParentNode->HostWindow;
17022 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Auto;
17024 if (node->WantMouseMove && node->HostWindow)
17025 DockNodeStartMouseMovingWindow(node, node->HostWindow);
17027 node->RefViewportId = 0;
17030 if (node->IsSplitNode())
17031 IM_ASSERT(node->TabBar == NULL);
17032 if (node->IsRootNode())
17033 if (ImGuiWindow* p_window =
g.NavWindow ?
g.NavWindow->RootWindow : NULL)
17034 while (p_window != NULL && p_window->DockNode != NULL)
17036 ImGuiDockNode* p_node = DockNodeGetRootNode(p_window->DockNode);
17037 if (p_node == node)
17039 node->LastFocusedNodeId = p_window->DockNode->ID;
17042 p_window = p_node->HostWindow ? p_node->HostWindow->RootWindow : NULL;
17046 ImGuiDockNode* central_node = node->CentralNode;
17047 const bool central_node_hole = node->IsRootNode() && host_window && (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0 && central_node != NULL && central_node->IsEmpty();
17048 bool central_node_hole_register_hit_test_hole = central_node_hole;
17049 if (central_node_hole)
17050 if (
const ImGuiPayload* payload = ImGui::GetDragDropPayload())
17051 if (payload->IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) && DockNodeIsDropAllowed(host_window, *(ImGuiWindow**)payload->Data))
17052 central_node_hole_register_hit_test_hole =
false;
17053 if (central_node_hole_register_hit_test_hole)
17058 IM_ASSERT(node->IsDockSpace());
17059 ImGuiDockNode* root_node = DockNodeGetRootNode(central_node);
17060 ImRect root_rect(root_node->Pos, root_node->Pos + root_node->Size);
17061 ImRect hole_rect(central_node->Pos, central_node->Pos + central_node->Size);
17062 if (hole_rect.Min.x > root_rect.Min.x) { hole_rect.Min.x += WINDOWS_HOVER_PADDING; }
17063 if (hole_rect.Max.x < root_rect.Max.x) { hole_rect.Max.x -= WINDOWS_HOVER_PADDING; }
17064 if (hole_rect.Min.y > root_rect.Min.y) { hole_rect.Min.y += WINDOWS_HOVER_PADDING; }
17065 if (hole_rect.Max.y < root_rect.Max.y) { hole_rect.Max.y -= WINDOWS_HOVER_PADDING; }
17067 if (central_node_hole && !hole_rect.IsInverted())
17069 SetWindowHitTestHole(host_window, hole_rect.Min, hole_rect.Max - hole_rect.Min);
17070 if (host_window->ParentWindow)
17071 SetWindowHitTestHole(host_window->ParentWindow, hole_rect.Min, hole_rect.Max - hole_rect.Min);
17076 if (node->IsRootNode() && host_window)
17078 DockNodeTreeUpdatePosSize(node, host_window->Pos, host_window->Size);
17079 PushStyleColor(ImGuiCol_Separator,
g.Style.Colors[ImGuiCol_Border]);
17080 PushStyleColor(ImGuiCol_SeparatorActive,
g.Style.Colors[ImGuiCol_ResizeGripActive]);
17081 PushStyleColor(ImGuiCol_SeparatorHovered,
g.Style.Colors[ImGuiCol_ResizeGripHovered]);
17082 DockNodeTreeUpdateSplitter(node);
17087 if (host_window && node->IsEmpty() && node->IsVisible)
17089 host_window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
17090 node->LastBgColor = (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) ? 0 : GetColorU32(ImGuiCol_DockingEmptyBg);
17091 if (node->LastBgColor != 0)
17092 host_window->DrawList->AddRectFilled(node->Pos, node->Pos + node->Size, node->LastBgColor);
17093 node->IsBgDrawnThisFrame =
true;
17099 const bool render_dockspace_bg = node->IsRootNode() && host_window && (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0;
17100 if (render_dockspace_bg && node->IsVisible)
17102 host_window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
17103 if (central_node_hole)
17104 RenderRectFilledWithHole(host_window->DrawList, node->Rect(), central_node->Rect(), GetColorU32(ImGuiCol_WindowBg), 0.0f);
17106 host_window->DrawList->AddRectFilled(node->Pos, node->Pos + node->Size, GetColorU32(ImGuiCol_WindowBg), 0.0f);
17111 host_window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_FG);
17112 if (host_window && node->Windows.Size > 0)
17114 DockNodeUpdateTabBar(node, host_window);
17118 node->WantCloseAll =
false;
17119 node->WantCloseTabId = 0;
17120 node->IsFocused =
false;
17122 if (node->TabBar && node->TabBar->SelectedTabId)
17123 node->SelectedTabId = node->TabBar->SelectedTabId;
17124 else if (node->Windows.Size > 0)
17125 node->SelectedTabId = node->Windows[0]->TabId;
17128 if (host_window && node->IsVisible)
17129 if (node->IsRootNode() && (
g.MovingWindow == NULL ||
g.MovingWindow->RootWindowDockTree != host_window))
17130 BeginDockableDragDropTarget(host_window);
17133 node->LastFrameActive =
g.FrameCount;
17139 if (node->ChildNodes[0])
17140 DockNodeUpdate(node->ChildNodes[0]);
17141 if (node->ChildNodes[1])
17142 DockNodeUpdate(node->ChildNodes[1]);
17145 if (node->IsRootNode())
17146 RenderWindowOuterBorders(host_window);
17150 if (beginned_into_host_window)
17155static int IMGUI_CDECL TabItemComparerByDockOrder(
const void* lhs,
const void* rhs)
17157 ImGuiWindow* a = ((
const ImGuiTabItem*)lhs)->Window;
17158 ImGuiWindow* b = ((
const ImGuiTabItem*)rhs)->Window;
17159 if (
int d = ((a->DockOrder == -1) ? INT_MAX : a->DockOrder) - ((b->DockOrder == -1) ? INT_MAX : b->DockOrder))
17161 return (a->BeginOrderWithinContext - b->BeginOrderWithinContext);
17169void ImGui::DockNodeWindowMenuHandler_Default(ImGuiContext* ctx, ImGuiDockNode* node, ImGuiTabBar* tab_bar)
17172 if (tab_bar->Tabs.Size == 1)
17175 if (MenuItem(LocalizeGetMsg(ImGuiLocKey_DockingHideTabBar), NULL, node->IsHiddenTabBar()))
17176 node->WantHiddenTabBarToggle =
true;
17181 for (
int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
17183 ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
17184 if (tab->Flags & ImGuiTabItemFlags_Button)
17186 if (Selectable(TabBarGetTabName(tab_bar, tab), tab->ID == tab_bar->SelectedTabId))
17187 TabBarQueueFocus(tab_bar, tab);
17194static void ImGui::DockNodeWindowMenuUpdate(ImGuiDockNode* node, ImGuiTabBar* tab_bar)
17198 if (
g.Style.WindowMenuButtonPosition == ImGuiDir_Left)
17199 SetNextWindowPos(ImVec2(node->Pos.x, node->Pos.y + GetFrameHeight()), ImGuiCond_Always, ImVec2(0.0f, 0.0f));
17201 SetNextWindowPos(ImVec2(node->Pos.x + node->Size.x, node->Pos.y + GetFrameHeight()), ImGuiCond_Always, ImVec2(1.0f, 0.0f));
17202 if (BeginPopup(
"#WindowMenu"))
17204 node->IsFocused =
true;
17205 g.DockNodeWindowMenuHandler(&
g, node, tab_bar);
17211bool ImGui::DockNodeBeginAmendTabBar(ImGuiDockNode* node)
17213 if (node->TabBar == NULL || node->HostWindow == NULL)
17215 if (node->MergedFlags & ImGuiDockNodeFlags_KeepAliveOnly)
17217 if (node->TabBar->ID == 0)
17219 Begin(node->HostWindow->Name);
17220 PushOverrideID(node->ID);
17221 bool ret = BeginTabBarEx(node->TabBar, node->TabBar->BarRect, node->TabBar->Flags);
17227void ImGui::DockNodeEndAmendTabBar()
17234static bool IsDockNodeTitleBarHighlighted(ImGuiDockNode* node, ImGuiDockNode* root_node)
17238 if (
g.NavWindowingTarget)
17239 return (
g.NavWindowingTarget->DockNode == node);
17242 if (
g.NavWindow && root_node->LastFocusedNodeId == node->ID)
17245 ImGuiWindow* parent_window =
g.NavWindow->RootWindow;
17246 while (parent_window->Flags & ImGuiWindowFlags_ChildMenu)
17247 parent_window = parent_window->ParentWindow->RootWindow;
17248 ImGuiDockNode* start_parent_node = parent_window->DockNodeAsHost ? parent_window->DockNodeAsHost : parent_window->DockNode;
17249 for (ImGuiDockNode* parent_node = start_parent_node; parent_node != NULL; parent_node = parent_node->HostWindow ? parent_node->HostWindow->RootWindow->DockNode : NULL)
17250 if ((parent_node = ImGui::DockNodeGetRootNode(parent_node)) == root_node)
17257static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_window)
17260 ImGuiStyle& style =
g.Style;
17262 const bool node_was_active = (node->LastFrameActive + 1 ==
g.FrameCount);
17263 const bool closed_all = node->WantCloseAll && node_was_active;
17264 const ImGuiID closed_one = node->WantCloseTabId && node_was_active;
17265 node->WantCloseAll =
false;
17266 node->WantCloseTabId = 0;
17269 bool is_focused =
false;
17270 ImGuiDockNode* root_node = DockNodeGetRootNode(node);
17271 if (IsDockNodeTitleBarHighlighted(node, root_node))
17275 if (node->IsHiddenTabBar() || node->IsNoTabBar())
17277 node->VisibleWindow = (node->Windows.Size > 0) ? node->Windows[0] : NULL;
17278 node->IsFocused = is_focused;
17280 node->LastFrameFocused =
g.FrameCount;
17281 if (node->VisibleWindow)
17284 if (is_focused || root_node->VisibleWindow == NULL)
17285 root_node->VisibleWindow = node->VisibleWindow;
17287 node->TabBar->VisibleTabId = node->VisibleWindow->TabId;
17293 bool backup_skip_item = host_window->SkipItems;
17294 if (!node->IsDockSpace())
17296 host_window->SkipItems =
false;
17297 host_window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
17303 PushOverrideID(node->ID);
17304 ImGuiTabBar* tab_bar = node->TabBar;
17305 bool tab_bar_is_recreated = (tab_bar == NULL);
17306 if (tab_bar == NULL)
17308 DockNodeAddTabBar(node);
17309 tab_bar = node->TabBar;
17312 ImGuiID focus_tab_id = 0;
17313 node->IsFocused = is_focused;
17315 const ImGuiDockNodeFlags node_flags = node->MergedFlags;
17316 const bool has_window_menu_button = (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0 && (style.WindowMenuButtonPosition != ImGuiDir_None);
17320 if (has_window_menu_button && IsPopupOpen(
"#WindowMenu"))
17322 ImGuiID next_selected_tab_id = tab_bar->NextSelectedTabId;
17323 DockNodeWindowMenuUpdate(node, tab_bar);
17324 if (tab_bar->NextSelectedTabId != 0 && tab_bar->NextSelectedTabId != next_selected_tab_id)
17325 focus_tab_id = tab_bar->NextSelectedTabId;
17326 is_focused |= node->IsFocused;
17330 ImRect title_bar_rect, tab_bar_rect;
17331 ImVec2 window_menu_button_pos;
17332 ImVec2 close_button_pos;
17333 DockNodeCalcTabBarLayout(node, &title_bar_rect, &tab_bar_rect, &window_menu_button_pos, &close_button_pos);
17336 const int tabs_count_old = tab_bar->Tabs.Size;
17337 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
17339 ImGuiWindow* window = node->Windows[window_n];
17340 if (TabBarFindTabByID(tab_bar, window->TabId) == NULL)
17341 TabBarAddTab(tab_bar, ImGuiTabItemFlags_Unsorted, window);
17346 node->LastFrameFocused =
g.FrameCount;
17347 ImU32 title_bar_col = GetColorU32(host_window->Collapsed ? ImGuiCol_TitleBgCollapsed : is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
17348 ImDrawFlags rounding_flags = CalcRoundingFlagsForRectInRect(title_bar_rect, host_window->Rect(),
g.Style.DockingSeparatorSize);
17349 host_window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, host_window->WindowRounding, rounding_flags);
17352 if (has_window_menu_button)
17354 if (CollapseButton(host_window->GetID(
"#COLLAPSE"), window_menu_button_pos, node))
17355 OpenPopup(
"#WindowMenu");
17356 if (IsItemActive())
17357 focus_tab_id = tab_bar->SelectedTabId;
17358 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_DelayNormal) &&
g.HoveredIdTimer > 0.5f)
17359 SetTooltip(
"%s", LocalizeGetMsg(ImGuiLocKey_DockingDragToUndockOrMoveNode));
17363 int tabs_unsorted_start = tab_bar->Tabs.Size;
17364 for (
int tab_n = tab_bar->Tabs.Size - 1; tab_n >= 0 && (tab_bar->Tabs[tab_n].Flags & ImGuiTabItemFlags_Unsorted); tab_n--)
17367 tab_bar->Tabs[tab_n].Flags &= ~ImGuiTabItemFlags_Unsorted;
17368 tabs_unsorted_start = tab_n;
17370 if (tab_bar->Tabs.Size > tabs_unsorted_start)
17372 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)" :
"");
17373 for (
int tab_n = tabs_unsorted_start; tab_n < tab_bar->Tabs.Size; tab_n++)
17375 ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
17376 IMGUI_DEBUG_LOG_DOCKING(
"[docking] - Tab 0x%08X '%s' Order %d\n", tab->ID, TabBarGetTabName(tab_bar, tab), tab->Window ? tab->Window->DockOrder : -1);
17378 IMGUI_DEBUG_LOG_DOCKING(
"[docking] SelectedTabId = 0x%08X, NavWindow->TabId = 0x%08X\n", node->SelectedTabId,
g.NavWindow ?
g.NavWindow->TabId : -1);
17379 if (tab_bar->Tabs.Size > tabs_unsorted_start + 1)
17380 ImQsort(tab_bar->Tabs.Data + tabs_unsorted_start, tab_bar->Tabs.Size - tabs_unsorted_start,
sizeof(ImGuiTabItem), TabItemComparerByDockOrder);
17384 if (
g.NavWindow &&
g.NavWindow->RootWindow->DockNode == node)
17385 tab_bar->SelectedTabId =
g.NavWindow->RootWindow->TabId;
17388 if (tab_bar_is_recreated && TabBarFindTabByID(tab_bar, node->SelectedTabId) != NULL)
17389 tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = node->SelectedTabId;
17390 else if (tab_bar->Tabs.Size > tabs_count_old)
17391 tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = tab_bar->Tabs.back().Window->TabId;
17394 ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_AutoSelectNewTabs;
17395 tab_bar_flags |= ImGuiTabBarFlags_SaveSettings | ImGuiTabBarFlags_DockNode;
17396 if (!host_window->Collapsed && is_focused)
17397 tab_bar_flags |= ImGuiTabBarFlags_IsFocused;
17398 tab_bar->ID = GetID(
"#TabBar");
17399 tab_bar->SeparatorMinX = node->Pos.x + host_window->WindowBorderSize;
17400 tab_bar->SeparatorMaxX = node->Pos.x + node->Size.x - host_window->WindowBorderSize;
17401 BeginTabBarEx(tab_bar, tab_bar_rect, tab_bar_flags);
17405 ImVec4 backup_style_cols[ImGuiWindowDockStyleCol_COUNT];
17406 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
17407 backup_style_cols[color_n] =
g.Style.Colors[GWindowDockStyleColors[color_n]];
17410 node->VisibleWindow = NULL;
17411 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
17413 ImGuiWindow* window = node->Windows[window_n];
17414 if ((closed_all || closed_one == window->TabId) && window->HasCloseButton && !(window->Flags & ImGuiWindowFlags_UnsavedDocument))
17416 if (window->LastFrameActive + 1 >=
g.FrameCount || !node_was_active)
17418 ImGuiTabItemFlags tab_item_flags = 0;
17419 tab_item_flags |= window->WindowClass.TabItemFlagsOverrideSet;
17420 if (window->Flags & ImGuiWindowFlags_UnsavedDocument)
17421 tab_item_flags |= ImGuiTabItemFlags_UnsavedDocument;
17422 if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
17423 tab_item_flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
17426 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
17427 g.Style.Colors[GWindowDockStyleColors[color_n]] = ColorConvertU32ToFloat4(window->DockStyle.Colors[color_n]);
17430 bool tab_open =
true;
17431 TabItemEx(tab_bar, window->Name, window->HasCloseButton ? &tab_open : NULL, tab_item_flags, window);
17433 node->WantCloseTabId = window->TabId;
17434 if (tab_bar->VisibleTabId == window->TabId)
17435 node->VisibleWindow = window;
17438 window->DockTabItemStatusFlags =
g.LastItemData.StatusFlags;
17439 window->DockTabItemRect =
g.LastItemData.Rect;
17442 if (
g.NavWindow &&
g.NavWindow->RootWindow == window && (window->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) == 0)
17443 host_window->NavLastIds[1] = window->TabId;
17448 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
17449 g.Style.Colors[GWindowDockStyleColors[color_n]] = backup_style_cols[color_n];
17452 if (node->VisibleWindow)
17453 if (is_focused || root_node->VisibleWindow == NULL)
17454 root_node->VisibleWindow = node->VisibleWindow;
17458 const bool close_button_is_enabled = node->HasCloseButton && node->VisibleWindow && node->VisibleWindow->HasCloseButton;
17459 const bool close_button_is_visible = node->HasCloseButton;
17461 if (close_button_is_visible)
17463 if (!close_button_is_enabled)
17465 PushItemFlag(ImGuiItemFlags_Disabled,
true);
17466 PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_Text] * ImVec4(1.0f,1.0f,1.0f,0.4f));
17468 if (CloseButton(host_window->GetID(
"#CLOSE"), close_button_pos))
17470 node->WantCloseAll =
true;
17471 for (
int n = 0; n < tab_bar->Tabs.Size; n++)
17472 TabBarCloseTab(tab_bar, &tab_bar->Tabs[n]);
17476 if (!close_button_is_enabled)
17485 ImGuiID title_bar_id = host_window->GetID(
"#TITLEBAR");
17486 if (
g.HoveredId == 0 ||
g.HoveredId == title_bar_id ||
g.ActiveId == title_bar_id)
17491 KeepAliveID(title_bar_id);
17492 ButtonBehavior(title_bar_rect, title_bar_id, NULL, &held, ImGuiButtonFlags_AllowOverlap);
17493 if (
g.HoveredId == title_bar_id)
17495 g.LastItemData.ID = title_bar_id;
17499 if (IsMouseClicked(0))
17500 focus_tab_id = tab_bar->SelectedTabId;
17503 if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
17504 StartMouseMovingWindowOrNode(tab->Window ? tab->Window : node->HostWindow, node, false);
17514 if (tab_bar->NextSelectedTabId)
17515 focus_tab_id = tab_bar->NextSelectedTabId;
17518 if (focus_tab_id != 0)
17519 if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, focus_tab_id))
17522 FocusWindow(tab->Window);
17523 NavInitWindow(tab->Window,
false);
17530 if (!node->IsDockSpace())
17532 host_window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
17533 host_window->SkipItems = backup_skip_item;
17537static void ImGui::DockNodeAddTabBar(ImGuiDockNode* node)
17539 IM_ASSERT(node->TabBar == NULL);
17540 node->TabBar = IM_NEW(ImGuiTabBar);
17543static void ImGui::DockNodeRemoveTabBar(ImGuiDockNode* node)
17545 if (node->TabBar == NULL)
17547 IM_DELETE(node->TabBar);
17548 node->TabBar = NULL;
17551static bool DockNodeIsDropAllowedOne(ImGuiWindow* payload, ImGuiWindow* host_window)
17553 if (host_window->DockNodeAsHost && host_window->DockNodeAsHost->IsDockSpace() && payload->BeginOrderWithinContext < host_window->BeginOrderWithinContext)
17556 ImGuiWindowClass* host_class = host_window->DockNodeAsHost ? &host_window->DockNodeAsHost->WindowClass : &host_window->WindowClass;
17557 ImGuiWindowClass* payload_class = &payload->WindowClass;
17558 if (host_class->ClassId != payload_class->ClassId)
17561 if (host_class->ClassId != 0 && host_class->DockingAllowUnclassed && payload_class->ClassId == 0)
17563 if (payload_class->ClassId != 0 && payload_class->DockingAllowUnclassed && host_class->ClassId == 0)
17575 for (
int i =
g.OpenPopupStack.Size - 1; i >= 0; i--)
17576 if (ImGuiWindow* popup_window =
g.OpenPopupStack[i].Window)
17577 if (ImGui::IsWindowWithinBeginStackOf(payload, popup_window))
17583static bool ImGui::DockNodeIsDropAllowed(ImGuiWindow* host_window, ImGuiWindow* root_payload)
17585 if (root_payload->DockNodeAsHost && root_payload->DockNodeAsHost->IsSplitNode())
17588 const int payload_count = root_payload->DockNodeAsHost ? root_payload->DockNodeAsHost->Windows.Size : 1;
17589 for (
int payload_n = 0; payload_n < payload_count; payload_n++)
17591 ImGuiWindow* payload = root_payload->DockNodeAsHost ? root_payload->DockNodeAsHost->Windows[payload_n] : root_payload;
17592 if (DockNodeIsDropAllowedOne(payload, host_window))
17600static 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)
17603 ImGuiStyle& style =
g.Style;
17605 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);
17606 if (out_title_rect) { *out_title_rect = r; }
17608 r.Min.x += style.WindowBorderSize;
17609 r.Max.x -= style.WindowBorderSize;
17611 float button_sz =
g.FontSize;
17612 r.Min.x += style.FramePadding.x;
17613 r.Max.x -= style.FramePadding.x;
17614 ImVec2 window_menu_button_pos = ImVec2(r.Min.x, r.Min.y + style.FramePadding.y);
17615 if (node->HasCloseButton)
17617 if (out_close_button_pos) *out_close_button_pos = ImVec2(r.Max.x - button_sz, r.Min.y + style.FramePadding.y);
17618 r.Max.x -= button_sz + style.ItemInnerSpacing.x;
17620 if (node->HasWindowMenuButton && style.WindowMenuButtonPosition == ImGuiDir_Left)
17622 r.Min.x += button_sz + style.ItemInnerSpacing.x;
17624 else if (node->HasWindowMenuButton && style.WindowMenuButtonPosition == ImGuiDir_Right)
17626 window_menu_button_pos = ImVec2(r.Max.x - button_sz, r.Min.y + style.FramePadding.y);
17627 r.Max.x -= button_sz + style.ItemInnerSpacing.x;
17629 if (out_tab_bar_rect) { *out_tab_bar_rect = r; }
17630 if (out_window_menu_button_pos) { *out_window_menu_button_pos = window_menu_button_pos; }
17633void ImGui::DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& pos_new, ImVec2& size_new, ImGuiDir dir, ImVec2 size_new_desired)
17636 const float dock_spacing =
g.Style.ItemInnerSpacing.x;
17637 const ImGuiAxis axis = (dir == ImGuiDir_Left || dir == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
17638 pos_new[axis ^ 1] = pos_old[axis ^ 1];
17639 size_new[axis ^ 1] = size_old[axis ^ 1];
17642 const float w_avail = size_old[axis] - dock_spacing;
17643 if (size_new_desired[axis] > 0.0f && size_new_desired[axis] <= w_avail * 0.5f)
17645 size_new[axis] = size_new_desired[axis];
17646 size_old[axis] = IM_TRUNC(w_avail - size_new[axis]);
17650 size_new[axis] = IM_TRUNC(w_avail * 0.5f);
17651 size_old[axis] = IM_TRUNC(w_avail - size_new[axis]);
17655 if (dir == ImGuiDir_Right || dir == ImGuiDir_Down)
17657 pos_new[axis] = pos_old[axis] + size_old[axis] + dock_spacing;
17659 else if (dir == ImGuiDir_Left || dir == ImGuiDir_Up)
17661 pos_new[axis] = pos_old[axis];
17662 pos_old[axis] = pos_new[axis] + size_new[axis] + dock_spacing;
17667bool ImGui::DockNodeCalcDropRectsAndTestMousePos(
const ImRect& parent, ImGuiDir dir, ImRect& out_r,
bool outer_docking, ImVec2* test_mouse_pos)
17671 const float parent_smaller_axis = ImMin(parent.GetWidth(), parent.GetHeight());
17672 const float hs_for_central_nodes = ImMin(
g.FontSize * 1.5f, ImMax(
g.FontSize * 0.5f, parent_smaller_axis / 8.0f));
17681 hs_w = ImTrunc(hs_for_central_nodes * 1.50f);
17682 hs_h = ImTrunc(hs_for_central_nodes * 0.80f);
17683 off = ImTrunc(ImVec2(parent.GetWidth() * 0.5f - hs_h, parent.GetHeight() * 0.5f - hs_h));
17687 hs_w = ImTrunc(hs_for_central_nodes);
17688 hs_h = ImTrunc(hs_for_central_nodes * 0.90f);
17689 off = ImTrunc(ImVec2(hs_w * 2.40f, hs_w * 2.40f));
17692 ImVec2 c = ImTrunc(parent.GetCenter());
17693 if (dir == ImGuiDir_None) { out_r = ImRect(c.x - hs_w, c.y - hs_w, c.x + hs_w, c.y + hs_w); }
17694 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); }
17695 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); }
17696 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); }
17697 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); }
17699 if (test_mouse_pos == NULL)
17702 ImRect hit_r = out_r;
17703 if (!outer_docking)
17706 hit_r.Expand(ImTrunc(hs_w * 0.30f));
17707 ImVec2 mouse_delta = (*test_mouse_pos - c);
17708 float mouse_delta_len2 = ImLengthSqr(mouse_delta);
17709 float r_threshold_center = hs_w * 1.4f;
17710 float r_threshold_sides = hs_w * (1.4f + 1.2f);
17711 if (mouse_delta_len2 < r_threshold_center * r_threshold_center)
17712 return (dir == ImGuiDir_None);
17713 if (mouse_delta_len2 < r_threshold_sides * r_threshold_sides)
17714 return (dir == ImGetDirQuadrantFromDelta(mouse_delta.x, mouse_delta.y));
17716 return hit_r.Contains(*test_mouse_pos);
17721static 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)
17728 if (payload_node == NULL)
17729 payload_node = payload_window->DockNodeAsHost;
17730 ImGuiDockNode* ref_node_for_rect = (host_node && !host_node->IsVisible) ? DockNodeGetRootNode(host_node) : host_node;
17731 if (ref_node_for_rect)
17732 IM_ASSERT(ref_node_for_rect->IsVisible ==
true);
17735 ImGuiDockNodeFlags src_node_flags = payload_node ? payload_node->MergedFlags : payload_window->WindowClass.DockNodeFlagsOverrideSet;
17736 ImGuiDockNodeFlags dst_node_flags = host_node ? host_node->MergedFlags : host_window->WindowClass.DockNodeFlagsOverrideSet;
17738 if (is_outer_docking)
17740 else if (dst_node_flags & ImGuiDockNodeFlags_NoDockingOverMe)
17742 else if (host_node && (dst_node_flags & ImGuiDockNodeFlags_NoDockingOverCentralNode) && host_node->IsCentralNode())
17744 else if ((!host_node || !host_node->IsEmpty()) && payload_node && payload_node->IsSplitNode() && (payload_node->OnlyNodeWithWindows == NULL))
17746 else if ((src_node_flags & ImGuiDockNodeFlags_NoDockingOverOther) && (!host_node || !host_node->IsEmpty()))
17748 else if ((src_node_flags & ImGuiDockNodeFlags_NoDockingOverEmpty) && host_node && host_node->IsEmpty())
17752 if ((dst_node_flags & ImGuiDockNodeFlags_NoDockingSplit) ||
g.IO.ConfigDockingNoSplit)
17754 else if (!is_outer_docking && host_node && host_node->ParentNode == NULL && host_node->IsCentralNode())
17756 else if (src_node_flags & ImGuiDockNodeFlags_NoDockingSplitOther)
17760 data->
FutureNode.HasCloseButton = (host_node ? host_node->HasCloseButton : host_window->HasCloseButton) || (payload_window->HasCloseButton);
17761 data->
FutureNode.HasWindowMenuButton = host_node ? true : ((host_window->Flags & ImGuiWindowFlags_NoCollapse) == 0);
17762 data->
FutureNode.Pos = ref_node_for_rect ? ref_node_for_rect->Pos : host_window->Pos;
17763 data->
FutureNode.Size = ref_node_for_rect ? ref_node_for_rect->Size : host_window->Size;
17766 IM_ASSERT(ImGuiDir_None == -1);
17770 if (!host_window->Collapsed)
17771 for (
int dir = ImGuiDir_None; dir < ImGuiDir_COUNT; dir++)
17777 if (DockNodeCalcDropRectsAndTestMousePos(data->
FutureNode.Rect(), (ImGuiDir)dir, data->
DropRectsDraw[dir+1], is_outer_docking, &
g.IO.MousePos))
17791 if (data->
SplitDir != ImGuiDir_None)
17793 ImGuiDir split_dir = data->
SplitDir;
17794 ImGuiAxis split_axis = (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
17795 ImVec2 pos_new, pos_old = data->
FutureNode.Pos;
17796 ImVec2 size_new, size_old = data->
FutureNode.Size;
17797 DockNodeCalcSplitRects(pos_old, size_old, pos_new, size_new, split_dir, payload_window->Size);
17800 float split_ratio = ImSaturate(size_new[split_axis] / data->
FutureNode.Size[split_axis]);
17803 data->
SplitRatio = (split_dir == ImGuiDir_Right || split_dir == ImGuiDir_Down) ? (1.0f - split_ratio) : (split_ratio);
17807static void ImGui::DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* root_payload,
const ImGuiDockPreviewData* data)
17810 IM_ASSERT(
g.CurrentWindow == host_window);
17814 const bool is_transparent_payload =
g.IO.ConfigDockingTransparentPayload;
17817 int overlay_draw_lists_count = 0;
17818 ImDrawList* overlay_draw_lists[2];
17819 overlay_draw_lists[overlay_draw_lists_count++] = GetForegroundDrawList(host_window->Viewport);
17820 if (host_window->Viewport != root_payload->Viewport && !is_transparent_payload)
17821 overlay_draw_lists[overlay_draw_lists_count++] = GetForegroundDrawList(root_payload->Viewport);
17824 const ImU32 overlay_col_main = GetColorU32(ImGuiCol_DockingPreview, is_transparent_payload ? 0.60f : 0.40f);
17825 const ImU32 overlay_col_drop = GetColorU32(ImGuiCol_DockingPreview, is_transparent_payload ? 0.90f : 0.70f);
17826 const ImU32 overlay_col_drop_hovered = GetColorU32(ImGuiCol_DockingPreview, is_transparent_payload ? 1.20f : 1.00f);
17827 const ImU32 overlay_col_lines = GetColorU32(ImGuiCol_NavWindowingHighlight, is_transparent_payload ? 0.80f : 0.60f);
17830 const bool can_preview_tabs = (root_payload->DockNodeAsHost == NULL || root_payload->DockNodeAsHost->Windows.Size > 0);
17833 ImRect overlay_rect = data->
FutureNode.Rect();
17834 if (data->
SplitDir == ImGuiDir_None && can_preview_tabs)
17835 overlay_rect.Min.y += GetFrameHeight();
17837 for (
int overlay_n = 0; overlay_n < overlay_draw_lists_count; overlay_n++)
17838 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));
17845 ImRect tab_bar_rect;
17846 DockNodeCalcTabBarLayout(&data->
FutureNode, NULL, &tab_bar_rect, NULL, NULL);
17847 ImVec2 tab_pos = tab_bar_rect.Min;
17848 if (host_node && host_node->TabBar)
17850 if (!host_node->IsHiddenTabBar() && !host_node->IsNoTabBar())
17851 tab_pos.x += host_node->TabBar->WidthAllTabs +
g.Style.ItemInnerSpacing.x;
17853 tab_pos.x +=
g.Style.ItemInnerSpacing.x + TabItemCalcSize(host_node->Windows[0]).x;
17855 else if (!(host_window->Flags & ImGuiWindowFlags_DockNodeHost))
17857 tab_pos.x +=
g.Style.ItemInnerSpacing.x + TabItemCalcSize(host_window).x;
17861 if (root_payload->DockNodeAsHost)
17862 IM_ASSERT(root_payload->DockNodeAsHost->Windows.Size <= root_payload->DockNodeAsHost->TabBar->Tabs.Size);
17863 ImGuiTabBar* tab_bar_with_payload = root_payload->DockNodeAsHost ? root_payload->DockNodeAsHost->TabBar : NULL;
17864 const int payload_count = tab_bar_with_payload ? tab_bar_with_payload->Tabs.Size : 1;
17865 for (
int payload_n = 0; payload_n < payload_count; payload_n++)
17868 ImGuiWindow* payload_window = tab_bar_with_payload ? tab_bar_with_payload->Tabs[payload_n].Window : root_payload;
17869 if (tab_bar_with_payload && payload_window == NULL)
17871 if (!DockNodeIsDropAllowedOne(payload_window, host_window))
17875 ImVec2 tab_size = TabItemCalcSize(payload_window);
17876 ImRect tab_bb(tab_pos.x, tab_pos.y, tab_pos.x + tab_size.x, tab_pos.y + tab_size.y);
17877 tab_pos.x += tab_size.x +
g.Style.ItemInnerSpacing.x;
17878 const ImU32 overlay_col_text = GetColorU32(payload_window->DockStyle.Colors[ImGuiWindowDockStyleCol_Text]);
17879 const ImU32 overlay_col_tabs = GetColorU32(payload_window->DockStyle.Colors[ImGuiWindowDockStyleCol_TabActive]);
17880 PushStyleColor(ImGuiCol_Text, overlay_col_text);
17881 for (
int overlay_n = 0; overlay_n < overlay_draw_lists_count; overlay_n++)
17883 ImGuiTabItemFlags tab_flags = (payload_window->Flags & ImGuiWindowFlags_UnsavedDocument) ? ImGuiTabItemFlags_UnsavedDocument : 0;
17884 if (!tab_bar_rect.Contains(tab_bb))
17885 overlay_draw_lists[overlay_n]->PushClipRect(tab_bar_rect.Min, tab_bar_rect.Max);
17886 TabItemBackground(overlay_draw_lists[overlay_n], tab_bb, tab_flags, overlay_col_tabs);
17887 TabItemLabelAndCloseButton(overlay_draw_lists[overlay_n], tab_bb, tab_flags,
g.Style.FramePadding, payload_window->Name, 0, 0,
false, NULL, NULL);
17888 if (!tab_bar_rect.Contains(tab_bb))
17889 overlay_draw_lists[overlay_n]->PopClipRect();
17896 const float overlay_rounding = ImMax(3.0f,
g.Style.FrameRounding);
17897 for (
int dir = ImGuiDir_None; dir < ImGuiDir_COUNT; dir++)
17902 ImRect draw_r_in = draw_r;
17903 draw_r_in.Expand(-2.0f);
17904 ImU32 overlay_col = (data->
SplitDir == (ImGuiDir)dir && data->
IsSplitDirExplicit) ? overlay_col_drop_hovered : overlay_col_drop;
17905 for (
int overlay_n = 0; overlay_n < overlay_draw_lists_count; overlay_n++)
17907 ImVec2 center = ImFloor(draw_r_in.GetCenter());
17908 overlay_draw_lists[overlay_n]->AddRectFilled(draw_r.Min, draw_r.Max, overlay_col, overlay_rounding);
17909 overlay_draw_lists[overlay_n]->AddRect(draw_r_in.Min, draw_r_in.Max, overlay_col_lines, overlay_rounding);
17910 if (dir == ImGuiDir_Left || dir == ImGuiDir_Right)
17911 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);
17912 if (dir == ImGuiDir_Up || dir == ImGuiDir_Down)
17913 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);
17918 if ((host_node && (host_node->MergedFlags & ImGuiDockNodeFlags_NoDockingSplit)) ||
g.IO.ConfigDockingNoSplit)
17935void ImGui::DockNodeTreeSplit(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiAxis split_axis,
int split_inheritor_child_idx,
float split_ratio, ImGuiDockNode* new_node)
17938 IM_ASSERT(split_axis != ImGuiAxis_None);
17940 ImGuiDockNode* child_0 = (new_node && split_inheritor_child_idx != 0) ? new_node : DockContextAddNode(ctx, 0);
17941 child_0->ParentNode = parent_node;
17943 ImGuiDockNode* child_1 = (new_node && split_inheritor_child_idx != 1) ? new_node : DockContextAddNode(ctx, 0);
17944 child_1->ParentNode = parent_node;
17946 ImGuiDockNode* child_inheritor = (split_inheritor_child_idx == 0) ? child_0 : child_1;
17947 DockNodeMoveChildNodes(child_inheritor, parent_node);
17948 parent_node->ChildNodes[0] = child_0;
17949 parent_node->ChildNodes[1] = child_1;
17950 parent_node->ChildNodes[split_inheritor_child_idx]->VisibleWindow = parent_node->VisibleWindow;
17951 parent_node->SplitAxis = split_axis;
17952 parent_node->VisibleWindow = NULL;
17953 parent_node->AuthorityForPos = parent_node->AuthorityForSize = ImGuiDataAuthority_DockNode;
17955 float size_avail = (parent_node->Size[split_axis] -
g.Style.DockingSeparatorSize);
17956 size_avail = ImMax(size_avail,
g.Style.WindowMinSize[split_axis] * 2.0f);
17957 IM_ASSERT(size_avail > 0.0f);
17958 child_0->SizeRef = child_1->SizeRef = parent_node->Size;
17959 child_0->SizeRef[split_axis] = ImTrunc(size_avail * split_ratio);
17960 child_1->SizeRef[split_axis] = ImTrunc(size_avail - child_0->SizeRef[split_axis]);
17962 DockNodeMoveWindows(parent_node->ChildNodes[split_inheritor_child_idx], parent_node);
17963 DockSettingsRenameNodeReferences(parent_node->ID, parent_node->ChildNodes[split_inheritor_child_idx]->ID);
17964 DockNodeUpdateHasCentralNodeChild(DockNodeGetRootNode(parent_node));
17965 DockNodeTreeUpdatePosSize(parent_node, parent_node->Pos, parent_node->Size);
17968 child_0->SharedFlags = parent_node->SharedFlags & ImGuiDockNodeFlags_SharedFlagsInheritMask_;
17969 child_1->SharedFlags = parent_node->SharedFlags & ImGuiDockNodeFlags_SharedFlagsInheritMask_;
17970 child_inheritor->LocalFlags = parent_node->LocalFlags & ImGuiDockNodeFlags_LocalFlagsTransferMask_;
17971 parent_node->LocalFlags &= ~ImGuiDockNodeFlags_LocalFlagsTransferMask_;
17972 child_0->UpdateMergedFlags();
17973 child_1->UpdateMergedFlags();
17974 parent_node->UpdateMergedFlags();
17975 if (child_inheritor->IsCentralNode())
17976 DockNodeGetRootNode(parent_node)->CentralNode = child_inheritor;
17979void ImGui::DockNodeTreeMerge(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiDockNode* merge_lead_child)
17983 ImGuiDockNode* child_0 = parent_node->ChildNodes[0];
17984 ImGuiDockNode* child_1 = parent_node->ChildNodes[1];
17985 IM_ASSERT(child_0 || child_1);
17986 IM_ASSERT(merge_lead_child == child_0 || merge_lead_child == child_1);
17987 if ((child_0 && child_0->Windows.Size > 0) || (child_1 && child_1->Windows.Size > 0))
17989 IM_ASSERT(parent_node->TabBar == NULL);
17990 IM_ASSERT(parent_node->Windows.Size == 0);
17992 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);
17994 ImVec2 backup_last_explicit_size = parent_node->SizeRef;
17995 DockNodeMoveChildNodes(parent_node, merge_lead_child);
17998 DockNodeMoveWindows(parent_node, child_0);
17999 DockSettingsRenameNodeReferences(child_0->ID, parent_node->ID);
18003 DockNodeMoveWindows(parent_node, child_1);
18004 DockSettingsRenameNodeReferences(child_1->ID, parent_node->ID);
18006 DockNodeApplyPosSizeToWindows(parent_node);
18007 parent_node->AuthorityForPos = parent_node->AuthorityForSize = parent_node->AuthorityForViewport = ImGuiDataAuthority_Auto;
18008 parent_node->VisibleWindow = merge_lead_child->VisibleWindow;
18009 parent_node->SizeRef = backup_last_explicit_size;
18012 parent_node->LocalFlags &= ~ImGuiDockNodeFlags_LocalFlagsTransferMask_;
18013 parent_node->LocalFlags |= (child_0 ? child_0->LocalFlags : 0) & ImGuiDockNodeFlags_LocalFlagsTransferMask_;
18014 parent_node->LocalFlags |= (child_1 ? child_1->LocalFlags : 0) & ImGuiDockNodeFlags_LocalFlagsTransferMask_;
18015 parent_node->LocalFlagsInWindows = (child_0 ? child_0->LocalFlagsInWindows : 0) | (child_1 ? child_1->LocalFlagsInWindows : 0);
18016 parent_node->UpdateMergedFlags();
18020 ctx->DockContext.Nodes.SetVoidPtr(child_0->ID, NULL);
18021 IM_DELETE(child_0);
18025 ctx->DockContext.Nodes.SetVoidPtr(child_1->ID, NULL);
18026 IM_DELETE(child_1);
18032void ImGui::DockNodeTreeUpdatePosSize(ImGuiDockNode* node, ImVec2 pos, ImVec2 size, ImGuiDockNode* only_write_to_single_node)
18037 const bool write_to_node = only_write_to_single_node == NULL || only_write_to_single_node == node;
18044 if (node->IsLeafNode())
18047 ImGuiDockNode* child_0 = node->ChildNodes[0];
18048 ImGuiDockNode* child_1 = node->ChildNodes[1];
18049 ImVec2 child_0_pos = pos, child_1_pos = pos;
18050 ImVec2 child_0_size =
size, child_1_size =
size;
18052 const bool child_0_is_toward_single_node = (only_write_to_single_node != NULL && DockNodeIsInHierarchyOf(only_write_to_single_node, child_0));
18053 const bool child_1_is_toward_single_node = (only_write_to_single_node != NULL && DockNodeIsInHierarchyOf(only_write_to_single_node, child_1));
18054 const bool child_0_is_or_will_be_visible = child_0->IsVisible || child_0_is_toward_single_node;
18055 const bool child_1_is_or_will_be_visible = child_1->IsVisible || child_1_is_toward_single_node;
18057 if (child_0_is_or_will_be_visible && child_1_is_or_will_be_visible)
18059 const float spacing =
g.Style.DockingSeparatorSize;
18060 const ImGuiAxis axis = (ImGuiAxis)node->SplitAxis;
18061 const float size_avail = ImMax(size[axis] - spacing, 0.0f);
18065 const float size_min_each = ImTrunc(ImMin(size_avail,
g.Style.WindowMinSize[axis] * 2.0f) * 0.5f);
18072 if (child_0->WantLockSizeOnce && !child_1->WantLockSizeOnce)
18074 child_0_size[axis] = child_0->SizeRef[axis] = ImMin(size_avail - 1.0f, child_0->Size[axis]);
18075 child_1_size[axis] = child_1->SizeRef[axis] = (size_avail - child_0_size[axis]);
18076 IM_ASSERT(child_0->SizeRef[axis] > 0.0f && child_1->SizeRef[axis] > 0.0f);
18078 else if (child_1->WantLockSizeOnce && !child_0->WantLockSizeOnce)
18080 child_1_size[axis] = child_1->SizeRef[axis] = ImMin(size_avail - 1.0f, child_1->Size[axis]);
18081 child_0_size[axis] = child_0->SizeRef[axis] = (size_avail - child_1_size[axis]);
18082 IM_ASSERT(child_0->SizeRef[axis] > 0.0f && child_1->SizeRef[axis] > 0.0f);
18084 else if (child_0->WantLockSizeOnce && child_1->WantLockSizeOnce)
18088 float split_ratio = child_0_size[axis] / (child_0_size[axis] + child_1_size[axis]);
18089 child_0_size[axis] = child_0->SizeRef[axis] = ImTrunc(size_avail * split_ratio);
18090 child_1_size[axis] = child_1->SizeRef[axis] = (size_avail - child_0_size[axis]);
18091 IM_ASSERT(child_0->SizeRef[axis] > 0.0f && child_1->SizeRef[axis] > 0.0f);
18095 else if (child_0->SizeRef[axis] != 0.0f && child_1->HasCentralNodeChild)
18097 child_0_size[axis] = ImMin(size_avail - size_min_each, child_0->SizeRef[axis]);
18098 child_1_size[axis] = (size_avail - child_0_size[axis]);
18100 else if (child_1->SizeRef[axis] != 0.0f && child_0->HasCentralNodeChild)
18102 child_1_size[axis] = ImMin(size_avail - size_min_each, child_1->SizeRef[axis]);
18103 child_0_size[axis] = (size_avail - child_1_size[axis]);
18108 float split_ratio = child_0->SizeRef[axis] / (child_0->SizeRef[axis] + child_1->SizeRef[axis]);
18109 child_0_size[axis] = ImMax(size_min_each, ImTrunc(size_avail * split_ratio + 0.5f));
18110 child_1_size[axis] = (size_avail - child_0_size[axis]);
18113 child_1_pos[axis] += spacing + child_0_size[axis];
18116 if (only_write_to_single_node == NULL)
18117 child_0->WantLockSizeOnce = child_1->WantLockSizeOnce =
false;
18119 const bool child_0_recurse = only_write_to_single_node ? child_0_is_toward_single_node : child_0->IsVisible;
18120 const bool child_1_recurse = only_write_to_single_node ? child_1_is_toward_single_node : child_1->IsVisible;
18121 if (child_0_recurse)
18122 DockNodeTreeUpdatePosSize(child_0, child_0_pos, child_0_size);
18123 if (child_1_recurse)
18124 DockNodeTreeUpdatePosSize(child_1, child_1_pos, child_1_size);
18127static void DockNodeTreeUpdateSplitterFindTouchingNode(ImGuiDockNode* node, ImGuiAxis axis,
int side, ImVector<ImGuiDockNode*>* touching_nodes)
18129 if (node->IsLeafNode())
18131 touching_nodes->push_back(node);
18134 if (node->ChildNodes[0]->IsVisible)
18135 if (node->SplitAxis != axis || side == 0 || !node->ChildNodes[1]->IsVisible)
18136 DockNodeTreeUpdateSplitterFindTouchingNode(node->ChildNodes[0], axis, side, touching_nodes);
18137 if (node->ChildNodes[1]->IsVisible)
18138 if (node->SplitAxis != axis || side == 1 || !node->ChildNodes[0]->IsVisible)
18139 DockNodeTreeUpdateSplitterFindTouchingNode(node->ChildNodes[1], axis, side, touching_nodes);
18143void ImGui::DockNodeTreeUpdateSplitter(ImGuiDockNode* node)
18145 if (node->IsLeafNode())
18150 ImGuiDockNode* child_0 = node->ChildNodes[0];
18151 ImGuiDockNode* child_1 = node->ChildNodes[1];
18152 if (child_0->IsVisible && child_1->IsVisible)
18155 const ImGuiAxis axis = (ImGuiAxis)node->SplitAxis;
18156 IM_ASSERT(axis != ImGuiAxis_None);
18158 bb.Min = child_0->Pos;
18159 bb.Max = child_1->Pos;
18160 bb.Min[axis] += child_0->Size[axis];
18161 bb.Max[axis ^ 1] += child_1->Size[axis ^ 1];
18164 const ImGuiDockNodeFlags merged_flags = child_0->MergedFlags | child_1->MergedFlags;
18165 const ImGuiDockNodeFlags no_resize_axis_flag = (axis == ImGuiAxis_X) ? ImGuiDockNodeFlags_NoResizeX : ImGuiDockNodeFlags_NoResizeY;
18166 if ((merged_flags & ImGuiDockNodeFlags_NoResize) || (merged_flags & no_resize_axis_flag))
18168 ImGuiWindow* window =
g.CurrentWindow;
18169 window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Separator),
g.Style.FrameRounding);
18178 ImVector<ImGuiDockNode*> touching_nodes[2];
18179 float min_size =
g.Style.WindowMinSize[axis];
18180 float resize_limits[2];
18181 resize_limits[0] = node->ChildNodes[0]->Pos[axis] + min_size;
18182 resize_limits[1] = node->ChildNodes[1]->Pos[axis] + node->ChildNodes[1]->Size[axis] - min_size;
18184 ImGuiID splitter_id = GetID(
"##Splitter");
18185 if (
g.ActiveId == splitter_id)
18187 DockNodeTreeUpdateSplitterFindTouchingNode(child_0, axis, 1, &touching_nodes[0]);
18188 DockNodeTreeUpdateSplitterFindTouchingNode(child_1, axis, 0, &touching_nodes[1]);
18189 for (
int touching_node_n = 0; touching_node_n < touching_nodes[0].Size; touching_node_n++)
18190 resize_limits[0] = ImMax(resize_limits[0], touching_nodes[0][touching_node_n]->Rect().Min[axis] + min_size);
18191 for (
int touching_node_n = 0; touching_node_n < touching_nodes[1].Size; touching_node_n++)
18192 resize_limits[1] = ImMin(resize_limits[1], touching_nodes[1][touching_node_n]->Rect().Max[axis] - min_size);
18210 float cur_size_0 = child_0->Size[axis];
18211 float cur_size_1 = child_1->Size[axis];
18212 float min_size_0 = resize_limits[0] - child_0->Pos[axis];
18213 float min_size_1 = child_1->Pos[axis] + child_1->Size[axis] - resize_limits[1];
18214 ImU32 bg_col = GetColorU32(ImGuiCol_WindowBg);
18215 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))
18217 if (touching_nodes[0].Size > 0 && touching_nodes[1].Size > 0)
18219 child_0->Size[axis] = child_0->SizeRef[axis] = cur_size_0;
18220 child_1->Pos[axis] -= cur_size_1 - child_1->Size[axis];
18221 child_1->Size[axis] = child_1->SizeRef[axis] = cur_size_1;
18225 for (
int side_n = 0; side_n < 2; side_n++)
18226 for (
int touching_node_n = 0; touching_node_n < touching_nodes[side_n].Size; touching_node_n++)
18228 ImGuiDockNode* touching_node = touching_nodes[side_n][touching_node_n];
18231 while (touching_node->ParentNode != node)
18233 if (touching_node->ParentNode->SplitAxis == axis)
18236 ImGuiDockNode* node_to_preserve = touching_node->ParentNode->ChildNodes[side_n];
18237 node_to_preserve->WantLockSizeOnce =
true;
18241 touching_node = touching_node->ParentNode;
18245 DockNodeTreeUpdatePosSize(child_0, child_0->Pos, child_0->Size);
18246 DockNodeTreeUpdatePosSize(child_1, child_1->Pos, child_1->Size);
18247 MarkIniSettingsDirty();
18254 if (child_0->IsVisible)
18255 DockNodeTreeUpdateSplitter(child_0);
18256 if (child_1->IsVisible)
18257 DockNodeTreeUpdateSplitter(child_1);
18260ImGuiDockNode* ImGui::DockNodeTreeFindFallbackLeafNode(ImGuiDockNode* node)
18262 if (node->IsLeafNode())
18264 if (ImGuiDockNode* leaf_node = DockNodeTreeFindFallbackLeafNode(node->ChildNodes[0]))
18266 if (ImGuiDockNode* leaf_node = DockNodeTreeFindFallbackLeafNode(node->ChildNodes[1]))
18271ImGuiDockNode* ImGui::DockNodeTreeFindVisibleNodeByPos(ImGuiDockNode* node, ImVec2 pos)
18273 if (!node->IsVisible)
18276 const float dock_spacing = 0.0f;
18277 ImRect r(node->Pos, node->Pos + node->Size);
18278 r.Expand(dock_spacing * 0.5f);
18279 bool inside = r.Contains(pos);
18283 if (node->IsLeafNode())
18285 if (ImGuiDockNode* hovered_node = DockNodeTreeFindVisibleNodeByPos(node->ChildNodes[0], pos))
18286 return hovered_node;
18287 if (ImGuiDockNode* hovered_node = DockNodeTreeFindVisibleNodeByPos(node->ChildNodes[1], pos))
18288 return hovered_node;
18303void ImGui::SetWindowDock(ImGuiWindow* window, ImGuiID dock_id, ImGuiCond cond)
18306 if (cond && (window->SetWindowDockAllowFlags & cond) == 0)
18308 window->SetWindowDockAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
18310 if (window->DockId == dock_id)
18315 if (ImGuiDockNode* new_node = DockContextFindNodeByID(&
g, dock_id))
18316 if (new_node->IsSplitNode())
18319 new_node = DockNodeGetRootNode(new_node);
18320 if (new_node->CentralNode)
18322 IM_ASSERT(new_node->CentralNode->IsCentralNode());
18323 dock_id = new_node->CentralNode->ID;
18327 dock_id = new_node->LastFocusedNodeId;
18331 if (window->DockId == dock_id)
18334 if (window->DockNode)
18335 DockNodeRemoveWindow(window->DockNode, window, 0);
18336 window->DockId = dock_id;
18343ImGuiID ImGui::DockSpace(ImGuiID
id,
const ImVec2& size_arg, ImGuiDockNodeFlags flags,
const ImGuiWindowClass* window_class)
18346 ImGuiWindow* window = GetCurrentWindowRead();
18347 if (!(
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
18353 if (window->SkipItems)
18354 flags |= ImGuiDockNodeFlags_KeepAliveOnly;
18355 if ((flags & ImGuiDockNodeFlags_KeepAliveOnly) == 0)
18356 window = GetCurrentWindow();
18358 IM_ASSERT((flags & ImGuiDockNodeFlags_DockSpace) == 0);
18359 IM_ASSERT(
id != 0);
18360 ImGuiDockNode* node = DockContextFindNodeByID(&
g,
id);
18363 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockSpace: dockspace node 0x%08X created\n",
id);
18364 node = DockContextAddNode(&
g,
id);
18365 node->SetLocalFlags(ImGuiDockNodeFlags_CentralNode);
18367 if (window_class && window_class->ClassId != node->WindowClass.ClassId)
18368 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockSpace: dockspace node 0x%08X: setup WindowClass 0x%08X -> 0x%08X\n",
id, node->WindowClass.ClassId, window_class->ClassId);
18369 node->SharedFlags = flags;
18370 node->WindowClass = window_class ? *window_class : ImGuiWindowClass();
18374 if (node->LastFrameActive ==
g.FrameCount && !(flags & ImGuiDockNodeFlags_KeepAliveOnly))
18376 IM_ASSERT(node->IsDockSpace() ==
false &&
"Cannot call DockSpace() twice a frame with the same ID");
18377 node->SetLocalFlags(node->LocalFlags | ImGuiDockNodeFlags_DockSpace);
18380 node->SetLocalFlags(node->LocalFlags | ImGuiDockNodeFlags_DockSpace);
18383 if (flags & ImGuiDockNodeFlags_KeepAliveOnly)
18385 node->LastFrameAlive =
g.FrameCount;
18389 const ImVec2 content_avail = GetContentRegionAvail();
18390 ImVec2
size = ImTrunc(size_arg);
18391 if (
size.x <= 0.0f)
18392 size.x = ImMax(content_avail.x +
size.x, 4.0f);
18393 if (
size.y <= 0.0f)
18394 size.y = ImMax(content_avail.y +
size.y, 4.0f);
18395 IM_ASSERT(
size.x > 0.0f &&
size.y > 0.0f);
18397 node->Pos = window->DC.CursorPos;
18398 node->Size = node->SizeRef =
size;
18399 SetNextWindowPos(node->Pos);
18400 SetNextWindowSize(node->Size);
18401 g.NextWindowData.PosUndock =
false;
18405 ImGuiWindowFlags window_flags = ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_DockNodeHost;
18406 window_flags |= ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar;
18407 window_flags |= ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
18408 window_flags |= ImGuiWindowFlags_NoBackground;
18411 ImFormatString(title, IM_ARRAYSIZE(title),
"%s/DockSpace_%08X", window->Name,
id);
18413 PushStyleVar(ImGuiStyleVar_ChildBorderSize, 0.0f);
18414 Begin(title, NULL, window_flags);
18417 ImGuiWindow* host_window =
g.CurrentWindow;
18418 DockNodeSetupHostWindow(node, host_window);
18419 host_window->ChildId = window->GetID(title);
18420 node->OnlyNodeWithWindows = NULL;
18422 IM_ASSERT(node->IsRootNode());
18430 if (node->IsLeafNode() && !node->IsCentralNode())
18431 node->SetLocalFlags(node->LocalFlags | ImGuiDockNodeFlags_CentralNode);
18434 DockNodeUpdate(node);
18438 ImRect bb(node->Pos, node->Pos + size);
18440 ItemAdd(bb,
id, NULL, ImGuiItemFlags_NoNav);
18441 if ((
g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && IsWindowChildOf(
g.HoveredWindow, host_window,
false,
true))
18442 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
18451ImGuiID ImGui::DockSpaceOverViewport(
const ImGuiViewport* viewport, ImGuiDockNodeFlags dockspace_flags,
const ImGuiWindowClass* window_class)
18453 if (viewport == NULL)
18454 viewport = GetMainViewport();
18456 SetNextWindowPos(viewport->WorkPos);
18457 SetNextWindowSize(viewport->WorkSize);
18458 SetNextWindowViewport(viewport->ID);
18460 ImGuiWindowFlags host_window_flags = 0;
18461 host_window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking;
18462 host_window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
18463 if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
18464 host_window_flags |= ImGuiWindowFlags_NoBackground;
18467 ImFormatString(label, IM_ARRAYSIZE(label),
"DockSpaceViewport_%08X", viewport->ID);
18469 PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
18470 PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
18471 PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
18472 Begin(label, NULL, host_window_flags);
18475 ImGuiID dockspace_id = GetID(
"DockSpace");
18476 DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags, window_class);
18479 return dockspace_id;
18505void ImGui::DockBuilderDockWindow(
const char* window_name, ImGuiID node_id)
18508 ImGuiContext&
g = *
GImGui; IM_UNUSED(
g);
18509 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderDockWindow '%s' to node 0x%08X\n", window_name, node_id);
18510 ImGuiID window_id =
ImHashStr(window_name);
18511 if (ImGuiWindow* window = FindWindowByID(window_id))
18514 ImGuiID prev_node_id = window->DockId;
18515 SetWindowDock(window, node_id, ImGuiCond_Always);
18516 if (window->DockId != prev_node_id)
18517 window->DockOrder = -1;
18522 ImGuiWindowSettings* settings = FindWindowSettingsByID(window_id);
18523 if (settings == NULL)
18524 settings = CreateNewWindowSettings(window_name);
18525 if (settings->DockId != node_id)
18526 settings->DockOrder = -1;
18527 settings->DockId = node_id;
18531ImGuiDockNode* ImGui::DockBuilderGetNode(ImGuiID node_id)
18534 return DockContextFindNodeByID(&
g, node_id);
18537void ImGui::DockBuilderSetNodePos(ImGuiID node_id, ImVec2 pos)
18540 ImGuiDockNode* node = DockContextFindNodeByID(&
g, node_id);
18544 node->AuthorityForPos = ImGuiDataAuthority_DockNode;
18547void ImGui::DockBuilderSetNodeSize(ImGuiID node_id, ImVec2 size)
18550 ImGuiDockNode* node = DockContextFindNodeByID(&
g, node_id);
18553 IM_ASSERT(
size.x > 0.0f &&
size.y > 0.0f);
18554 node->Size = node->SizeRef =
size;
18555 node->AuthorityForSize = ImGuiDataAuthority_DockNode;
18565ImGuiID ImGui::DockBuilderAddNode(ImGuiID node_id, ImGuiDockNodeFlags flags)
18567 ImGuiContext&
g = *
GImGui; IM_UNUSED(
g);
18568 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderAddNode 0x%08X flags=%08X\n", node_id, flags);
18571 DockBuilderRemoveNode(node_id);
18573 ImGuiDockNode* node = NULL;
18574 if (flags & ImGuiDockNodeFlags_DockSpace)
18576 DockSpace(node_id, ImVec2(0, 0), (flags & ~ImGuiDockNodeFlags_DockSpace) | ImGuiDockNodeFlags_KeepAliveOnly);
18577 node = DockContextFindNodeByID(&
g, node_id);
18581 node = DockContextAddNode(&
g, node_id);
18582 node->SetLocalFlags(flags);
18584 node->LastFrameAlive =
g.FrameCount;
18588void ImGui::DockBuilderRemoveNode(ImGuiID node_id)
18590 ImGuiContext&
g = *
GImGui; IM_UNUSED(
g);
18591 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderRemoveNode 0x%08X\n", node_id);
18593 ImGuiDockNode* node = DockContextFindNodeByID(&
g, node_id);
18596 DockBuilderRemoveNodeDockedWindows(node_id,
true);
18597 DockBuilderRemoveNodeChildNodes(node_id);
18599 node = DockContextFindNodeByID(&
g, node_id);
18602 if (node->IsCentralNode() && node->ParentNode)
18603 node->ParentNode->SetLocalFlags(node->ParentNode->LocalFlags | ImGuiDockNodeFlags_CentralNode);
18604 DockContextRemoveNode(&
g, node,
true);
18608void ImGui::DockBuilderRemoveNodeChildNodes(ImGuiID root_id)
18611 ImGuiDockContext* dc = &
g.DockContext;
18613 ImGuiDockNode* root_node = root_id ? DockContextFindNodeByID(&
g, root_id) : NULL;
18614 if (root_id && root_node == NULL)
18616 bool has_central_node =
false;
18618 ImGuiDataAuthority backup_root_node_authority_for_pos = root_node ? root_node->AuthorityForPos : ImGuiDataAuthority_Auto;
18619 ImGuiDataAuthority backup_root_node_authority_for_size = root_node ? root_node->AuthorityForSize : ImGuiDataAuthority_Auto;
18622 ImVector<ImGuiDockNode*> nodes_to_remove;
18623 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
18624 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
18626 bool want_removal = (root_id == 0) || (node->ID != root_id && DockNodeGetRootNode(node)->ID == root_id);
18629 if (node->IsCentralNode())
18630 has_central_node =
true;
18632 DockContextQueueNotifyRemovedNode(&
g, node);
18635 DockNodeMoveWindows(root_node, node);
18636 DockSettingsRenameNodeReferences(node->ID, root_node->ID);
18638 nodes_to_remove.push_back(node);
18646 root_node->AuthorityForPos = backup_root_node_authority_for_pos;
18647 root_node->AuthorityForSize = backup_root_node_authority_for_size;
18651 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
18652 if (ImGuiID window_settings_dock_id = settings->DockId)
18653 for (
int n = 0; n < nodes_to_remove.Size; n++)
18654 if (nodes_to_remove[n]->ID == window_settings_dock_id)
18656 settings->DockId = root_id;
18661 if (nodes_to_remove.Size > 1)
18662 ImQsort(nodes_to_remove.Data, nodes_to_remove.Size,
sizeof(ImGuiDockNode*), DockNodeComparerDepthMostFirst);
18663 for (
int n = 0; n < nodes_to_remove.Size; n++)
18664 DockContextRemoveNode(&
g, nodes_to_remove[n],
false);
18669 dc->Requests.clear();
18671 else if (has_central_node)
18673 root_node->CentralNode = root_node;
18674 root_node->SetLocalFlags(root_node->LocalFlags | ImGuiDockNodeFlags_CentralNode);
18678void ImGui::DockBuilderRemoveNodeDockedWindows(ImGuiID root_id,
bool clear_settings_refs)
18682 if (clear_settings_refs)
18684 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
18686 bool want_removal = (root_id == 0) || (settings->DockId == root_id);
18687 if (!want_removal && settings->DockId != 0)
18688 if (ImGuiDockNode* node = DockContextFindNodeByID(&
g, settings->DockId))
18689 if (DockNodeGetRootNode(node)->ID == root_id)
18690 want_removal =
true;
18692 settings->DockId = 0;
18697 for (
int n = 0; n <
g.Windows.Size; n++)
18699 ImGuiWindow* window =
g.Windows[n];
18700 bool want_removal = (root_id == 0) || (window->DockNode && DockNodeGetRootNode(window->DockNode)->ID == root_id) || (window->DockNodeAsHost && window->DockNodeAsHost->ID == root_id);
18703 const ImGuiID backup_dock_id = window->DockId;
18704 IM_UNUSED(backup_dock_id);
18705 DockContextProcessUndockWindow(&
g, window, clear_settings_refs);
18706 if (!clear_settings_refs)
18707 IM_ASSERT(window->DockId == backup_dock_id);
18715ImGuiID 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)
18718 IM_ASSERT(split_dir != ImGuiDir_None);
18719 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderSplitNode: node 0x%08X, split_dir %d\n",
id, split_dir);
18721 ImGuiDockNode* node = DockContextFindNodeByID(&
g,
id);
18724 IM_ASSERT(node != NULL);
18728 IM_ASSERT(!node->IsSplitNode());
18736 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);
18738 DockContextProcessDock(&
g, &req);
18740 ImGuiID id_at_dir = node->ChildNodes[(split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up) ? 0 : 1]->
ID;
18741 ImGuiID id_at_opposite_dir = node->ChildNodes[(split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up) ? 1 : 0]->
ID;
18743 *out_id_at_dir = id_at_dir;
18744 if (out_id_at_opposite_dir)
18745 *out_id_at_opposite_dir = id_at_opposite_dir;
18749static ImGuiDockNode* DockBuilderCopyNodeRec(ImGuiDockNode* src_node, ImGuiID dst_node_id_if_known, ImVector<ImGuiID>* out_node_remap_pairs)
18752 ImGuiDockNode* dst_node = ImGui::DockContextAddNode(&
g, dst_node_id_if_known);
18753 dst_node->SharedFlags = src_node->SharedFlags;
18754 dst_node->LocalFlags = src_node->LocalFlags;
18755 dst_node->LocalFlagsInWindows = ImGuiDockNodeFlags_None;
18756 dst_node->Pos = src_node->Pos;
18757 dst_node->Size = src_node->Size;
18758 dst_node->SizeRef = src_node->SizeRef;
18759 dst_node->SplitAxis = src_node->SplitAxis;
18760 dst_node->UpdateMergedFlags();
18762 out_node_remap_pairs->push_back(src_node->ID);
18763 out_node_remap_pairs->push_back(dst_node->ID);
18765 for (
int child_n = 0; child_n < IM_ARRAYSIZE(src_node->ChildNodes); child_n++)
18766 if (src_node->ChildNodes[child_n])
18768 dst_node->ChildNodes[child_n] = DockBuilderCopyNodeRec(src_node->ChildNodes[child_n], 0, out_node_remap_pairs);
18769 dst_node->ChildNodes[child_n]->ParentNode = dst_node;
18772 IMGUI_DEBUG_LOG_DOCKING(
"[docking] Fork node %08X -> %08X (%d childs)\n", src_node->ID, dst_node->ID, dst_node->IsSplitNode() ? 2 : 0);
18776void ImGui::DockBuilderCopyNode(ImGuiID src_node_id, ImGuiID dst_node_id, ImVector<ImGuiID>* out_node_remap_pairs)
18779 IM_ASSERT(src_node_id != 0);
18780 IM_ASSERT(dst_node_id != 0);
18781 IM_ASSERT(out_node_remap_pairs != NULL);
18783 DockBuilderRemoveNode(dst_node_id);
18785 ImGuiDockNode* src_node = DockContextFindNodeByID(&
g, src_node_id);
18786 IM_ASSERT(src_node != NULL);
18788 out_node_remap_pairs->clear();
18789 DockBuilderCopyNodeRec(src_node, dst_node_id, out_node_remap_pairs);
18791 IM_ASSERT((out_node_remap_pairs->Size % 2) == 0);
18794void ImGui::DockBuilderCopyWindowSettings(
const char* src_name,
const char* dst_name)
18796 ImGuiWindow* src_window = FindWindowByName(src_name);
18797 if (src_window == NULL)
18799 if (ImGuiWindow* dst_window = FindWindowByName(dst_name))
18801 dst_window->Pos = src_window->Pos;
18802 dst_window->Size = src_window->Size;
18803 dst_window->SizeFull = src_window->SizeFull;
18804 dst_window->Collapsed = src_window->Collapsed;
18808 ImGuiWindowSettings* dst_settings = FindWindowSettingsByID(
ImHashStr(dst_name));
18810 dst_settings = CreateNewWindowSettings(dst_name);
18811 ImVec2ih window_pos_2ih = ImVec2ih(src_window->Pos);
18812 if (src_window->ViewportId != 0 && src_window->ViewportId != IMGUI_VIEWPORT_DEFAULT_ID)
18814 dst_settings->ViewportPos = window_pos_2ih;
18815 dst_settings->ViewportId = src_window->ViewportId;
18816 dst_settings->Pos = ImVec2ih(0, 0);
18820 dst_settings->Pos = window_pos_2ih;
18822 dst_settings->Size = ImVec2ih(src_window->SizeFull);
18823 dst_settings->Collapsed = src_window->Collapsed;
18828void ImGui::DockBuilderCopyDockSpace(ImGuiID src_dockspace_id, ImGuiID dst_dockspace_id, ImVector<const char*>* in_window_remap_pairs)
18831 IM_ASSERT(src_dockspace_id != 0);
18832 IM_ASSERT(dst_dockspace_id != 0);
18833 IM_ASSERT(in_window_remap_pairs != NULL);
18834 IM_ASSERT((in_window_remap_pairs->Size % 2) == 0);
18839 ImVector<ImGuiID> node_remap_pairs;
18840 DockBuilderCopyNode(src_dockspace_id, dst_dockspace_id, &node_remap_pairs);
18844 ImVector<ImGuiID> src_windows;
18845 for (
int remap_window_n = 0; remap_window_n < in_window_remap_pairs->Size; remap_window_n += 2)
18847 const char* src_window_name = (*in_window_remap_pairs)[remap_window_n];
18848 const char* dst_window_name = (*in_window_remap_pairs)[remap_window_n + 1];
18849 ImGuiID src_window_id =
ImHashStr(src_window_name);
18850 src_windows.push_back(src_window_id);
18853 ImGuiID src_dock_id = 0;
18854 if (ImGuiWindow* src_window = FindWindowByID(src_window_id))
18855 src_dock_id = src_window->DockId;
18856 else if (ImGuiWindowSettings* src_window_settings = FindWindowSettingsByID(src_window_id))
18857 src_dock_id = src_window_settings->DockId;
18858 ImGuiID dst_dock_id = 0;
18859 for (
int dock_remap_n = 0; dock_remap_n < node_remap_pairs.Size; dock_remap_n += 2)
18860 if (node_remap_pairs[dock_remap_n] == src_dock_id)
18862 dst_dock_id = node_remap_pairs[dock_remap_n + 1];
18867 if (dst_dock_id != 0)
18870 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);
18871 DockBuilderDockWindow(dst_window_name, dst_dock_id);
18877 IMGUI_DEBUG_LOG_DOCKING(
"[docking] Remap window settings '%s' -> '%s'\n", src_window_name, dst_window_name);
18878 DockBuilderCopyWindowSettings(src_window_name, dst_window_name);
18885 struct DockRemainingWindowTask { ImGuiWindow*
Window; ImGuiID DockId; DockRemainingWindowTask(ImGuiWindow* window, ImGuiID dock_id) {
Window = window; DockId = dock_id; } };
18886 ImVector<DockRemainingWindowTask> dock_remaining_windows;
18887 for (
int dock_remap_n = 0; dock_remap_n < node_remap_pairs.Size; dock_remap_n += 2)
18888 if (ImGuiID src_dock_id = node_remap_pairs[dock_remap_n])
18890 ImGuiID dst_dock_id = node_remap_pairs[dock_remap_n + 1];
18891 ImGuiDockNode* node = DockBuilderGetNode(src_dock_id);
18892 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
18894 ImGuiWindow* window = node->Windows[window_n];
18895 if (src_windows.contains(window->ID))
18899 IMGUI_DEBUG_LOG_DOCKING(
"[docking] Remap window '%s' %08X -> %08X\n", window->Name, src_dock_id, dst_dock_id);
18900 dock_remaining_windows.push_back(DockRemainingWindowTask(window, dst_dock_id));
18903 for (
const DockRemainingWindowTask& task : dock_remaining_windows)
18904 DockBuilderDockWindow(task.
Window->Name, task.DockId);
18908void ImGui::DockBuilderFinish(ImGuiID root_id)
18912 DockContextBuildAddWindowsToNodes(&
g, root_id);
18925bool ImGui::GetWindowAlwaysWantOwnTabBar(ImGuiWindow* window)
18928 if (
g.IO.ConfigDockingAlwaysTabBar || window->WindowClass.DockingAlwaysTabBar)
18929 if ((window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDocking)) == 0)
18930 if (!window->IsFallbackWindow)
18935static ImGuiDockNode* ImGui::DockContextBindNodeToWindow(ImGuiContext* ctx, ImGuiWindow* window)
18937 ImGuiContext&
g = *ctx;
18938 ImGuiDockNode* node = DockContextFindNodeByID(ctx, window->DockId);
18939 IM_ASSERT(window->DockNode == NULL);
18942 if (node && node->IsSplitNode())
18944 DockContextProcessUndockWindow(ctx, window);
18951 node = DockContextAddNode(ctx, window->DockId);
18952 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Window;
18953 node->LastFrameAlive =
g.FrameCount;
18960 if (!node->IsVisible)
18962 ImGuiDockNode* ancestor_node = node;
18963 while (!ancestor_node->IsVisible && ancestor_node->ParentNode)
18964 ancestor_node = ancestor_node->ParentNode;
18965 IM_ASSERT(ancestor_node->Size.x > 0.0f && ancestor_node->Size.y > 0.0f);
18966 DockNodeUpdateHasCentralNodeChild(DockNodeGetRootNode(ancestor_node));
18967 DockNodeTreeUpdatePosSize(ancestor_node, ancestor_node->Pos, ancestor_node->Size, node);
18971 bool node_was_visible = node->IsVisible;
18972 DockNodeAddWindow(node, window,
true);
18973 node->IsVisible = node_was_visible;
18974 IM_ASSERT(node == window->DockNode);
18978void ImGui::BeginDocked(ImGuiWindow* window,
bool* p_open)
18983 window->DockIsActive = window->DockNodeIsVisible = window->DockTabIsVisible =
false;
18985 const bool auto_dock_node = GetWindowAlwaysWantOwnTabBar(window);
18986 if (auto_dock_node)
18988 if (window->DockId == 0)
18990 IM_ASSERT(window->DockNode == NULL);
18991 window->DockId = DockContextGenNodeID(&
g);
18997 bool want_undock =
false;
18998 want_undock |= (window->Flags & ImGuiWindowFlags_NoDocking) != 0;
18999 want_undock |= (
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) && (window->SetWindowPosAllowFlags &
g.NextWindowData.PosCond) &&
g.NextWindowData.PosUndock;
19002 DockContextProcessUndockWindow(&
g, window);
19008 ImGuiDockNode* node = window->DockNode;
19010 IM_ASSERT(window->DockId == node->ID);
19011 if (window->DockId != 0 && node == NULL)
19013 node = DockContextBindNodeToWindow(&
g, window);
19020 if (node->IsCentralNode && (node->Flags & ImGuiDockNodeFlags_NoDockingInCentralNode))
19022 DockContextProcessUndockWindow(ctx, window);
19029 if (node->LastFrameAlive <
g.FrameCount)
19032 ImGuiDockNode* root_node = DockNodeGetRootNode(node);
19033 if (root_node->LastFrameAlive <
g.FrameCount)
19034 DockContextProcessUndockWindow(&
g, window);
19036 window->DockIsActive =
true;
19041 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
19042 window->DockStyle.Colors[color_n] = ColorConvertFloat4ToU32(
g.Style.Colors[GWindowDockStyleColors[color_n]]);
19047 if (node->HostWindow == NULL)
19049 if (node->State == ImGuiDockNodeState_HostWindowHiddenBecauseWindowsAreResizing)
19050 window->DockIsActive =
true;
19051 if (node->Windows.Size > 1 && window->Appearing)
19052 DockNodeHideWindowDuringHostWindowCreation(window);
19057 IM_ASSERT(node->HostWindow);
19058 IM_ASSERT(node->IsLeafNode());
19059 IM_ASSERT(node->Size.x >= 0.0f && node->Size.y >= 0.0f);
19060 node->State = ImGuiDockNodeState_HostWindowVisible;
19063 if (!(node->MergedFlags & ImGuiDockNodeFlags_KeepAliveOnly) && window->BeginOrderWithinContext < node->HostWindow->BeginOrderWithinContext)
19065 DockContextProcessUndockWindow(&
g, window);
19070 SetNextWindowPos(node->Pos);
19071 SetNextWindowSize(node->Size);
19072 g.NextWindowData.PosUndock =
false;
19073 window->DockIsActive =
true;
19074 window->DockNodeIsVisible =
true;
19075 window->DockTabIsVisible =
false;
19076 if (node->MergedFlags & ImGuiDockNodeFlags_KeepAliveOnly)
19080 if (node->VisibleWindow == window)
19081 window->DockTabIsVisible =
true;
19084 IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) == 0);
19085 window->Flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoResize;
19086 window->ChildFlags |= ImGuiChildFlags_AlwaysUseWindowPadding;
19087 if (node->IsHiddenTabBar() || node->IsNoTabBar())
19088 window->Flags |= ImGuiWindowFlags_NoTitleBar;
19090 window->Flags &= ~ImGuiWindowFlags_NoTitleBar;
19094 if (node->TabBar && window->WasActive)
19095 window->DockOrder = (short)DockNodeGetTabOrder(window);
19097 if ((node->WantCloseAll || node->WantCloseTabId == window->TabId) && p_open != NULL)
19101 ImGuiWindow* parent_window = window->DockNode->HostWindow;
19102 window->ChildId = parent_window->GetID(window->Name);
19105void ImGui::BeginDockableDragDropSource(ImGuiWindow* window)
19108 IM_ASSERT(
g.ActiveId == window->MoveId);
19109 IM_ASSERT(
g.MovingWindow == window);
19110 IM_ASSERT(
g.CurrentWindow == window);
19113 if (
g.IO.ConfigDockingWithShift !=
g.IO.KeyShift)
19118 if (
g.IO.ConfigDockingWithShift &&
g.MouseStationaryTimer >= 1.0f &&
g.ActiveId >= 1.0f)
19119 SetTooltip(
"%s", LocalizeGetMsg(ImGuiLocKey_DockingHoldShiftToDock));
19123 g.LastItemData.ID = window->MoveId;
19124 window = window->RootWindowDockTree;
19125 IM_ASSERT((window->Flags & ImGuiWindowFlags_NoDocking) == 0);
19126 bool is_drag_docking = (
g.IO.ConfigDockingWithShift) || ImRect(0, 0, window->SizeFull.x, GetFrameHeight()).Contains(
g.ActiveIdClickOffset);
19127 if (is_drag_docking && BeginDragDropSource(ImGuiDragDropFlags_SourceNoPreviewTooltip | ImGuiDragDropFlags_SourceNoHoldToOpenOthers | ImGuiDragDropFlags_SourceAutoExpirePayload))
19129 SetDragDropPayload(IMGUI_PAYLOAD_TYPE_WINDOW, &window,
sizeof(window));
19130 EndDragDropSource();
19133 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
19134 window->DockStyle.Colors[color_n] = ColorConvertFloat4ToU32(
g.Style.Colors[GWindowDockStyleColors[color_n]]);
19138void ImGui::BeginDockableDragDropTarget(ImGuiWindow* window)
19143 IM_ASSERT((window->Flags & ImGuiWindowFlags_NoDocking) == 0);
19144 if (!
g.DragDropActive)
19147 if (!BeginDragDropTargetCustom(window->Rect(), window->ID))
19152 const ImGuiPayload* payload = &
g.DragDropPayload;
19153 if (!payload->IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) || !DockNodeIsDropAllowed(window, *(ImGuiWindow**)payload->Data))
19155 EndDragDropTarget();
19159 ImGuiWindow* payload_window = *(ImGuiWindow**)payload->Data;
19160 if (AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_WINDOW, ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect))
19164 bool dock_into_floating_window =
false;
19165 ImGuiDockNode* node = NULL;
19166 if (window->DockNodeAsHost)
19169 node = DockNodeTreeFindVisibleNodeByPos(window->DockNodeAsHost,
g.IO.MousePos);
19174 if (node && node->IsDockSpace() && node->IsRootNode())
19175 node = (node->CentralNode && node->IsLeafNode()) ? node->CentralNode : DockNodeTreeFindFallbackLeafNode(node);
19179 if (window->DockNode)
19180 node = window->DockNode;
19182 dock_into_floating_window =
true;
19185 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()));
19186 const bool is_explicit_target =
g.IO.ConfigDockingWithShift || IsMouseHoveringRect(explicit_target_rect.Min, explicit_target_rect.Max);
19190 const bool do_preview = payload->IsPreview() || payload->IsDelivery();
19191 if (do_preview && (node != NULL || dock_into_floating_window))
19197 if (node && (node->ParentNode || node->IsCentralNode() || !node->IsLeafNode()))
19198 if (ImGuiDockNode* root_node = DockNodeGetRootNode(node))
19200 DockNodePreviewDockSetup(window, root_node, payload_window, NULL, &split_outer, is_explicit_target,
true);
19202 split_data = &split_outer;
19204 if (!node || node->IsLeafNode())
19205 DockNodePreviewDockSetup(window, node, payload_window, NULL, &split_inner, is_explicit_target,
false);
19206 if (split_data == &split_outer)
19210 DockNodePreviewDockRender(window, node, payload_window, &split_inner);
19211 DockNodePreviewDockRender(window, node, payload_window, &split_outer);
19215 DockContextQueueDock(&
g, window, split_data->
SplitNode, payload_window, split_data->
SplitDir, split_data->
SplitRatio, split_data == &split_outer);
19218 EndDragDropTarget();
19234static void ImGui::DockSettingsRenameNodeReferences(ImGuiID old_node_id, ImGuiID new_node_id)
19237 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockSettingsRenameNodeReferences: from 0x%08X -> to 0x%08X\n", old_node_id, new_node_id);
19238 for (
int window_n = 0; window_n <
g.Windows.Size; window_n++)
19240 ImGuiWindow* window =
g.Windows[window_n];
19241 if (window->DockId == old_node_id && window->DockNode == NULL)
19242 window->DockId = new_node_id;
19245 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
19246 if (settings->DockId == old_node_id)
19247 settings->DockId = new_node_id;
19251static void ImGui::DockSettingsRemoveNodeReferences(ImGuiID* node_ids,
int node_ids_count)
19256 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
19257 for (
int node_n = 0; node_n < node_ids_count; node_n++)
19258 if (settings->DockId == node_ids[node_n])
19260 settings->DockId = 0;
19261 settings->DockOrder = -1;
19262 if (++found < node_ids_count)
19271 ImGuiDockContext* dc = &ctx->DockContext;
19272 for (
int n = 0; n < dc->NodesSettings.Size; n++)
19273 if (dc->NodesSettings[n].ID ==
id)
19274 return &dc->NodesSettings[n];
19279static void ImGui::DockSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
19281 ImGuiDockContext* dc = &ctx->DockContext;
19282 dc->NodesSettings.clear();
19283 DockContextClearNodes(ctx, 0,
true);
19287static void ImGui::DockSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
19290 ImGuiDockContext* dc = &ctx->DockContext;
19291 if (ctx->Windows.Size == 0)
19292 DockContextPruneUnusedSettingsNodes(ctx);
19293 DockContextBuildNodesFromSettings(ctx, dc->NodesSettings.Data, dc->NodesSettings.Size);
19294 DockContextBuildAddWindowsToNodes(ctx, 0);
19297static void* ImGui::DockSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*,
const char* name)
19299 if (strcmp(name,
"Data") != 0)
19304static void ImGui::DockSettingsHandler_ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler*,
void*,
const char* line)
19316 if (strncmp(line,
"DockNode", 8) == 0) { line =
ImStrSkipBlank(line + strlen(
"DockNode")); }
19317 else if (strncmp(line,
"DockSpace", 9) == 0) { line =
ImStrSkipBlank(line + strlen(
"DockSpace")); node.
Flags |= ImGuiDockNodeFlags_DockSpace; }
19319 if (sscanf(line,
"ID=0x%08X%n", &node.
ID, &r) == 1) { line += r; }
else return;
19320 if (sscanf(line,
" Parent=0x%08X%n", &node.
ParentNodeId, &r) == 1) { line += r;
if (node.
ParentNodeId == 0)
return; }
19324 if (sscanf(line,
" Pos=%i,%i%n", &x, &y, &r) == 2) { line += r; node.
Pos = ImVec2ih((
short)x, (
short)y); }
else return;
19325 if (sscanf(line,
" Size=%i,%i%n", &x, &y, &r) == 2) { line += r; node.
Size = ImVec2ih((
short)x, (
short)y); }
else return;
19329 if (sscanf(line,
" SizeRef=%i,%i%n", &x, &y, &r) == 2) { line += r; node.
SizeRef = ImVec2ih((
short)x, (
short)y); }
19331 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; }
19332 if (sscanf(line,
" NoResize=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_NoResize; }
19333 if (sscanf(line,
" CentralNode=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_CentralNode; }
19334 if (sscanf(line,
" NoTabBar=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_NoTabBar; }
19335 if (sscanf(line,
" HiddenTabBar=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_HiddenTabBar; }
19336 if (sscanf(line,
" NoWindowMenuButton=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_NoWindowMenuButton; }
19337 if (sscanf(line,
" NoCloseButton=%d%n", &x, &r) == 1) { line += r;
if (x != 0) node.
Flags |= ImGuiDockNodeFlags_NoCloseButton; }
19338 if (sscanf(line,
" Selected=0x%08X%n", &node.
SelectedTabId,&r) == 1) { line += r; }
19341 node.
Depth = parent_settings->Depth + 1;
19342 ctx->DockContext.NodesSettings.push_back(node);
19345static void DockSettingsHandler_DockNodeToSettings(ImGuiDockContext* dc, ImGuiDockNode* node,
int depth)
19348 IM_ASSERT(depth < (1 << (
sizeof(node_settings.
Depth) << 3)));
19349 node_settings.
ID = node->ID;
19350 node_settings.
ParentNodeId = node->ParentNode ? node->ParentNode->ID : 0;
19351 node_settings.
ParentWindowId = (node->IsDockSpace() && node->HostWindow && node->HostWindow->ParentWindow) ? node->HostWindow->ParentWindow->ID : 0;
19353 node_settings.
SplitAxis = (
signed char)(node->IsSplitNode() ? node->SplitAxis : ImGuiAxis_None);
19354 node_settings.
Depth = (char)depth;
19355 node_settings.
Flags = (node->LocalFlags & ImGuiDockNodeFlags_SavedFlagsMask_);
19356 node_settings.
Pos = ImVec2ih(node->Pos);
19357 node_settings.
Size = ImVec2ih(node->Size);
19358 node_settings.
SizeRef = ImVec2ih(node->SizeRef);
19359 dc->NodesSettings.push_back(node_settings);
19360 if (node->ChildNodes[0])
19361 DockSettingsHandler_DockNodeToSettings(dc, node->ChildNodes[0], depth + 1);
19362 if (node->ChildNodes[1])
19363 DockSettingsHandler_DockNodeToSettings(dc, node->ChildNodes[1], depth + 1);
19366static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
19368 ImGuiContext&
g = *ctx;
19369 ImGuiDockContext* dc = &ctx->DockContext;
19370 if (!(
g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
19375 dc->NodesSettings.resize(0);
19376 dc->NodesSettings.reserve(dc->Nodes.Data.Size);
19377 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
19378 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
19379 if (node->IsRootNode())
19380 DockSettingsHandler_DockNodeToSettings(dc, node, 0);
19383 for (
int node_n = 0; node_n < dc->NodesSettings.Size; node_n++)
19384 max_depth = ImMax((
int)dc->NodesSettings[node_n].Depth, max_depth);
19387 buf->appendf(
"[%s][Data]\n", handler->TypeName);
19388 for (
int node_n = 0; node_n < dc->NodesSettings.Size; node_n++)
19390 const int line_start_pos = buf->size(); (void)line_start_pos;
19392 buf->appendf(
"%*s%s%*s", node_settings->
Depth * 2,
"", (node_settings->
Flags & ImGuiDockNodeFlags_DockSpace) ?
"DockSpace" :
"DockNode ", (max_depth - node_settings->
Depth) * 2,
"");
19393 buf->appendf(
" ID=0x%08X", node_settings->
ID);
19396 buf->appendf(
" Parent=0x%08X SizeRef=%d,%d", node_settings->
ParentNodeId, node_settings->
SizeRef.x, node_settings->
SizeRef.y);
19402 buf->appendf(
" Pos=%d,%d Size=%d,%d", node_settings->
Pos.x, node_settings->
Pos.y, node_settings->
Size.x, node_settings->
Size.y);
19404 if (node_settings->
SplitAxis != ImGuiAxis_None)
19405 buf->appendf(
" Split=%c", (node_settings->
SplitAxis == ImGuiAxis_X) ?
'X' :
'Y');
19406 if (node_settings->
Flags & ImGuiDockNodeFlags_NoResize)
19407 buf->appendf(
" NoResize=1");
19408 if (node_settings->
Flags & ImGuiDockNodeFlags_CentralNode)
19409 buf->appendf(
" CentralNode=1");
19410 if (node_settings->
Flags & ImGuiDockNodeFlags_NoTabBar)
19411 buf->appendf(
" NoTabBar=1");
19412 if (node_settings->
Flags & ImGuiDockNodeFlags_HiddenTabBar)
19413 buf->appendf(
" HiddenTabBar=1");
19414 if (node_settings->
Flags & ImGuiDockNodeFlags_NoWindowMenuButton)
19415 buf->appendf(
" NoWindowMenuButton=1");
19416 if (node_settings->
Flags & ImGuiDockNodeFlags_NoCloseButton)
19417 buf->appendf(
" NoCloseButton=1");
19419 buf->appendf(
" Selected=0x%08X", node_settings->
SelectedTabId);
19422 if (
g.IO.ConfigDebugIniSettings)
19423 if (ImGuiDockNode* node = DockContextFindNodeByID(ctx, node_settings->
ID))
19425 buf->appendf(
"%*s", ImMax(2, (line_start_pos + 92) - buf->size()),
"");
19426 if (node->IsDockSpace() && node->HostWindow && node->HostWindow->ParentWindow)
19427 buf->appendf(
" ; in '%s'", node->HostWindow->ParentWindow->Name);
19429 int contains_window = 0;
19430 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
19431 if (settings->DockId == node_settings->
ID)
19433 if (contains_window++ == 0)
19434 buf->appendf(
" ; contains ");
19435 buf->appendf(
"'%s' ", settings->GetName());
19439 buf->appendf(
"\n");
19441 buf->appendf(
"\n");
19449#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS)
19452#pragma comment(lib, "user32")
19453#pragma comment(lib, "kernel32")
19458static const char* GetClipboardTextFn_DefaultImpl(
void* user_data_ctx)
19460 ImGuiContext&
g = *(ImGuiContext*)user_data_ctx;
19461 g.ClipboardHandlerData.clear();
19462 if (!::OpenClipboard(NULL))
19464 HANDLE wbuf_handle = ::GetClipboardData(CF_UNICODETEXT);
19465 if (wbuf_handle == NULL)
19467 ::CloseClipboard();
19470 if (
const WCHAR* wbuf_global = (
const WCHAR*)::GlobalLock(wbuf_handle))
19472 int buf_len = ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, NULL, 0, NULL, NULL);
19473 g.ClipboardHandlerData.resize(buf_len);
19474 ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1,
g.ClipboardHandlerData.Data, buf_len, NULL, NULL);
19476 ::GlobalUnlock(wbuf_handle);
19477 ::CloseClipboard();
19478 return g.ClipboardHandlerData.Data;
19481static void SetClipboardTextFn_DefaultImpl(
void*,
const char* text)
19483 if (!::OpenClipboard(NULL))
19485 const int wbuf_length = ::MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
19486 HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length *
sizeof(WCHAR));
19487 if (wbuf_handle == NULL)
19489 ::CloseClipboard();
19492 WCHAR* wbuf_global = (WCHAR*)::GlobalLock(wbuf_handle);
19493 ::MultiByteToWideChar(CP_UTF8, 0, text, -1, wbuf_global, wbuf_length);
19494 ::GlobalUnlock(wbuf_handle);
19495 ::EmptyClipboard();
19496 if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL)
19497 ::GlobalFree(wbuf_handle);
19498 ::CloseClipboard();
19501#elif defined(__APPLE__) && TARGET_OS_OSX && defined(IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS)
19503#include <Carbon/Carbon.h>
19504static PasteboardRef main_clipboard = 0;
19508static void SetClipboardTextFn_DefaultImpl(
void*,
const char* text)
19510 if (!main_clipboard)
19511 PasteboardCreate(kPasteboardClipboard, &main_clipboard);
19512 PasteboardClear(main_clipboard);
19513 CFDataRef cf_data = CFDataCreate(kCFAllocatorDefault, (
const UInt8*)text, strlen(text));
19516 PasteboardPutItemFlavor(main_clipboard, (PasteboardItemID)1, CFSTR(
"public.utf8-plain-text"), cf_data, 0);
19517 CFRelease(cf_data);
19521static const char* GetClipboardTextFn_DefaultImpl(
void* user_data_ctx)
19523 ImGuiContext&
g = *(ImGuiContext*)user_data_ctx;
19524 if (!main_clipboard)
19525 PasteboardCreate(kPasteboardClipboard, &main_clipboard);
19526 PasteboardSynchronize(main_clipboard);
19528 ItemCount item_count = 0;
19529 PasteboardGetItemCount(main_clipboard, &item_count);
19530 for (ItemCount i = 0; i < item_count; i++)
19532 PasteboardItemID item_id = 0;
19533 PasteboardGetItemIdentifier(main_clipboard, i + 1, &item_id);
19534 CFArrayRef flavor_type_array = 0;
19535 PasteboardCopyItemFlavors(main_clipboard, item_id, &flavor_type_array);
19536 for (CFIndex j = 0, nj = CFArrayGetCount(flavor_type_array); j < nj; j++)
19539 if (PasteboardCopyItemFlavorData(main_clipboard, item_id, CFSTR(
"public.utf8-plain-text"), &cf_data) == noErr)
19541 g.ClipboardHandlerData.clear();
19542 int length = (int)CFDataGetLength(cf_data);
19543 g.ClipboardHandlerData.resize(length + 1);
19544 CFDataGetBytes(cf_data, CFRangeMake(0, length), (UInt8*)
g.ClipboardHandlerData.Data);
19545 g.ClipboardHandlerData[
length] = 0;
19546 CFRelease(cf_data);
19547 return g.ClipboardHandlerData.Data;
19557static const char* GetClipboardTextFn_DefaultImpl(
void* user_data_ctx)
19559 ImGuiContext&
g = *(ImGuiContext*)user_data_ctx;
19560 return g.ClipboardHandlerData.empty() ? NULL :
g.ClipboardHandlerData.begin();
19563static void SetClipboardTextFn_DefaultImpl(
void* user_data_ctx,
const char* text)
19565 ImGuiContext&
g = *(ImGuiContext*)user_data_ctx;
19566 g.ClipboardHandlerData.clear();
19567 const char* text_end = text + strlen(text);
19568 g.ClipboardHandlerData.resize((
int)(text_end - text) + 1);
19569 memcpy(&
g.ClipboardHandlerData[0], text, (
size_t)(text_end - text));
19570 g.ClipboardHandlerData[(int)(text_end - text)] = 0;
19576#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
19580#pragma comment(lib, "imm32")
19583static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatformImeData* data)
19586 HWND hwnd = (HWND)viewport->PlatformHandleRaw;
19591 if (HIMC himc = ::ImmGetContext(hwnd))
19593 COMPOSITIONFORM composition_form = {};
19594 composition_form.ptCurrentPos.x = (LONG)(data->InputPos.x - viewport->Pos.x);
19595 composition_form.ptCurrentPos.y = (LONG)(data->InputPos.y - viewport->Pos.y);
19596 composition_form.dwStyle = CFS_FORCE_POSITION;
19597 ::ImmSetCompositionWindow(himc, &composition_form);
19598 CANDIDATEFORM candidate_form = {};
19599 candidate_form.dwStyle = CFS_CANDIDATEPOS;
19600 candidate_form.ptCurrentPos.x = (LONG)(data->InputPos.x - viewport->Pos.x);
19601 candidate_form.ptCurrentPos.y = (LONG)(data->InputPos.y - viewport->Pos.y);
19602 ::ImmSetCandidateWindow(himc, &candidate_form);
19603 ::ImmReleaseContext(hwnd, himc);
19609static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport*, ImGuiPlatformImeData*) {}
19637#ifndef IMGUI_DISABLE_DEBUG_TOOLS
19639void ImGui::DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport,
const ImRect& bb)
19642 ImGuiWindow* window =
g.CurrentWindow;
19644 ImVec2
scale = bb.GetSize() / viewport->Size;
19645 ImVec2 off = bb.Min - viewport->Pos *
scale;
19646 float alpha_mul = (viewport->Flags & ImGuiViewportFlags_IsMinimized) ? 0.30f : 1.00f;
19647 window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul * 0.40f));
19648 for (ImGuiWindow* thumb_window :
g.Windows)
19650 if (!thumb_window->WasActive || (thumb_window->Flags & ImGuiWindowFlags_ChildWindow))
19652 if (thumb_window->Viewport != viewport)
19655 ImRect thumb_r = thumb_window->Rect();
19656 ImRect title_r = thumb_window->TitleBarRect();
19657 thumb_r = ImRect(ImTrunc(off + thumb_r.Min * scale), ImTrunc(off + thumb_r.Max * scale));
19658 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));
19659 thumb_r.ClipWithFull(bb);
19660 title_r.ClipWithFull(bb);
19661 const bool window_is_focused = (
g.NavWindow && thumb_window->RootWindowForTitleBarHighlight ==
g.NavWindow->RootWindowForTitleBarHighlight);
19662 window->DrawList->AddRectFilled(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_WindowBg, alpha_mul));
19663 window->DrawList->AddRectFilled(title_r.Min, title_r.Max, GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg, alpha_mul));
19664 window->DrawList->AddRect(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_Border, alpha_mul));
19665 window->DrawList->AddText(
g.Font,
g.FontSize * 1.0f, title_r.Min, GetColorU32(ImGuiCol_Text, alpha_mul), thumb_window->Name, FindRenderedTextEnd(thumb_window->Name));
19667 draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul));
19668 if (viewport->ID ==
g.DebugMetricsConfig.HighlightViewportID)
19669 window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
19672static void RenderViewportsThumbnails()
19675 ImGuiWindow* window =
g.CurrentWindow;
19678 float SCALE = 1.0f / 8.0f;
19679 ImRect bb_full(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
19680 for (ImGuiPlatformMonitor& monitor :
g.PlatformIO.Monitors)
19681 bb_full.Add(ImRect(monitor.MainPos, monitor.MainPos + monitor.MainSize));
19682 ImVec2 p = window->DC.CursorPos;
19683 ImVec2 off = p - bb_full.Min * SCALE;
19684 for (ImGuiPlatformMonitor& monitor :
g.PlatformIO.Monitors)
19686 ImRect monitor_draw_bb(off + (monitor.MainPos) * SCALE, off + (monitor.MainPos + monitor.MainSize) * SCALE);
19687 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);
19688 window->DrawList->AddRectFilled(monitor_draw_bb.Min, monitor_draw_bb.Max, ImGui::GetColorU32(ImGuiCol_Border, 0.10f), 4.0f);
19692 for (ImGuiViewportP* viewport :
g.Viewports)
19694 ImRect viewport_draw_bb(off + (viewport->Pos) * SCALE, off + (viewport->Pos + viewport->Size) * SCALE);
19695 ImGui::DebugRenderViewportThumbnail(window->DrawList, viewport, viewport_draw_bb);
19697 ImGui::Dummy(bb_full.GetSize() * SCALE);
19700static int IMGUI_CDECL ViewportComparerByLastFocusedStampCount(
const void* lhs,
const void* rhs)
19702 const ImGuiViewportP* a = *(
const ImGuiViewportP*
const*)lhs;
19703 const ImGuiViewportP* b = *(
const ImGuiViewportP*
const*)rhs;
19704 return b->LastFocusedStampCount - a->LastFocusedStampCount;
19708void ImGui::DebugRenderKeyboardPreview(ImDrawList* draw_list)
19710 const float scale = ImGui::GetFontSize() / 13.0f;
19711 const ImVec2 key_size = ImVec2(35.0f, 35.0f) *
scale;
19712 const float key_rounding = 3.0f *
scale;
19713 const ImVec2 key_face_size = ImVec2(25.0f, 25.0f) *
scale;
19714 const ImVec2 key_face_pos = ImVec2(5.0f, 3.0f) *
scale;
19715 const float key_face_rounding = 2.0f *
scale;
19716 const ImVec2 key_label_pos = ImVec2(7.0f, 4.0f) *
scale;
19717 const ImVec2 key_step = ImVec2(key_size.x - 1.0f, key_size.y - 1.0f);
19718 const float key_row_offset = 9.0f *
scale;
19720 ImVec2 board_min = GetCursorScreenPos();
19721 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);
19722 ImVec2 start_pos = ImVec2(board_min.x + 5.0f - key_step.x, board_min.y);
19724 struct KeyLayoutData {
int Row, Col;
const char* Label; ImGuiKey Key; };
19725 const KeyLayoutData keys_to_display[] =
19727 { 0, 0,
"", ImGuiKey_Tab }, { 0, 1,
"Q", ImGuiKey_Q }, { 0, 2,
"W", ImGuiKey_W }, { 0, 3,
"E", ImGuiKey_E }, { 0, 4,
"R", ImGuiKey_R },
19728 { 1, 0,
"", ImGuiKey_CapsLock }, { 1, 1,
"A", ImGuiKey_A }, { 1, 2,
"S", ImGuiKey_S }, { 1, 3,
"D", ImGuiKey_D }, { 1, 4,
"F", ImGuiKey_F },
19729 { 2, 0,
"", ImGuiKey_LeftShift },{ 2, 1,
"Z", ImGuiKey_Z }, { 2, 2,
"X", ImGuiKey_X }, { 2, 3,
"C", ImGuiKey_C }, { 2, 4,
"V", ImGuiKey_V }
19734 Dummy(board_max - board_min);
19735 if (!IsItemVisible())
19737 draw_list->PushClipRect(board_min, board_max,
true);
19738 for (
int n = 0; n < IM_ARRAYSIZE(keys_to_display); n++)
19740 const KeyLayoutData* key_data = &keys_to_display[n];
19741 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);
19742 ImVec2 key_max = key_min + key_size;
19743 draw_list->AddRectFilled(key_min, key_max, IM_COL32(204, 204, 204, 255), key_rounding);
19744 draw_list->AddRect(key_min, key_max, IM_COL32(24, 24, 24, 255), key_rounding);
19745 ImVec2 face_min = ImVec2(key_min.x + key_face_pos.x, key_min.y + key_face_pos.y);
19746 ImVec2 face_max = ImVec2(face_min.x + key_face_size.x, face_min.y + key_face_size.y);
19747 draw_list->AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, ImDrawFlags_None, 2.0f);
19748 draw_list->AddRectFilled(face_min, face_max, IM_COL32(252, 252, 252, 255), key_face_rounding);
19749 ImVec2 label_min = ImVec2(key_min.x + key_label_pos.x, key_min.y + key_label_pos.y);
19750 draw_list->AddText(label_min, IM_COL32(64, 64, 64, 255), key_data->Label);
19751 if (IsKeyDown(key_data->Key))
19752 draw_list->AddRectFilled(key_min, key_max, IM_COL32(255, 0, 0, 128), key_rounding);
19754 draw_list->PopClipRect();
19758void ImGui::DebugTextEncoding(
const char* str)
19760 Text(
"Text: \"%s\"", str);
19761 if (!BeginTable(
"##DebugTextEncoding", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable))
19763 TableSetupColumn(
"Offset");
19764 TableSetupColumn(
"UTF-8");
19765 TableSetupColumn(
"Glyph");
19766 TableSetupColumn(
"Codepoint");
19768 for (
const char* p = str; *p != 0; )
19773 Text(
"%d", (
int)(p - str));
19775 for (
int byte_index = 0; byte_index < c_utf8_len; byte_index++)
19777 if (byte_index > 0)
19779 Text(
"0x%02X", (
int)(
unsigned char)p[byte_index]);
19782 if (GetFont()->FindGlyphNoFallback((ImWchar)c))
19785 TextUnformatted((c == IM_UNICODE_CODEPOINT_INVALID) ?
"[invalid]" :
"[missing]");
19787 Text(
"U+%04X", (
int)c);
19793static void DebugFlashStyleColorStop()
19796 if (
g.DebugFlashStyleColorIdx != ImGuiCol_COUNT)
19797 g.Style.Colors[
g.DebugFlashStyleColorIdx] =
g.DebugFlashStyleColorBackup;
19798 g.DebugFlashStyleColorIdx = ImGuiCol_COUNT;
19802void ImGui::DebugFlashStyleColor(ImGuiCol idx)
19805 DebugFlashStyleColorStop();
19806 g.DebugFlashStyleColorTime = 0.5f;
19807 g.DebugFlashStyleColorIdx = idx;
19808 g.DebugFlashStyleColorBackup =
g.Style.Colors[idx];
19811void ImGui::UpdateDebugToolFlashStyleColor()
19814 if (
g.DebugFlashStyleColorTime <= 0.0f)
19816 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);
19817 g.Style.Colors[
g.DebugFlashStyleColorIdx].w = 1.0f;
19818 if ((
g.DebugFlashStyleColorTime -=
g.IO.DeltaTime) <= 0.0f)
19819 DebugFlashStyleColorStop();
19823static void MetricsHelpMarker(
const char* desc)
19825 ImGui::TextDisabled(
"(?)");
19826 if (ImGui::BeginItemTooltip())
19828 ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
19830 ImGui::PopTextWrapPos();
19831 ImGui::EndTooltip();
19838 for (ImFont* font : atlas->Fonts)
19841 DebugNodeFont(font);
19844 if (TreeNode(
"Font Atlas",
"Font Atlas (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
19847 ImGuiMetricsConfig* cfg = &
g.DebugMetricsConfig;
19848 Checkbox(
"Tint with Text Color", &cfg->ShowAtlasTintedWithTextColor);
19849 ImVec4 tint_col = cfg->ShowAtlasTintedWithTextColor ? GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
19850 ImVec4 border_col = GetStyleColorVec4(ImGuiCol_Border);
19851 Image(atlas->TexID, ImVec2((
float)atlas->TexWidth, (
float)atlas->TexHeight), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), tint_col, border_col);
19856void ImGui::ShowMetricsWindow(
bool* p_open)
19859 ImGuiIO& io =
g.IO;
19860 ImGuiMetricsConfig* cfg = &
g.DebugMetricsConfig;
19861 if (cfg->ShowDebugLog)
19862 ShowDebugLogWindow(&cfg->ShowDebugLog);
19863 if (cfg->ShowIDStackTool)
19864 ShowIDStackToolWindow(&cfg->ShowIDStackTool);
19866 if (!Begin(
"Dear ImGui Metrics/Debugger", p_open) || GetCurrentWindow()->BeginCount > 1)
19873 DebugBreakClearData();
19876 Text(
"Dear ImGui %s", GetVersion());
19877 Text(
"Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
19878 Text(
"%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3);
19879 Text(
"%d visible windows, %d current allocations", io.MetricsRenderWindows,
g.DebugAllocInfo.TotalAllocCount -
g.DebugAllocInfo.TotalFreeCount);
19885 enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentIdeal, WRT_ContentRegionRect, WRT_Count };
19886 const char* wrt_rects_names[WRT_Count] = {
"OuterRect",
"OuterRectClipped",
"InnerRect",
"InnerClipRect",
"WorkRect",
"Content",
"ContentIdeal",
"ContentRegionRect" };
19887 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 };
19888 const char* trt_rects_names[TRT_Count] = {
"OuterRect",
"InnerRect",
"WorkRect",
"HostClipRect",
"InnerClipRect",
"BackgroundClipRect",
"ColumnsRect",
"ColumnsWorkRect",
"ColumnsClipRect",
"ColumnsContentHeadersUsed",
"ColumnsContentHeadersIdeal",
"ColumnsContentFrozen",
"ColumnsContentUnfrozen" };
19889 if (cfg->ShowWindowsRectsType < 0)
19890 cfg->ShowWindowsRectsType = WRT_WorkRect;
19891 if (cfg->ShowTablesRectsType < 0)
19892 cfg->ShowTablesRectsType = TRT_WorkRect;
19896 static ImRect GetTableRect(ImGuiTable* table,
int rect_type,
int n)
19898 ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
19899 if (rect_type == TRT_OuterRect) {
return table->OuterRect; }
19900 else if (rect_type == TRT_InnerRect) {
return table->InnerRect; }
19901 else if (rect_type == TRT_WorkRect) {
return table->WorkRect; }
19902 else if (rect_type == TRT_HostClipRect) {
return table->HostClipRect; }
19903 else if (rect_type == TRT_InnerClipRect) {
return table->InnerClipRect; }
19904 else if (rect_type == TRT_BackgroundClipRect) {
return table->BgClipRect; }
19905 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); }
19906 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); }
19907 else if (rect_type == TRT_ColumnsClipRect) { ImGuiTableColumn* c = &table->Columns[n];
return c->ClipRect; }
19908 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); }
19909 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); }
19910 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); }
19911 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); }
19916 static ImRect GetWindowRect(ImGuiWindow* window,
int rect_type)
19918 if (rect_type == WRT_OuterRect) {
return window->Rect(); }
19919 else if (rect_type == WRT_OuterRectClipped) {
return window->OuterRectClipped; }
19920 else if (rect_type == WRT_InnerRect) {
return window->InnerRect; }
19921 else if (rect_type == WRT_InnerClipRect) {
return window->InnerClipRect; }
19922 else if (rect_type == WRT_WorkRect) {
return window->WorkRect; }
19923 else if (rect_type == WRT_Content) { ImVec2
min = window->InnerRect.Min - window->Scroll + window->WindowPadding;
return ImRect(min, min + window->ContentSize); }
19924 else if (rect_type == WRT_ContentIdeal) { ImVec2
min = window->InnerRect.Min - window->Scroll + window->WindowPadding;
return ImRect(min, min + window->ContentSizeIdeal); }
19925 else if (rect_type == WRT_ContentRegionRect) {
return window->ContentRegionRect; }
19936 SeparatorTextEx(0,
"Debug breaks", NULL,
CalcTextSize(
"(?)").x +
g.Style.SeparatorTextPadding.x);
19938 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.");
19939 if (
Checkbox(
"Show Item Picker", &
g.DebugItemPickerActive) &&
g.DebugItemPickerActive)
19940 DebugStartItemPicker();
19941 Checkbox(
"Show \"Debug Break\" buttons in other sections (io.ConfigDebugIsDebuggerPresent)", &
g.IO.ConfigDebugIsDebuggerPresent);
19943 SeparatorText(
"Visualize");
19945 Checkbox(
"Show Debug Log", &cfg->ShowDebugLog);
19947 MetricsHelpMarker(
"You can also call ImGui::ShowDebugLogWindow() from your code.");
19949 Checkbox(
"Show ID Stack Tool", &cfg->ShowIDStackTool);
19951 MetricsHelpMarker(
"You can also call ImGui::ShowIDStackToolWindow() from your code.");
19953 Checkbox(
"Show windows begin order", &cfg->ShowWindowsBeginOrder);
19954 Checkbox(
"Show windows rectangles", &cfg->ShowWindowsRects);
19956 SetNextItemWidth(GetFontSize() * 12);
19957 cfg->ShowWindowsRects |=
Combo(
"##show_windows_rect_type", &cfg->ShowWindowsRectsType, wrt_rects_names, WRT_Count, WRT_Count);
19958 if (cfg->ShowWindowsRects &&
g.NavWindow != NULL)
19960 BulletText(
"'%s':",
g.NavWindow->Name);
19962 for (
int rect_n = 0; rect_n < WRT_Count; rect_n++)
19964 ImRect r = Funcs::GetWindowRect(
g.NavWindow, rect_n);
19965 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]);
19970 Checkbox(
"Show tables rectangles", &cfg->ShowTablesRects);
19972 SetNextItemWidth(GetFontSize() * 12);
19973 cfg->ShowTablesRects |=
Combo(
"##show_table_rects_type", &cfg->ShowTablesRectsType, trt_rects_names, TRT_Count, TRT_Count);
19974 if (cfg->ShowTablesRects &&
g.NavWindow != NULL)
19976 for (
int table_n = 0; table_n <
g.Tables.GetMapSize(); table_n++)
19978 ImGuiTable* table =
g.Tables.TryGetMapData(table_n);
19979 if (table == NULL || table->LastFrameActive <
g.FrameCount - 1 || (table->OuterWindow !=
g.NavWindow && table->InnerWindow !=
g.NavWindow))
19982 BulletText(
"Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);
19983 if (IsItemHovered())
19984 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);
19987 for (
int rect_n = 0; rect_n < TRT_Count; rect_n++)
19989 if (rect_n >= TRT_ColumnsRect)
19991 if (rect_n != TRT_ColumnsRect && rect_n != TRT_ColumnsClipRect)
19993 for (
int column_n = 0; column_n < table->ColumnsCount; column_n++)
19995 ImRect r = Funcs::GetTableRect(table, rect_n, column_n);
19996 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]);
19998 if (IsItemHovered())
19999 GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
20004 ImRect r = Funcs::GetTableRect(table, rect_n, -1);
20005 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]);
20007 if (IsItemHovered())
20008 GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
20014 Checkbox(
"Show groups rectangles", &
g.DebugShowGroupRects);
20016 SeparatorText(
"Validate");
20018 Checkbox(
"Debug Begin/BeginChild return value", &io.ConfigDebugBeginReturnValueLoop);
20020 MetricsHelpMarker(
"Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running.");
20022 Checkbox(
"UTF-8 Encoding viewer", &cfg->ShowTextEncodingViewer);
20024 MetricsHelpMarker(
"You can also call ImGui::DebugTextEncoding() from your code with a given string to test that your UTF-8 encoding settings are correct.");
20025 if (cfg->ShowTextEncodingViewer)
20027 static char buf[64] =
"";
20028 SetNextItemWidth(-FLT_MIN);
20029 InputText(
"##DebugTextEncodingBuf", buf, IM_ARRAYSIZE(buf));
20031 DebugTextEncoding(buf);
20038 if (
TreeNode(
"Windows",
"Windows (%d)",
g.Windows.Size))
20041 DebugNodeWindowsList(&
g.Windows,
"By display order");
20042 DebugNodeWindowsList(&
g.WindowsFocusOrder,
"By focus order (root windows)");
20043 if (
TreeNode(
"By submission order (begin stack)"))
20046 ImVector<ImGuiWindow*>& temp_buffer =
g.WindowsTempSortBuffer;
20047 temp_buffer.resize(0);
20048 for (ImGuiWindow* window :
g.Windows)
20049 if (window->LastFrameActive + 1 >=
g.FrameCount)
20050 temp_buffer.push_back(window);
20051 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); } };
20052 ImQsort(temp_buffer.Data, (
size_t)temp_buffer.Size,
sizeof(ImGuiWindow*), Func::WindowComparerByBeginOrder);
20053 DebugNodeWindowsListByBeginStackParent(temp_buffer.Data, temp_buffer.Size, NULL);
20061 int drawlist_count = 0;
20062 for (ImGuiViewportP* viewport :
g.Viewports)
20063 drawlist_count += viewport->DrawDataP.CmdLists.Size;
20064 if (
TreeNode(
"DrawLists",
"DrawLists (%d)", drawlist_count))
20066 Checkbox(
"Show ImDrawCmd mesh when hovering", &cfg->ShowDrawCmdMesh);
20067 Checkbox(
"Show ImDrawCmd bounding boxes when hovering", &cfg->ShowDrawCmdBoundingBoxes);
20068 for (ImGuiViewportP* viewport :
g.Viewports)
20070 bool viewport_has_drawlist =
false;
20071 for (ImDrawList* draw_list : viewport->DrawDataP.CmdLists)
20073 if (!viewport_has_drawlist)
20074 Text(
"Active DrawLists in Viewport #%d, ID: 0x%08X", viewport->Idx, viewport->ID);
20075 viewport_has_drawlist =
true;
20076 DebugNodeDrawList(NULL, viewport, draw_list,
"DrawList");
20083 if (
TreeNode(
"Viewports",
"Viewports (%d)",
g.Viewports.Size))
20085 cfg->HighlightMonitorIdx = -1;
20086 bool open =
TreeNode(
"Monitors",
"Monitors (%d)",
g.PlatformIO.Monitors.Size);
20088 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.");
20091 for (
int i = 0; i <
g.PlatformIO.Monitors.Size; i++)
20093 const ImGuiPlatformMonitor& mon =
g.PlatformIO.Monitors[i];
20094 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)",
20095 i, mon.DpiScale * 100.0f,
20096 mon.MainPos.x, mon.MainPos.y, mon.MainPos.x + mon.MainSize.x, mon.MainPos.y + mon.MainSize.y, mon.MainSize.x, mon.MainSize.y,
20097 mon.WorkPos.x, mon.WorkPos.y, mon.WorkPos.x + mon.WorkSize.x, mon.WorkPos.y + mon.WorkSize.y, mon.WorkSize.x, mon.WorkSize.y);
20098 if (IsItemHovered())
20099 cfg->HighlightMonitorIdx = i;
20104 SetNextItemOpen(
true, ImGuiCond_Once);
20107 RenderViewportsThumbnails();
20110 cfg->HighlightViewportID = 0;
20112 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);
20113 if (
TreeNode(
"Inferred Z order (front-to-back)"))
20115 static ImVector<ImGuiViewportP*> viewports;
20116 viewports.resize(
g.Viewports.Size);
20117 memcpy(viewports.Data,
g.Viewports.Data,
g.Viewports.size_in_bytes());
20118 if (viewports.Size > 1)
20119 ImQsort(viewports.Data, viewports.Size,
sizeof(ImGuiViewport*), ViewportComparerByLastFocusedStampCount);
20120 for (ImGuiViewportP* viewport : viewports)
20122 BulletText(
"Viewport #%d, ID: 0x%08X, LastFocused = %08d, PlatformFocused = %s, Window: \"%s\"",
20123 viewport->Idx, viewport->ID, viewport->LastFocusedStampCount,
20124 (
g.PlatformIO.Platform_GetWindowFocus && viewport->PlatformWindowCreated) ? (
g.PlatformIO.Platform_GetWindowFocus(viewport) ?
"1" :
"0") :
"N/A",
20126 if (IsItemHovered())
20127 cfg->HighlightViewportID = viewport->ID;
20132 for (ImGuiViewportP* viewport :
g.Viewports)
20133 DebugNodeViewport(viewport);
20138 if (
TreeNode(
"Popups",
"Popups (%d)",
g.OpenPopupStack.Size))
20140 for (
const ImGuiPopupData& popup_data :
g.OpenPopupStack)
20143 ImGuiWindow* window = popup_data.Window;
20144 BulletText(
"PopupID: %08x, Window: '%s' (%s%s), RestoreNavWindow '%s', ParentWindow '%s'",
20145 popup_data.PopupId, window ? window->Name :
"NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ?
"Child;" :
"", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ?
"Menu;" :
"",
20146 popup_data.RestoreNavWindow ? popup_data.RestoreNavWindow->Name :
"NULL", window && window->ParentWindow ? window->ParentWindow->Name :
"NULL");
20152 if (
TreeNode(
"TabBars",
"Tab Bars (%d)",
g.TabBars.GetAliveCount()))
20154 for (
int n = 0; n <
g.TabBars.GetMapSize(); n++)
20155 if (ImGuiTabBar* tab_bar =
g.TabBars.TryGetMapData(n))
20158 DebugNodeTabBar(tab_bar,
"TabBar");
20165 if (
TreeNode(
"Tables",
"Tables (%d)",
g.Tables.GetAliveCount()))
20167 for (
int n = 0; n <
g.Tables.GetMapSize(); n++)
20168 if (ImGuiTable* table =
g.Tables.TryGetMapData(n))
20169 DebugNodeTable(table);
20174 ImFontAtlas* atlas =
g.IO.Fonts;
20175 if (
TreeNode(
"Fonts",
"Fonts (%d)", atlas->Fonts.Size))
20184 DebugNodeInputTextState(&
g.InputTextState);
20189 if (
TreeNode(
"TypingSelect",
"TypingSelect (%d)",
g.TypingSelectState.SearchBuffer[0] != 0 ? 1 : 0))
20191 DebugNodeTypingSelectState(&
g.TypingSelectState);
20196#ifdef IMGUI_HAS_DOCK
20199 static bool root_nodes_only =
true;
20200 ImGuiDockContext* dc = &
g.DockContext;
20201 Checkbox(
"List root nodes", &root_nodes_only);
20202 Checkbox(
"Ctrl shows window dock info", &cfg->ShowDockingNodes);
20203 if (SmallButton(
"Clear nodes")) { DockContextClearNodes(&
g, 0,
true); }
20205 if (SmallButton(
"Rebuild all")) { dc->WantFullRebuild =
true; }
20206 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
20207 if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
20208 if (!root_nodes_only || node->IsRootNode())
20209 DebugNodeDockNode(node,
"Node");
20217 if (SmallButton(
"Clear"))
20218 ClearIniSettings();
20220 if (SmallButton(
"Save to memory"))
20221 SaveIniSettingsToMemory();
20223 if (SmallButton(
"Save to disk"))
20224 SaveIniSettingsToDisk(
g.IO.IniFilename);
20226 if (
g.IO.IniFilename)
20227 Text(
"\"%s\"",
g.IO.IniFilename);
20230 Checkbox(
"io.ConfigDebugIniSettings", &io.ConfigDebugIniSettings);
20231 Text(
"SettingsDirtyTimer %.2f",
g.SettingsDirtyTimer);
20232 if (
TreeNode(
"SettingsHandlers",
"Settings handlers: (%d)",
g.SettingsHandlers.Size))
20234 for (ImGuiSettingsHandler& handler :
g.SettingsHandlers)
20235 BulletText(
"\"%s\"", handler.TypeName);
20238 if (
TreeNode(
"SettingsWindows",
"Settings packed data: Windows: %d bytes",
g.SettingsWindows.size()))
20240 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
20241 DebugNodeWindowSettings(settings);
20245 if (
TreeNode(
"SettingsTables",
"Settings packed data: Tables: %d bytes",
g.SettingsTables.size()))
20247 for (ImGuiTableSettings* settings =
g.SettingsTables.begin(); settings != NULL; settings =
g.SettingsTables.next_chunk(settings))
20248 DebugNodeTableSettings(settings);
20252#ifdef IMGUI_HAS_DOCK
20253 if (
TreeNode(
"SettingsDocking",
"Settings packed data: Docking"))
20255 ImGuiDockContext* dc = &
g.DockContext;
20256 Text(
"In SettingsWindows:");
20257 for (ImGuiWindowSettings* settings =
g.SettingsWindows.begin(); settings != NULL; settings =
g.SettingsWindows.next_chunk(settings))
20258 if (settings->DockId != 0)
20259 BulletText(
"Window '%s' -> DockId %08X DockOrder=%d", settings->GetName(), settings->DockId, settings->DockOrder);
20260 Text(
"In SettingsNodes:");
20261 for (
int n = 0; n < dc->NodesSettings.Size; n++)
20264 const char* selected_tab_name = NULL;
20267 if (ImGuiWindow* window = FindWindowByID(settings->
SelectedTabId))
20268 selected_tab_name = window->Name;
20269 else if (ImGuiWindowSettings* window_settings = FindWindowSettingsByID(settings->
SelectedTabId))
20270 selected_tab_name = window_settings->GetName();
20272 BulletText(
"Node %08X, Parent %08X, SelectedTab %08X ('%s')", settings->
ID, settings->
ParentNodeId, settings->
SelectedTabId, selected_tab_name ? selected_tab_name : settings->SelectedTabId ?
"N/A" :
"");
20278 if (
TreeNode(
"SettingsIniData",
"Settings unpacked data (.ini): %d bytes",
g.SettingsIniData.size()))
20280 InputTextMultiline(
"##Ini", (
char*)(
void*)
g.SettingsIniData.c_str(),
g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, GetTextLineHeight() * 20), ImGuiInputTextFlags_ReadOnly);
20287 if (
TreeNode(
"Memory allocations"))
20289 ImGuiDebugAllocInfo* info = &
g.DebugAllocInfo;
20290 Text(
"%d current allocations", info->TotalAllocCount - info->TotalFreeCount);
20291 if (SmallButton(
"GC now")) {
g.GcCompactAll =
true; }
20292 Text(
"Recent frames with allocations:");
20293 int buf_size = IM_ARRAYSIZE(info->LastEntriesBuf);
20294 for (
int n = buf_size - 1; n >= 0; n--)
20296 ImGuiDebugAllocEntry* entry = &info->LastEntriesBuf[(info->LastEntriesIdx - n + buf_size) % buf_size];
20297 BulletText(
"Frame %06d: %+3d ( %2d malloc, %2d free )%s", entry->FrameCount, entry->AllocCount - entry->FreeCount, entry->AllocCount, entry->FreeCount, (n == 0) ?
" (most recent)" :
"");
20304 Text(
"KEYBOARD/GAMEPAD/MOUSE KEYS");
20309#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
20310 struct funcs {
static bool IsLegacyNativeDupe(ImGuiKey) {
return false; } };
20312 struct funcs {
static bool IsLegacyNativeDupe(ImGuiKey key) {
return key >= 0 && key < 512 && GetIO().KeyMap[key] != -1; } };
20315 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); }
20316 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); }
20317 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); }
20318 Text(
"Keys mods: %s%s%s%s", io.KeyCtrl ?
"CTRL " :
"", io.KeyShift ?
"SHIFT " :
"", io.KeyAlt ?
"ALT " :
"", io.KeySuper ?
"SUPER " :
"");
20319 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); }
20320 DebugRenderKeyboardPreview(GetWindowDrawList());
20324 Text(
"MOUSE STATE");
20327 if (IsMousePosValid())
20328 Text(
"Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
20330 Text(
"Mouse pos: <INVALID>");
20331 Text(
"Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
20332 int count = IM_ARRAYSIZE(io.MouseDown);
20333 Text(
"Mouse down:");
for (
int i = 0; i <
count; i++)
if (IsMouseDown(i)) { SameLine(); Text(
"b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
20334 Text(
"Mouse clicked:");
for (
int i = 0; i <
count; i++)
if (IsMouseClicked(i)) { SameLine(); Text(
"b%d (%d)", i, io.MouseClickedCount[i]); }
20335 Text(
"Mouse released:");
for (
int i = 0; i <
count; i++)
if (IsMouseReleased(i)) { SameLine(); Text(
"b%d", i); }
20336 Text(
"Mouse wheel: %.1f", io.MouseWheel);
20337 Text(
"MouseStationaryTimer: %.2f",
g.MouseStationaryTimer);
20338 Text(
"Mouse source: %s", GetMouseSourceName(io.MouseSource));
20339 Text(
"Pen Pressure: %.1f", io.PenPressure);
20343 Text(
"MOUSE WHEELING");
20346 Text(
"WheelingWindow: '%s'",
g.WheelingWindow ?
g.WheelingWindow->Name :
"NULL");
20347 Text(
"WheelingWindowReleaseTimer: %.2f",
g.WheelingWindowReleaseTimer);
20348 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>");
20352 Text(
"KEY OWNERS");
20355 if (BeginChild(
"##owners", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_NoSavedSettings))
20356 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
20358 ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&
g, key);
20359 if (owner_data->OwnerCurr == ImGuiKeyOwner_None)
20361 Text(
"%s: 0x%08X%s", GetKeyName(key), owner_data->OwnerCurr,
20362 owner_data->LockUntilRelease ?
" LockUntilRelease" : owner_data->LockThisFrame ?
" LockThisFrame" :
"");
20363 DebugLocateItemOnHover(owner_data->OwnerCurr);
20368 Text(
"SHORTCUT ROUTING");
20370 MetricsHelpMarker(
"Declared shortcut routes automatically set key owner when mods matches.");
20373 if (BeginChild(
"##routes", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_NoSavedSettings))
20374 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
20376 ImGuiKeyRoutingTable* rt = &
g.KeysRoutingTable;
20377 for (ImGuiKeyRoutingIndex idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; idx != -1; )
20379 ImGuiKeyRoutingData* routing_data = &rt->Entries[idx];
20380 ImGuiKeyChord key_chord = key | routing_data->Mods;
20381 Text(
"%s: 0x%08X (scored %d)", GetKeyChordName(key_chord), routing_data->RoutingCurr, routing_data->RoutingCurrScore);
20382 DebugLocateItemOnHover(routing_data->RoutingCurr);
20383 if (
g.IO.ConfigDebugIsDebuggerPresent)
20386 if (DebugBreakButton(
"**DebugBreak**",
"in SetShortcutRouting() for this KeyChord"))
20387 g.DebugBreakInShortcutRouting = key_chord;
20389 idx = routing_data->NextEntryIndex;
20393 Text(
"(ActiveIdUsing: AllKeyboardKeys: %d, NavDirMask: 0x%X)",
g.ActiveIdUsingAllKeyboardKeys,
g.ActiveIdUsingNavDirMask);
20403 Text(
"HoveredWindow: '%s'",
g.HoveredWindow ?
g.HoveredWindow->Name :
"NULL");
20404 Text(
"HoveredWindow->Root: '%s'",
g.HoveredWindow ?
g.HoveredWindow->RootWindowDockTree->Name :
"NULL");
20405 Text(
"HoveredWindowUnderMovingWindow: '%s'",
g.HoveredWindowUnderMovingWindow ?
g.HoveredWindowUnderMovingWindow->Name :
"NULL");
20406 Text(
"HoveredDockNode: 0x%08X",
g.DebugHoveredDockNode ?
g.DebugHoveredDockNode->ID : 0);
20407 Text(
"MovingWindow: '%s'",
g.MovingWindow ?
g.MovingWindow->Name :
"NULL");
20408 Text(
"MouseViewport: 0x%08X (UserHovered 0x%08X, LastHovered 0x%08X)",
g.MouseViewport->ID,
g.IO.MouseHoveredViewport,
g.MouseLastHoveredViewport ?
g.MouseLastHoveredViewport->ID : 0);
20413 Text(
"ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s",
g.ActiveId,
g.ActiveIdPreviousFrame,
g.ActiveIdTimer,
g.ActiveIdAllowOverlap, GetInputSourceName(
g.ActiveIdSource));
20414 DebugLocateItemOnHover(
g.ActiveId);
20415 Text(
"ActiveIdWindow: '%s'",
g.ActiveIdWindow ?
g.ActiveIdWindow->Name :
"NULL");
20416 Text(
"ActiveIdUsing: AllKeyboardKeys: %d, NavDirMask: %X",
g.ActiveIdUsingAllKeyboardKeys,
g.ActiveIdUsingNavDirMask);
20417 Text(
"HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d",
g.HoveredIdPreviousFrame,
g.HoveredIdTimer,
g.HoveredIdAllowOverlap);
20418 Text(
"HoverItemDelayId: 0x%08X, Timer: %.2f, ClearTimer: %.2f",
g.HoverItemDelayId,
g.HoverItemDelayTimer,
g.HoverItemDelayClearTimer);
20419 Text(
"DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)",
g.DragDropActive,
g.DragDropPayload.SourceId,
g.DragDropPayload.DataType,
g.DragDropPayload.DataSize);
20420 DebugLocateItemOnHover(
g.DragDropPayload.SourceId);
20425 Text(
"NavWindow: '%s'",
g.NavWindow ?
g.NavWindow->Name :
"NULL");
20426 Text(
"NavId: 0x%08X, NavLayer: %d",
g.NavId,
g.NavLayer);
20427 DebugLocateItemOnHover(
g.NavId);
20428 Text(
"NavInputSource: %s", GetInputSourceName(
g.NavInputSource));
20429 Text(
"NavLastValidSelectionUserData = %" IM_PRId64
" (0x%" IM_PRIX64
")",
g.NavLastValidSelectionUserData,
g.NavLastValidSelectionUserData);
20430 Text(
"NavActive: %d, NavVisible: %d",
g.IO.NavActive,
g.IO.NavVisible);
20431 Text(
"NavActivateId/DownId/PressedId: %08X/%08X/%08X",
g.NavActivateId,
g.NavActivateDownId,
g.NavActivatePressedId);
20432 Text(
"NavActivateFlags: %04X",
g.NavActivateFlags);
20433 Text(
"NavDisableHighlight: %d, NavDisableMouseHover: %d",
g.NavDisableHighlight,
g.NavDisableMouseHover);
20434 Text(
"NavFocusScopeId = 0x%08X",
g.NavFocusScopeId);
20435 Text(
"NavFocusRoute[] = ");
20436 for (
int path_n =
g.NavFocusRoute.Size - 1; path_n >= 0; path_n--)
20438 const ImGuiFocusScopeData& focus_scope =
g.NavFocusRoute[path_n];
20439 SameLine(0.0f, 0.0f);
20440 Text(
"0x%08X/", focus_scope.ID);
20441 SetItemTooltip(
"In window \"%s\"", FindWindowByID(focus_scope.WindowID)->Name);
20443 Text(
"NavWindowingTarget: '%s'",
g.NavWindowingTarget ?
g.NavWindowingTarget->Name :
"NULL");
20450 if (cfg->ShowWindowsRects || cfg->ShowWindowsBeginOrder)
20452 for (ImGuiWindow* window :
g.Windows)
20454 if (!window->WasActive)
20456 ImDrawList* draw_list = GetForegroundDrawList(window);
20457 if (cfg->ShowWindowsRects)
20459 ImRect r = Funcs::GetWindowRect(window, cfg->ShowWindowsRectsType);
20460 draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255));
20462 if (cfg->ShowWindowsBeginOrder && !(window->Flags & ImGuiWindowFlags_ChildWindow))
20465 ImFormatString(buf, IM_ARRAYSIZE(buf),
"%d", window->BeginOrderWithinContext);
20466 float font_size = GetFontSize();
20467 draw_list->AddRectFilled(window->Pos, window->Pos + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255));
20468 draw_list->AddText(window->Pos, IM_COL32(255, 255, 255, 255), buf);
20474 if (cfg->ShowTablesRects)
20476 for (
int table_n = 0; table_n <
g.Tables.GetMapSize(); table_n++)
20478 ImGuiTable* table =
g.Tables.TryGetMapData(table_n);
20479 if (table == NULL || table->LastFrameActive <
g.FrameCount - 1)
20481 ImDrawList* draw_list = GetForegroundDrawList(table->OuterWindow);
20482 if (cfg->ShowTablesRectsType >= TRT_ColumnsRect)
20484 for (
int column_n = 0; column_n < table->ColumnsCount; column_n++)
20486 ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, column_n);
20487 ImU32 col = (table->HoveredColumnBody == column_n) ? IM_COL32(255, 255, 128, 255) : IM_COL32(255, 0, 128, 255);
20488 float thickness = (table->HoveredColumnBody == column_n) ? 3.0f : 1.0f;
20489 draw_list->AddRect(r.Min, r.Max, col, 0.0f, 0, thickness);
20494 ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, -1);
20495 draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255));
20500#ifdef IMGUI_HAS_DOCK
20502 if (cfg->ShowDockingNodes &&
g.IO.KeyCtrl &&
g.DebugHoveredDockNode)
20506 ImGuiDockNode* node =
g.DebugHoveredDockNode;
20507 ImDrawList* overlay_draw_list = node->HostWindow ? GetForegroundDrawList(node->HostWindow) : GetForegroundDrawList(GetMainViewport());
20508 p +=
ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"DockId: %X%s\n", node->ID, node->IsCentralNode() ?
" *CentralNode*" :
"");
20509 p +=
ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"WindowClass: %08X\n", node->WindowClass.ClassId);
20510 p +=
ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"Size: (%.0f, %.0f)\n", node->Size.x, node->Size.y);
20511 p +=
ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"SizeRef: (%.0f, %.0f)\n", node->SizeRef.x, node->SizeRef.y);
20512 int depth = DockNodeGetDepth(node);
20513 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));
20514 ImVec2 pos = node->Pos + ImVec2(3, 3) * (float)depth;
20515 overlay_draw_list->AddRectFilled(pos - ImVec2(1, 1), pos +
CalcTextSize(buf) + ImVec2(1, 1), IM_COL32(200, 100, 100, 255));
20516 overlay_draw_list->AddText(NULL, 0.0f, pos, IM_COL32(255, 255, 255, 255), buf);
20523void ImGui::DebugBreakClearData()
20527 g.DebugBreakInWindow = 0;
20528 g.DebugBreakInTable = 0;
20529 g.DebugBreakInShortcutRouting = ImGuiKey_None;
20532void ImGui::DebugBreakButtonTooltip(
bool keyboard_only,
const char* description_of_location)
20534 if (!BeginItemTooltip())
20536 Text(
"To call IM_DEBUG_BREAK() %s:", description_of_location);
20538 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.");
20540 TextUnformatted(
"Choose one way that doesn't interfere with what you are trying to debug!\nYou need a debugger attached or this will crash!");
20546bool ImGui::DebugBreakButton(
const char* label,
const char* description_of_location)
20548 ImGuiWindow* window = GetCurrentWindow();
20549 if (window->SkipItems)
20553 const ImGuiID
id = window->GetID(label);
20554 const ImVec2 label_size =
CalcTextSize(label, NULL,
true);
20555 ImVec2 pos = window->DC.CursorPos + ImVec2(0.0f, window->DC.CurrLineTextBaseOffset);
20556 ImVec2
size = ImVec2(label_size.x +
g.Style.FramePadding.x * 2.0f, label_size.y);
20558 const ImRect bb(pos, pos + size);
20559 ItemSize(size, 0.0f);
20560 if (!ItemAdd(bb,
id))
20564 bool hovered = ItemHoverable(bb,
id,
g.CurrentItemFlags);
20565 bool pressed = hovered && (IsKeyChordPressed(
g.DebugBreakKeyChord) || IsMouseClicked(0) ||
g.NavActivateId ==
id);
20566 DebugBreakButtonTooltip(
false, description_of_location);
20568 ImVec4 col4f = GetStyleColorVec4(hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
20570 ColorConvertRGBtoHSV(col4f.x, col4f.y, col4f.z, hsv.x, hsv.y, hsv.z);
20571 ColorConvertHSVtoRGB(hsv.x + 0.20f, hsv.y, hsv.z, col4f.x, col4f.y, col4f.z);
20573 RenderNavHighlight(bb,
id);
20574 RenderFrame(bb.Min, bb.Max, GetColorU32(col4f),
true,
g.Style.FrameRounding);
20575 RenderTextClipped(bb.Min, bb.Max, label, NULL, &label_size,
g.Style.ButtonTextAlign, &bb);
20577 IMGUI_TEST_ENGINE_ITEM_INFO(
id, label,
g.LastItemData.StatusFlags);
20582void ImGui::DebugNodeColumns(ImGuiOldColumns* columns)
20584 if (!
TreeNode((
void*)(uintptr_t)columns->ID,
"Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags))
20586 BulletText(
"Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->OffMaxX - columns->OffMinX, columns->OffMinX, columns->OffMaxX);
20587 for (ImGuiOldColumnData& column : columns->Columns)
20588 BulletText(
"Column %02d: OffsetNorm %.3f (= %.1f px)", (int)columns->Columns.index_from_ptr(&column), column.OffsetNorm, GetColumnOffsetFromNorm(columns, column.OffsetNorm));
20592static void DebugNodeDockNodeFlags(ImGuiDockNodeFlags* p_flags,
const char* label,
bool enabled)
20594 using namespace ImGui;
20596 PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
20597 Text(
"%s:", label);
20600 CheckboxFlags(
"NoResize", p_flags, ImGuiDockNodeFlags_NoResize);
20601 CheckboxFlags(
"NoResizeX", p_flags, ImGuiDockNodeFlags_NoResizeX);
20602 CheckboxFlags(
"NoResizeY",p_flags, ImGuiDockNodeFlags_NoResizeY);
20603 CheckboxFlags(
"NoTabBar", p_flags, ImGuiDockNodeFlags_NoTabBar);
20604 CheckboxFlags(
"HiddenTabBar", p_flags, ImGuiDockNodeFlags_HiddenTabBar);
20605 CheckboxFlags(
"NoWindowMenuButton", p_flags, ImGuiDockNodeFlags_NoWindowMenuButton);
20606 CheckboxFlags(
"NoCloseButton", p_flags, ImGuiDockNodeFlags_NoCloseButton);
20607 CheckboxFlags(
"DockedWindowsInFocusRoute", p_flags, ImGuiDockNodeFlags_DockedWindowsInFocusRoute);
20608 CheckboxFlags(
"NoDocking", p_flags, ImGuiDockNodeFlags_NoDocking);
20609 CheckboxFlags(
"NoDockingSplit", p_flags, ImGuiDockNodeFlags_NoDockingSplit);
20610 CheckboxFlags(
"NoDockingSplitOther", p_flags, ImGuiDockNodeFlags_NoDockingSplitOther);
20611 CheckboxFlags(
"NoDockingOver", p_flags, ImGuiDockNodeFlags_NoDockingOverMe);
20612 CheckboxFlags(
"NoDockingOverOther", p_flags, ImGuiDockNodeFlags_NoDockingOverOther);
20613 CheckboxFlags(
"NoDockingOverEmpty", p_flags, ImGuiDockNodeFlags_NoDockingOverEmpty);
20614 CheckboxFlags(
"NoUndocking", p_flags, ImGuiDockNodeFlags_NoUndocking);
20622void ImGui::DebugNodeDockNode(ImGuiDockNode* node,
const char* label)
20625 const bool is_alive = (
g.FrameCount - node->LastFrameAlive < 2);
20626 const bool is_active = (
g.FrameCount - node->LastFrameActive < 2);
20627 if (!is_alive) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
20629 ImGuiTreeNodeFlags tree_node_flags = node->IsFocused ? ImGuiTreeNodeFlags_Selected : ImGuiTreeNodeFlags_None;
20630 if (node->Windows.Size > 0)
20631 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");
20633 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");
20634 if (!is_alive) { PopStyleColor(); }
20635 if (is_active && IsItemHovered())
20636 if (ImGuiWindow* window = node->HostWindow ? node->HostWindow : node->VisibleWindow)
20637 GetForegroundDrawList(window)->AddRect(node->Pos, node->Pos + node->Size, IM_COL32(255, 255, 0, 255));
20640 IM_ASSERT(node->ChildNodes[0] == NULL || node->ChildNodes[0]->ParentNode == node);
20641 IM_ASSERT(node->ChildNodes[1] == NULL || node->ChildNodes[1]->ParentNode == node);
20642 BulletText(
"Pos (%.0f,%.0f), Size (%.0f, %.0f) Ref (%.0f, %.0f)",
20643 node->Pos.x, node->Pos.y, node->Size.x, node->Size.y, node->SizeRef.x, node->SizeRef.y);
20644 DebugNodeWindow(node->HostWindow,
"HostWindow");
20645 DebugNodeWindow(node->VisibleWindow,
"VisibleWindow");
20646 BulletText(
"SelectedTabID: 0x%08X, LastFocusedNodeID: 0x%08X", node->SelectedTabId, node->LastFocusedNodeId);
20647 BulletText(
"Misc:%s%s%s%s%s%s%s",
20648 node->IsDockSpace() ?
" IsDockSpace" :
"",
20649 node->IsCentralNode() ?
" IsCentralNode" :
"",
20650 is_alive ?
" IsAlive" :
"", is_active ?
" IsActive" :
"", node->IsFocused ?
" IsFocused" :
"",
20651 node->WantLockSizeOnce ?
" WantLockSizeOnce" :
"",
20652 node->HasCentralNodeChild ?
" HasCentralNodeChild" :
"");
20653 if (
TreeNode(
"flags",
"Flags Merged: 0x%04X, Local: 0x%04X, InWindows: 0x%04X, Shared: 0x%04X", node->MergedFlags, node->LocalFlags, node->LocalFlagsInWindows, node->SharedFlags))
20655 if (BeginTable(
"flags", 4))
20657 TableNextColumn(); DebugNodeDockNodeFlags(&node->MergedFlags,
"MergedFlags",
false);
20658 TableNextColumn(); DebugNodeDockNodeFlags(&node->LocalFlags,
"LocalFlags",
true);
20659 TableNextColumn(); DebugNodeDockNodeFlags(&node->LocalFlagsInWindows,
"LocalFlagsInWindows",
false);
20660 TableNextColumn(); DebugNodeDockNodeFlags(&node->SharedFlags,
"SharedFlags",
true);
20665 if (node->ParentNode)
20666 DebugNodeDockNode(node->ParentNode,
"ParentNode");
20667 if (node->ChildNodes[0])
20668 DebugNodeDockNode(node->ChildNodes[0],
"Child[0]");
20669 if (node->ChildNodes[1])
20670 DebugNodeDockNode(node->ChildNodes[1],
"Child[1]");
20672 DebugNodeTabBar(node->TabBar,
"TabBar");
20673 DebugNodeWindowsList(&node->Windows,
"Windows");
20679static void FormatTextureIDForDebugDisplay(
char* buf,
int buf_size, ImTextureID tex_id)
20681 union {
void* ptr;
int integer; } tex_id_opaque;
20682 memcpy(&tex_id_opaque, &tex_id, ImMin(
sizeof(
void*),
sizeof(tex_id)));
20683 if (
sizeof(tex_id) >=
sizeof(
void*))
20691void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport,
const ImDrawList* draw_list,
const char* label)
20694 ImGuiMetricsConfig* cfg = &
g.DebugMetricsConfig;
20695 int cmd_count = draw_list->CmdBuffer.Size;
20696 if (cmd_count > 0 && draw_list->CmdBuffer.back().ElemCount == 0 && draw_list->CmdBuffer.back().UserCallback == NULL)
20698 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);
20699 if (draw_list == GetWindowDrawList())
20702 TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f),
"CURRENTLY APPENDING");
20708 ImDrawList* fg_draw_list = viewport ? GetForegroundDrawList(viewport) : NULL;
20709 if (window && IsItemHovered() && fg_draw_list)
20710 fg_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
20714 if (window && !window->WasActive)
20715 TextDisabled(
"Warning: owning Window is inactive. This DrawList is not being rendered!");
20717 for (
const ImDrawCmd* pcmd = draw_list->CmdBuffer.Data; pcmd < draw_list->CmdBuffer.Data + cmd_count; pcmd++)
20719 if (pcmd->UserCallback)
20721 BulletText(
"Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData);
20725 char texid_desc[20];
20726 FormatTextureIDForDebugDisplay(texid_desc, IM_ARRAYSIZE(texid_desc), pcmd->TextureId);
20728 ImFormatString(buf, IM_ARRAYSIZE(buf),
"DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
20729 pcmd->ElemCount / 3, texid_desc, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
20730 bool pcmd_node_open =
TreeNode((
void*)(pcmd - draw_list->CmdBuffer.begin()),
"%s", buf);
20731 if (IsItemHovered() && (cfg->ShowDrawCmdMesh || cfg->ShowDrawCmdBoundingBoxes) && fg_draw_list)
20732 DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, cfg->ShowDrawCmdMesh, cfg->ShowDrawCmdBoundingBoxes);
20733 if (!pcmd_node_open)
20738 const ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
20739 const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + pcmd->VtxOffset;
20740 float total_area = 0.0f;
20741 for (
unsigned int idx_n = pcmd->IdxOffset; idx_n < pcmd->IdxOffset + pcmd->ElemCount; )
20743 ImVec2 triangle[3];
20744 for (
int n = 0; n < 3; n++, idx_n++)
20745 triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos;
20746 total_area += ImTriangleArea(triangle[0], triangle[1], triangle[2]);
20750 ImFormatString(buf, IM_ARRAYSIZE(buf),
"Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area);
20752 if (IsItemHovered() && fg_draw_list)
20753 DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd,
true,
false);
20756 ImGuiListClipper clipper;
20757 clipper.Begin(pcmd->ElemCount / 3);
20758 while (clipper.Step())
20759 for (
int prim = clipper.DisplayStart, idx_i = pcmd->IdxOffset + clipper.DisplayStart * 3; prim < clipper.DisplayEnd; prim++)
20761 char* buf_p = buf, * buf_end = buf + IM_ARRAYSIZE(buf);
20762 ImVec2 triangle[3];
20763 for (
int n = 0; n < 3; n++, idx_i++)
20765 const ImDrawVert& v = vtx_buffer[idx_buffer ? idx_buffer[idx_i] : idx_i];
20766 triangle[n] = v.pos;
20767 buf_p +=
ImFormatString(buf_p, buf_end - buf_p,
"%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n",
20768 (n == 0) ?
"Vert:" :
" ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);
20771 Selectable(buf,
false);
20772 if (fg_draw_list && IsItemHovered())
20774 ImDrawListFlags backup_flags = fg_draw_list->Flags;
20775 fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines;
20776 fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f);
20777 fg_draw_list->Flags = backup_flags;
20786void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list,
const ImDrawList* draw_list,
const ImDrawCmd* draw_cmd,
bool show_mesh,
bool show_aabb)
20788 IM_ASSERT(show_mesh || show_aabb);
20791 ImRect clip_rect = draw_cmd->ClipRect;
20792 ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
20793 ImDrawListFlags backup_flags = out_draw_list->Flags;
20794 out_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines;
20795 for (
unsigned int idx_n = draw_cmd->IdxOffset, idx_end = draw_cmd->IdxOffset + draw_cmd->ElemCount; idx_n < idx_end; )
20797 ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
20798 ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + draw_cmd->VtxOffset;
20800 ImVec2 triangle[3];
20801 for (
int n = 0; n < 3; n++, idx_n++)
20802 vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos));
20804 out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f);
20809 out_draw_list->AddRect(ImTrunc(clip_rect.Min), ImTrunc(clip_rect.Max), IM_COL32(255, 0, 255, 255));
20810 out_draw_list->AddRect(ImTrunc(vtxs_rect.Min), ImTrunc(vtxs_rect.Max), IM_COL32(0, 255, 255, 255));
20812 out_draw_list->Flags = backup_flags;
20816void ImGui::DebugNodeFont(ImFont* font)
20818 bool opened =
TreeNode(font,
"Font: \"%s\"\n%.2f px, %d glyphs, %d file(s)",
20819 font->ConfigData ? font->ConfigData[0].Name :
"", font->FontSize, font->Glyphs.Size, font->ConfigDataCount);
20821 if (SmallButton(
"Set as default"))
20822 GetIO().FontDefault = font;
20828 Text(
"The quick brown fox jumps over the lazy dog");
20832 SetNextItemWidth(GetFontSize() * 8);
20833 DragFloat(
"Font scale", &font->Scale, 0.005f, 0.3f, 2.0f,
"%.1f");
20834 SameLine(); MetricsHelpMarker(
20835 "Note that the default embedded font is NOT meant to be scaled.\n\n"
20836 "Font are currently rendered into bitmaps at a given size at the time of building the atlas. "
20837 "You may oversample them to get some flexibility with scaling. "
20838 "You can also render at multiple sizes and select which one to use at runtime.\n\n"
20839 "(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)");
20840 Text(
"Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
20842 Text(
"Fallback character: '%s' (U+%04X)",
ImTextCharToUtf8(c_str, font->FallbackChar), font->FallbackChar);
20843 Text(
"Ellipsis character: '%s' (U+%04X)",
ImTextCharToUtf8(c_str, font->EllipsisChar), font->EllipsisChar);
20844 const int surface_sqrt = (int)ImSqrt((
float)font->MetricsTotalSurface);
20845 Text(
"Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt);
20846 for (
int config_i = 0; config_i < font->ConfigDataCount; config_i++)
20847 if (font->ConfigData)
20848 if (
const ImFontConfig* cfg = &font->ConfigData[config_i])
20849 BulletText(
"Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d, Offset: (%.1f,%.1f)",
20850 config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y);
20853 if (
TreeNode(
"Glyphs",
"Glyphs (%d)", font->Glyphs.Size))
20855 ImDrawList* draw_list = GetWindowDrawList();
20856 const ImU32 glyph_col = GetColorU32(ImGuiCol_Text);
20857 const float cell_size = font->FontSize * 1;
20858 const float cell_spacing = GetStyle().ItemSpacing.y;
20859 for (
unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256)
20864 if (!(base & 4095) && font->IsGlyphRangeUnused(base, base + 4095))
20866 base += 4096 - 256;
20871 for (
unsigned int n = 0; n < 256; n++)
20872 if (font->FindGlyphNoFallback((ImWchar)(base + n)))
20876 if (!
TreeNode((
void*)(intptr_t)base,
"U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ?
"glyphs" :
"glyph"))
20880 ImVec2 base_pos = GetCursorScreenPos();
20881 for (
unsigned int n = 0; n < 256; n++)
20885 ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));
20886 ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
20887 const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));
20888 draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
20891 font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n));
20892 if (IsMouseHoveringRect(cell_p1, cell_p2) && BeginTooltip())
20894 DebugNodeFontGlyph(font, glyph);
20898 Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));
20906void ImGui::DebugNodeFontGlyph(ImFont*,
const ImFontGlyph* glyph)
20908 Text(
"Codepoint: U+%04X", glyph->Codepoint);
20910 Text(
"Visible: %d", glyph->Visible);
20911 Text(
"AdvanceX: %.1f", glyph->AdvanceX);
20912 Text(
"Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
20913 Text(
"UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
20917void ImGui::DebugNodeStorage(ImGuiStorage* storage,
const char* label)
20919 if (!
TreeNode(label,
"%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes()))
20921 for (
const ImGuiStorage::ImGuiStoragePair& p : storage->Data)
20922 BulletText(
"Key 0x%08X Value { i: %d }", p.key, p.val_i);
20927void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar,
const char* label)
20932 const char* buf_end = buf + IM_ARRAYSIZE(buf);
20933 const bool is_active = (tab_bar->PrevFrameVisible >= GetFrameCount() - 2);
20934 p +=
ImFormatString(p, buf_end - p,
"%s 0x%08X (%d tabs)%s {", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ?
"" :
" *Inactive*");
20935 for (
int tab_n = 0; tab_n < ImMin(tab_bar->Tabs.Size, 3); tab_n++)
20937 ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
20938 p +=
ImFormatString(p, buf_end - p,
"%s'%s'", tab_n > 0 ?
", " :
"", TabBarGetTabName(tab_bar, tab));
20940 p +=
ImFormatString(p, buf_end - p, (tab_bar->Tabs.Size > 3) ?
" ... }" :
" } ");
20941 if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
20942 bool open =
TreeNode(label,
"%s", buf);
20943 if (!is_active) { PopStyleColor(); }
20944 if (is_active && IsItemHovered())
20946 ImDrawList* draw_list = GetForegroundDrawList();
20947 draw_list->AddRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, IM_COL32(255, 255, 0, 255));
20948 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));
20949 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));
20953 for (
int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
20955 ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
20957 if (SmallButton(
"<")) { TabBarQueueReorder(tab_bar, tab, -1); } SameLine(0, 2);
20958 if (SmallButton(
">")) { TabBarQueueReorder(tab_bar, tab, +1); } SameLine();
20959 Text(
"%02d%c Tab 0x%08X '%s' Offset: %.2f, Width: %.2f/%.2f",
20960 tab_n, (tab->ID == tab_bar->SelectedTabId) ?
'*' :
' ', tab->
ID, TabBarGetTabName(tab_bar, tab), tab->Offset, tab->Width, tab->ContentWidth);
20967void ImGui::DebugNodeViewport(ImGuiViewportP* viewport)
20970 SetNextItemOpen(
true, ImGuiCond_Once);
20971 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");
20972 if (IsItemHovered())
20973 g.DebugMetricsConfig.HighlightViewportID = viewport->ID;
20976 ImGuiWindowFlags flags = viewport->Flags;
20977 BulletText(
"Main Pos: (%.0f,%.0f), Size: (%.0f,%.0f)\nWorkArea Offset Left: %.0f Top: %.0f, Right: %.0f, Bottom: %.0f\nMonitor: %d, DpiScale: %.0f%%",
20978 viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y,
20979 viewport->WorkOffsetMin.x, viewport->WorkOffsetMin.y, viewport->WorkOffsetMax.x, viewport->WorkOffsetMax.y,
20980 viewport->PlatformMonitor, viewport->DpiScale * 100.0f);
20981 if (viewport->Idx > 0) { SameLine();
if (SmallButton(
"Reset Pos")) { viewport->Pos = ImVec2(200, 200); viewport->UpdateWorkRect();
if (viewport->Window) viewport->Window->Pos = viewport->Pos; } }
20982 BulletText(
"Flags: 0x%04X =%s%s%s%s%s%s%s%s%s%s%s%s%s", viewport->Flags,
20984 (flags & ImGuiViewportFlags_IsPlatformMonitor) ?
" IsPlatformMonitor" :
"",
20985 (flags & ImGuiViewportFlags_IsMinimized) ?
" IsMinimized" :
"",
20986 (flags & ImGuiViewportFlags_IsFocused) ?
" IsFocused" :
"",
20987 (flags & ImGuiViewportFlags_OwnedByApp) ?
" OwnedByApp" :
"",
20988 (flags & ImGuiViewportFlags_NoDecoration) ?
" NoDecoration" :
"",
20989 (flags & ImGuiViewportFlags_NoTaskBarIcon) ?
" NoTaskBarIcon" :
"",
20990 (flags & ImGuiViewportFlags_NoFocusOnAppearing) ?
" NoFocusOnAppearing" :
"",
20991 (flags & ImGuiViewportFlags_NoFocusOnClick) ?
" NoFocusOnClick" :
"",
20992 (flags & ImGuiViewportFlags_NoInputs) ?
" NoInputs" :
"",
20993 (flags & ImGuiViewportFlags_NoRendererClear) ?
" NoRendererClear" :
"",
20994 (flags & ImGuiViewportFlags_NoAutoMerge) ?
" NoAutoMerge" :
"",
20995 (flags & ImGuiViewportFlags_TopMost) ?
" TopMost" :
"",
20996 (flags & ImGuiViewportFlags_CanHostOtherWindows) ?
" CanHostOtherWindows" :
"");
20997 for (ImDrawList* draw_list : viewport->DrawDataP.CmdLists)
20998 DebugNodeDrawList(NULL, viewport, draw_list,
"DrawList");
21003void ImGui::DebugNodeWindow(ImGuiWindow* window,
const char* label)
21005 if (window == NULL)
21007 BulletText(
"%s: NULL", label);
21012 const bool is_active = window->WasActive;
21013 ImGuiTreeNodeFlags tree_node_flags = (window ==
g.NavWindow) ? ImGuiTreeNodeFlags_Selected : ImGuiTreeNodeFlags_None;
21014 if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
21015 const bool open = TreeNodeEx(label, tree_node_flags,
"%s '%s'%s", label, window->Name, is_active ?
"" :
" *Inactive*");
21016 if (!is_active) { PopStyleColor(); }
21017 if (IsItemHovered() && is_active)
21018 GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
21022 if (window->MemoryCompacted)
21023 TextDisabled(
"Note: some memory buffers have been compacted/freed.");
21025 if (
g.IO.ConfigDebugIsDebuggerPresent && DebugBreakButton(
"**DebugBreak**",
"in Begin()"))
21026 g.DebugBreakInWindow = window->ID;
21028 ImGuiWindowFlags flags = window->Flags;
21029 DebugNodeDrawList(window, window->Viewport, window->DrawList,
"DrawList");
21030 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);
21031 BulletText(
"Flags: 0x%08X (%s%s%s%s%s%s%s%s%s..)", flags,
21032 (flags & ImGuiWindowFlags_ChildWindow) ?
"Child " :
"", (flags & ImGuiWindowFlags_Tooltip) ?
"Tooltip " :
"", (flags & ImGuiWindowFlags_Popup) ?
"Popup " :
"",
21033 (flags & ImGuiWindowFlags_Modal) ?
"Modal " :
"", (flags & ImGuiWindowFlags_ChildMenu) ?
"ChildMenu " :
"", (flags & ImGuiWindowFlags_NoSavedSettings) ?
"NoSavedSettings " :
"",
21034 (flags & ImGuiWindowFlags_NoMouseInputs)?
"NoMouseInputs":
"", (flags & ImGuiWindowFlags_NoNavInputs) ?
"NoNavInputs" :
"", (flags & ImGuiWindowFlags_AlwaysAutoResize) ?
"AlwaysAutoResize" :
"");
21035 BulletText(
"WindowClassId: 0x%08X", window->WindowClass.ClassId);
21036 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" :
"");
21037 BulletText(
"Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1);
21038 BulletText(
"Appearing: %d, Hidden: %d (CanSkip %d Cannot %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesCanSkipItems, window->HiddenFramesCannotSkipItems, window->SkipItems);
21039 for (
int layer = 0; layer < ImGuiNavLayer_COUNT; layer++)
21041 ImRect r = window->NavRectRel[layer];
21042 if (r.Min.x >= r.Max.y && r.Min.y >= r.Max.y)
21043 BulletText(
"NavLastIds[%d]: 0x%08X", layer, window->NavLastIds[layer]);
21045 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);
21046 DebugLocateItemOnHover(window->NavLastIds[layer]);
21048 const ImVec2* pr = window->NavPreferredScoringPosRel;
21049 for (
int layer = 0; layer < ImGuiNavLayer_COUNT; layer++)
21050 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));
21051 BulletText(
"NavLayersActiveMask: %X, NavLastChildNavWindow: %s", window->DC.NavLayersActiveMask, window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name :
"NULL");
21053 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);
21054 BulletText(
"ViewportMonitor: %d", window->Viewport ? window->Viewport->PlatformMonitor : -1);
21055 BulletText(
"DockId: 0x%04X, DockOrder: %d, Act: %d, Vis: %d", window->DockId, window->DockOrder, window->DockIsActive, window->DockTabIsVisible);
21056 if (window->DockNode || window->DockNodeAsHost)
21057 DebugNodeDockNode(window->DockNodeAsHost ? window->DockNodeAsHost : window->DockNode, window->DockNodeAsHost ?
"DockNodeAsHost" :
"DockNode");
21059 if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow,
"RootWindow"); }
21060 if (window->RootWindowDockTree != window->RootWindow) { DebugNodeWindow(window->RootWindowDockTree,
"RootWindowDockTree"); }
21061 if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow,
"ParentWindow"); }
21062 if (window->ParentWindowForFocusRoute != NULL) { DebugNodeWindow(window->ParentWindowForFocusRoute,
"ParentWindowForFocusRoute"); }
21063 if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows,
"ChildWindows"); }
21064 if (window->ColumnsStorage.Size > 0 &&
TreeNode(
"Columns",
"Columns sets (%d)", window->ColumnsStorage.Size))
21066 for (ImGuiOldColumns& columns : window->ColumnsStorage)
21067 DebugNodeColumns(&columns);
21070 DebugNodeStorage(&window->StateStorage,
"Storage");
21074void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings* settings)
21076 if (settings->WantDelete)
21078 Text(
"0x%08X \"%s\" Pos (%d,%d) Size (%d,%d) Collapsed=%d",
21079 settings->ID, settings->GetName(), settings->Pos.x, settings->Pos.y, settings->Size.x, settings->Size.y, settings->Collapsed);
21080 if (settings->WantDelete)
21084void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows,
const char* label)
21086 if (!
TreeNode(label,
"%s (%d)", label, windows->Size))
21088 for (
int i = windows->Size - 1; i >= 0; i--)
21090 PushID((*windows)[i]);
21091 DebugNodeWindow((*windows)[i],
"Window");
21098void ImGui::DebugNodeWindowsListByBeginStackParent(ImGuiWindow** windows,
int windows_size, ImGuiWindow* parent_in_begin_stack)
21100 for (
int i = 0; i < windows_size; i++)
21102 ImGuiWindow* window = windows[i];
21103 if (window->ParentWindowInBeginStack != parent_in_begin_stack)
21106 ImFormatString(buf, IM_ARRAYSIZE(buf),
"[%04d] Window", window->BeginOrderWithinContext);
21108 DebugNodeWindow(window, buf);
21110 DebugNodeWindowsListByBeginStackParent(windows + i + 1, windows_size - i - 1, window);
21119void ImGui::DebugLog(
const char* fmt, ...)
21122 va_start(args, fmt);
21123 DebugLogV(fmt, args);
21127void ImGui::DebugLogV(
const char* fmt, va_list args)
21130 const int old_size =
g.DebugLogBuf.size();
21131 g.DebugLogBuf.appendf(
"[%05d] ",
g.FrameCount);
21132 g.DebugLogBuf.appendfv(fmt, args);
21133 g.DebugLogIndex.append(
g.DebugLogBuf.c_str(), old_size,
g.DebugLogBuf.size());
21134 if (
g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTTY)
21135 IMGUI_DEBUG_PRINTF(
"%s",
g.DebugLogBuf.begin() + old_size);
21136#ifdef IMGUI_ENABLE_TEST_ENGINE
21137 if (
g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTestEngine)
21138 IMGUI_TEST_ENGINE_LOG(
"%s",
g.DebugLogBuf.begin() + old_size);
21143static void SameLineOrWrap(
const ImVec2& size)
21146 ImGuiWindow* window =
g.CurrentWindow;
21147 ImVec2 pos(window->DC.CursorPosPrevLine.x +
g.Style.ItemSpacing.x, window->DC.CursorPosPrevLine.y);
21148 if (window->ClipRect.Contains(ImRect(pos, pos + size)))
21152static void ShowDebugLogFlag(
const char* name, ImGuiDebugLogFlags flags)
21155 ImVec2
size(ImGui::GetFrameHeight() +
g.Style.ItemInnerSpacing.x +
ImGui::CalcTextSize(name).x, ImGui::GetFrameHeight());
21156 SameLineOrWrap(size);
21157 if (ImGui::CheckboxFlags(name, &
g.DebugLogFlags, flags) &&
g.IO.KeyShift && (
g.DebugLogFlags & flags) != 0)
21159 g.DebugLogAutoDisableFrames = 2;
21160 g.DebugLogAutoDisableFlags |= flags;
21162 ImGui::SetItemTooltip(
"Hold SHIFT when clicking to enable for 2 frames only (useful for spammy log entries)");
21165void ImGui::ShowDebugLogWindow(
bool* p_open)
21168 if (!(
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize))
21169 SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 12.0f), ImGuiCond_FirstUseEver);
21170 if (!Begin(
"Dear ImGui Debug Log", p_open) || GetCurrentWindow()->BeginCount > 1)
21176 ImGuiDebugLogFlags all_enable_flags = ImGuiDebugLogFlags_EventMask_ & ~ImGuiDebugLogFlags_EventInputRouting;
21177 CheckboxFlags(
"All", &
g.DebugLogFlags, all_enable_flags);
21178 SetItemTooltip(
"(except InputRouting which is spammy)");
21180 ShowDebugLogFlag(
"ActiveId", ImGuiDebugLogFlags_EventActiveId);
21181 ShowDebugLogFlag(
"Clipper", ImGuiDebugLogFlags_EventClipper);
21182 ShowDebugLogFlag(
"Docking", ImGuiDebugLogFlags_EventDocking);
21183 ShowDebugLogFlag(
"Focus", ImGuiDebugLogFlags_EventFocus);
21184 ShowDebugLogFlag(
"IO", ImGuiDebugLogFlags_EventIO);
21185 ShowDebugLogFlag(
"Nav", ImGuiDebugLogFlags_EventNav);
21186 ShowDebugLogFlag(
"Popup", ImGuiDebugLogFlags_EventPopup);
21188 ShowDebugLogFlag(
"Viewport", ImGuiDebugLogFlags_EventViewport);
21189 ShowDebugLogFlag(
"InputRouting", ImGuiDebugLogFlags_EventInputRouting);
21191 if (SmallButton(
"Clear"))
21193 g.DebugLogBuf.clear();
21194 g.DebugLogIndex.clear();
21197 if (SmallButton(
"Copy"))
21198 SetClipboardText(
g.DebugLogBuf.c_str());
21199 BeginChild(
"##log", ImVec2(0.0f, 0.0f), ImGuiChildFlags_Border, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar);
21201 const ImGuiDebugLogFlags backup_log_flags =
g.DebugLogFlags;
21202 g.DebugLogFlags &= ~ImGuiDebugLogFlags_EventClipper;
21204 ImGuiListClipper clipper;
21205 clipper.Begin(
g.DebugLogIndex.size());
21206 while (clipper.Step())
21207 for (
int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
21209 const char* line_begin =
g.DebugLogIndex.get_line_begin(
g.DebugLogBuf.c_str(), line_no);
21210 const char* line_end =
g.DebugLogIndex.get_line_end(
g.DebugLogBuf.c_str(), line_no);
21212 ImRect text_rect =
g.LastItemData.Rect;
21213 if (IsItemHovered())
21214 for (
const char* p = line_begin; p <= line_end - 10; p++)
21217 if (p[0] !=
'0' || (p[1] !=
'x' && p[1] !=
'X') || sscanf(p + 2,
"%X", &
id) != 1)
21221 g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0f), text_rect.Min + ImVec2(p0.x + p1.x, p1.y));
21222 if (IsMouseHoveringRect(
g.LastItemData.Rect.Min,
g.LastItemData.Rect.Max,
true))
21223 DebugLocateItemOnHover(
id);
21227 g.DebugLogFlags = backup_log_flags;
21228 if (GetScrollY() >= GetScrollMaxY())
21229 SetScrollHereY(1.0f);
21240void ImGui::DebugDrawCursorPos(ImU32 col)
21243 ImGuiWindow* window =
g.CurrentWindow;
21244 ImVec2 pos = window->DC.CursorPos;
21245 window->DrawList->AddLine(ImVec2(pos.x, pos.y - 3.0f), ImVec2(pos.x, pos.y + 4.0f), col, 1.0f);
21246 window->DrawList->AddLine(ImVec2(pos.x - 3.0f, pos.y), ImVec2(pos.x + 4.0f, pos.y), col, 1.0f);
21250void ImGui::DebugDrawLineExtents(ImU32 col)
21253 ImGuiWindow* window =
g.CurrentWindow;
21254 float curr_x = window->DC.CursorPos.x;
21255 float line_y1 = (window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y);
21256 float line_y2 = line_y1 + (window->DC.IsSameLine ? window->DC.PrevLineSize.y : window->DC.CurrLineSize.y);
21257 window->DrawList->AddLine(ImVec2(curr_x - 5.0f, line_y1), ImVec2(curr_x + 5.0f, line_y1), col, 1.0f);
21258 window->DrawList->AddLine(ImVec2(curr_x - 0.5f, line_y1), ImVec2(curr_x - 0.5f, line_y2), col, 1.0f);
21259 window->DrawList->AddLine(ImVec2(curr_x - 5.0f, line_y2), ImVec2(curr_x + 5.0f, line_y2), col, 1.0f);
21263void ImGui::DebugDrawItemRect(ImU32 col)
21266 ImGuiWindow* window =
g.CurrentWindow;
21267 GetForegroundDrawList(window)->AddRect(
g.LastItemData.Rect.Min,
g.LastItemData.Rect.Max, col);
21271static const ImU32 DEBUG_LOCATE_ITEM_COLOR = IM_COL32(0, 255, 0, 255);
21273void ImGui::DebugLocateItem(ImGuiID target_id)
21276 g.DebugLocateId = target_id;
21277 g.DebugLocateFrames = 2;
21278 g.DebugBreakInLocateId =
false;
21282void ImGui::DebugLocateItemOnHover(ImGuiID target_id)
21284 if (target_id == 0 || !IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenBlockedByPopup))
21287 DebugLocateItem(target_id);
21288 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);
21291 if (
g.IO.ConfigDebugIsDebuggerPresent &&
g.MouseStationaryTimer > 1.0f)
21293 DebugBreakButtonTooltip(
false,
"in ItemAdd()");
21294 if (IsKeyChordPressed(
g.DebugBreakKeyChord))
21295 g.DebugBreakInLocateId =
true;
21299void ImGui::DebugLocateItemResolveWithLastItem()
21304 if (
g.DebugBreakInLocateId)
21307 ImGuiLastItemData item_data =
g.LastItemData;
21308 g.DebugLocateId = 0;
21309 ImDrawList* draw_list = GetForegroundDrawList(
g.CurrentWindow);
21310 ImRect r = item_data.Rect;
21312 ImVec2 p1 =
g.IO.MousePos;
21313 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);
21314 draw_list->AddRect(r.Min, r.Max, DEBUG_LOCATE_ITEM_COLOR);
21315 draw_list->AddLine(p1, p2, DEBUG_LOCATE_ITEM_COLOR);
21318void ImGui::DebugStartItemPicker()
21321 g.DebugItemPickerActive =
true;
21325void ImGui::UpdateDebugToolItemPicker()
21328 g.DebugItemPickerBreakId = 0;
21329 if (!
g.DebugItemPickerActive)
21332 const ImGuiID hovered_id =
g.HoveredIdPreviousFrame;
21333 SetMouseCursor(ImGuiMouseCursor_Hand);
21334 if (IsKeyPressed(ImGuiKey_Escape))
21335 g.DebugItemPickerActive =
false;
21336 const bool change_mapping =
g.IO.KeyMods == (ImGuiMod_Ctrl | ImGuiMod_Shift);
21337 if (!change_mapping && IsMouseClicked(
g.DebugItemPickerMouseButton) && hovered_id)
21339 g.DebugItemPickerBreakId = hovered_id;
21340 g.DebugItemPickerActive =
false;
21342 for (
int mouse_button = 0; mouse_button < 3; mouse_button++)
21343 if (change_mapping && IsMouseClicked(mouse_button))
21344 g.DebugItemPickerMouseButton = (ImU8)mouse_button;
21345 SetNextWindowBgAlpha(0.70f);
21346 if (!BeginTooltip())
21348 Text(
"HoveredId: 0x%08X", hovered_id);
21349 Text(
"Press ESC to abort picking.");
21350 const char* mouse_button_names[] = {
"Left",
"Right",
"Middle" };
21351 if (change_mapping)
21352 Text(
"Remap w/ Ctrl+Shift: click anywhere to select new mouse button.");
21354 TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled),
"Click %s Button to break in debugger! (remap w/ Ctrl+Shift)", mouse_button_names[
g.DebugItemPickerMouseButton]);
21359void ImGui::UpdateDebugToolStackQueries()
21362 ImGuiIDStackTool* tool = &
g.DebugIDStackTool;
21365 g.DebugHookIdInfo = 0;
21366 if (
g.FrameCount != tool->LastActiveFrame + 1)
21371 const ImGuiID query_id =
g.HoveredIdPreviousFrame ?
g.HoveredIdPreviousFrame :
g.ActiveId;
21372 if (tool->QueryId != query_id)
21374 tool->QueryId = query_id;
21375 tool->StackLevel = -1;
21376 tool->Results.resize(0);
21382 int stack_level = tool->StackLevel;
21383 if (stack_level >= 0 && stack_level < tool->Results.Size)
21384 if (tool->Results[stack_level].QuerySuccess || tool->Results[stack_level].QueryFrameCount > 2)
21385 tool->StackLevel++;
21388 stack_level = tool->StackLevel;
21389 if (stack_level == -1)
21390 g.DebugHookIdInfo = query_id;
21391 if (stack_level >= 0 && stack_level < tool->Results.Size)
21393 g.DebugHookIdInfo = tool->Results[stack_level].ID;
21394 tool->Results[stack_level].QueryFrameCount++;
21399void ImGui::DebugHookIdInfo(ImGuiID
id, ImGuiDataType data_type,
const void* data_id,
const void* data_id_end)
21402 ImGuiWindow* window =
g.CurrentWindow;
21403 ImGuiIDStackTool* tool = &
g.DebugIDStackTool;
21407 if (tool->StackLevel == -1)
21409 tool->StackLevel++;
21410 tool->Results.resize(window->IDStack.Size + 1, ImGuiStackLevelInfo());
21411 for (
int n = 0; n < window->IDStack.Size + 1; n++)
21412 tool->Results[n].ID = (n < window->IDStack.Size) ? window->IDStack[n] :
id;
21417 IM_ASSERT(tool->StackLevel >= 0);
21418 if (tool->StackLevel != window->IDStack.Size)
21420 ImGuiStackLevelInfo* info = &tool->Results[tool->StackLevel];
21421 IM_ASSERT(info->ID ==
id && info->QueryFrameCount > 0);
21425 case ImGuiDataType_S32:
21426 ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc),
"%d", (
int)(intptr_t)data_id);
21428 case ImGuiDataType_String:
21429 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);
21431 case ImGuiDataType_Pointer:
21432 ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc),
"(void*)0x%p", data_id);
21434 case ImGuiDataType_ID:
21435 if (info->Desc[0] != 0)
21437 ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc),
"0x%08X [override]",
id);
21442 info->QuerySuccess =
true;
21443 info->DataType = data_type;
21446static int StackToolFormatLevelInfo(ImGuiIDStackTool* tool,
int n,
bool format_for_ui,
char* buf,
size_t buf_size)
21448 ImGuiStackLevelInfo* info = &tool->Results[n];
21449 ImGuiWindow* window = (info->Desc[0] == 0 && n == 0) ? ImGui::FindWindowByID(info->ID) : NULL;
21451 return ImFormatString(buf, buf_size, format_for_ui ?
"\"%s\" [window]" :
"%s", window->Name);
21452 if (info->QuerySuccess)
21453 return ImFormatString(buf, buf_size, (format_for_ui && info->DataType == ImGuiDataType_String) ?
"\"%s\"" :
"%s", info->Desc);
21454 if (tool->StackLevel < tool->Results.Size)
21456#ifdef IMGUI_ENABLE_TEST_ENGINE
21457 if (
const char* label = ImGuiTestEngine_FindItemDebugLabel(
GImGui, info->ID))
21458 return ImFormatString(buf, buf_size, format_for_ui ?
"??? \"%s\"" :
"%s", label);
21464void ImGui::ShowIDStackToolWindow(
bool* p_open)
21467 if (!(
g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize))
21468 SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 8.0f), ImGuiCond_FirstUseEver);
21469 if (!Begin(
"Dear ImGui ID Stack Tool", p_open) || GetCurrentWindow()->BeginCount > 1)
21476 ImGuiIDStackTool* tool = &
g.DebugIDStackTool;
21477 const ImGuiID hovered_id =
g.HoveredIdPreviousFrame;
21478 const ImGuiID active_id =
g.ActiveId;
21479#ifdef IMGUI_ENABLE_TEST_ENGINE
21480 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) :
"");
21482 Text(
"HoveredId: 0x%08X, ActiveId: 0x%08X", hovered_id, active_id);
21485 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.");
21488 const float time_since_copy = (float)
g.Time - tool->CopyToClipboardLastTime;
21489 Checkbox(
"Ctrl+C: copy path to clipboard", &tool->CopyToClipboardOnCtrlC);
21491 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*");
21492 if (tool->CopyToClipboardOnCtrlC && Shortcut(ImGuiMod_Ctrl | ImGuiKey_C, 0, ImGuiInputFlags_RouteGlobal))
21494 tool->CopyToClipboardLastTime = (float)
g.Time;
21495 char* p =
g.TempBuffer.Data;
21496 char* p_end = p +
g.TempBuffer.Size;
21497 for (
int stack_n = 0; stack_n < tool->Results.Size && p + 3 < p_end; stack_n++)
21500 char level_desc[256];
21501 StackToolFormatLevelInfo(tool, stack_n,
false, level_desc, IM_ARRAYSIZE(level_desc));
21502 for (
int n = 0; level_desc[n] && p + 2 < p_end; n++)
21504 if (level_desc[n] ==
'/')
21506 *p++ = level_desc[n];
21510 SetClipboardText(
g.TempBuffer.Data);
21514 tool->LastActiveFrame =
g.FrameCount;
21515 if (tool->Results.Size > 0 && BeginTable(
"##table", 3, ImGuiTableFlags_Borders))
21518 TableSetupColumn(
"Seed", ImGuiTableColumnFlags_WidthFixed, id_width);
21519 TableSetupColumn(
"PushID", ImGuiTableColumnFlags_WidthStretch);
21520 TableSetupColumn(
"Result", ImGuiTableColumnFlags_WidthFixed, id_width);
21522 for (
int n = 0; n < tool->Results.Size; n++)
21524 ImGuiStackLevelInfo* info = &tool->Results[n];
21526 Text(
"0x%08X", (n > 0) ? tool->Results[n - 1].ID : 0);
21528 StackToolFormatLevelInfo(tool, n,
true,
g.TempBuffer.Data,
g.TempBuffer.Size);
21531 Text(
"0x%08X", info->ID);
21532 if (n == tool->Results.Size - 1)
21533 TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_Header));
21542void ImGui::ShowMetricsWindow(
bool*) {}
21544void ImGui::DebugNodeColumns(ImGuiOldColumns*) {}
21545void ImGui::DebugNodeDrawList(ImGuiWindow*, ImGuiViewportP*,
const ImDrawList*,
const char*) {}
21546void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList*,
const ImDrawList*,
const ImDrawCmd*,
bool,
bool) {}
21547void ImGui::DebugNodeFont(ImFont*) {}
21548void ImGui::DebugNodeStorage(ImGuiStorage*,
const char*) {}
21549void ImGui::DebugNodeTabBar(ImGuiTabBar*,
const char*) {}
21550void ImGui::DebugNodeWindow(ImGuiWindow*,
const char*) {}
21551void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings*) {}
21552void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>*,
const char*) {}
21553void ImGui::DebugNodeViewport(ImGuiViewportP*) {}
21555void ImGui::DebugLog(
const char*, ...) {}
21556void ImGui::DebugLogV(
const char*, va_list) {}
21557void ImGui::ShowDebugLogWindow(
bool*) {}
21558void ImGui::ShowIDStackToolWindow(
bool*) {}
21559void ImGui::DebugStartItemPicker() {}
21560void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType,
const void*,
const void*) {}
21568#ifdef IMGUI_INCLUDE_IMGUI_USER_INL
21569#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)
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.