1
0
mirror of https://github.com/ocornut/imgui.git synced 2024-11-24 07:40:22 +01:00

Merge branch 'ocornut:master' into master

This commit is contained in:
Pinwhell 2024-09-27 21:46:32 -04:00 committed by GitHub
commit 888e0ff297
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 736 additions and 443 deletions

View File

@ -310,7 +310,8 @@ static void ImGui_ImplAllegro5_SetClipboardText(ImGuiContext*, const char* text)
} }
#endif #endif
static ImGuiKey ImGui_ImplAllegro5_KeyCodeToImGuiKey(int key_code) // Not static to allow third-party code to use that if they want to (but undocumented)
ImGuiKey ImGui_ImplAllegro5_KeyCodeToImGuiKey(int key_code)
{ {
switch (key_code) switch (key_code)
{ {

View File

@ -185,9 +185,12 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()
} }
// Functions // Functions
static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key)
// Not static to allow third-party code to use that if they want to (but undocumented)
ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode)
{ {
switch (key) IM_UNUSED(scancode);
switch (keycode)
{ {
case GLFW_KEY_TAB: return ImGuiKey_Tab; case GLFW_KEY_TAB: return ImGuiKey_Tab;
case GLFW_KEY_LEFT: return ImGuiKey_LeftArrow; case GLFW_KEY_LEFT: return ImGuiKey_LeftArrow;
@ -355,6 +358,7 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
io.AddMouseWheelEvent((float)xoffset, (float)yoffset); io.AddMouseWheelEvent((float)xoffset, (float)yoffset);
} }
// FIXME: should this be baked into ImGui_ImplGlfw_KeyToImGuiKey()? then what about the values passed to io.SetKeyEventNativeData()?
static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode) static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
{ {
#if GLFW_HAS_GETKEYNAME && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3) #if GLFW_HAS_GETKEYNAME && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3)
@ -402,7 +406,7 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i
keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode); keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode);
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode); ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode, scancode);
io.AddKeyEvent(imgui_key, (action == GLFW_PRESS)); io.AddKeyEvent(imgui_key, (action == GLFW_PRESS));
io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code) io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code)
} }

View File

@ -259,7 +259,9 @@ static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view);
@end @end
// Functions // Functions
static ImGuiKey ImGui_ImplOSX_KeyCodeToImGuiKey(int key_code)
// Not static to allow third-party code to use that if they want to (but undocumented)
ImGuiKey ImGui_ImplOSX_KeyCodeToImGuiKey(int key_code)
{ {
switch (key_code) switch (key_code)
{ {

View File

@ -180,7 +180,8 @@ static void ImGui_ImplSDL2_PlatformSetImeData(ImGuiContext*, ImGuiViewport*, ImG
} }
} }
static ImGuiKey ImGui_ImplSDL2_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode) // Not static to allow third-party code to use that if they want to (but undocumented)
ImGuiKey ImGui_ImplSDL2_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode)
{ {
IM_UNUSED(scancode); IM_UNUSED(scancode);
switch (keycode) switch (keycode)

View File

@ -159,7 +159,8 @@ static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport* view
} }
} }
static ImGuiKey ImGui_ImplSDL3_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode) // Not static to allow third-party code to use that if they want to (but undocumented)
ImGuiKey ImGui_ImplSDL3_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode)
{ {
// Keypad doesn't have individual key values in SDL3 // Keypad doesn't have individual key values in SDL3
switch (scancode) switch (scancode)
@ -563,7 +564,7 @@ static void ImGui_ImplSDL3_UpdateMouseData()
// We forward mouse input when hovered or captured (via SDL_EVENT_MOUSE_MOTION) or when focused (below) // We forward mouse input when hovered or captured (via SDL_EVENT_MOUSE_MOTION) or when focused (below)
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside
SDL_CaptureMouse((bd->MouseButtonsDown != 0) ? SDL_TRUE : SDL_FALSE); SDL_CaptureMouse(bd->MouseButtonsDown != 0);
SDL_Window* focused_window = SDL_GetKeyboardFocus(); SDL_Window* focused_window = SDL_GetKeyboardFocus();
const bool is_app_focused = (bd->Window == focused_window); const bool is_app_focused = (bd->Window == focused_window);
#else #else

View File

@ -158,8 +158,8 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
SDL_Rect ClipRect; SDL_Rect ClipRect;
}; };
BackupSDLRendererState old = {}; BackupSDLRendererState old = {};
old.ViewportEnabled = SDL_RenderViewportSet(renderer) == SDL_TRUE; old.ViewportEnabled = SDL_RenderViewportSet(renderer);
old.ClipEnabled = SDL_RenderClipEnabled(renderer) == SDL_TRUE; old.ClipEnabled = SDL_RenderClipEnabled(renderer);
SDL_GetRenderViewport(renderer, &old.Viewport); SDL_GetRenderViewport(renderer, &old.Viewport);
SDL_GetRenderClipRect(renderer, &old.ClipRect); SDL_GetRenderClipRect(renderer, &old.ClipRect);

View File

@ -257,13 +257,15 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c
{ {
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
WGPUShaderModuleWGSLDescriptor wgsl_desc = {};
#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN #ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
WGPUShaderSourceWGSL wgsl_desc = {};
wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL; wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL;
wgsl_desc.code = { wgsl_source, WGPU_STRLEN };
#else #else
WGPUShaderModuleWGSLDescriptor wgsl_desc = {};
wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
#endif
wgsl_desc.code = wgsl_source; wgsl_desc.code = wgsl_source;
#endif
WGPUShaderModuleDescriptor desc = {}; WGPUShaderModuleDescriptor desc = {};
desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&wgsl_desc); desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&wgsl_desc);

View File

@ -419,12 +419,14 @@ void ImGui_ImplWin32_NewFrame()
ImGui_ImplWin32_UpdateGamepads(); ImGui_ImplWin32_UpdateGamepads();
} }
// There is no distinct VK_xxx for keypad enter, instead it is VK_RETURN + KF_EXTENDED, we assign it an arbitrary value to make code more readable (VK_ codes go up to 255)
#define IM_VK_KEYPAD_ENTER (VK_RETURN + 256)
// Map VK_xxx to ImGuiKey_xxx. // Map VK_xxx to ImGuiKey_xxx.
static ImGuiKey ImGui_ImplWin32_VirtualKeyToImGuiKey(WPARAM wParam) // Not static to allow third-party code to use that if they want to (but undocumented)
ImGuiKey ImGui_ImplWin32_KeyEventToImGuiKey(WPARAM wParam, LPARAM lParam)
{ {
// There is no distinct VK_xxx for keypad enter, instead it is VK_RETURN + KF_EXTENDED.
if ((wParam == VK_RETURN) && (HIWORD(lParam) & KF_EXTENDED))
return ImGuiKey_KeypadEnter;
switch (wParam) switch (wParam)
{ {
case VK_TAB: return ImGuiKey_Tab; case VK_TAB: return ImGuiKey_Tab;
@ -473,7 +475,6 @@ static ImGuiKey ImGui_ImplWin32_VirtualKeyToImGuiKey(WPARAM wParam)
case VK_MULTIPLY: return ImGuiKey_KeypadMultiply; case VK_MULTIPLY: return ImGuiKey_KeypadMultiply;
case VK_SUBTRACT: return ImGuiKey_KeypadSubtract; case VK_SUBTRACT: return ImGuiKey_KeypadSubtract;
case VK_ADD: return ImGuiKey_KeypadAdd; case VK_ADD: return ImGuiKey_KeypadAdd;
case IM_VK_KEYPAD_ENTER: return ImGuiKey_KeypadEnter;
case VK_LSHIFT: return ImGuiKey_LeftShift; case VK_LSHIFT: return ImGuiKey_LeftShift;
case VK_LCONTROL: return ImGuiKey_LeftCtrl; case VK_LCONTROL: return ImGuiKey_LeftCtrl;
case VK_LMENU: return ImGuiKey_LeftAlt; case VK_LMENU: return ImGuiKey_LeftAlt;
@ -692,12 +693,9 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
// Submit modifiers // Submit modifiers
ImGui_ImplWin32_UpdateKeyModifiers(); ImGui_ImplWin32_UpdateKeyModifiers();
// Obtain virtual key code // Obtain virtual key code and convert to ImGuiKey
// (keypad enter doesn't have its own... VK_RETURN with KF_EXTENDED flag means keypad enter, see IM_VK_KEYPAD_ENTER definition for details, it is mapped to ImGuiKey_KeyPadEnter.) const ImGuiKey key = ImGui_ImplWin32_KeyEventToImGuiKey(wParam, lParam);
int vk = (int)wParam; const int vk = (int)wParam;
if ((wParam == VK_RETURN) && (HIWORD(lParam) & KF_EXTENDED))
vk = IM_VK_KEYPAD_ENTER;
const ImGuiKey key = ImGui_ImplWin32_VirtualKeyToImGuiKey(vk);
const int scancode = (int)LOBYTE(HIWORD(lParam)); const int scancode = (int)LOBYTE(HIWORD(lParam));
// Special behavior for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit the key down event. // Special behavior for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit the key down event.

View File

@ -36,13 +36,47 @@ HOW TO UPDATE?
- Please report any issue! - Please report any issue!
----------------------------------------------------------------------- -----------------------------------------------------------------------
VERSION 1.91.2 WIP (In Progress) VERSION 1.91.3 WIP (In Progress)
----------------------------------------------------------------------- -----------------------------------------------------------------------
Breaking changes: Breaking changes:
Other changes: Other changes:
- Error Handling: Enabled/improved error recovery systems. (#1651, #5654)
- Error recovery is not perfect nor guaranteed! It is a feature to ease development.
- Functions that support error recovery are using IM_ASSERT_USER_ERROR() instead of IM_ASSERT().
- You not are not supposed to rely on it in the course of a normal application run.
- Possible usage: facilitate recovery from errors triggered from a scripting language or
after specific exceptions handlers. Surface errors to programmers in less agressive ways.
- Always ensure that on programmers seats you have at minimum Asserts or Tooltips enabled
when making direct imgui API calls! Otherwise it would severely hinder your ability to
catch and correct mistakes!
- Added io.ConfigErrorRecovery to enable error recovery support.
- Added io.ConfigErrorRecoveryEnableAssert to assert on recoverable errors.
- Added io.ConfigErrorRecoveryEnableDebugLog to output to debug log on recoverable errors.
- Added io.ConfigErrorRecoveryEnableTooltip to enable displaying an error tooltip on recoverable errors.
The tooltip include a way to enable asserts if they were disabled.
- All options are enabled by default.
- Read https://github.com/ocornut/imgui/wiki/Error-Handling for a bit more details.
- Windows: BeginChild(): made it possible to call SetNextWindowSize() on a child window
using ImGuiChildFlags_ResizeX,ImGuiChildFlags_ResizeY in order to override its current
size. (#1710, #8020)
- Scrollbar: Shift+Click scroll to clicked location (pre-1.90.8 default). (#8002, #7328)
- Scrollbar: added io.ConfigScrollbarScrollByPage setting (default to true). (#8002, #7328)
Set io.ConfigScrollbarScrollByPage=false to enforce always scrolling to clicked location.
- Backends: SDL3: Update for API changes: SDL_bool removal. SDL_INIT_TIMER removal.
- Backends: WebGPU: Fixed DAWN api change using WGPUStringView in WGPUShaderSourceWGSL.
(#8009, #8010) [@blitz-research]
-----------------------------------------------------------------------
VERSION 1.91.2 (Released 2024-09-19)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.91.2
Other changes:
- Added io.ConfigDebugHighlightIdConflicts debug feature! (#7961, #7669) - Added io.ConfigDebugHighlightIdConflicts debug feature! (#7961, #7669)
THIS DETECTS THE MOST COMMON USER ERROR BY FIRST-TIME DEAR IMGUI PROGRAMMERS! THIS DETECTS THE MOST COMMON USER ERROR BY FIRST-TIME DEAR IMGUI PROGRAMMERS!
- The tool detects when multiple items are sharing the same identifier, due to not - The tool detects when multiple items are sharing the same identifier, due to not
@ -54,7 +88,7 @@ Other changes:
- I've been wanting to add this tool for a long time, but was stalled by finding a way to - I've been wanting to add this tool for a long time, but was stalled by finding a way to
not make it spammy + make it practically zero cost. After @pthom made various proposals to not make it spammy + make it practically zero cost. After @pthom made various proposals to
solve the same problem (thanks for pushing me!), I decided it was time to finish it. solve the same problem (thanks for pushing me!), I decided it was time to finish it.
- Added ImGuiItemFlags_AllowDuplicateId to use with PushItemFlag/PopItemFlag() if for some - Added ImGuiItemFlags_AllowDuplicateId to use with PushItemFlag()/PopItemFlag() if for some
reason you intend to have duplicate identifiers. reason you intend to have duplicate identifiers.
- (#74, #96, #480, #501, #647, #654, #719, #843, #894, #1057, #1173, #1390, #1414, #1556, #1768, - (#74, #96, #480, #501, #647, #654, #719, #843, #894, #1057, #1173, #1390, #1414, #1556, #1768,
#2041, #2116, #2330, #2475, #2562, #2667, #2807, #2885, #3102, #3375, #3526, #3964, #4008, #2041, #2116, #2330, #2475, #2562, #2667, #2807, #2885, #3102, #3375, #3526, #3964, #4008,

View File

@ -27,7 +27,7 @@
int main(int, char**) int main(int, char**)
{ {
// Setup SDL // Setup SDL
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD)) if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
{ {
printf("Error: SDL_Init(): %s\n", SDL_GetError()); printf("Error: SDL_Init(): %s\n", SDL_GetError());
return -1; return -1;

View File

@ -25,7 +25,7 @@
int main(int, char**) int main(int, char**)
{ {
// Setup SDL // Setup SDL
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD)) if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
{ {
printf("Error: SDL_Init(): %s\n", SDL_GetError()); printf("Error: SDL_Init(): %s\n", SDL_GetError());
return -1; return -1;

685
imgui.cpp
View File

@ -1,4 +1,4 @@
// dear imgui, v1.91.2 WIP // dear imgui, v1.91.3 WIP
// (main code and documentation) // (main code and documentation)
// Help: // Help:
@ -79,7 +79,7 @@ CODE
// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!) // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
// [SECTION] ID STACK // [SECTION] ID STACK
// [SECTION] INPUTS // [SECTION] INPUTS
// [SECTION] ERROR CHECKING // [SECTION] ERROR CHECKING, STATE RECOVERY
// [SECTION] ITEM SUBMISSION // [SECTION] ITEM SUBMISSION
// [SECTION] LAYOUT // [SECTION] LAYOUT
// [SECTION] SCROLLING // [SECTION] SCROLLING
@ -1394,12 +1394,18 @@ ImGuiIO::ImGuiIO()
ConfigDragClickToInputText = false; ConfigDragClickToInputText = false;
ConfigWindowsResizeFromEdges = true; ConfigWindowsResizeFromEdges = true;
ConfigWindowsMoveFromTitleBarOnly = false; ConfigWindowsMoveFromTitleBarOnly = false;
ConfigScrollbarScrollByPage = true;
ConfigMemoryCompactTimer = 60.0f; ConfigMemoryCompactTimer = 60.0f;
ConfigDebugIsDebuggerPresent = false; ConfigDebugIsDebuggerPresent = false;
ConfigDebugHighlightIdConflicts = true; ConfigDebugHighlightIdConflicts = true;
ConfigDebugBeginReturnValueOnce = false; ConfigDebugBeginReturnValueOnce = false;
ConfigDebugBeginReturnValueLoop = false; ConfigDebugBeginReturnValueLoop = false;
ConfigErrorRecovery = true;
ConfigErrorRecoveryEnableAssert = true;
ConfigErrorRecoveryEnableDebugLog = true;
ConfigErrorRecoveryEnableTooltip = true;
// Inputs Behaviors // Inputs Behaviors
MouseDoubleClickTime = 0.30f; MouseDoubleClickTime = 0.30f;
MouseDoubleClickMaxDist = 6.0f; MouseDoubleClickMaxDist = 6.0f;
@ -3272,7 +3278,7 @@ void ImGui::PopStyleColor(int count)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.ColorStack.Size < count) if (g.ColorStack.Size < count)
{ {
IM_ASSERT_USER_ERROR(g.ColorStack.Size > count, "Calling PopStyleColor() too many times!"); IM_ASSERT_USER_ERROR(0, "Calling PopStyleColor() too many times!");
count = g.ColorStack.Size; count = g.ColorStack.Size;
} }
while (count > 0) while (count > 0)
@ -3389,7 +3395,7 @@ void ImGui::PopStyleVar(int count)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.StyleVarStack.Size < count) if (g.StyleVarStack.Size < count)
{ {
IM_ASSERT_USER_ERROR(g.StyleVarStack.Size > count, "Calling PopStyleVar() too many times!"); IM_ASSERT_USER_ERROR(0, "Calling PopStyleVar() too many times!");
count = g.StyleVarStack.Size; count = g.StyleVarStack.Size;
} }
while (count > 0) while (count > 0)
@ -3798,6 +3804,219 @@ static const ImGuiLocEntry GLocalizationEntriesEnUS[] =
{ ImGuiLocKey_CopyLink, "Copy Link###CopyLink" }, { ImGuiLocKey_CopyLink, "Copy Link###CopyLink" },
}; };
ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
{
IO.Ctx = this;
InputTextState.Ctx = this;
Initialized = false;
FontAtlasOwnedByContext = shared_font_atlas ? false : true;
Font = NULL;
FontSize = FontBaseSize = FontScale = CurrentDpiScale = 0.0f;
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
Time = 0.0f;
FrameCount = 0;
FrameCountEnded = FrameCountRendered = -1;
WithinFrameScope = WithinFrameScopeWithImplicitWindow = WithinEndChild = false;
GcCompactAll = false;
TestEngineHookItems = false;
TestEngine = NULL;
memset(ContextName, 0, sizeof(ContextName));
InputEventsNextMouseSource = ImGuiMouseSource_Mouse;
InputEventsNextEventId = 1;
WindowsActiveCount = 0;
CurrentWindow = NULL;
HoveredWindow = NULL;
HoveredWindowUnderMovingWindow = NULL;
HoveredWindowBeforeClear = NULL;
MovingWindow = NULL;
WheelingWindow = NULL;
WheelingWindowStartFrame = WheelingWindowScrolledFrame = -1;
WheelingWindowReleaseTimer = 0.0f;
DebugDrawIdConflicts = 0;
DebugHookIdInfo = 0;
HoveredId = HoveredIdPreviousFrame = 0;
HoveredIdPreviousFrameItemCount = 0;
HoveredIdAllowOverlap = false;
HoveredIdIsDisabled = false;
HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
ItemUnclipByLog = false;
ActiveId = 0;
ActiveIdIsAlive = 0;
ActiveIdTimer = 0.0f;
ActiveIdIsJustActivated = false;
ActiveIdAllowOverlap = false;
ActiveIdNoClearOnFocusLoss = false;
ActiveIdHasBeenPressedBefore = false;
ActiveIdHasBeenEditedBefore = false;
ActiveIdHasBeenEditedThisFrame = false;
ActiveIdFromShortcut = false;
ActiveIdClickOffset = ImVec2(-1, -1);
ActiveIdWindow = NULL;
ActiveIdSource = ImGuiInputSource_None;
ActiveIdMouseButton = -1;
ActiveIdPreviousFrame = 0;
ActiveIdPreviousFrameIsAlive = false;
ActiveIdPreviousFrameHasBeenEditedBefore = false;
ActiveIdPreviousFrameWindow = NULL;
LastActiveId = 0;
LastActiveIdTimer = 0.0f;
LastKeyboardKeyPressTime = LastKeyModsChangeTime = LastKeyModsChangeFromNoneTime = -1.0;
ActiveIdUsingNavDirMask = 0x00;
ActiveIdUsingAllKeyboardKeys = false;
CurrentFocusScopeId = 0;
CurrentItemFlags = ImGuiItemFlags_None;
DebugShowGroupRects = false;
NavWindow = NULL;
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
NavLayer = ImGuiNavLayer_Main;
NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavHighlightActivatedId = 0;
NavHighlightActivatedTimer = 0.0f;
NavInputSource = ImGuiInputSource_Keyboard;
NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
NavIdIsAlive = false;
NavMousePosDirty = false;
NavDisableHighlight = true;
NavDisableMouseHover = false;
NavAnyRequest = false;
NavInitRequest = false;
NavInitRequestFromMove = false;
NavMoveSubmitted = false;
NavMoveScoringItems = false;
NavMoveForwardToNextFrame = false;
NavMoveFlags = ImGuiNavMoveFlags_None;
NavMoveScrollFlags = ImGuiScrollFlags_None;
NavMoveKeyMods = ImGuiMod_None;
NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None;
NavScoringDebugCount = 0;
NavTabbingDir = 0;
NavTabbingCounter = 0;
NavJustMovedFromFocusScopeId = NavJustMovedToId = NavJustMovedToFocusScopeId = 0;
NavJustMovedToKeyMods = ImGuiMod_None;
NavJustMovedToIsTabbing = false;
NavJustMovedToHasSelectionData = false;
// All platforms use Ctrl+Tab but Ctrl<>Super are swapped on Mac...
// FIXME: Because this value is stored, it annoyingly interfere with toggling io.ConfigMacOSXBehaviors updating this..
ConfigNavWindowingKeyNext = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiKey_Tab);
ConfigNavWindowingKeyPrev = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab);
NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
NavWindowingToggleLayer = false;
NavWindowingToggleKey = ImGuiKey_None;
DimBgRatio = 0.0f;
DragDropActive = DragDropWithinSource = DragDropWithinTarget = false;
DragDropSourceFlags = ImGuiDragDropFlags_None;
DragDropSourceFrameCount = -1;
DragDropMouseButton = -1;
DragDropTargetId = 0;
DragDropAcceptFlags = ImGuiDragDropFlags_None;
DragDropAcceptIdCurrRectSurface = 0.0f;
DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0;
DragDropAcceptFrameCount = -1;
DragDropHoldJustPressedId = 0;
memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal));
ClipperTempDataStacked = 0;
CurrentTable = NULL;
TablesTempDataStacked = 0;
CurrentTabBar = NULL;
CurrentMultiSelect = NULL;
MultiSelectTempDataStacked = 0;
HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId = 0;
HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f;
MouseCursor = ImGuiMouseCursor_Arrow;
MouseStationaryTimer = 0.0f;
TempInputId = 0;
memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue));
BeginMenuDepth = BeginComboDepth = 0;
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
ColorEditCurrentID = ColorEditSavedID = 0;
ColorEditSavedHue = ColorEditSavedSat = 0.0f;
ColorEditSavedColor = 0;
WindowResizeRelativeMode = false;
ScrollbarSeekMode = 0;
ScrollbarClickDeltaToGrabCenter = 0.0f;
SliderGrabClickOffset = 0.0f;
SliderCurrentAccum = 0.0f;
SliderCurrentAccumDirty = false;
DragCurrentAccumDirty = false;
DragCurrentAccum = 0.0f;
DragSpeedDefaultRatio = 1.0f / 100.0f;
DisabledAlphaBackup = 0.0f;
DisabledStackSize = 0;
LockMarkEdited = 0;
TooltipOverrideCount = 0;
PlatformImeData.InputPos = ImVec2(0.0f, 0.0f);
PlatformImeDataPrev.InputPos = ImVec2(-1.0f, -1.0f); // Different to ensure initial submission
SettingsLoaded = false;
SettingsDirtyTimer = 0.0f;
HookIdNext = 0;
memset(LocalizationTable, 0, sizeof(LocalizationTable));
LogEnabled = false;
LogType = ImGuiLogType_None;
LogNextPrefix = LogNextSuffix = NULL;
LogFile = NULL;
LogLinePosY = FLT_MAX;
LogLineFirstItem = false;
LogDepthRef = 0;
LogDepthToExpand = LogDepthToExpandDefault = 2;
ErrorCallback = NULL;
ErrorCallbackUserData = NULL;
ErrorFirst = true;
ErrorCountCurrentFrame = 0;
StackSizesInBeginForCurrentWindow = NULL;
DebugDrawIdConflictsCount = 0;
DebugLogFlags = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_OutputToTTY;
DebugLocateId = 0;
DebugLogSkippedErrors = 0;
DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
DebugLogAutoDisableFrames = 0;
DebugLocateFrames = 0;
DebugBeginReturnValueCullDepth = -1;
DebugItemPickerActive = false;
DebugItemPickerMouseButton = ImGuiMouseButton_Left;
DebugItemPickerBreakId = 0;
DebugFlashStyleColorTime = 0.0f;
DebugFlashStyleColorIdx = ImGuiCol_COUNT;
// Same as DebugBreakClearData(). Those fields are scattered in their respective subsystem to stay in hot-data locations
DebugBreakInWindow = 0;
DebugBreakInTable = 0;
DebugBreakInLocateId = false;
DebugBreakKeyChord = ImGuiKey_Pause;
DebugBreakInShortcutRouting = ImGuiKey_None;
memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0;
FramerateSecPerFrameAccum = 0.0f;
WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;
memset(TempKeychordName, 0, sizeof(TempKeychordName));
}
void ImGui::Initialize() void ImGui::Initialize()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -4003,6 +4222,7 @@ static void SetCurrentWindow(ImGuiWindow* window)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
g.CurrentWindow = window; g.CurrentWindow = window;
g.StackSizesInBeginForCurrentWindow = g.CurrentWindow ? &g.CurrentWindowStack.back().StackSizesInBegin : NULL;
g.CurrentTable = window && window->DC.CurrentTableIdx != -1 ? g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL; g.CurrentTable = window && window->DC.CurrentTableIdx != -1 ? g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL;
g.CurrentDpiScale = 1.0f; // FIXME-DPI: WIP this is modified in docking g.CurrentDpiScale = 1.0f; // FIXME-DPI: WIP this is modified in docking
if (window) if (window)
@ -4848,6 +5068,7 @@ void ImGui::NewFrame()
KeepAliveID(g.DragDropPayload.SourceId); KeepAliveID(g.DragDropPayload.SourceId);
// [DEBUG] // [DEBUG]
if (!g.IO.ConfigDebugHighlightIdConflicts || !g.IO.KeyCtrl) // Count is locked while holding CTRL
g.DebugDrawIdConflicts = 0; g.DebugDrawIdConflicts = 0;
if (g.IO.ConfigDebugHighlightIdConflicts && g.HoveredIdPreviousFrameItemCount > 1) if (g.IO.ConfigDebugHighlightIdConflicts && g.HoveredIdPreviousFrameItemCount > 1)
g.DebugDrawIdConflicts = g.HoveredIdPreviousFrame; g.DebugDrawIdConflicts = g.HoveredIdPreviousFrame;
@ -4950,8 +5171,25 @@ void ImGui::NewFrame()
// Update mouse input state // Update mouse input state
UpdateMouseInputs(); UpdateMouseInputs();
// Mark all windows as not visible and compact unused memory.
IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size);
const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
for (ImGuiWindow* window : g.Windows)
{
window->WasActive = window->Active;
window->Active = false;
window->WriteAccessed = false;
window->BeginCountPreviousFrame = window->BeginCount;
window->BeginCount = 0;
// Garbage collect transient buffers of recently unused windows
if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
GcCompactTransientWindowBuffers(window);
}
// Find hovered window // Find hovered window
// (needs to be before UpdateMouseMovingWindowNewFrame so we fill g.HoveredWindowUnderMovingWindow on the mouse release frame) // (needs to be before UpdateMouseMovingWindowNewFrame so we fill g.HoveredWindowUnderMovingWindow on the mouse release frame)
// (currently needs to be done after the WasActive=Active loop and FindHoveredWindowEx uses ->Active)
UpdateHoveredWindowAndCaptureFlags(); UpdateHoveredWindowAndCaptureFlags();
// Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering) // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering)
@ -4973,22 +5211,6 @@ void ImGui::NewFrame()
// Mouse wheel scrolling, scale // Mouse wheel scrolling, scale
UpdateMouseWheel(); UpdateMouseWheel();
// Mark all windows as not visible and compact unused memory.
IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size);
const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
for (ImGuiWindow* window : g.Windows)
{
window->WasActive = window->Active;
window->Active = false;
window->WriteAccessed = false;
window->BeginCountPreviousFrame = window->BeginCount;
window->BeginCount = 0;
// Garbage collect transient buffers of recently unused windows
if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
GcCompactTransientWindowBuffers(window);
}
// Garbage collect transient buffers of recently unused tables // Garbage collect transient buffers of recently unused tables
for (int i = 0; i < g.TablesLastTimeActive.Size; i++) for (int i = 0; i < g.TablesLastTimeActive.Size; i++)
if (g.TablesLastTimeActive[i] >= 0.0f && g.TablesLastTimeActive[i] < memory_compact_start_time) if (g.TablesLastTimeActive[i] >= 0.0f && g.TablesLastTimeActive[i] < memory_compact_start_time)
@ -5039,6 +5261,10 @@ void ImGui::NewFrame()
Begin("Debug##Default"); Begin("Debug##Default");
IM_ASSERT(g.CurrentWindow->IsFallbackWindow == true); IM_ASSERT(g.CurrentWindow->IsFallbackWindow == true);
// Store stack sizes
g.ErrorCountCurrentFrame = 0;
ErrorRecoveryStoreState(&g.StackSizesInNewFrame);
// [DEBUG] When io.ConfigDebugBeginReturnValue is set, we make Begin()/BeginChild() return false at different level of the window-stack, // [DEBUG] When io.ConfigDebugBeginReturnValue is set, we make Begin()/BeginChild() return false at different level of the window-stack,
// allowing to validate correct Begin/End behavior in user code. // allowing to validate correct Begin/End behavior in user code.
#ifndef IMGUI_DISABLE_DEBUG_TOOLS #ifndef IMGUI_DISABLE_DEBUG_TOOLS
@ -5255,32 +5481,13 @@ void ImGui::EndFrame()
return; return;
IM_ASSERT(g.WithinFrameScope && "Forgot to call ImGui::NewFrame()?"); IM_ASSERT(g.WithinFrameScope && "Forgot to call ImGui::NewFrame()?");
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
if (g.DebugDrawIdConflicts != 0)
{
PushStyleColor(ImGuiCol_PopupBg, ImLerp(g.Style.Colors[ImGuiCol_PopupBg], ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.10f));
if (g.DebugItemPickerActive == false && BeginTooltipEx(ImGuiTooltipFlags_OverridePrevious, ImGuiWindowFlags_None))
{
SeparatorText("MESSAGE FROM DEAR IMGUI");
Text("Programmer error: %d visible items with conflicting ID!", g.HoveredIdPreviousFrameItemCount);
BulletText("Code should use PushID()/PopID() in loops, or append \"##xx\" to same-label identifiers!");
BulletText("Empty label e.g. Button(\"\") == same ID as parent widget/node. Use Button(\"##xx\") instead!");
BulletText("Press F1 to open \"FAQ -> About the ID Stack System\" and read details.");
BulletText("Press CTRL+P to activate Item Picker and debug-break in item call-stack.");
BulletText("Set io.ConfigDebugDetectIdConflicts=false to disable this warning in non-programmers builds.");
EndTooltip();
}
PopStyleColor();
if (Shortcut(ImGuiMod_Ctrl | ImGuiKey_P, ImGuiInputFlags_RouteGlobal))
DebugStartItemPicker();
if (Shortcut(ImGuiKey_F1, ImGuiInputFlags_RouteGlobal) && g.PlatformIO.Platform_OpenInShellFn != NULL)
g.PlatformIO.Platform_OpenInShellFn(&g, "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage");
}
#endif
CallContextHooks(&g, ImGuiContextHookType_EndFramePre); CallContextHooks(&g, ImGuiContextHookType_EndFramePre);
// [EXPERIMENTAL] Recover from errors
if (g.IO.ConfigErrorRecovery)
ErrorRecoveryTryToRecoverState(&g.StackSizesInNewFrame);
ErrorCheckEndFrameSanityChecks(); ErrorCheckEndFrameSanityChecks();
ErrorCheckEndFrameFinalizeErrorTooltip();
// Notify Platform/OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) // Notify Platform/OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
ImGuiPlatformImeData* ime_data = &g.PlatformImeData; ImGuiPlatformImeData* ime_data = &g.PlatformImeData;
@ -5474,7 +5681,7 @@ void ImGui::FindHoveredWindowEx(const ImVec2& pos, bool find_first_and_in_any_vi
{ {
ImGuiWindow* window = g.Windows[i]; ImGuiWindow* window = g.Windows[i];
IM_MSVC_WARNING_SUPPRESS(28182); // [Static Analyzer] Dereferencing NULL pointer. IM_MSVC_WARNING_SUPPRESS(28182); // [Static Analyzer] Dereferencing NULL pointer.
if (!window->Active || window->Hidden) if (!window->WasActive || window->Hidden)
continue; continue;
if (window->Flags & ImGuiWindowFlags_NoMouseInputs) if (window->Flags & ImGuiWindowFlags_NoMouseInputs)
continue; continue;
@ -5731,18 +5938,35 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I
window_flags |= ImGuiWindowFlags_NoMove; window_flags |= ImGuiWindowFlags_NoMove;
} }
// Forward child flags
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags;
g.NextWindowData.ChildFlags = child_flags;
// Forward size // Forward size
// Important: Begin() has special processing to switch condition to ImGuiCond_FirstUseEver for a given axis when ImGuiChildFlags_ResizeXXX is set. // Important: Begin() has special processing to switch condition to ImGuiCond_FirstUseEver for a given axis when ImGuiChildFlags_ResizeXXX is set.
// (the alternative would to store conditional flags per axis, which is possible but more code) // (the alternative would to store conditional flags per axis, which is possible but more code)
const ImVec2 size_avail = GetContentRegionAvail(); const ImVec2 size_avail = GetContentRegionAvail();
const ImVec2 size_default((child_flags & ImGuiChildFlags_AutoResizeX) ? 0.0f : size_avail.x, (child_flags & ImGuiChildFlags_AutoResizeY) ? 0.0f : size_avail.y); const ImVec2 size_default((child_flags & ImGuiChildFlags_AutoResizeX) ? 0.0f : size_avail.x, (child_flags & ImGuiChildFlags_AutoResizeY) ? 0.0f : size_avail.y);
const ImVec2 size = CalcItemSize(size_arg, size_default.x, size_default.y); ImVec2 size = CalcItemSize(size_arg, size_default.x, size_default.y);
// A SetNextWindowSize() call always has priority (#8020)
// (since the code in Begin() never supported SizeVal==0.0f aka auto-resize via SetNextWindowSize() call, we don't support it here for now)
// FIXME: We only support ImGuiCond_Always in this path. Supporting other paths would requires to obtain window pointer.
if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) != 0 && (g.NextWindowData.SizeCond & ImGuiCond_Always) != 0)
{
if (g.NextWindowData.SizeVal.x > 0.0f)
{
size.x = g.NextWindowData.SizeVal.x;
child_flags &= ~ImGuiChildFlags_ResizeX;
}
if (g.NextWindowData.SizeVal.y > 0.0f)
{
size.y = g.NextWindowData.SizeVal.y;
child_flags &= ~ImGuiChildFlags_ResizeY;
}
}
SetNextWindowSize(size); SetNextWindowSize(size);
// Forward child flags
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags;
g.NextWindowData.ChildFlags = child_flags;
// Build up name. If you need to append to a same child from multiple location in the ID stack, use BeginChild(ImGuiID id) with a stable value. // Build up name. If you need to append to a same child from multiple location in the ID stack, use BeginChild(ImGuiID id) with a stable value.
// FIXME: 2023/11/14: commented out shorted version. We had an issue with multiple ### in child window path names, which the trailing hash helped workaround. // FIXME: 2023/11/14: commented out shorted version. We had an issue with multiple ### in child window path names, which the trailing hash helped workaround.
// e.g. "ParentName###ParentIdentifier/ChildName###ChildIdentifier" would get hashed incorrectly by ImHashStr(), trailing _%08X somehow fixes it. // e.g. "ParentName###ParentIdentifier/ChildName###ChildIdentifier" would get hashed incorrectly by ImHashStr(), trailing _%08X somehow fixes it.
@ -6755,12 +6979,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Add to stack // Add to stack
g.CurrentWindow = window; g.CurrentWindow = window;
ImGuiWindowStackData window_stack_data; g.CurrentWindowStack.resize(g.CurrentWindowStack.Size + 1);
ImGuiWindowStackData& window_stack_data = g.CurrentWindowStack.back();
window_stack_data.Window = window; window_stack_data.Window = window;
window_stack_data.ParentLastItemDataBackup = g.LastItemData; window_stack_data.ParentLastItemDataBackup = g.LastItemData;
window_stack_data.StackSizesOnBegin.SetToContextState(&g);
window_stack_data.DisabledOverrideReenable = (flags & ImGuiWindowFlags_Tooltip) && (g.CurrentItemFlags & ImGuiItemFlags_Disabled); window_stack_data.DisabledOverrideReenable = (flags & ImGuiWindowFlags_Tooltip) && (g.CurrentItemFlags & ImGuiItemFlags_Disabled);
g.CurrentWindowStack.push_back(window_stack_data); ErrorRecoveryStoreState(&window_stack_data.StackSizesInBegin);
g.StackSizesInBeginForCurrentWindow = &window_stack_data.StackSizesInBegin;
if (flags & ImGuiWindowFlags_ChildMenu) if (flags & ImGuiWindowFlags_ChildMenu)
g.BeginMenuDepth++; g.BeginMenuDepth++;
@ -7488,7 +7713,11 @@ void ImGui::End()
g.BeginMenuDepth--; g.BeginMenuDepth--;
if (window->Flags & ImGuiWindowFlags_Popup) if (window->Flags & ImGuiWindowFlags_Popup)
g.BeginPopupStack.pop_back(); g.BeginPopupStack.pop_back();
window_stack_data.StackSizesOnBegin.CompareWithContextState(&g);
// Error handling, state recovery
if (g.IO.ConfigErrorRecovery)
ErrorRecoveryTryToRecoverWindowState(&window_stack_data.StackSizesInBegin);
g.CurrentWindowStack.pop_back(); g.CurrentWindowStack.pop_back();
SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window); SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window);
} }
@ -7702,7 +7931,11 @@ void ImGui::PushFont(ImFont* font)
void ImGui::PopFont() void ImGui::PopFont()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(g.FontStack.Size > 0); if (g.FontStack.Size <= 0)
{
IM_ASSERT_USER_ERROR(0, "Calling PopFont() too many times!");
return;
}
g.FontStack.pop_back(); g.FontStack.pop_back();
ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back(); ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back();
SetCurrentFont(font); SetCurrentFont(font);
@ -7725,7 +7958,11 @@ void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)
void ImGui::PopItemFlag() void ImGui::PopItemFlag()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(g.ItemFlagsStack.Size > 1); // Too many calls to PopItemFlag() - we always leave a 0 at the bottom of the stack. if (g.ItemFlagsStack.Size <= 1)
{
IM_ASSERT_USER_ERROR(0, "Calling PopItemFlag() too many times!");
return;
}
g.ItemFlagsStack.pop_back(); g.ItemFlagsStack.pop_back();
g.CurrentItemFlags = g.ItemFlagsStack.back(); g.CurrentItemFlags = g.ItemFlagsStack.back();
} }
@ -7734,8 +7971,9 @@ void ImGui::PopItemFlag()
// - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled) // - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled)
// - Visually this is currently altering alpha, but it is expected that in a future styling system this would work differently. // - Visually this is currently altering alpha, but it is expected that in a future styling system this would work differently.
// - Feedback welcome at https://github.com/ocornut/imgui/issues/211 // - Feedback welcome at https://github.com/ocornut/imgui/issues/211
// - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. If you can avoid calling BeginDisabled(False)/EndDisabled() best to avoid it. // - BeginDisabled(false)/EndDisabled() essentially does nothing but is provided to facilitate use of boolean expressions.
// - Optimized shortcuts instead of PushStyleVar() + PushItemFlag() // (as a micro-optimization: if you have tens of thousands of BeginDisabled(false)/EndDisabled() pairs, you might want to reformulate your code to avoid making those calls)
// - Note: mixing up BeginDisabled() and PushItemFlag(ImGuiItemFlags_Disabled) is currently NOT SUPPORTED.
void ImGui::BeginDisabled(bool disabled) void ImGui::BeginDisabled(bool disabled)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -7754,7 +7992,11 @@ void ImGui::BeginDisabled(bool disabled)
void ImGui::EndDisabled() void ImGui::EndDisabled()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(g.DisabledStackSize > 0); if (g.DisabledStackSize <= 0)
{
IM_ASSERT_USER_ERROR(0, "Calling EndDisabled() too many times!");
return;
}
g.DisabledStackSize--; g.DisabledStackSize--;
bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0; bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
//PopItemFlag(); //PopItemFlag();
@ -7789,14 +8031,21 @@ void ImGui::EndDisabledOverrideReenable()
void ImGui::PushTextWrapPos(float wrap_pos_x) void ImGui::PushTextWrapPos(float wrap_pos_x)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
window->DC.TextWrapPosStack.push_back(window->DC.TextWrapPos); window->DC.TextWrapPosStack.push_back(window->DC.TextWrapPos);
window->DC.TextWrapPos = wrap_pos_x; window->DC.TextWrapPos = wrap_pos_x;
} }
void ImGui::PopTextWrapPos() void ImGui::PopTextWrapPos()
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if (window->DC.TextWrapPosStack.Size <= 0)
{
IM_ASSERT_USER_ERROR(0, "Calling PopTextWrapPos() too many times!");
return;
}
window->DC.TextWrapPos = window->DC.TextWrapPosStack.back(); window->DC.TextWrapPos = window->DC.TextWrapPosStack.back();
window->DC.TextWrapPosStack.pop_back(); window->DC.TextWrapPosStack.pop_back();
} }
@ -8229,9 +8478,9 @@ void ImGui::PushFocusScope(ImGuiID id)
void ImGui::PopFocusScope() void ImGui::PopFocusScope()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.FocusScopeStack.Size == 0) if (g.FocusScopeStack.Size <= g.StackSizesInBeginForCurrentWindow->SizeOfFocusScopeStack)
{ {
IM_ASSERT_USER_ERROR(g.FocusScopeStack.Size > 0, "Calling PopFocusScope() too many times!"); IM_ASSERT_USER_ERROR(0, "Calling PopFocusScope() too many times!");
return; return;
} }
g.FocusScopeStack.pop_back(); g.FocusScopeStack.pop_back();
@ -8502,7 +8751,11 @@ ImGuiID ImGui::GetIDWithSeed(int n, ImGuiID seed)
void ImGui::PopID() void ImGui::PopID()
{ {
ImGuiWindow* window = GImGui->CurrentWindow; ImGuiWindow* window = GImGui->CurrentWindow;
IM_ASSERT(window->IDStack.Size > 1); // Too many PopID(), or could be popping in a wrong/different window? if (window->IDStack.Size <= 1)
{
IM_ASSERT_USER_ERROR(0, "Calling PopID() too many times!");
return;
}
window->IDStack.pop_back(); window->IDStack.pop_back();
} }
@ -10068,7 +10321,16 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID own
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] ERROR CHECKING // [SECTION] ERROR CHECKING, STATE RECOVERY
//-----------------------------------------------------------------------------
// - DebugCheckVersionAndDataLayout() (called via IMGUI_CHECKVERSION() macros)
// - ErrorCheckUsingSetCursorPosToExtendParentBoundaries()
// - ErrorCheckNewFrameSanityChecks()
// - ErrorCheckEndFrameSanityChecks()
// - ErrorRecoveryStoreState()
// - ErrorRecoveryTryToRecoverState()
// - ErrorRecoveryTryToRecoverWindowState()
// - ErrorLog()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Verify ABI compatibility between caller code and compiled version of Dear ImGui. This helps detects some build issues. // Verify ABI compatibility between caller code and compiled version of Dear ImGui. This helps detects some build issues.
@ -10167,6 +10429,10 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation."); IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation.");
#endif #endif
// Error handling: we do not accept 100% silent recovery! Please contact me if you feel this is getting in your way.
if (g.IO.ConfigErrorRecovery)
IM_ASSERT(g.IO.ConfigErrorRecoveryEnableAssert || g.IO.ConfigErrorRecoveryEnableDebugLog || g.IO.ConfigErrorRecoveryEnableTooltip || g.ErrorCallback != NULL);
// Remap legacy clipboard handlers (OBSOLETED in 1.91.1, August 2024) // Remap legacy clipboard handlers (OBSOLETED in 1.91.1, August 2024)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
if (g.IO.GetClipboardTextFn != NULL && (g.PlatformIO.Platform_GetClipboardTextFn == NULL || g.PlatformIO.Platform_GetClipboardTextFn == Platform_GetClipboardTextFn_DefaultImpl)) if (g.IO.GetClipboardTextFn != NULL && (g.PlatformIO.Platform_GetClipboardTextFn == NULL || g.PlatformIO.Platform_GetClipboardTextFn == Platform_GetClipboardTextFn_DefaultImpl))
@ -10178,114 +10444,115 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
static void ImGui::ErrorCheckEndFrameSanityChecks() static void ImGui::ErrorCheckEndFrameSanityChecks()
{ {
ImGuiContext& g = *GImGui;
// Verify that io.KeyXXX fields haven't been tampered with. Key mods should not be modified between NewFrame() and EndFrame() // Verify that io.KeyXXX fields haven't been tampered with. Key mods should not be modified between NewFrame() and EndFrame()
// One possible reason leading to this assert is that your backends update inputs _AFTER_ NewFrame(). // One possible reason leading to this assert is that your backends update inputs _AFTER_ NewFrame().
// It is known that when some modal native windows called mid-frame takes focus away, some backends such as GLFW will // It is known that when some modal native windows called mid-frame takes focus away, some backends such as GLFW will
// send key release events mid-frame. This would normally trigger this assertion and lead to sheared inputs. // send key release events mid-frame. This would normally trigger this assertion and lead to sheared inputs.
// We silently accommodate for this case by ignoring the case where all io.KeyXXX modifiers were released (aka key_mod_flags == 0), // We silently accommodate for this case by ignoring the case where all io.KeyXXX modifiers were released (aka key_mod_flags == 0),
// while still correctly asserting on mid-frame key press events. // while still correctly asserting on mid-frame key press events.
ImGuiContext& g = *GImGui;
const ImGuiKeyChord key_mods = GetMergedModsFromKeys(); const ImGuiKeyChord key_mods = GetMergedModsFromKeys();
IM_UNUSED(g);
IM_UNUSED(key_mods);
IM_ASSERT((key_mods == 0 || g.IO.KeyMods == key_mods) && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods"); IM_ASSERT((key_mods == 0 || g.IO.KeyMods == key_mods) && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
IM_UNUSED(key_mods); IM_UNUSED(key_mods);
// [EXPERIMENTAL] Recover from errors: You may call this yourself before EndFrame(). IM_ASSERT(g.CurrentWindowStack.Size == 1);
//ErrorCheckEndFrameRecover(); IM_ASSERT(g.CurrentWindowStack[0].Window->IsFallbackWindow);
// Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you
// to always call End/EndChild even if Begin/BeginChild returns false! (this is unfortunately inconsistent with most other Begin* API).
if (g.CurrentWindowStack.Size != 1)
{
if (g.CurrentWindowStack.Size > 1)
{
ImGuiWindow* window = g.CurrentWindowStack.back().Window; // <-- This window was not Ended!
IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?");
IM_UNUSED(window);
while (g.CurrentWindowStack.Size > 1)
End();
}
else
{
IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?");
}
} }
IM_ASSERT_USER_ERROR(g.GroupStack.Size == 0, "Missing EndGroup call!"); // Save current stack sizes. Called e.g. by NewFrame() and by Begin() but may be called for manual recovery.
void ImGui::ErrorRecoveryStoreState(ImGuiErrorRecoveryState* state_out)
{
ImGuiContext& g = *GImGui;
state_out->SizeOfWindowStack = (short)g.CurrentWindowStack.Size;
state_out->SizeOfIDStack = (short)g.CurrentWindow->IDStack.Size;
state_out->SizeOfTreeStack = (short)g.CurrentWindow->DC.TreeDepth; // NOT g.TreeNodeStack.Size which is a partial stack!
state_out->SizeOfColorStack = (short)g.ColorStack.Size;
state_out->SizeOfStyleVarStack = (short)g.StyleVarStack.Size;
state_out->SizeOfFontStack = (short)g.FontStack.Size;
state_out->SizeOfFocusScopeStack = (short)g.FocusScopeStack.Size;
state_out->SizeOfGroupStack = (short)g.GroupStack.Size;
state_out->SizeOfItemFlagsStack = (short)g.ItemFlagsStack.Size;
state_out->SizeOfBeginPopupStack = (short)g.BeginPopupStack.Size;
state_out->SizeOfDisabledStack = (short)g.DisabledStackSize;
} }
// Experimental recovery from incorrect usage of BeginXXX/EndXXX/PushXXX/PopXXX calls. // Chosen name "Try to recover" over e.g. "Restore" to suggest this is not a 100% guaranteed recovery.
// Must be called during or before EndFrame(). // Called by e.g. EndFrame() but may be called for manual recovery.
// This is generally flawed as we are not necessarily End/Popping things in the right order. // Attempt to recover full window stack.
// FIXME: Can't recover from inside BeginTabItem/EndTabItem yet. void ImGui::ErrorRecoveryTryToRecoverState(const ImGuiErrorRecoveryState* state_in)
// FIXME: Can't recover from interleaved BeginTabBar/Begin
void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data)
{ {
// PVS-Studio V1044 is "Loop break conditions do not depend on the number of iterations" // PVS-Studio V1044 is "Loop break conditions do not depend on the number of iterations"
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
while (g.CurrentWindowStack.Size > 0) //-V1044 while (g.CurrentWindowStack.Size > state_in->SizeOfWindowStack) //-V1044
{ {
ErrorCheckEndWindowRecover(log_callback, user_data); // Recap:
// - Begin()/BeginChild() return false to indicate the window is collapsed or fully clipped.
// - Always call a matching End() for each Begin() call, regardless of its return value!
// - Begin/End and BeginChild/EndChild logic is KNOWN TO BE INCONSISTENT WITH ALL OTHER BEGIN/END FUNCTIONS.
// - We will fix that in a future major update.
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
if (g.CurrentWindowStack.Size == 1)
{
IM_ASSERT(window->IsFallbackWindow);
break;
}
if (window->Flags & ImGuiWindowFlags_ChildWindow) if (window->Flags & ImGuiWindowFlags_ChildWindow)
{ {
if (log_callback) log_callback(user_data, "Recovered from missing EndChild() for '%s'", window->Name); IM_ASSERT_USER_ERROR(0, "Missing EndChild()");
EndChild(); EndChild();
} }
else else
{ {
if (log_callback) log_callback(user_data, "Recovered from missing End() for '%s'", window->Name); IM_ASSERT_USER_ERROR(0, "Missing End()");
End(); End();
} }
} }
if (g.CurrentWindowStack.Size == state_in->SizeOfWindowStack)
ErrorRecoveryTryToRecoverWindowState(state_in);
} }
// Must be called before End()/EndChild() // Called by e.g. End() but may be called for manual recovery.
void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data) // Read '// Error Handling [BETA]' block in imgui_internal.h for details.
// Attempt to recover from incorrect usage of BeginXXX/EndXXX/PushXXX/PopXXX calls.
void ImGui::ErrorRecoveryTryToRecoverWindowState(const ImGuiErrorRecoveryState* state_in)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
while (g.CurrentTable && (g.CurrentTable->OuterWindow == g.CurrentWindow || g.CurrentTable->InnerWindow == g.CurrentWindow))
while (g.CurrentTable != NULL && g.CurrentTable->InnerWindow == g.CurrentWindow)
{ {
if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'", g.CurrentTable->OuterWindow->Name); IM_ASSERT_USER_ERROR(0, "Missing EndTable()");
EndTable(); EndTable();
} }
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
ImGuiStackSizes* stack_sizes = &g.CurrentWindowStack.back().StackSizesOnBegin;
IM_ASSERT(window != NULL); // FIXME: Can't recover from inside BeginTabItem/EndTabItem yet.
while (g.CurrentTabBar != NULL) //-V1044 while (g.CurrentTabBar != NULL && g.CurrentTabBar->Window == window) //-V1044
{ {
if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'", window->Name); IM_ASSERT_USER_ERROR(0, "Missing EndTabBar()");
EndTabBar(); EndTabBar();
} }
while (g.CurrentMultiSelect != NULL && g.CurrentMultiSelect->Storage->Window == window) while (g.CurrentMultiSelect != NULL && g.CurrentMultiSelect->Storage->Window == window)
{ {
if (log_callback) log_callback(user_data, "Recovered from missing EndMultiSelect() in '%s'", window->Name); IM_ASSERT_USER_ERROR(0, "Missing EndMultiSelect()");
EndMultiSelect(); EndMultiSelect();
} }
while (window->DC.TreeDepth > 0) while (window->DC.TreeDepth > state_in->SizeOfTreeStack) //-V1044
{ {
if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'", window->Name); IM_ASSERT_USER_ERROR(0, "Missing TreePop()");
TreePop(); TreePop();
} }
while (g.GroupStack.Size > stack_sizes->SizeOfGroupStack) //-V1044 while (g.GroupStack.Size > state_in->SizeOfGroupStack) //-V1044
{ {
if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'", window->Name); IM_ASSERT_USER_ERROR(0, "Missing EndGroup()");
EndGroup(); EndGroup();
} }
while (window->IDStack.Size > 1) IM_ASSERT(g.GroupStack.Size == state_in->SizeOfGroupStack);
while (window->IDStack.Size > state_in->SizeOfIDStack) //-V1044
{ {
if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'", window->Name); IM_ASSERT_USER_ERROR(0, "Missing PopID()");
PopID(); PopID();
} }
while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044 while (g.DisabledStackSize > state_in->SizeOfDisabledStack) //-V1044
{ {
if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'", window->Name); IM_ASSERT_USER_ERROR(0, "Missing EndDisabled()");
if (g.CurrentItemFlags & ImGuiItemFlags_Disabled) if (g.CurrentItemFlags & ImGuiItemFlags_Disabled)
EndDisabled(); EndDisabled();
else else
@ -10294,70 +10561,150 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo
g.CurrentWindowStack.back().DisabledOverrideReenable = false; g.CurrentWindowStack.back().DisabledOverrideReenable = false;
} }
} }
while (g.ColorStack.Size > stack_sizes->SizeOfColorStack) IM_ASSERT(g.DisabledStackSize == state_in->SizeOfDisabledStack);
while (g.ColorStack.Size > state_in->SizeOfColorStack)
{ {
if (log_callback) log_callback(user_data, "Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s", window->Name, GetStyleColorName(g.ColorStack.back().Col)); IM_ASSERT_USER_ERROR(0, "Missing PopStyleColor()");
PopStyleColor(); PopStyleColor();
} }
while (g.ItemFlagsStack.Size > stack_sizes->SizeOfItemFlagsStack) //-V1044 while (g.ItemFlagsStack.Size > state_in->SizeOfItemFlagsStack) //-V1044
{ {
if (log_callback) log_callback(user_data, "Recovered from missing PopItemFlag() in '%s'", window->Name); IM_ASSERT_USER_ERROR(0, "Missing PopItemFlag()");
PopItemFlag(); PopItemFlag();
} }
while (g.StyleVarStack.Size > stack_sizes->SizeOfStyleVarStack) //-V1044 while (g.StyleVarStack.Size > state_in->SizeOfStyleVarStack) //-V1044
{ {
if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'", window->Name); IM_ASSERT_USER_ERROR(0, "Missing PopStyleVar()");
PopStyleVar(); PopStyleVar();
} }
while (g.FontStack.Size > stack_sizes->SizeOfFontStack) //-V1044 while (g.FontStack.Size > state_in->SizeOfFontStack) //-V1044
{ {
if (log_callback) log_callback(user_data, "Recovered from missing PopFont() in '%s'", window->Name); IM_ASSERT_USER_ERROR(0, "Missing PopFont()");
PopFont(); PopFont();
} }
while (g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack + 1) //-V1044 while (g.FocusScopeStack.Size > state_in->SizeOfFocusScopeStack) //-V1044
{ {
if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'", window->Name); IM_ASSERT_USER_ERROR(0, "Missing PopFocusScope()");
PopFocusScope(); PopFocusScope();
} }
//IM_ASSERT(g.FocusScopeStack.Size == state_in->SizeOfFocusScopeStack);
} }
// Save current stack sizes for later compare bool ImGui::ErrorLog(const char* msg)
void ImGuiStackSizes::SetToContextState(ImGuiContext* ctx)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *GImGui;
// Output to debug log
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
SizeOfIDStack = (short)window->IDStack.Size;
SizeOfColorStack = (short)g.ColorStack.Size; if (g.IO.ConfigErrorRecoveryEnableDebugLog)
SizeOfStyleVarStack = (short)g.StyleVarStack.Size; {
SizeOfFontStack = (short)g.FontStack.Size; if (g.ErrorFirst)
SizeOfFocusScopeStack = (short)g.FocusScopeStack.Size; IMGUI_DEBUG_LOG_ERROR("[imgui-error] (current settings: Assert=%d, Log=%d, Tooltip=%d)\n",
SizeOfGroupStack = (short)g.GroupStack.Size; g.IO.ConfigErrorRecoveryEnableAssert, g.IO.ConfigErrorRecoveryEnableDebugLog, g.IO.ConfigErrorRecoveryEnableTooltip);
SizeOfItemFlagsStack = (short)g.ItemFlagsStack.Size; IMGUI_DEBUG_LOG_ERROR("[imgui-error] In window '%s': %s\n", window ? window->Name : "NULL", msg);
SizeOfBeginPopupStack = (short)g.BeginPopupStack.Size; }
SizeOfDisabledStack = (short)g.DisabledStackSize; g.ErrorFirst = false;
// Output to tooltip
if (g.IO.ConfigErrorRecoveryEnableTooltip)
{
if (BeginErrorTooltip())
{
if (g.ErrorCountCurrentFrame < 20)
{
Text("In window '%s': %s", window ? window->Name : "NULL", msg);
if (window && (!window->IsFallbackWindow || window->WasActive))
GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 0, 0, 255));
}
if (g.ErrorCountCurrentFrame == 20)
Text("(and more errors)");
// EndFrame() will amend debug buttons to this window, after all errors have been submitted.
EndErrorTooltip();
}
g.ErrorCountCurrentFrame++;
}
#endif
// Output to callback
if (g.ErrorCallback != NULL)
g.ErrorCallback(&g, g.ErrorCallbackUserData, msg);
// Return whether we should assert
return g.IO.ConfigErrorRecoveryEnableAssert;
} }
// Compare to detect usage errors void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
void ImGuiStackSizes::CompareWithContextState(ImGuiContext* ctx)
{ {
ImGuiContext& g = *ctx; #ifndef IMGUI_DISABLE_DEBUG_TOOLS
ImGuiWindow* window = g.CurrentWindow; ImGuiContext& g = *GImGui;
IM_UNUSED(window); if (g.DebugDrawIdConflicts != 0 && g.IO.KeyCtrl == false)
g.DebugDrawIdConflictsCount = g.HoveredIdPreviousFrameItemCount;
if (g.DebugDrawIdConflicts != 0 && g.DebugItemPickerActive == false && BeginErrorTooltip())
{
Text("Programmer error: %d visible items with conflicting ID!", g.DebugDrawIdConflictsCount);
BulletText("Code should use PushID()/PopID() in loops, or append \"##xx\" to same-label identifiers!");
BulletText("Empty label e.g. Button(\"\") == same ID as parent widget/node. Use Button(\"##xx\") instead!");
BulletText("Set io.ConfigDebugDetectIdConflicts=false to disable this warning in non-programmers builds.");
Separator();
Text("(Hold CTRL and: use");
SameLine();
if (SmallButton("Item Picker"))
DebugStartItemPicker();
SameLine();
Text("to break in item call-stack, or");
SameLine();
if (SmallButton("Open FAQ->About ID Stack System") && g.PlatformIO.Platform_OpenInShellFn != NULL)
g.PlatformIO.Platform_OpenInShellFn(&g, "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage");
EndErrorTooltip();
}
// Window stacks if (g.ErrorCountCurrentFrame > 0 && BeginErrorTooltip()) // Amend at end of frame
// NOT checking: DC.ItemWidth, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin) {
IM_ASSERT(SizeOfIDStack == window->IDStack.Size && "PushID/PopID or TreeNode/TreePop Mismatch!"); Separator();
Text("(Hold CTRL and:");
SameLine();
if (SmallButton("Enable Asserts"))
g.IO.ConfigErrorRecoveryEnableAssert = true;
//SameLine();
//if (SmallButton("Hide Error Tooltips"))
// g.IO.ConfigErrorRecoveryEnableTooltip = false; // Too dangerous
SameLine(0, 0);
Text(")");
EndErrorTooltip();
}
#endif
}
// Global stacks // Pseudo-tooltip. Follow mouse until CTRL is held. When CTRL is held we lock position, allowing to click it.
// For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them. bool ImGui::BeginErrorTooltip()
IM_ASSERT(SizeOfGroupStack == g.GroupStack.Size && "BeginGroup/EndGroup Mismatch!"); {
IM_ASSERT(SizeOfBeginPopupStack == g.BeginPopupStack.Size && "BeginPopup/EndPopup or BeginMenu/EndMenu Mismatch!"); ImGuiContext& g = *GImGui;
IM_ASSERT(SizeOfDisabledStack == g.DisabledStackSize && "BeginDisabled/EndDisabled Mismatch!"); ImGuiWindow* window = FindWindowByName("##Tooltip_Error");
IM_ASSERT(SizeOfItemFlagsStack >= g.ItemFlagsStack.Size && "PushItemFlag/PopItemFlag Mismatch!"); const bool use_locked_pos = (g.IO.KeyCtrl && window && window->WasActive);
IM_ASSERT(SizeOfColorStack >= g.ColorStack.Size && "PushStyleColor/PopStyleColor Mismatch!"); PushStyleColor(ImGuiCol_PopupBg, ImLerp(g.Style.Colors[ImGuiCol_PopupBg], ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.15f));
IM_ASSERT(SizeOfStyleVarStack >= g.StyleVarStack.Size && "PushStyleVar/PopStyleVar Mismatch!"); if (use_locked_pos)
IM_ASSERT(SizeOfFontStack >= g.FontStack.Size && "PushFont/PopFont Mismatch!"); SetNextWindowPos(g.ErrorTooltipLockedPos);
IM_ASSERT(SizeOfFocusScopeStack == g.FocusScopeStack.Size && "PushFocusScope/PopFocusScope Mismatch!"); bool is_visible = Begin("##Tooltip_Error", NULL, ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize);
PopStyleColor();
if (is_visible && g.CurrentWindow->BeginCount == 1)
{
SeparatorText("MESSAGE FROM DEAR IMGUI");
BringWindowToDisplayFront(g.CurrentWindow);
BringWindowToFocusFront(g.CurrentWindow);
g.ErrorTooltipLockedPos = GetWindowPos();
}
else if (!is_visible)
{
End();
}
return is_visible;
}
void ImGui::EndErrorTooltip()
{
End();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -10689,7 +11036,13 @@ void ImGui::PushMultiItemsWidths(int components, float w_full)
void ImGui::PopItemWidth() void ImGui::PopItemWidth()
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if (window->DC.ItemWidthStack.Size <= 0)
{
IM_ASSERT_USER_ERROR(0, "Calling PopItemWidth() too many times!");
return;
}
window->DC.ItemWidth = window->DC.ItemWidthStack.back(); window->DC.ItemWidth = window->DC.ItemWidthStack.back();
window->DC.ItemWidthStack.pop_back(); window->DC.ItemWidthStack.pop_back();
} }
@ -15999,13 +16352,25 @@ static void ShowDebugLogFlag(const char* name, ImGuiDebugLogFlags flags)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImVec2 size(ImGui::GetFrameHeight() + g.Style.ItemInnerSpacing.x + ImGui::CalcTextSize(name).x, ImGui::GetFrameHeight()); ImVec2 size(ImGui::GetFrameHeight() + g.Style.ItemInnerSpacing.x + ImGui::CalcTextSize(name).x, ImGui::GetFrameHeight());
SameLineOrWrap(size); // FIXME-LAYOUT: To be done automatically once we rework ItemSize/ItemAdd into ItemLayout. SameLineOrWrap(size); // FIXME-LAYOUT: To be done automatically once we rework ItemSize/ItemAdd into ItemLayout.
bool highlight_errors = (flags == ImGuiDebugLogFlags_EventError && g.DebugLogSkippedErrors > 0);
if (highlight_errors)
ImGui::PushStyleColor(ImGuiCol_Text, ImLerp(g.Style.Colors[ImGuiCol_Text], ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.30f));
if (ImGui::CheckboxFlags(name, &g.DebugLogFlags, flags) && g.IO.KeyShift && (g.DebugLogFlags & flags) != 0) if (ImGui::CheckboxFlags(name, &g.DebugLogFlags, flags) && g.IO.KeyShift && (g.DebugLogFlags & flags) != 0)
{ {
g.DebugLogAutoDisableFrames = 2; g.DebugLogAutoDisableFrames = 2;
g.DebugLogAutoDisableFlags |= flags; g.DebugLogAutoDisableFlags |= flags;
} }
if (highlight_errors)
{
ImGui::PopStyleColor();
ImGui::SetItemTooltip("%d past errors skipped.", g.DebugLogSkippedErrors);
}
else
{
ImGui::SetItemTooltip("Hold SHIFT when clicking to enable for 2 frames only (useful for spammy log entries)"); ImGui::SetItemTooltip("Hold SHIFT when clicking to enable for 2 frames only (useful for spammy log entries)");
} }
}
void ImGui::ShowDebugLogWindow(bool* p_open) void ImGui::ShowDebugLogWindow(bool* p_open)
{ {
@ -16022,6 +16387,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
CheckboxFlags("All", &g.DebugLogFlags, all_enable_flags); CheckboxFlags("All", &g.DebugLogFlags, all_enable_flags);
SetItemTooltip("(except InputRouting which is spammy)"); SetItemTooltip("(except InputRouting which is spammy)");
ShowDebugLogFlag("Errors", ImGuiDebugLogFlags_EventError);
ShowDebugLogFlag("ActiveId", ImGuiDebugLogFlags_EventActiveId); ShowDebugLogFlag("ActiveId", ImGuiDebugLogFlags_EventActiveId);
ShowDebugLogFlag("Clipper", ImGuiDebugLogFlags_EventClipper); ShowDebugLogFlag("Clipper", ImGuiDebugLogFlags_EventClipper);
ShowDebugLogFlag("Focus", ImGuiDebugLogFlags_EventFocus); ShowDebugLogFlag("Focus", ImGuiDebugLogFlags_EventFocus);
@ -16035,6 +16401,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
{ {
g.DebugLogBuf.clear(); g.DebugLogBuf.clear();
g.DebugLogIndex.clear(); g.DebugLogIndex.clear();
g.DebugLogSkippedErrors = 0;
} }
SameLine(); SameLine();
if (SmallButton("Copy")) if (SmallButton("Copy"))

28
imgui.h
View File

@ -1,4 +1,4 @@
// dear imgui, v1.91.2 WIP // dear imgui, v1.91.3 WIP
// (headers) // (headers)
// Help: // Help:
@ -28,8 +28,8 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.91.2 WIP" #define IMGUI_VERSION "1.91.3 WIP"
#define IMGUI_VERSION_NUM 19115 #define IMGUI_VERSION_NUM 19123
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
/* /*
@ -888,7 +888,7 @@ namespace ImGui
// - Disable all user interactions and dim items visuals (applying style.DisabledAlpha over current colors) // - Disable all user interactions and dim items visuals (applying style.DisabledAlpha over current colors)
// - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled) // - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled)
// - Tooltips windows by exception are opted out of disabling. // - Tooltips windows by exception are opted out of disabling.
// - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. If you can avoid calling BeginDisabled(False)/EndDisabled() best to avoid it. // - BeginDisabled(false)/EndDisabled() essentially does nothing but is provided to facilitate use of boolean expressions (as a micro-optimization: if you have tens of thousands of BeginDisabled(false)/EndDisabled() pairs, you might want to reformulate your code to avoid making those calls)
IMGUI_API void BeginDisabled(bool disabled = true); IMGUI_API void BeginDisabled(bool disabled = true);
IMGUI_API void EndDisabled(); IMGUI_API void EndDisabled();
@ -2250,6 +2250,7 @@ struct ImGuiIO
bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard. bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag) bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar. bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
bool ConfigScrollbarScrollByPage; // = true // Enable scrolling page by page when clicking outside the scrollbar grab. When disabled, always scroll to clicked location. When enabled, Shift+Click scrolls to clicked location.
float ConfigMemoryCompactTimer; // = 60.0f // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable. float ConfigMemoryCompactTimer; // = 60.0f // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable.
// Inputs Behaviors // Inputs Behaviors
@ -2264,6 +2265,23 @@ struct ImGuiIO
// Debug options // Debug options
//------------------------------------------------------------------ //------------------------------------------------------------------
// Options to configure how we handle recoverable errors [EXPERIMENTAL]
// - Error recovery is not perfect nor guaranteed! It is a feature to ease development.
// - Functions that support error recovery are using IM_ASSERT_USER_ERROR() instead of IM_ASSERT().
// - You not are not supposed to rely on it in the course of a normal application run.
// - Possible usage: facilitate recovery from errors triggered from a scripting language or after specific exceptions handlers.
// - Always ensure that on programmers seat you have at minimum Asserts or Tooltips enabled when making direct imgui API calls!
// Otherwise it would severely hinder your ability to catch and correct mistakes!
// Read https://github.com/ocornut/imgui/wiki/Error-Handling for details about typical usage scenarios:
// - Programmer seats: keep asserts (default), or disable asserts and keep error tooltips (new and nice!)
// - Non-programmer seats: maybe disable asserts, but make sure errors are resurfaced (visible log entries, use callback etc.)
// - Recovery after error from scripting language: record stack sizes before running script, disable assert, trigger breakpoint from ErrorCallback, recover with ErrorRecoveryTryToRecoverState(), restore settings.
// - Recovery after an exception handler: record stack sizes before try {} block, disable assert, set log callback, recover with ErrorRecoveryTryToRecoverState(), restore settings.
bool ConfigErrorRecovery; // = true // Enable error recovery support. Some errors won't be detected and lead to direct crashes if recovery is disabled.
bool ConfigErrorRecoveryEnableAssert; // = true // Enable asserts on recoverable error. By default call IM_ASSERT() when returning from a failing IM_ASSERT_USER_ERROR()
bool ConfigErrorRecoveryEnableDebugLog; // = true // Enable debug log output on recoverable errors.
bool ConfigErrorRecoveryEnableTooltip; // = true // Enable tooltip on recoverable errors. The tooltip include a way to enable asserts if they were disabled.
// Option to enable various debug tools showing buttons that will call the IM_DEBUG_BREAK() macro. // Option to enable various debug tools showing buttons that will call the IM_DEBUG_BREAK() macro.
// - The Item Picker tool will be available regardless of this being enabled, in order to maximize its discoverability. // - The Item Picker tool will be available regardless of this being enabled, in order to maximize its discoverability.
// - Requires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application. // - Requires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application.
@ -2292,7 +2310,7 @@ struct ImGuiIO
bool ConfigDebugIniSettings; // = false // Save .ini data with extra comments (particularly helpful for Docking, but makes saving slower) bool ConfigDebugIniSettings; // = false // Save .ini data with extra comments (particularly helpful for Docking, but makes saving slower)
//------------------------------------------------------------------ //------------------------------------------------------------------
// Platform Functions // Platform Identifiers
// (the imgui_impl_xxxx backend files are setting those up for you) // (the imgui_impl_xxxx backend files are setting those up for you)
//------------------------------------------------------------------ //------------------------------------------------------------------

View File

@ -1,4 +1,4 @@
// dear imgui, v1.91.2 WIP // dear imgui, v1.91.3 WIP
// (demo code) // (demo code)
// Help: // Help:
@ -539,10 +539,30 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges); ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback."); ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback.");
ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly); ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
ImGui::Checkbox("io.ConfigScrollbarScrollByPage", &io.ConfigScrollbarScrollByPage);
ImGui::SameLine(); HelpMarker("Enable scrolling page by page when clicking outside the scrollbar grab.\nWhen disabled, always scroll to clicked location.\nWhen enabled, Shift+Click scrolls to clicked location.");
ImGui::Checkbox("io.ConfigMacOSXBehaviors", &io.ConfigMacOSXBehaviors); ImGui::Checkbox("io.ConfigMacOSXBehaviors", &io.ConfigMacOSXBehaviors);
ImGui::SameLine(); HelpMarker("Swap Cmd<>Ctrl keys, enable various MacOS style behaviors."); ImGui::SameLine(); HelpMarker("Swap Cmd<>Ctrl keys, enable various MacOS style behaviors.");
ImGui::Text("Also see Style->Rendering for rendering options."); ImGui::Text("Also see Style->Rendering for rendering options.");
// Also read: https://github.com/ocornut/imgui/wiki/Error-Handling
ImGui::SeparatorText("Error Handling");
ImGui::Checkbox("io.ConfigErrorRecovery", &io.ConfigErrorRecovery);
ImGui::SameLine(); HelpMarker(
"Options to configure how we handle recoverable errors.\n"
"- Error recovery is not perfect nor guaranteed! It is a feature to ease development.\n"
"- You not are not supposed to rely on it in the course of a normal application run.\n"
"- Possible usage: facilitate recovery from errors triggered from a scripting language or after specific exceptions handlers.\n"
"- Always ensure that on programmers seat you have at minimum Asserts or Tooltips enabled when making direct imgui API call!"
"Otherwise it would severely hinder your ability to catch and correct mistakes!");
ImGui::Checkbox("io.ConfigErrorRecoveryEnableAssert", &io.ConfigErrorRecoveryEnableAssert);
ImGui::Checkbox("io.ConfigErrorRecoveryEnableDebugLog", &io.ConfigErrorRecoveryEnableDebugLog);
ImGui::Checkbox("io.ConfigErrorRecoveryEnableTooltip", &io.ConfigErrorRecoveryEnableTooltip);
if (!io.ConfigErrorRecoveryEnableAssert && !io.ConfigErrorRecoveryEnableDebugLog && !io.ConfigErrorRecoveryEnableTooltip)
io.ConfigErrorRecoveryEnableAssert = io.ConfigErrorRecoveryEnableDebugLog = io.ConfigErrorRecoveryEnableTooltip = true;
// Also read: https://github.com/ocornut/imgui/wiki/Debug-Tools
ImGui::SeparatorText("Debug"); ImGui::SeparatorText("Debug");
ImGui::Checkbox("io.ConfigDebugIsDebuggerPresent", &io.ConfigDebugIsDebuggerPresent); ImGui::Checkbox("io.ConfigDebugIsDebuggerPresent", &io.ConfigDebugIsDebuggerPresent);
ImGui::SameLine(); HelpMarker("Enable various tools calling IM_DEBUG_BREAK().\n\nRequires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application."); ImGui::SameLine(); HelpMarker("Enable various tools calling IM_DEBUG_BREAK().\n\nRequires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application.");
@ -577,6 +597,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", &io.BackendFlags, ImGuiBackendFlags_HasSetMousePos); ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", &io.BackendFlags, ImGuiBackendFlags_HasSetMousePos);
ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", &io.BackendFlags, ImGuiBackendFlags_RendererHasVtxOffset); ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", &io.BackendFlags, ImGuiBackendFlags_RendererHasVtxOffset);
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::TreePop(); ImGui::TreePop();
ImGui::Spacing(); ImGui::Spacing();
} }
@ -3929,6 +3950,9 @@ static void ShowDemoWindowLayout()
ImGui::SeparatorText("Manual-resize"); ImGui::SeparatorText("Manual-resize");
{ {
HelpMarker("Drag bottom border to resize. Double-click bottom border to auto-fit to vertical contents."); HelpMarker("Drag bottom border to resize. Double-click bottom border to auto-fit to vertical contents.");
//if (ImGui::Button("Set Height to 200"))
// ImGui::SetNextWindowSize(ImVec2(-FLT_MIN, 200.0f));
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg)); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg));
if (ImGui::BeginChild("ResizableChild", ImVec2(-FLT_MIN, ImGui::GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY)) if (ImGui::BeginChild("ResizableChild", ImVec2(-FLT_MIN, ImGui::GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY))
for (int n = 0; n < 10; n++) for (int n = 0; n < 10; n++)

View File

@ -1,4 +1,4 @@
// dear imgui, v1.91.2 WIP // dear imgui, v1.91.3 WIP
// (drawing and font code) // (drawing and font code)
/* /*

View File

@ -1,4 +1,4 @@
// dear imgui, v1.91.2 WIP // dear imgui, v1.91.3 WIP
// (internal structures/api) // (internal structures/api)
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
@ -28,6 +28,7 @@ Index of this file:
// [SECTION] Viewport support // [SECTION] Viewport support
// [SECTION] Settings support // [SECTION] Settings support
// [SECTION] Localization support // [SECTION] Localization support
// [SECTION] Error handling, State recovery support
// [SECTION] Metrics, Debug tools // [SECTION] Metrics, Debug tools
// [SECTION] Generic context hooks // [SECTION] Generic context hooks
// [SECTION] ImGuiContext (main imgui context) // [SECTION] ImGuiContext (main imgui context)
@ -131,6 +132,7 @@ struct ImGuiContext; // Main Dear ImGui context
struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine
struct ImGuiDataVarInfo; // Variable information (e.g. to access style variables from an enum) struct ImGuiDataVarInfo; // Variable information (e.g. to access style variables from an enum)
struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum
struct ImGuiErrorRecoveryState; // Storage of stack sizes for error handling and recovery
struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup() struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup()
struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box
struct ImGuiInputTextDeactivateData;// Short term storage to backup text of a deactivating InputText() while another is stealing active id struct ImGuiInputTextDeactivateData;// Short term storage to backup text of a deactivating InputText() while another is stealing active id
@ -147,7 +149,6 @@ struct ImGuiOldColumnData; // Storage data for a single column for lega
struct ImGuiOldColumns; // Storage data for a columns set for legacy Columns() api struct ImGuiOldColumns; // Storage data for a columns set for legacy Columns() api
struct ImGuiPopupData; // Storage for current popup stack struct ImGuiPopupData; // Storage for current popup stack
struct ImGuiSettingsHandler; // Storage for one type registered in the .ini file struct ImGuiSettingsHandler; // Storage for one type registered in the .ini file
struct ImGuiStackSizes; // Storage of stack sizes for debugging/asserting
struct ImGuiStyleMod; // Stacked style modifier, backup of modified data so we can restore it struct ImGuiStyleMod; // Stacked style modifier, backup of modified data so we can restore it
struct ImGuiTabBar; // Storage for a tab bar struct ImGuiTabBar; // Storage for a tab bar
struct ImGuiTabItem; // Storage for a tab item (within a tab bar) struct ImGuiTabItem; // Storage for a tab item (within a tab bar)
@ -173,7 +174,7 @@ typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // E
// Flags // Flags
typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later) typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later)
typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags
typedef int ImGuiFocusRequestFlags; // -> enum ImGuiFocusRequestFlags_ // Flags: for FocusWindow(); typedef int ImGuiFocusRequestFlags; // -> enum ImGuiFocusRequestFlags_ // Flags: for FocusWindow()
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for g.LastItemData.StatusFlags typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for g.LastItemData.StatusFlags
typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns() typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns()
typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight() typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight()
@ -187,8 +188,6 @@ typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // F
typedef int ImGuiTypingSelectFlags; // -> enum ImGuiTypingSelectFlags_ // Flags: for GetTypingSelectRequest() typedef int ImGuiTypingSelectFlags; // -> enum ImGuiTypingSelectFlags_ // Flags: for GetTypingSelectRequest()
typedef int ImGuiWindowRefreshFlags; // -> enum ImGuiWindowRefreshFlags_ // Flags: for SetNextWindowRefreshPolicy() typedef int ImGuiWindowRefreshFlags; // -> enum ImGuiWindowRefreshFlags_ // Flags: for SetNextWindowRefreshPolicy()
typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Context pointer // [SECTION] Context pointer
// See implementation of this variable in imgui.cpp for comments and details. // See implementation of this variable in imgui.cpp for comments and details.
@ -218,6 +217,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
#else #else
#define IMGUI_DEBUG_LOG(...) ((void)0) #define IMGUI_DEBUG_LOG(...) ((void)0)
#endif #endif
#define IMGUI_DEBUG_LOG_ERROR(...) do { ImGuiContext& g2 = *GImGui; if (g2.DebugLogFlags & ImGuiDebugLogFlags_EventError) IMGUI_DEBUG_LOG(__VA_ARGS__); else g2.DebugLogSkippedErrors++; } while (0)
#define IMGUI_DEBUG_LOG_ACTIVEID(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventActiveId) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_ACTIVEID(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventActiveId) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_FOCUS(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_FOCUS(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
@ -239,12 +239,6 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
#define IM_ASSERT_PARANOID(_EXPR) #define IM_ASSERT_PARANOID(_EXPR)
#endif #endif
// Error handling
// Down the line in some frameworks/languages we would like to have a way to redirect those to the programmer and recover from more faults.
#ifndef IM_ASSERT_USER_ERROR
#define IM_ASSERT_USER_ERROR(_EXP,_MSG) IM_ASSERT((_EXP) && _MSG) // Recoverable User Error
#endif
// Misc Macros // Misc Macros
#define IM_PI 3.14159265358979323846f #define IM_PI 3.14159265358979323846f
#ifdef _WIN32 #ifdef _WIN32
@ -834,7 +828,7 @@ enum ImGuiDataTypePrivate_
enum ImGuiItemFlagsPrivate_ enum ImGuiItemFlagsPrivate_
{ {
// Controlled by user // Controlled by user
ImGuiItemFlags_Disabled = 1 << 10, // false // Disable interactions (DOES NOT affect visuals, see BeginDisabled()/EndDisabled() for full disable feature, and github #211). ImGuiItemFlags_Disabled = 1 << 10, // false // Disable interactions (DOES NOT affect visuals. DO NOT mix direct use of this with BeginDisabled(). See BeginDisabled()/EndDisabled() for full disable feature, and github #211).
ImGuiItemFlags_ReadOnly = 1 << 11, // false // [ALPHA] Allow hovering interactions but underlying value is not changed. ImGuiItemFlags_ReadOnly = 1 << 11, // false // [ALPHA] Allow hovering interactions but underlying value is not changed.
ImGuiItemFlags_MixedValue = 1 << 12, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets) ImGuiItemFlags_MixedValue = 1 << 12, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
ImGuiItemFlags_NoWindowHoverableCheck = 1 << 13, // false // Disable hoverable check in ItemHoverable() ImGuiItemFlags_NoWindowHoverableCheck = 1 << 13, // false // Disable hoverable check in ItemHoverable()
@ -1259,9 +1253,12 @@ struct ImGuiTreeNodeStackData
ImRect NavRect; // Used for nav landing ImRect NavRect; // Used for nav landing
}; };
struct IMGUI_API ImGuiStackSizes // sizeof() = 20
struct IMGUI_API ImGuiErrorRecoveryState
{ {
short SizeOfWindowStack;
short SizeOfIDStack; short SizeOfIDStack;
short SizeOfTreeStack;
short SizeOfColorStack; short SizeOfColorStack;
short SizeOfStyleVarStack; short SizeOfStyleVarStack;
short SizeOfFontStack; short SizeOfFontStack;
@ -1271,9 +1268,7 @@ struct IMGUI_API ImGuiStackSizes
short SizeOfBeginPopupStack; short SizeOfBeginPopupStack;
short SizeOfDisabledStack; short SizeOfDisabledStack;
ImGuiStackSizes() { memset(this, 0, sizeof(*this)); } ImGuiErrorRecoveryState() { memset(this, 0, sizeof(*this)); }
void SetToContextState(ImGuiContext* ctx);
void CompareWithContextState(ImGuiContext* ctx);
}; };
// Data saved for each window pushed into the stack // Data saved for each window pushed into the stack
@ -1281,7 +1276,7 @@ struct ImGuiWindowStackData
{ {
ImGuiWindow* Window; ImGuiWindow* Window;
ImGuiLastItemData ParentLastItemDataBackup; ImGuiLastItemData ParentLastItemDataBackup;
ImGuiStackSizes StackSizesOnBegin; // Store size of various stacks for asserting ImGuiErrorRecoveryState StackSizesInBegin; // Store size of various stacks for asserting
bool DisabledOverrideReenable; // Non-child window override disabled flag bool DisabledOverrideReenable; // Non-child window override disabled flag
}; };
@ -1885,6 +1880,21 @@ struct ImGuiLocEntry
const char* Text; const char* Text;
}; };
//-----------------------------------------------------------------------------
// [SECTION] Error handling, State recovery support
//-----------------------------------------------------------------------------
// Macros used by Recoverable Error handling
// - Only dispatch error if _EXPR: evaluate as assert (similar to an assert macro).
// - The message will always be a string literal, in order to increase likelihood of being display by an assert handler.
// - See 'Demo->Configuration->Error Handling' and ImGuiIO definitions for details on error handling.
// - Read https://github.com/ocornut/imgui/wiki/Error-Handling for details on error handling.
#ifndef IM_ASSERT_USER_ERROR
#define IM_ASSERT_USER_ERROR(_EXPR,_MSG) do { if (!(_EXPR) && ImGui::ErrorLog(_MSG)) { IM_ASSERT((_EXPR) && _MSG); } } while (0) // Recoverable User Error
#endif
// The error callback is currently not public, as it is expected that only advanced users will rely on it.
typedef void (*ImGuiErrorCallback)(ImGuiContext* ctx, void* user_data, const char* msg); // Function signature for g.ErrorCallback
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Metrics, Debug Tools // [SECTION] Metrics, Debug Tools
@ -1894,16 +1904,19 @@ enum ImGuiDebugLogFlags_
{ {
// Event types // Event types
ImGuiDebugLogFlags_None = 0, ImGuiDebugLogFlags_None = 0,
ImGuiDebugLogFlags_EventActiveId = 1 << 0, ImGuiDebugLogFlags_EventError = 1 << 0, // Error submitted by IM_ASSERT_USER_ERROR()
ImGuiDebugLogFlags_EventFocus = 1 << 1, ImGuiDebugLogFlags_EventActiveId = 1 << 1,
ImGuiDebugLogFlags_EventPopup = 1 << 2, ImGuiDebugLogFlags_EventFocus = 1 << 2,
ImGuiDebugLogFlags_EventNav = 1 << 3, ImGuiDebugLogFlags_EventPopup = 1 << 3,
ImGuiDebugLogFlags_EventClipper = 1 << 4, ImGuiDebugLogFlags_EventNav = 1 << 4,
ImGuiDebugLogFlags_EventSelection = 1 << 5, ImGuiDebugLogFlags_EventClipper = 1 << 5,
ImGuiDebugLogFlags_EventIO = 1 << 6, ImGuiDebugLogFlags_EventSelection = 1 << 6,
ImGuiDebugLogFlags_EventInputRouting = 1 << 7, ImGuiDebugLogFlags_EventIO = 1 << 7,
ImGuiDebugLogFlags_EventInputRouting = 1 << 8,
ImGuiDebugLogFlags_EventDocking = 1 << 9, // Unused in this branch
ImGuiDebugLogFlags_EventViewport = 1 << 10, // Unused in this branch
ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventInputRouting, ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventInputRouting | ImGuiDebugLogFlags_EventDocking | ImGuiDebugLogFlags_EventViewport,
ImGuiDebugLogFlags_OutputToTTY = 1 << 20, // Also send output to TTY ImGuiDebugLogFlags_OutputToTTY = 1 << 20, // Also send output to TTY
ImGuiDebugLogFlags_OutputToTestEngine = 1 << 21, // Also send output to Test Engine ImGuiDebugLogFlags_OutputToTestEngine = 1 << 21, // Also send output to Test Engine
}; };
@ -2258,8 +2271,8 @@ struct ImGuiContext
ImGuiComboPreviewData ComboPreviewData; ImGuiComboPreviewData ComboPreviewData;
ImRect WindowResizeBorderExpectedRect; // Expected border rect, switch to relative edit if moving ImRect WindowResizeBorderExpectedRect; // Expected border rect, switch to relative edit if moving
bool WindowResizeRelativeMode; bool WindowResizeRelativeMode;
short ScrollbarSeekMode; // 0: relative, -1/+1: prev/next page. short ScrollbarSeekMode; // 0: scroll to clicked location, -1/+1: prev/next page.
float ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? float ScrollbarClickDeltaToGrabCenter; // When scrolling to mouse location: distance between mouse and center of grab box, normalized in parent space.
float SliderGrabClickOffset; float SliderGrabClickOffset;
float SliderCurrentAccum; // Accumulated slider delta when using navigation controls. float SliderCurrentAccum; // Accumulated slider delta when using navigation controls.
bool SliderCurrentAccumDirty; // Has the accumulated slider delta changed since last time we tried to apply it? bool SliderCurrentAccumDirty; // Has the accumulated slider delta changed since last time we tried to apply it?
@ -2304,11 +2317,22 @@ struct ImGuiContext
int LogDepthToExpand; int LogDepthToExpand;
int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call. int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call.
// Error Handling
ImGuiErrorCallback ErrorCallback; // = NULL. May be exposed in public API eventually.
void* ErrorCallbackUserData; // = NULL
ImVec2 ErrorTooltipLockedPos;
bool ErrorFirst;
int ErrorCountCurrentFrame; // [Internal] Number of errors submitted this frame.
ImGuiErrorRecoveryState StackSizesInNewFrame; // [Internal]
ImGuiErrorRecoveryState*StackSizesInBeginForCurrentWindow; // [Internal]
// Debug Tools // Debug Tools
// (some of the highly frequently used data are interleaved in other structures above: DebugBreakXXX fields, DebugHookIdInfo, DebugLocateId etc.) // (some of the highly frequently used data are interleaved in other structures above: DebugBreakXXX fields, DebugHookIdInfo, DebugLocateId etc.)
int DebugDrawIdConflictsCount; // Locked count (preserved when holding CTRL)
ImGuiDebugLogFlags DebugLogFlags; ImGuiDebugLogFlags DebugLogFlags;
ImGuiTextBuffer DebugLogBuf; ImGuiTextBuffer DebugLogBuf;
ImGuiTextIndex DebugLogIndex; ImGuiTextIndex DebugLogIndex;
int DebugLogSkippedErrors;
ImGuiDebugLogFlags DebugLogAutoDisableFlags; ImGuiDebugLogFlags DebugLogAutoDisableFlags;
ImU8 DebugLogAutoDisableFrames; ImU8 DebugLogAutoDisableFrames;
ImU8 DebugLocateFrames; // For DebugLocateItemOnHover(). This is used together with DebugLocateId which is in a hot/cached spot above. ImU8 DebugLocateFrames; // For DebugLocateItemOnHover(). This is used together with DebugLocateId which is in a hot/cached spot above.
@ -2335,210 +2359,7 @@ struct ImGuiContext
ImVector<char> TempBuffer; // Temporary text buffer ImVector<char> TempBuffer; // Temporary text buffer
char TempKeychordName[64]; char TempKeychordName[64];
ImGuiContext(ImFontAtlas* shared_font_atlas) ImGuiContext(ImFontAtlas* shared_font_atlas);
{
IO.Ctx = this;
InputTextState.Ctx = this;
Initialized = false;
FontAtlasOwnedByContext = shared_font_atlas ? false : true;
Font = NULL;
FontSize = FontBaseSize = FontScale = CurrentDpiScale = 0.0f;
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
Time = 0.0f;
FrameCount = 0;
FrameCountEnded = FrameCountRendered = -1;
WithinFrameScope = WithinFrameScopeWithImplicitWindow = WithinEndChild = false;
GcCompactAll = false;
TestEngineHookItems = false;
TestEngine = NULL;
memset(ContextName, 0, sizeof(ContextName));
InputEventsNextMouseSource = ImGuiMouseSource_Mouse;
InputEventsNextEventId = 1;
WindowsActiveCount = 0;
CurrentWindow = NULL;
HoveredWindow = NULL;
HoveredWindowUnderMovingWindow = NULL;
HoveredWindowBeforeClear = NULL;
MovingWindow = NULL;
WheelingWindow = NULL;
WheelingWindowStartFrame = WheelingWindowScrolledFrame = -1;
WheelingWindowReleaseTimer = 0.0f;
DebugDrawIdConflicts = 0;
DebugHookIdInfo = 0;
HoveredId = HoveredIdPreviousFrame = 0;
HoveredIdPreviousFrameItemCount = 0;
HoveredIdAllowOverlap = false;
HoveredIdIsDisabled = false;
HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
ItemUnclipByLog = false;
ActiveId = 0;
ActiveIdIsAlive = 0;
ActiveIdTimer = 0.0f;
ActiveIdIsJustActivated = false;
ActiveIdAllowOverlap = false;
ActiveIdNoClearOnFocusLoss = false;
ActiveIdHasBeenPressedBefore = false;
ActiveIdHasBeenEditedBefore = false;
ActiveIdHasBeenEditedThisFrame = false;
ActiveIdFromShortcut = false;
ActiveIdClickOffset = ImVec2(-1, -1);
ActiveIdWindow = NULL;
ActiveIdSource = ImGuiInputSource_None;
ActiveIdMouseButton = -1;
ActiveIdPreviousFrame = 0;
ActiveIdPreviousFrameIsAlive = false;
ActiveIdPreviousFrameHasBeenEditedBefore = false;
ActiveIdPreviousFrameWindow = NULL;
LastActiveId = 0;
LastActiveIdTimer = 0.0f;
LastKeyboardKeyPressTime = LastKeyModsChangeTime = LastKeyModsChangeFromNoneTime = -1.0;
ActiveIdUsingNavDirMask = 0x00;
ActiveIdUsingAllKeyboardKeys = false;
CurrentFocusScopeId = 0;
CurrentItemFlags = ImGuiItemFlags_None;
DebugShowGroupRects = false;
NavWindow = NULL;
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
NavLayer = ImGuiNavLayer_Main;
NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavHighlightActivatedId = 0;
NavHighlightActivatedTimer = 0.0f;
NavInputSource = ImGuiInputSource_Keyboard;
NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
NavIdIsAlive = false;
NavMousePosDirty = false;
NavDisableHighlight = true;
NavDisableMouseHover = false;
NavAnyRequest = false;
NavInitRequest = false;
NavInitRequestFromMove = false;
NavMoveSubmitted = false;
NavMoveScoringItems = false;
NavMoveForwardToNextFrame = false;
NavMoveFlags = ImGuiNavMoveFlags_None;
NavMoveScrollFlags = ImGuiScrollFlags_None;
NavMoveKeyMods = ImGuiMod_None;
NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None;
NavScoringDebugCount = 0;
NavTabbingDir = 0;
NavTabbingCounter = 0;
NavJustMovedFromFocusScopeId = NavJustMovedToId = NavJustMovedToFocusScopeId = 0;
NavJustMovedToKeyMods = ImGuiMod_None;
NavJustMovedToIsTabbing = false;
NavJustMovedToHasSelectionData = false;
// All platforms use Ctrl+Tab but Ctrl<>Super are swapped on Mac...
// FIXME: Because this value is stored, it annoyingly interfere with toggling io.ConfigMacOSXBehaviors updating this..
ConfigNavWindowingKeyNext = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiKey_Tab);
ConfigNavWindowingKeyPrev = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab);
NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
NavWindowingToggleLayer = false;
NavWindowingToggleKey = ImGuiKey_None;
DimBgRatio = 0.0f;
DragDropActive = DragDropWithinSource = DragDropWithinTarget = false;
DragDropSourceFlags = ImGuiDragDropFlags_None;
DragDropSourceFrameCount = -1;
DragDropMouseButton = -1;
DragDropTargetId = 0;
DragDropAcceptFlags = ImGuiDragDropFlags_None;
DragDropAcceptIdCurrRectSurface = 0.0f;
DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0;
DragDropAcceptFrameCount = -1;
DragDropHoldJustPressedId = 0;
memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal));
ClipperTempDataStacked = 0;
CurrentTable = NULL;
TablesTempDataStacked = 0;
CurrentTabBar = NULL;
CurrentMultiSelect = NULL;
MultiSelectTempDataStacked = 0;
HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId = 0;
HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f;
MouseCursor = ImGuiMouseCursor_Arrow;
MouseStationaryTimer = 0.0f;
TempInputId = 0;
memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue));
BeginMenuDepth = BeginComboDepth = 0;
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
ColorEditCurrentID = ColorEditSavedID = 0;
ColorEditSavedHue = ColorEditSavedSat = 0.0f;
ColorEditSavedColor = 0;
WindowResizeRelativeMode = false;
ScrollbarSeekMode = 0;
ScrollbarClickDeltaToGrabCenter = 0.0f;
SliderGrabClickOffset = 0.0f;
SliderCurrentAccum = 0.0f;
SliderCurrentAccumDirty = false;
DragCurrentAccumDirty = false;
DragCurrentAccum = 0.0f;
DragSpeedDefaultRatio = 1.0f / 100.0f;
DisabledAlphaBackup = 0.0f;
DisabledStackSize = 0;
LockMarkEdited = 0;
TooltipOverrideCount = 0;
PlatformImeData.InputPos = ImVec2(0.0f, 0.0f);
PlatformImeDataPrev.InputPos = ImVec2(-1.0f, -1.0f); // Different to ensure initial submission
SettingsLoaded = false;
SettingsDirtyTimer = 0.0f;
HookIdNext = 0;
memset(LocalizationTable, 0, sizeof(LocalizationTable));
LogEnabled = false;
LogType = ImGuiLogType_None;
LogNextPrefix = LogNextSuffix = NULL;
LogFile = NULL;
LogLinePosY = FLT_MAX;
LogLineFirstItem = false;
LogDepthRef = 0;
LogDepthToExpand = LogDepthToExpandDefault = 2;
DebugLogFlags = ImGuiDebugLogFlags_OutputToTTY;
DebugLocateId = 0;
DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
DebugLogAutoDisableFrames = 0;
DebugLocateFrames = 0;
DebugBeginReturnValueCullDepth = -1;
DebugItemPickerActive = false;
DebugItemPickerMouseButton = ImGuiMouseButton_Left;
DebugItemPickerBreakId = 0;
DebugFlashStyleColorTime = 0.0f;
DebugFlashStyleColorIdx = ImGuiCol_COUNT;
// Same as DebugBreakClearData(). Those fields are scattered in their respective subsystem to stay in hot-data locations
DebugBreakInWindow = 0;
DebugBreakInTable = 0;
DebugBreakInLocateId = false;
DebugBreakKeyChord = ImGuiKey_Pause;
DebugBreakInShortcutRouting = ImGuiKey_None;
memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0;
FramerateSecPerFrameAccum = 0.0f;
WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;
memset(TempKeychordName, 0, sizeof(TempKeychordName));
}
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -2761,9 +2582,10 @@ struct ImGuiTabItem
ImGuiTabItem() { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; RequestedWidth = -1.0f; NameOffset = -1; BeginOrder = IndexDuringLayout = -1; } ImGuiTabItem() { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; RequestedWidth = -1.0f; NameOffset = -1; BeginOrder = IndexDuringLayout = -1; }
}; };
// Storage for a tab bar (sizeof() 152 bytes) // Storage for a tab bar (sizeof() 160 bytes)
struct IMGUI_API ImGuiTabBar struct IMGUI_API ImGuiTabBar
{ {
ImGuiWindow* Window;
ImVector<ImGuiTabItem> Tabs; ImVector<ImGuiTabItem> Tabs;
ImGuiTabBarFlags Flags; ImGuiTabBarFlags Flags;
ImGuiID ID; // Zero for tab-bars used by docking ImGuiID ID; // Zero for tab-bars used by docking
@ -3606,11 +3428,18 @@ namespace ImGui
IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window); IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window);
IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window); IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window);
// Error handling, State Recovery
IMGUI_API bool ErrorLog(const char* msg);
IMGUI_API void ErrorRecoveryStoreState(ImGuiErrorRecoveryState* state_out);
IMGUI_API void ErrorRecoveryTryToRecoverState(const ImGuiErrorRecoveryState* state_in);
IMGUI_API void ErrorRecoveryTryToRecoverWindowState(const ImGuiErrorRecoveryState* state_in);
IMGUI_API void ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
IMGUI_API void ErrorCheckEndFrameFinalizeErrorTooltip();
IMGUI_API bool BeginErrorTooltip();
IMGUI_API void EndErrorTooltip();
// Debug Tools // Debug Tools
IMGUI_API void DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free IMGUI_API void DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free
IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
IMGUI_API void ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
IMGUI_API void ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
IMGUI_API void DebugDrawCursorPos(ImU32 col = IM_COL32(255, 0, 0, 255)); IMGUI_API void DebugDrawCursorPos(ImU32 col = IM_COL32(255, 0, 0, 255));
IMGUI_API void DebugDrawLineExtents(ImU32 col = IM_COL32(255, 0, 0, 255)); IMGUI_API void DebugDrawLineExtents(ImU32 col = IM_COL32(255, 0, 0, 255));
IMGUI_API void DebugDrawItemRect(ImU32 col = IM_COL32(255, 0, 0, 255)); IMGUI_API void DebugDrawItemRect(ImU32 col = IM_COL32(255, 0, 0, 255));
@ -3698,7 +3527,7 @@ extern const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext* ctx, ImGuiI
// In IMGUI_VERSION_NUM >= 18934: changed IMGUI_TEST_ENGINE_ITEM_ADD(bb,id) to IMGUI_TEST_ENGINE_ITEM_ADD(id,bb,item_data); // In IMGUI_VERSION_NUM >= 18934: changed IMGUI_TEST_ENGINE_ITEM_ADD(bb,id) to IMGUI_TEST_ENGINE_ITEM_ADD(id,bb,item_data);
#define IMGUI_TEST_ENGINE_ITEM_ADD(_ID,_BB,_ITEM_DATA) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _ID, _BB, _ITEM_DATA) // Register item bounding box #define IMGUI_TEST_ENGINE_ITEM_ADD(_ID,_BB,_ITEM_DATA) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _ID, _BB, _ITEM_DATA) // Register item bounding box
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional) #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional)
#define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log #define IMGUI_TEST_ENGINE_LOG(_FMT,...) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log
#else #else
#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) ((void)0) #define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) ((void)0)
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)g) #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)g)

View File

@ -1,4 +1,4 @@
// dear imgui, v1.91.2 WIP // dear imgui, v1.91.3 WIP
// (tables and columns code) // (tables and columns code)
/* /*
@ -1484,7 +1484,9 @@ void ImGui::EndTable()
{ {
short backup_nav_layers_active_mask = inner_window->DC.NavLayersActiveMask; short backup_nav_layers_active_mask = inner_window->DC.NavLayersActiveMask;
inner_window->DC.NavLayersActiveMask |= 1 << ImGuiNavLayer_Main; // So empty table don't appear to navigate differently. inner_window->DC.NavLayersActiveMask |= 1 << ImGuiNavLayer_Main; // So empty table don't appear to navigate differently.
g.CurrentTable = NULL; // To avoid error recovery recursing
EndChild(); EndChild();
g.CurrentTable = table;
inner_window->DC.NavLayersActiveMask = backup_nav_layers_active_mask; inner_window->DC.NavLayersActiveMask = backup_nav_layers_active_mask;
} }
else else

View File

@ -1,4 +1,4 @@
// dear imgui, v1.91.2 WIP // dear imgui, v1.91.3 WIP
// (widgets code) // (widgets code)
/* /*
@ -999,9 +999,10 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
const int held_dir = (clicked_v_norm < grab_v_norm) ? -1 : (clicked_v_norm > grab_v_norm + grab_h_norm) ? +1 : 0; const int held_dir = (clicked_v_norm < grab_v_norm) ? -1 : (clicked_v_norm > grab_v_norm + grab_h_norm) ? +1 : 0;
if (g.ActiveIdIsJustActivated) if (g.ActiveIdIsJustActivated)
{ {
// On initial click calculate the distance between mouse and the center of the grab // On initial click when held_dir == 0 (clicked over grab): calculate the distance between mouse and the center of the grab
g.ScrollbarSeekMode = (short)held_dir; const bool scroll_to_clicked_location = (g.IO.ConfigScrollbarScrollByPage == false || g.IO.KeyShift || held_dir == 0);
g.ScrollbarClickDeltaToGrabCenter = (g.ScrollbarSeekMode == 0.0f) ? clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f : 0.0f; g.ScrollbarSeekMode = scroll_to_clicked_location ? 0 : (short)held_dir;
g.ScrollbarClickDeltaToGrabCenter = (held_dir == 0 && !g.IO.KeyShift) ? clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f : 0.0f;
} }
// Apply scroll (p_scroll_v will generally point on one member of window->Scroll) // Apply scroll (p_scroll_v will generally point on one member of window->Scroll)
@ -7390,6 +7391,7 @@ void ImGui::EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flag
static void DebugLogMultiSelectRequests(const char* function, const ImGuiMultiSelectIO* io) static void DebugLogMultiSelectRequests(const char* function, const ImGuiMultiSelectIO* io)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_UNUSED(function);
for (const ImGuiSelectionRequest& req : io->Requests) for (const ImGuiSelectionRequest& req : io->Requests)
{ {
if (req.Type == ImGuiSelectionRequestType_SetAll) IMGUI_DEBUG_LOG_SELECTION("[selection] %s: Request: SetAll %d (= %s)\n", function, req.Selected, req.Selected ? "SelectAll" : "Clear"); if (req.Type == ImGuiSelectionRequestType_SetAll) IMGUI_DEBUG_LOG_SELECTION("[selection] %s: Request: SetAll %d (= %s)\n", function, req.Selected, req.Selected ? "SelectAll" : "Clear");
@ -7549,7 +7551,7 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect()
ImGuiMultiSelectTempData* ms = g.CurrentMultiSelect; ImGuiMultiSelectTempData* ms = g.CurrentMultiSelect;
ImGuiMultiSelectState* storage = ms->Storage; ImGuiMultiSelectState* storage = ms->Storage;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
IM_ASSERT(ms->FocusScopeId == g.CurrentFocusScopeId); IM_ASSERT_USER_ERROR(ms->FocusScopeId == g.CurrentFocusScopeId, "EndMultiSelect() FocusScope mismatch!");
IM_ASSERT(g.CurrentMultiSelect != NULL && storage->Window == g.CurrentWindow); IM_ASSERT(g.CurrentMultiSelect != NULL && storage->Window == g.CurrentWindow);
IM_ASSERT(g.MultiSelectTempDataStacked > 0 && &g.MultiSelectTempData[g.MultiSelectTempDataStacked - 1] == g.CurrentMultiSelect); IM_ASSERT(g.MultiSelectTempDataStacked > 0 && &g.MultiSelectTempData[g.MultiSelectTempDataStacked - 1] == g.CurrentMultiSelect);
@ -8156,6 +8158,13 @@ void ImGuiSelectionExternalStorage::ApplyRequests(ImGuiMultiSelectIO* ms_io)
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label. // This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label.
// This handle some subtleties with capturing info from the label, but for 99% uses it could essentially be rewritten as:
// if (ImGui::BeginChild("...", ImVec2(ImGui::CalcItemWidth(), ImGui::GetTextLineHeight() * 7.5f), ImGuiChildFlags_FrameStyle))
// { .... }
// ImGui::EndChild();
// ImGui::SameLine();
// ImGui::AlignTextToFramePadding();
// ImGui::Text("Label");
// Tip: To have a list filling the entire window width, use size.x = -FLT_MIN and pass an non-visible label e.g. "##empty" // Tip: To have a list filling the entire window width, use size.x = -FLT_MIN and pass an non-visible label e.g. "##empty"
// Tip: If your vertical size is calculated from an item count (e.g. 10 * item_height) consider adding a fractional part to facilitate seeing scrolling boundaries (e.g. 10.25 * item_height). // Tip: If your vertical size is calculated from an item count (e.g. 10 * item_height) consider adding a fractional part to facilitate seeing scrolling boundaries (e.g. 10.25 * item_height).
bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg) bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg)
@ -9145,6 +9154,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
// Add to stack // Add to stack
g.CurrentTabBarStack.push_back(GetTabBarRefFromTabBar(tab_bar)); g.CurrentTabBarStack.push_back(GetTabBarRefFromTabBar(tab_bar));
g.CurrentTabBar = tab_bar; g.CurrentTabBar = tab_bar;
tab_bar->Window = window;
// Append with multiple BeginTabBar()/EndTabBar() pairs. // Append with multiple BeginTabBar()/EndTabBar() pairs.
tab_bar->BackupCursorPos = window->DC.CursorPos; tab_bar->BackupCursorPos = window->DC.CursorPos;