Updated ImGui.

This commit is contained in:
Бранимир Караџић 2024-06-15 10:28:55 -07:00
parent 8432a0a76d
commit 739b1156e7
7 changed files with 426 additions and 301 deletions

View File

@ -1,4 +1,4 @@
// dear imgui, v1.90.7 // dear imgui, v1.90.9 WIP
// (main code and documentation) // (main code and documentation)
// Help: // Help:
@ -430,6 +430,9 @@ CODE
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
You can read releases logs https://github.com/ocornut/imgui/releases for more details. You can read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2024/06/10 (1.90.9) - removed old nested structure: renaming ImGuiStorage::ImGuiStoragePair type to ImGuiStoragePair (simpler for many languages).
- 2024/06/06 (1.90.8) - reordered ImGuiInputTextFlags values. This should not be breaking unless you are using generated headers that have values not matching the main library.
- 2024/06/06 (1.90.8) - removed 'ImGuiButtonFlags_MouseButtonDefault_ = ImGuiButtonFlags_MouseButtonLeft', was mostly unused and misleading.
- 2024/05/27 (1.90.7) - commented out obsolete symbols marked obsolete in 1.88 (May 2022): - 2024/05/27 (1.90.7) - commented out obsolete symbols marked obsolete in 1.88 (May 2022):
- old: CaptureKeyboardFromApp(bool) - old: CaptureKeyboardFromApp(bool)
- new: SetNextFrameWantCaptureKeyboard(bool) - new: SetNextFrameWantCaptureKeyboard(bool)
@ -2502,18 +2505,16 @@ void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float&
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// std::lower_bound but without the bullshit // std::lower_bound but without the bullshit
static ImGuiStorage::ImGuiStoragePair* LowerBound(ImVector<ImGuiStorage::ImGuiStoragePair>& data, ImGuiID key) ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStoragePair* in_end, ImGuiID key)
{ {
ImGuiStorage::ImGuiStoragePair* first = data.Data; ImGuiStoragePair* in_p = in_begin;
ImGuiStorage::ImGuiStoragePair* last = data.Data + data.Size; for (size_t count = (size_t)(in_end - in_p); count > 0; )
size_t count = (size_t)(last - first);
while (count > 0)
{ {
size_t count2 = count >> 1; size_t count2 = count >> 1;
ImGuiStorage::ImGuiStoragePair* mid = first + count2; ImGuiStoragePair* mid = in_p + count2;
if (mid->key < key) if (mid->key < key)
{ {
first = ++mid; in_p = ++mid;
count -= count2 + 1; count -= count2 + 1;
} }
else else
@ -2521,7 +2522,7 @@ static ImGuiStorage::ImGuiStoragePair* LowerBound(ImVector<ImGuiStorage::ImGuiSt
count = count2; count = count2;
} }
} }
return first; return in_p;
} }
// For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once. // For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once.
@ -2542,7 +2543,7 @@ void ImGuiStorage::BuildSortByKey()
int ImGuiStorage::GetInt(ImGuiID key, int default_val) const int ImGuiStorage::GetInt(ImGuiID key, int default_val) const
{ {
ImGuiStoragePair* it = LowerBound(const_cast<ImVector<ImGuiStoragePair>&>(Data), key); ImGuiStoragePair* it = ImLowerBound(const_cast<ImGuiStoragePair*>(Data.Data), const_cast<ImGuiStoragePair*>(Data.Data + Data.Size), key);
if (it == Data.end() || it->key != key) if (it == Data.end() || it->key != key)
return default_val; return default_val;
return it->val_i; return it->val_i;
@ -2555,7 +2556,7 @@ bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const
float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const
{ {
ImGuiStoragePair* it = LowerBound(const_cast<ImVector<ImGuiStoragePair>&>(Data), key); ImGuiStoragePair* it = ImLowerBound(const_cast<ImGuiStoragePair*>(Data.Data), const_cast<ImGuiStoragePair*>(Data.Data + Data.Size), key);
if (it == Data.end() || it->key != key) if (it == Data.end() || it->key != key)
return default_val; return default_val;
return it->val_f; return it->val_f;
@ -2563,7 +2564,7 @@ float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const
void* ImGuiStorage::GetVoidPtr(ImGuiID key) const void* ImGuiStorage::GetVoidPtr(ImGuiID key) const
{ {
ImGuiStoragePair* it = LowerBound(const_cast<ImVector<ImGuiStoragePair>&>(Data), key); ImGuiStoragePair* it = ImLowerBound(const_cast<ImGuiStoragePair*>(Data.Data), const_cast<ImGuiStoragePair*>(Data.Data + Data.Size), key);
if (it == Data.end() || it->key != key) if (it == Data.end() || it->key != key)
return NULL; return NULL;
return it->val_p; return it->val_p;
@ -2572,7 +2573,7 @@ void* ImGuiStorage::GetVoidPtr(ImGuiID key) const
// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer. // References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.
int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val) int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val)
{ {
ImGuiStoragePair* it = LowerBound(Data, key); ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
if (it == Data.end() || it->key != key) if (it == Data.end() || it->key != key)
it = Data.insert(it, ImGuiStoragePair(key, default_val)); it = Data.insert(it, ImGuiStoragePair(key, default_val));
return &it->val_i; return &it->val_i;
@ -2585,7 +2586,7 @@ bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val)
float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val) float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
{ {
ImGuiStoragePair* it = LowerBound(Data, key); ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
if (it == Data.end() || it->key != key) if (it == Data.end() || it->key != key)
it = Data.insert(it, ImGuiStoragePair(key, default_val)); it = Data.insert(it, ImGuiStoragePair(key, default_val));
return &it->val_f; return &it->val_f;
@ -2593,7 +2594,7 @@ float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val) void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)
{ {
ImGuiStoragePair* it = LowerBound(Data, key); ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
if (it == Data.end() || it->key != key) if (it == Data.end() || it->key != key)
it = Data.insert(it, ImGuiStoragePair(key, default_val)); it = Data.insert(it, ImGuiStoragePair(key, default_val));
return &it->val_p; return &it->val_p;
@ -2602,7 +2603,7 @@ void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)
// FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame) // FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame)
void ImGuiStorage::SetInt(ImGuiID key, int val) void ImGuiStorage::SetInt(ImGuiID key, int val)
{ {
ImGuiStoragePair* it = LowerBound(Data, key); ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
if (it == Data.end() || it->key != key) if (it == Data.end() || it->key != key)
Data.insert(it, ImGuiStoragePair(key, val)); Data.insert(it, ImGuiStoragePair(key, val));
else else
@ -2616,7 +2617,7 @@ void ImGuiStorage::SetBool(ImGuiID key, bool val)
void ImGuiStorage::SetFloat(ImGuiID key, float val) void ImGuiStorage::SetFloat(ImGuiID key, float val)
{ {
ImGuiStoragePair* it = LowerBound(Data, key); ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
if (it == Data.end() || it->key != key) if (it == Data.end() || it->key != key)
Data.insert(it, ImGuiStoragePair(key, val)); Data.insert(it, ImGuiStoragePair(key, val));
else else
@ -2625,7 +2626,7 @@ void ImGuiStorage::SetFloat(ImGuiID key, float val)
void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val) void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val)
{ {
ImGuiStoragePair* it = LowerBound(Data, key); ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
if (it == Data.end() || it->key != key) if (it == Data.end() || it->key != key)
Data.insert(it, ImGuiStoragePair(key, val)); Data.insert(it, ImGuiStoragePair(key, val));
else else
@ -4172,7 +4173,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
// Done with rectangle culling so we can perform heavier checks now. // Done with rectangle culling so we can perform heavier checks now.
if (!(item_flags & ImGuiItemFlags_NoWindowHoverableCheck) && !IsWindowContentHoverable(window, ImGuiHoveredFlags_None)) if (!(item_flags & ImGuiItemFlags_NoWindowHoverableCheck) && !IsWindowContentHoverable(window, ImGuiHoveredFlags_None))
{ {
g.HoveredIdDisabled = true; g.HoveredIdIsDisabled = true;
return false; return false;
} }
@ -4207,7 +4208,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
// Release active id if turning disabled // Release active id if turning disabled
if (g.ActiveId == id && id != 0) if (g.ActiveId == id && id != 0)
ClearActiveID(); ClearActiveID();
g.HoveredIdDisabled = true; g.HoveredIdIsDisabled = true;
return false; return false;
} }
@ -4239,7 +4240,7 @@ bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id)
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
if (!bb.Overlaps(window->ClipRect)) if (!bb.Overlaps(window->ClipRect))
if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId)) if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId))
if (!g.LogEnabled) if (!g.ItemUnclipByLog)
return true; return true;
return false; return false;
} }
@ -4510,7 +4511,7 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
g.MovingWindow = NULL; g.MovingWindow = NULL;
// Cancel moving if clicked over an item which was disabled or inhibited by popups (note that we know HoveredId == 0 already) // Cancel moving if clicked over an item which was disabled or inhibited by popups (note that we know HoveredId == 0 already)
if (g.HoveredIdDisabled) if (g.HoveredIdIsDisabled)
g.MovingWindow = NULL; g.MovingWindow = NULL;
} }
else if (root_window == NULL && g.NavWindow != NULL) else if (root_window == NULL && g.NavWindow != NULL)
@ -4704,7 +4705,7 @@ void ImGui::NewFrame()
g.HoveredIdPreviousFrame = g.HoveredId; g.HoveredIdPreviousFrame = g.HoveredId;
g.HoveredId = 0; g.HoveredId = 0;
g.HoveredIdAllowOverlap = false; g.HoveredIdAllowOverlap = false;
g.HoveredIdDisabled = false; g.HoveredIdIsDisabled = false;
// Clear ActiveID if the item is not alive anymore. // Clear ActiveID if the item is not alive anymore.
// In 1.87, the common most call to KeepAliveID() was moved from GetID() to ItemAdd(). // In 1.87, the common most call to KeepAliveID() was moved from GetID() to ItemAdd().
@ -5779,7 +5780,7 @@ static inline ImVec2 CalcWindowMinSize(ImGuiWindow* window)
// Reduce artifacts with very small windows // Reduce artifacts with very small windows
ImGuiWindow* window_for_height = window; ImGuiWindow* window_for_height = window;
size_min.y = ImMax(size_min.y, window_for_height->TitleBarHeight() + window_for_height->MenuBarHeight() + ImMax(0.0f, g.Style.WindowRounding - 1.0f)); size_min.y = ImMax(size_min.y, window_for_height->TitleBarHeight + window_for_height->MenuBarHeight + ImMax(0.0f, g.Style.WindowRounding - 1.0f));
return size_min; return size_min;
} }
@ -5990,7 +5991,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
ImRect clamp_rect = visibility_rect; ImRect clamp_rect = visibility_rect;
const bool window_move_from_title_bar = g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar); const bool window_move_from_title_bar = g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar);
if (window_move_from_title_bar) if (window_move_from_title_bar)
clamp_rect.Min.y -= window->TitleBarHeight(); clamp_rect.Min.y -= window->TitleBarHeight;
ImVec2 pos_target(FLT_MAX, FLT_MAX); ImVec2 pos_target(FLT_MAX, FLT_MAX);
ImVec2 size_target(FLT_MAX, FLT_MAX); ImVec2 size_target(FLT_MAX, FLT_MAX);
@ -6189,7 +6190,7 @@ static inline void ClampWindowPos(ImGuiWindow* window, const ImRect& visibility_
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImVec2 size_for_clamping = window->Size; ImVec2 size_for_clamping = window->Size;
if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
size_for_clamping.y = window->TitleBarHeight(); size_for_clamping.y = window->TitleBarHeight;
window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max); window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max);
} }
@ -6225,7 +6226,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
} }
if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
{ {
float y = window->Pos.y + window->TitleBarHeight() - 1; float y = window->Pos.y + window->TitleBarHeight - 1;
window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), border_col, g.Style.FrameBorderSize); window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), border_col, g.Style.FrameBorderSize);
} }
} }
@ -6270,7 +6271,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
} }
if (override_alpha) if (override_alpha)
bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT); bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT);
window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom); window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
} }
// Title bar // Title bar
@ -6564,6 +6565,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
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.StackSizesOnBegin.SetToContextState(&g);
window_stack_data.DisabledOverrideReenable = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
g.CurrentWindowStack.push_back(window_stack_data); g.CurrentWindowStack.push_back(window_stack_data);
if (flags & ImGuiWindowFlags_ChildMenu) if (flags & ImGuiWindowFlags_ChildMenu)
g.BeginMenuDepth++; g.BeginMenuDepth++;
@ -6650,6 +6652,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// [EXPERIMENTAL] Skip Refresh mode // [EXPERIMENTAL] Skip Refresh mode
UpdateWindowSkipRefresh(window); UpdateWindowSkipRefresh(window);
// Nested root windows (typically tooltips) override disabled state
if (window_stack_data.DisabledOverrideReenable && window->RootWindow == window)
BeginDisabledOverrideReenable();
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow() // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
g.CurrentWindow = NULL; g.CurrentWindow = NULL;
@ -6732,6 +6738,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Lock menu offset so size calculation can use it as menu-bar windows need a minimum size. // Lock menu offset so size calculation can use it as menu-bar windows need a minimum size.
window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x); window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x);
window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y; window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y;
window->TitleBarHeight = (flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : g.FontSize + g.Style.FramePadding.y * 2.0f;
window->MenuBarHeight = (flags & ImGuiWindowFlags_MenuBar) ? window->DC.MenuBarOffset.y + g.FontSize + g.Style.FramePadding.y * 2.0f : 0.0f;
// Depending on condition we use previous or current window size to compare against contents size to decide if a scrollbar should be visible. // Depending on condition we use previous or current window size to compare against contents size to decide if a scrollbar should be visible.
// Those flags will be altered further down in the function depending on more conditions. // Those flags will be altered further down in the function depending on more conditions.
@ -6772,7 +6780,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
const ImVec2 scrollbar_sizes_from_last_frame = window->ScrollbarSizes; const ImVec2 scrollbar_sizes_from_last_frame = window->ScrollbarSizes;
window->DecoOuterSizeX1 = 0.0f; window->DecoOuterSizeX1 = 0.0f;
window->DecoOuterSizeX2 = 0.0f; window->DecoOuterSizeX2 = 0.0f;
window->DecoOuterSizeY1 = window->TitleBarHeight() + window->MenuBarHeight(); window->DecoOuterSizeY1 = window->TitleBarHeight + window->MenuBarHeight;
window->DecoOuterSizeY2 = 0.0f; window->DecoOuterSizeY2 = 0.0f;
window->ScrollbarSizes = ImVec2(0.0f, 0.0f); window->ScrollbarSizes = ImVec2(0.0f, 0.0f);
@ -6921,7 +6929,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar)); window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
if (window->ScrollbarX && !window->ScrollbarY) if (window->ScrollbarX && !window->ScrollbarY)
window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar); window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
// Amend the partially filled window->DecorationXXX values. // Amend the partially filled window->DecorationXXX values.
@ -7247,7 +7255,7 @@ void ImGui::End()
IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size > 1, "Calling End() too many times!"); IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size > 1, "Calling End() too many times!");
return; return;
} }
IM_ASSERT(g.CurrentWindowStack.Size > 0); ImGuiWindowStackData& window_stack_data = g.CurrentWindowStack.back();
// Error checking: verify that user doesn't directly call End() on a child window. // Error checking: verify that user doesn't directly call End() on a child window.
if (window->Flags & ImGuiWindowFlags_ChildWindow) if (window->Flags & ImGuiWindowFlags_ChildWindow)
@ -7259,6 +7267,8 @@ void ImGui::End()
if (!window->SkipRefresh) if (!window->SkipRefresh)
PopClipRect(); // Inner window clip rectangle PopClipRect(); // Inner window clip rectangle
PopFocusScope(); PopFocusScope();
if (window_stack_data.DisabledOverrideReenable && window->RootWindow == window)
EndDisabledOverrideReenable();
if (window->SkipRefresh) if (window->SkipRefresh)
{ {
@ -7274,12 +7284,12 @@ void ImGui::End()
ErrorCheckUsingSetCursorPosToExtendParentBoundaries(); ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
// Pop from window stack // Pop from window stack
g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup; g.LastItemData = window_stack_data.ParentLastItemDataBackup;
if (window->Flags & ImGuiWindowFlags_ChildMenu) if (window->Flags & ImGuiWindowFlags_ChildMenu)
g.BeginMenuDepth--; g.BeginMenuDepth--;
if (window->Flags & ImGuiWindowFlags_Popup) if (window->Flags & ImGuiWindowFlags_Popup)
g.BeginPopupStack.pop_back(); g.BeginPopupStack.pop_back();
g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithContextState(&g); window_stack_data.StackSizesOnBegin.CompareWithContextState(&g);
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);
} }
@ -7371,9 +7381,13 @@ void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags)
if ((flags & ImGuiFocusRequestFlags_UnlessBelowModal) && (g.NavWindow != window)) // Early out in common case. if ((flags & ImGuiFocusRequestFlags_UnlessBelowModal) && (g.NavWindow != window)) // Early out in common case.
if (ImGuiWindow* blocking_modal = FindBlockingModal(window)) if (ImGuiWindow* blocking_modal = FindBlockingModal(window))
{ {
// This block would typically be reached in two situations:
// - API call to FocusWindow() with a window under a modal and ImGuiFocusRequestFlags_UnlessBelowModal flag.
// - User clicking on void or anything behind a modal while a modal is open (window == NULL)
IMGUI_DEBUG_LOG_FOCUS("[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n", window ? window->Name : "<NULL>", blocking_modal->Name); IMGUI_DEBUG_LOG_FOCUS("[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n", window ? window->Name : "<NULL>", blocking_modal->Name);
if (window && window == window->RootWindow && (window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0) if (window && window == window->RootWindow && (window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
BringWindowToDisplayBehind(window, blocking_modal); // Still bring to right below modal. BringWindowToDisplayBehind(window, blocking_modal); // Still bring right under modal. (FIXME: Could move in focus list too?)
ClosePopupsOverWindow(GetTopMostPopupModal(), false); // Note how we need to use GetTopMostPopupModal() aad NOT blocking_modal, to handle nested modals
return; return;
} }
@ -7523,7 +7537,7 @@ void ImGui::BeginDisabled(bool disabled)
} }
if (was_disabled || disabled) if (was_disabled || disabled)
g.CurrentItemFlags |= ImGuiItemFlags_Disabled; g.CurrentItemFlags |= ImGuiItemFlags_Disabled;
g.ItemFlagsStack.push_back(g.CurrentItemFlags); g.ItemFlagsStack.push_back(g.CurrentItemFlags); // FIXME-OPT: can we simply skip this and use DisabledStackSize?
g.DisabledStackSize++; g.DisabledStackSize++;
} }
@ -7540,6 +7554,29 @@ void ImGui::EndDisabled()
g.Style.Alpha = g.DisabledAlphaBackup; //PopStyleVar(); g.Style.Alpha = g.DisabledAlphaBackup; //PopStyleVar();
} }
// Could have been called BeginDisabledDisable() but it didn't want to be award nominated for most awkward function name.
// Ideally we would use a shared e.g. BeginDisabled()->BeginDisabledEx() but earlier needs to be optimal.
// The whole code for this is awkward, will reevaluate if we find a way to implement SetNextItemDisabled().
void ImGui::BeginDisabledOverrideReenable()
{
ImGuiContext& g = *GImGui;
IM_ASSERT(g.CurrentItemFlags & ImGuiItemFlags_Disabled);
g.Style.Alpha = g.DisabledAlphaBackup;
g.CurrentItemFlags &= ~ImGuiItemFlags_Disabled;
g.ItemFlagsStack.push_back(g.CurrentItemFlags);
g.DisabledStackSize++;
}
void ImGui::EndDisabledOverrideReenable()
{
ImGuiContext& g = *GImGui;
g.DisabledStackSize--;
IM_ASSERT(g.DisabledStackSize > 0);
g.ItemFlagsStack.pop_back();
g.CurrentItemFlags = g.ItemFlagsStack.back();
g.Style.Alpha = g.DisabledAlphaBackup * g.Style.DisabledAlpha;
}
void ImGui::PushTabStop(bool tab_stop) void ImGui::PushTabStop(bool tab_stop)
{ {
PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop);
@ -8870,7 +8907,7 @@ bool ImGui::IsMouseDown(ImGuiMouseButton button, ImGuiID owner_id)
bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat) bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat)
{ {
return IsMouseClicked(button, ImGuiKeyOwner_Any, repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None); return IsMouseClicked(button, repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None, ImGuiKeyOwner_Any);
} }
bool ImGui::IsMouseClicked(ImGuiMouseButton button, ImGuiInputFlags flags, ImGuiID owner_id) bool ImGui::IsMouseClicked(ImGuiMouseButton button, ImGuiInputFlags flags, ImGuiID owner_id)
@ -9695,7 +9732,7 @@ void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
// This is the only public API until we expose owner_id versions of the API as replacements. // This is the only public API until we expose owner_id versions of the API as replacements.
bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord) bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord)
{ {
return IsKeyChordPressed(key_chord, 0, ImGuiInputFlags_None); return IsKeyChordPressed(key_chord, ImGuiInputFlags_None, ImGuiKeyOwner_Any);
} }
// This is equivalent to comparing KeyMods + doing a IsKeyPressed() // This is equivalent to comparing KeyMods + doing a IsKeyPressed()
@ -9884,10 +9921,6 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && g.IO.BackendUsingLegacyKeyArrays == 1) if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && g.IO.BackendUsingLegacyKeyArrays == 1)
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
// Check: the io.ConfigWindowsResizeFromEdges option requires backend to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly.
if (g.IO.ConfigWindowsResizeFromEdges && !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors))
g.IO.ConfigWindowsResizeFromEdges = false;
} }
static void ImGui::ErrorCheckEndFrameSanityChecks() static void ImGui::ErrorCheckEndFrameSanityChecks()
@ -9995,7 +10028,13 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo
while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044 while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044
{ {
if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'", window->Name); if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'", window->Name);
EndDisabled(); if (g.CurrentItemFlags & ImGuiItemFlags_Disabled)
EndDisabled();
else
{
EndDisabledOverrideReenable();
g.CurrentWindowStack.back().DisabledOverrideReenable = false;
}
} }
while (g.ColorStack.Size > stack_sizes->SizeOfColorStack) while (g.ColorStack.Size > stack_sizes->SizeOfColorStack)
{ {
@ -10084,6 +10123,7 @@ void ImGui::KeepAliveID(ImGuiID id)
// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface // Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface
// declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction. // declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction.
// THIS IS IN THE PERFORMANCE CRITICAL PATH (UNTIL THE CLIPPING TEST AND EARLY-RETURN) // THIS IS IN THE PERFORMANCE CRITICAL PATH (UNTIL THE CLIPPING TEST AND EARLY-RETURN)
IM_MSVC_RUNTIME_CHECKS_OFF
bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags) bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -10136,15 +10176,12 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
#endif #endif
// Clipping test // Clipping test
// (this is a modified copy of IsClippedEx() so we can reuse the is_rect_visible value) // (this is an inline copy of IsClippedEx() so we can reuse the is_rect_visible value, otherwise we'd do 'if (IsClippedEx(bb, id)) return false')
//const bool is_clipped = IsClippedEx(bb, id);
//if (is_clipped)
// return false;
// g.NavActivateId is not necessarily == g.NavId, in the case of remote activation (e.g. shortcuts) // g.NavActivateId is not necessarily == g.NavId, in the case of remote activation (e.g. shortcuts)
const bool is_rect_visible = bb.Overlaps(window->ClipRect); const bool is_rect_visible = bb.Overlaps(window->ClipRect);
if (!is_rect_visible) if (!is_rect_visible)
if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId)) if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId))
if (!g.LogEnabled) if (!g.ItemUnclipByLog)
return false; return false;
// [DEBUG] // [DEBUG]
@ -10171,7 +10208,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect;
return true; return true;
} }
IM_MSVC_RUNTIME_CHECKS_RESTORE
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] LAYOUT // [SECTION] LAYOUT
@ -10208,6 +10245,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
// Register minimum needed size so it can extend the bounding box used for auto-fit calculation. // Register minimum needed size so it can extend the bounding box used for auto-fit calculation.
// See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different. // See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different.
// THIS IS IN THE PERFORMANCE CRITICAL PATH. // THIS IS IN THE PERFORMANCE CRITICAL PATH.
IM_MSVC_RUNTIME_CHECKS_OFF
void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) void ImGui::ItemSize(const ImVec2& size, float text_baseline_y)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -10243,6 +10281,7 @@ void ImGui::ItemSize(const ImVec2& size, float text_baseline_y)
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
SameLine(); SameLine();
} }
IM_MSVC_RUNTIME_CHECKS_RESTORE
// Gets back to previous line and continue with horizontal layout // Gets back to previous line and continue with horizontal layout
// offset_from_start_x == 0 : follow right after previous item // offset_from_start_x == 0 : follow right after previous item
@ -11196,8 +11235,8 @@ void ImGui::CloseCurrentPopup()
window->DC.NavHideHighlightOneFrame = true; window->DC.NavHideHighlightOneFrame = true;
} }
// Attention! BeginPopup() adds default flags which BeginPopupEx()! // Attention! BeginPopup() adds default flags when calling BeginPopupEx()!
bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags) bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (!IsPopupOpen(id, ImGuiPopupFlags_None)) if (!IsPopupOpen(id, ImGuiPopupFlags_None))
@ -11207,13 +11246,12 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags)
} }
char name[20]; char name[20];
if (flags & ImGuiWindowFlags_ChildMenu) if (extra_window_flags & ImGuiWindowFlags_ChildMenu)
ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginMenuDepth); // Recycle windows based on depth ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginMenuDepth); // Recycle windows based on depth
else else
ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame
flags |= ImGuiWindowFlags_Popup; bool is_open = Begin(name, NULL, extra_window_flags | ImGuiWindowFlags_Popup);
bool is_open = Begin(name, NULL, flags);
if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display) if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display)
EndPopup(); EndPopup();
@ -13096,6 +13134,8 @@ bool ImGui::IsDragDropActive()
void ImGui::ClearDragDrop() void ImGui::ClearDragDrop()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.DragDropActive)
IMGUI_DEBUG_LOG_ACTIVEID("[dragdrop] ClearDragDrop()\n");
g.DragDropActive = false; g.DragDropActive = false;
g.DragDropPayload.Clear(); g.DragDropPayload.Clear();
g.DragDropAcceptFlags = ImGuiDragDropFlags_None; g.DragDropAcceptFlags = ImGuiDragDropFlags_None;
@ -13134,7 +13174,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
bool source_drag_active = false; bool source_drag_active = false;
ImGuiID source_id = 0; ImGuiID source_id = 0;
ImGuiID source_parent_id = 0; ImGuiID source_parent_id = 0;
if (!(flags & ImGuiDragDropFlags_SourceExtern)) if ((flags & ImGuiDragDropFlags_SourceExtern) == 0)
{ {
source_id = g.LastItemData.ID; source_id = g.LastItemData.ID;
if (source_id != 0) if (source_id != 0)
@ -13196,43 +13236,44 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
} }
IM_ASSERT(g.DragDropWithinTarget == false); // Can't nest BeginDragDropSource() and BeginDragDropTarget() IM_ASSERT(g.DragDropWithinTarget == false); // Can't nest BeginDragDropSource() and BeginDragDropTarget()
if (source_drag_active) if (!source_drag_active)
return false;
// Activate drag and drop
if (!g.DragDropActive)
{ {
if (!g.DragDropActive) IM_ASSERT(source_id != 0);
{ ClearDragDrop();
IM_ASSERT(source_id != 0); IMGUI_DEBUG_LOG_ACTIVEID("[dragdrop] BeginDragDropSource() DragDropActive = true, source_id = %08X\n", source_id);
ClearDragDrop(); ImGuiPayload& payload = g.DragDropPayload;
ImGuiPayload& payload = g.DragDropPayload; payload.SourceId = source_id;
payload.SourceId = source_id; payload.SourceParentId = source_parent_id;
payload.SourceParentId = source_parent_id; g.DragDropActive = true;
g.DragDropActive = true; g.DragDropSourceFlags = flags;
g.DragDropSourceFlags = flags; g.DragDropMouseButton = mouse_button;
g.DragDropMouseButton = mouse_button; if (payload.SourceId == g.ActiveId)
if (payload.SourceId == g.ActiveId) g.ActiveIdNoClearOnFocusLoss = true;
g.ActiveIdNoClearOnFocusLoss = true;
}
g.DragDropSourceFrameCount = g.FrameCount;
g.DragDropWithinSource = true;
if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
{
// Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit)
// We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents.
bool ret;
if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
ret = BeginTooltipHidden();
else
ret = BeginTooltip();
IM_ASSERT(ret); // FIXME-NEWBEGIN: If this ever becomes false, we need to Begin("##Hidden", NULL, ImGuiWindowFlags_NoSavedSettings) + SetWindowHiddendAndSkipItemsForCurrentFrame().
IM_UNUSED(ret);
}
if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
return true;
} }
return false; g.DragDropSourceFrameCount = g.FrameCount;
g.DragDropWithinSource = true;
if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
{
// Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit)
// We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents.
bool ret;
if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
ret = BeginTooltipHidden();
else
ret = BeginTooltip();
IM_ASSERT(ret); // FIXME-NEWBEGIN: If this ever becomes false, we need to Begin("##Hidden", NULL, ImGuiWindowFlags_NoSavedSettings) + SetWindowHiddendAndSkipItemsForCurrentFrame().
IM_UNUSED(ret);
}
if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
return true;
} }
void ImGui::EndDragDropSource() void ImGui::EndDragDropSource()
@ -13543,7 +13584,7 @@ void ImGui::LogBegin(ImGuiLogType type, int auto_open_depth)
IM_ASSERT(g.LogEnabled == false); IM_ASSERT(g.LogEnabled == false);
IM_ASSERT(g.LogFile == NULL); IM_ASSERT(g.LogFile == NULL);
IM_ASSERT(g.LogBuffer.empty()); IM_ASSERT(g.LogBuffer.empty());
g.LogEnabled = true; g.LogEnabled = g.ItemUnclipByLog = true;
g.LogType = type; g.LogType = type;
g.LogNextPrefix = g.LogNextSuffix = NULL; g.LogNextPrefix = g.LogNextSuffix = NULL;
g.LogDepthRef = window->DC.TreeDepth; g.LogDepthRef = window->DC.TreeDepth;
@ -13642,7 +13683,7 @@ void ImGui::LogFinish()
break; break;
} }
g.LogEnabled = false; g.LogEnabled = g.ItemUnclipByLog = false;
g.LogType = ImGuiLogType_None; g.LogType = ImGuiLogType_None;
g.LogFile = NULL; g.LogFile = NULL;
g.LogBuffer.clear(); g.LogBuffer.clear();
@ -15374,7 +15415,7 @@ void ImGui::DebugNodeStorage(ImGuiStorage* storage, const char* label)
{ {
if (!TreeNode(label, "%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes())) if (!TreeNode(label, "%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes()))
return; return;
for (const ImGuiStorage::ImGuiStoragePair& p : storage->Data) for (const ImGuiStoragePair& p : storage->Data)
BulletText("Key 0x%08X Value { i: %d }", p.key, p.val_i); // Important: we currently don't store a type, real value may not be integer. BulletText("Key 0x%08X Value { i: %d }", p.key, p.val_i); // Important: we currently don't store a type, real value may not be integer.
TreePop(); TreePop();
} }
@ -15568,8 +15609,11 @@ void ImGui::DebugLogV(const char* fmt, va_list args)
if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTTY) if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTTY)
IMGUI_DEBUG_PRINTF("%s", g.DebugLogBuf.begin() + old_size); IMGUI_DEBUG_PRINTF("%s", g.DebugLogBuf.begin() + old_size);
#ifdef IMGUI_ENABLE_TEST_ENGINE #ifdef IMGUI_ENABLE_TEST_ENGINE
// IMGUI_TEST_ENGINE_LOG() adds a trailing \n automatically
const int new_size = g.DebugLogBuf.size();
const bool trailing_carriage_return = (g.DebugLogBuf[new_size - 1] == '\n');
if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTestEngine) if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTestEngine)
IMGUI_TEST_ENGINE_LOG("%s", g.DebugLogBuf.begin() + old_size); IMGUI_TEST_ENGINE_LOG("%.*s", new_size - old_size - (trailing_carriage_return ? 1 : 0), g.DebugLogBuf.begin() + old_size);
#endif #endif
} }
@ -15637,25 +15681,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
clipper.Begin(g.DebugLogIndex.size()); clipper.Begin(g.DebugLogIndex.size());
while (clipper.Step()) while (clipper.Step())
for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++) for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
{ DebugTextUnformattedWithLocateItem(g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no), g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no));
const char* line_begin = g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no);
const char* line_end = g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no);
TextUnformatted(line_begin, line_end); // Display line
ImRect text_rect = g.LastItemData.Rect;
if (IsItemHovered())
for (const char* p = line_begin; p <= line_end - 10; p++) // Search for 0x???????? identifiers
{
ImGuiID id = 0;
if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1)
continue;
ImVec2 p0 = CalcTextSize(line_begin, p);
ImVec2 p1 = CalcTextSize(p, p + 10);
g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0f), text_rect.Min + ImVec2(p0.x + p1.x, p1.y));
if (IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, true))
DebugLocateItemOnHover(id);
p += 10;
}
}
g.DebugLogFlags = backup_log_flags; g.DebugLogFlags = backup_log_flags;
if (GetScrollY() >= GetScrollMaxY()) if (GetScrollY() >= GetScrollMaxY())
SetScrollHereY(1.0f); SetScrollHereY(1.0f);
@ -15664,6 +15690,28 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
End(); End();
} }
// Display line, search for 0xXXXXXXXX identifiers and call DebugLocateItemOnHover() when hovered.
void ImGui::DebugTextUnformattedWithLocateItem(const char* line_begin, const char* line_end)
{
TextUnformatted(line_begin, line_end);
if (!IsItemHovered())
return;
ImGuiContext& g = *GImGui;
ImRect text_rect = g.LastItemData.Rect;
for (const char* p = line_begin; p <= line_end - 10; p++)
{
ImGuiID id = 0;
if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1)
continue;
ImVec2 p0 = CalcTextSize(line_begin, p);
ImVec2 p1 = CalcTextSize(p, p + 10);
g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0f), text_rect.Min + ImVec2(p0.x + p1.x, p1.y));
if (IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, true))
DebugLocateItemOnHover(id);
p += 10;
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, ID STACK TOOL) // [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, ID STACK TOOL)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -1,4 +1,4 @@
// dear imgui, v1.90.7 // dear imgui, v1.90.9 WIP
// (headers) // (headers)
// Help: // Help:
@ -27,8 +27,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.90.7" #define IMGUI_VERSION "1.90.9 WIP"
#define IMGUI_VERSION_NUM 19070 #define IMGUI_VERSION_NUM 19081
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
/* /*
@ -143,6 +143,17 @@ Index of this file:
// [SECTION] Forward declarations and basic types // [SECTION] Forward declarations and basic types
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Scalar data types
typedef unsigned int ImGuiID;// A unique ID used by widgets (typically the result of hashing a stack of string)
typedef signed char ImS8; // 8-bit signed integer
typedef unsigned char ImU8; // 8-bit unsigned integer
typedef signed short ImS16; // 16-bit signed integer
typedef unsigned short ImU16; // 16-bit unsigned integer
typedef signed int ImS32; // 32-bit signed integer == int
typedef unsigned int ImU32; // 32-bit unsigned integer (often used to store packed colors)
typedef signed long long ImS64; // 64-bit signed integer
typedef unsigned long long ImU64; // 64-bit unsigned integer
// Forward declarations // Forward declarations
struct ImDrawChannel; // Temporary storage to output draw commands out of order, used by ImDrawListSplitter and ImDrawList::ChannelsSplit() struct ImDrawChannel; // Temporary storage to output draw commands out of order, used by ImDrawListSplitter and ImDrawList::ChannelsSplit()
struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call, unless it is a callback) struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call, unless it is a callback)
@ -167,7 +178,8 @@ struct ImGuiOnceUponAFrame; // Helper for running a block of code not mo
struct ImGuiPayload; // User data payload for drag and drop operations struct ImGuiPayload; // User data payload for drag and drop operations
struct ImGuiPlatformImeData; // Platform IME data for io.SetPlatformImeDataFn() function. struct ImGuiPlatformImeData; // Platform IME data for io.SetPlatformImeDataFn() function.
struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use) struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use)
struct ImGuiStorage; // Helper for key->value storage struct ImGuiStorage; // Helper for key->value storage (container sorted by key)
struct ImGuiStoragePair; // Helper for key->value storage (pair)
struct ImGuiStyle; // Runtime data for styling/colors struct ImGuiStyle; // Runtime data for styling/colors
struct ImGuiTableSortSpecs; // Sorting specifications for a table (often handling sort specs for a single column, occasionally more) struct ImGuiTableSortSpecs; // Sorting specifications for a table (often handling sort specs for a single column, occasionally more)
struct ImGuiTableColumnSortSpecs; // Sorting specification for one column of a table struct ImGuiTableColumnSortSpecs; // Sorting specification for one column of a table
@ -181,15 +193,15 @@ struct ImGuiViewport; // A Platform Window (always only one in 'ma
// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments. // - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments.
// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments. // - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments.
enum ImGuiDir : int; // -> enum ImGuiDir // Enum: A cardinal direction (Left, Right, Up, Down)
enum ImGuiKey : int; // -> enum ImGuiKey // Enum: A key identifier (ImGuiKey_XXX or ImGuiMod_XXX value) enum ImGuiKey : int; // -> enum ImGuiKey // Enum: A key identifier (ImGuiKey_XXX or ImGuiMod_XXX value)
enum ImGuiMouseSource : int; // -> enum ImGuiMouseSource // Enum; A mouse input source identifier (Mouse, TouchScreen, Pen) enum ImGuiMouseSource : int; // -> enum ImGuiMouseSource // Enum; A mouse input source identifier (Mouse, TouchScreen, Pen)
enum ImGuiSortDirection : ImU8; // -> enum ImGuiSortDirection // Enum: A sorting direction (ascending or descending)
typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling
typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions
typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type
typedef int ImGuiDir; // -> enum ImGuiDir_ // Enum: A cardinal direction
typedef int ImGuiMouseButton; // -> enum ImGuiMouseButton_ // Enum: A mouse button identifier (0=left, 1=right, 2=middle) typedef int ImGuiMouseButton; // -> enum ImGuiMouseButton_ // Enum: A mouse button identifier (0=left, 1=right, 2=middle)
typedef int ImGuiMouseCursor; // -> enum ImGuiMouseCursor_ // Enum: A mouse cursor shape typedef int ImGuiMouseCursor; // -> enum ImGuiMouseCursor_ // Enum: A mouse cursor shape
typedef int ImGuiSortDirection; // -> enum ImGuiSortDirection_ // Enum: A sorting direction (ascending or descending)
typedef int ImGuiStyleVar; // -> enum ImGuiStyleVar_ // Enum: A variable identifier for styling typedef int ImGuiStyleVar; // -> enum ImGuiStyleVar_ // Enum: A variable identifier for styling
typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A color target for TableSetBgColor() typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A color target for TableSetBgColor()
@ -239,17 +251,6 @@ typedef void* ImTextureID; // Default: store a pointer or an integer fi
typedef unsigned short ImDrawIdx; // Default: 16-bit (for maximum compatibility with renderer backends) typedef unsigned short ImDrawIdx; // Default: 16-bit (for maximum compatibility with renderer backends)
#endif #endif
// Scalar data types
typedef unsigned int ImGuiID;// A unique ID used by widgets (typically the result of hashing a stack of string)
typedef signed char ImS8; // 8-bit signed integer
typedef unsigned char ImU8; // 8-bit unsigned integer
typedef signed short ImS16; // 16-bit signed integer
typedef unsigned short ImU16; // 16-bit unsigned integer
typedef signed int ImS32; // 32-bit signed integer == int
typedef unsigned int ImU32; // 32-bit unsigned integer (often used to store packed colors)
typedef signed long long ImS64; // 64-bit signed integer
typedef unsigned long long ImU64; // 64-bit unsigned integer
// Character types // Character types
// (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display) // (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display)
typedef unsigned int ImWchar32; // A single decoded U32 character/code point. We encode them as multi bytes UTF-8 when used in strings. typedef unsigned int ImWchar32; // A single decoded U32 character/code point. We encode them as multi bytes UTF-8 when used in strings.
@ -1082,28 +1083,37 @@ enum ImGuiChildFlags_
// (Those are per-item flags. There are shared flags in ImGuiIO: io.ConfigInputTextCursorBlink and io.ConfigInputTextEnterKeepActive) // (Those are per-item flags. There are shared flags in ImGuiIO: io.ConfigInputTextCursorBlink and io.ConfigInputTextEnterKeepActive)
enum ImGuiInputTextFlags_ enum ImGuiInputTextFlags_
{ {
// Basic filters (also see ImGuiInputTextFlags_CallbackCharFilter)
ImGuiInputTextFlags_None = 0, ImGuiInputTextFlags_None = 0,
ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/ ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/
ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef
ImGuiInputTextFlags_CharsUppercase = 1 << 2, // Turn a..z into A..Z ImGuiInputTextFlags_CharsScientific = 1 << 2, // Allow 0123456789.+-*/eE (Scientific notation input)
ImGuiInputTextFlags_CharsNoBlank = 1 << 3, // Filter out spaces, tabs ImGuiInputTextFlags_CharsUppercase = 1 << 3, // Turn a..z into A..Z
ImGuiInputTextFlags_AutoSelectAll = 1 << 4, // Select entire text when first taking mouse focus ImGuiInputTextFlags_CharsNoBlank = 1 << 4, // Filter out spaces, tabs
ImGuiInputTextFlags_EnterReturnsTrue = 1 << 5, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider looking at the IsItemDeactivatedAfterEdit() function.
ImGuiInputTextFlags_CallbackCompletion = 1 << 6, // Callback on pressing TAB (for completion handling) // Inputs
ImGuiInputTextFlags_CallbackHistory = 1 << 7, // Callback on pressing Up/Down arrows (for history handling) ImGuiInputTextFlags_AllowTabInput = 1 << 5, // Pressing TAB input a '\t' character into the text field
ImGuiInputTextFlags_CallbackAlways = 1 << 8, // Callback on each iteration. User code may query cursor position, modify text buffer. ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider looking at the IsItemDeactivatedAfterEdit() function.
ImGuiInputTextFlags_CallbackCharFilter = 1 << 9, // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard. ImGuiInputTextFlags_EscapeClearsAll = 1 << 7, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert)
ImGuiInputTextFlags_AllowTabInput = 1 << 10, // Pressing TAB input a '\t' character into the text field ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8, // In multi-line mode, validate with Enter, add new line with Ctrl+Enter (default is opposite: validate with Ctrl+Enter, add line with Enter).
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11, // In multi-line mode, unfocus with Enter, add new line with Ctrl+Enter (default is opposite: unfocus with Ctrl+Enter, add line with Enter).
ImGuiInputTextFlags_NoHorizontalScroll = 1 << 12, // Disable following the cursor horizontally // Other options
ImGuiInputTextFlags_AlwaysOverwrite = 1 << 13, // Overwrite mode ImGuiInputTextFlags_ReadOnly = 1 << 9, // Read-only mode
ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode ImGuiInputTextFlags_Password = 1 << 10, // Password mode, display all characters as '*', disable copy
ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*' ImGuiInputTextFlags_AlwaysOverwrite = 1 << 11, // Overwrite mode
ImGuiInputTextFlags_AutoSelectAll = 1 << 12, // Select entire text when first taking mouse focus
ImGuiInputTextFlags_ParseEmptyRefVal = 1 << 13, // InputFloat(), InputInt(), InputScalar() etc. only: parse empty string as zero value.
ImGuiInputTextFlags_DisplayEmptyRefVal = 1 << 14, // InputFloat(), InputInt(), InputScalar() etc. only: when value is zero, do not display it. Generally used with ImGuiInputTextFlags_ParseEmptyRefVal.
ImGuiInputTextFlags_NoHorizontalScroll = 1 << 15, // Disable following the cursor horizontally
ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID(). ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID().
ImGuiInputTextFlags_CharsScientific = 1 << 17, // Allow 0123456789.+-*/eE (Scientific notation input)
ImGuiInputTextFlags_CallbackResize = 1 << 18, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this) // Callback features
ImGuiInputTextFlags_CallbackEdit = 1 << 19, // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active) ImGuiInputTextFlags_CallbackCompletion = 1 << 17, // Callback on pressing TAB (for completion handling)
ImGuiInputTextFlags_EscapeClearsAll = 1 << 20, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert) ImGuiInputTextFlags_CallbackHistory = 1 << 18, // Callback on pressing Up/Down arrows (for history handling)
ImGuiInputTextFlags_CallbackAlways = 1 << 19, // Callback on each iteration. User code may query cursor position, modify text buffer.
ImGuiInputTextFlags_CallbackCharFilter = 1 << 20, // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard.
ImGuiInputTextFlags_CallbackResize = 1 << 21, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this)
ImGuiInputTextFlags_CallbackEdit = 1 << 22, // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active)
// Obsolete names // Obsolete names
//ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior //ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior
@ -1123,7 +1133,7 @@ enum ImGuiTreeNodeFlags_
ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open. ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open.
ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes).
ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow. IMPORTANT: node can still be marked open/close if you don't set the _Leaf flag! ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow. IMPORTANT: node can still be marked open/close if you don't set the _Leaf flag!
ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding(). ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding() before the node.
ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line without using AllowOverlap mode. ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line without using AllowOverlap mode.
ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (cover the indent area). ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (cover the indent area).
ImGuiTreeNodeFlags_SpanTextWidth = 1 << 13, // Narrow hit box + narrow hovering highlight, will only cover the label text. ImGuiTreeNodeFlags_SpanTextWidth = 1 << 13, // Narrow hit box + narrow hovering highlight, will only cover the label text.
@ -1314,7 +1324,7 @@ enum ImGuiDataType_
}; };
// A cardinal direction // A cardinal direction
enum ImGuiDir_ enum ImGuiDir : int
{ {
ImGuiDir_None = -1, ImGuiDir_None = -1,
ImGuiDir_Left = 0, ImGuiDir_Left = 0,
@ -1325,7 +1335,7 @@ enum ImGuiDir_
}; };
// A sorting direction // A sorting direction
enum ImGuiSortDirection_ enum ImGuiSortDirection : ImU8
{ {
ImGuiSortDirection_None = 0, ImGuiSortDirection_None = 0,
ImGuiSortDirection_Ascending = 1, // Ascending = 0->9, A->Z etc. ImGuiSortDirection_Ascending = 1, // Ascending = 0->9, A->Z etc.
@ -1648,10 +1658,8 @@ enum ImGuiButtonFlags_
ImGuiButtonFlags_MouseButtonLeft = 1 << 0, // React on left mouse button (default) ImGuiButtonFlags_MouseButtonLeft = 1 << 0, // React on left mouse button (default)
ImGuiButtonFlags_MouseButtonRight = 1 << 1, // React on right mouse button ImGuiButtonFlags_MouseButtonRight = 1 << 1, // React on right mouse button
ImGuiButtonFlags_MouseButtonMiddle = 1 << 2, // React on center mouse button ImGuiButtonFlags_MouseButtonMiddle = 1 << 2, // React on center mouse button
ImGuiButtonFlags_MouseButtonMask_ = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle, // [Internal]
// [Internal] //ImGuiButtonFlags_MouseButtonDefault_ = ImGuiButtonFlags_MouseButtonLeft,
ImGuiButtonFlags_MouseButtonMask_ = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle,
ImGuiButtonFlags_MouseButtonDefault_ = ImGuiButtonFlags_MouseButtonLeft,
}; };
// Flags for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton() // Flags for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton()
@ -1924,7 +1932,7 @@ struct ImGuiTableColumnSortSpecs
ImGuiID ColumnUserID; // User id of the column (if specified by a TableSetupColumn() call) ImGuiID ColumnUserID; // User id of the column (if specified by a TableSetupColumn() call)
ImS16 ColumnIndex; // Index of the column ImS16 ColumnIndex; // Index of the column
ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here) ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here)
ImGuiSortDirection SortDirection : 8; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending ImGuiSortDirection SortDirection; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
ImGuiTableColumnSortSpecs() { memset(this, 0, sizeof(*this)); } ImGuiTableColumnSortSpecs() { memset(this, 0, sizeof(*this)); }
}; };
@ -2073,9 +2081,9 @@ struct ImGuiStyle
float SeparatorTextBorderSize; // Thickkness of border in SeparatorText() float SeparatorTextBorderSize; // Thickkness of border in SeparatorText()
ImVec2 SeparatorTextAlign; // Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center). ImVec2 SeparatorTextAlign; // Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
ImVec2 SeparatorTextPadding; // Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y. ImVec2 SeparatorTextPadding; // Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y.
ImVec2 DisplayWindowPadding; // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows. ImVec2 DisplayWindowPadding; // Apply to regular windows: amount which we enforce to keep visible when moving near edges of your screen.
ImVec2 DisplaySafeAreaPadding; // If you cannot see the edges of your screen (e.g. on a TV) increase the safe area padding. Apply to popups/tooltips as well regular windows. NB: Prefer configuring your TV sets correctly! ImVec2 DisplaySafeAreaPadding; // Apply to every windows, menus, popups, tooltips: amount where we avoid displaying contents. Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).
float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later. float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). We apply per-monitor DPI scaling over this scale. May be removed later.
bool AntiAliasedLines; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList). bool AntiAliasedLines; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).
bool AntiAliasedLinesUseTex; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). Latched at the beginning of the frame (copied to ImDrawList). bool AntiAliasedLinesUseTex; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). Latched at the beginning of the frame (copied to ImDrawList).
bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList). bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).
@ -2453,6 +2461,16 @@ struct ImGuiTextBuffer
IMGUI_API void appendfv(const char* fmt, va_list args) IM_FMTLIST(2); IMGUI_API void appendfv(const char* fmt, va_list args) IM_FMTLIST(2);
}; };
// [Internal] Key+Value for ImGuiStorage
struct ImGuiStoragePair
{
ImGuiID key;
union { int val_i; float val_f; void* val_p; };
ImGuiStoragePair(ImGuiID _key, int _val) { key = _key; val_i = _val; }
ImGuiStoragePair(ImGuiID _key, float _val) { key = _key; val_f = _val; }
ImGuiStoragePair(ImGuiID _key, void* _val) { key = _key; val_p = _val; }
};
// Helper: Key->Value storage // Helper: Key->Value storage
// Typically you don't have to worry about this since a storage is held within each Window. // Typically you don't have to worry about this since a storage is held within each Window.
// We use it to e.g. store collapse state for a tree (Int 0/1) // We use it to e.g. store collapse state for a tree (Int 0/1)
@ -2464,15 +2482,6 @@ struct ImGuiTextBuffer
struct ImGuiStorage struct ImGuiStorage
{ {
// [Internal] // [Internal]
struct ImGuiStoragePair
{
ImGuiID key;
union { int val_i; float val_f; void* val_p; };
ImGuiStoragePair(ImGuiID _key, int _val) { key = _key; val_i = _val; }
ImGuiStoragePair(ImGuiID _key, float _val) { key = _key; val_f = _val; }
ImGuiStoragePair(ImGuiID _key, void* _val) { key = _key; val_p = _val; }
};
ImVector<ImGuiStoragePair> Data; ImVector<ImGuiStoragePair> Data;
// - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N) // - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N)
@ -2501,6 +2510,10 @@ struct ImGuiStorage
IMGUI_API void BuildSortByKey(); IMGUI_API void BuildSortByKey();
// Obsolete: use on your own storage if you know only integer are being stored (open/close all tree nodes) // Obsolete: use on your own storage if you know only integer are being stored (open/close all tree nodes)
IMGUI_API void SetAllInt(int val); IMGUI_API void SetAllInt(int val);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//typedef ::ImGuiStoragePair ImGuiStoragePair; // 1.90.8: moved type outside struct
#endif
}; };
// Helper: Manually clip large list of items. // Helper: Manually clip large list of items.
@ -3256,7 +3269,7 @@ namespace ImGui
static inline void PopAllowKeyboardFocus() { PopTabStop(); } static inline void PopAllowKeyboardFocus() { PopTabStop(); }
// OBSOLETED in 1.89 (from August 2022) // OBSOLETED in 1.89 (from August 2022)
IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // Use new ImageButton() signature (explicit item id, regular FramePadding) IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // Use new ImageButton() signature (explicit item id, regular FramePadding)
// OBSOLETED in 1.87 (from February 2022) // OBSOLETED in 1.87 (from February 2022 but more formally obsoleted April 2024)
IMGUI_API ImGuiKey GetKeyIndex(ImGuiKey key); // Map ImGuiKey_* values into legacy native key index. == io.KeyMap[key]. When using a 1.87+ backend using io.AddKeyEvent(), calling GetKeyIndex() with ANY ImGuiKey_XXXX values will return the same value! IMGUI_API ImGuiKey GetKeyIndex(ImGuiKey key); // Map ImGuiKey_* values into legacy native key index. == io.KeyMap[key]. When using a 1.87+ backend using io.AddKeyEvent(), calling GetKeyIndex() with ANY ImGuiKey_XXXX values will return the same value!
//static inline ImGuiKey GetKeyIndex(ImGuiKey key) { IM_ASSERT(key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END); return key; } //static inline ImGuiKey GetKeyIndex(ImGuiKey key) { IM_ASSERT(key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END); return key; }

View File

@ -1,4 +1,4 @@
// dear imgui, v1.90.7 // dear imgui, v1.90.9 WIP
// (demo code) // (demo code)
// Help: // Help:
@ -2273,20 +2273,24 @@ static void ShowDemoWindowWidgets()
IMGUI_DEMO_MARKER("Widgets/Data Types/Inputs"); IMGUI_DEMO_MARKER("Widgets/Data Types/Inputs");
static bool inputs_step = true; static bool inputs_step = true;
static ImGuiInputTextFlags flags = ImGuiInputTextFlags_None;
ImGui::SeparatorText("Inputs"); ImGui::SeparatorText("Inputs");
ImGui::Checkbox("Show step buttons", &inputs_step); ImGui::Checkbox("Show step buttons", &inputs_step);
ImGui::InputScalar("input s8", ImGuiDataType_S8, &s8_v, inputs_step ? &s8_one : NULL, NULL, "%d"); ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly);
ImGui::InputScalar("input u8", ImGuiDataType_U8, &u8_v, inputs_step ? &u8_one : NULL, NULL, "%u"); ImGui::CheckboxFlags("ImGuiInputTextFlags_ParseEmptyRefVal", &flags, ImGuiInputTextFlags_ParseEmptyRefVal);
ImGui::InputScalar("input s16", ImGuiDataType_S16, &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d"); ImGui::CheckboxFlags("ImGuiInputTextFlags_DisplayEmptyRefVal", &flags, ImGuiInputTextFlags_DisplayEmptyRefVal);
ImGui::InputScalar("input u16", ImGuiDataType_U16, &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u"); ImGui::InputScalar("input s8", ImGuiDataType_S8, &s8_v, inputs_step ? &s8_one : NULL, NULL, "%d", flags);
ImGui::InputScalar("input s32", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d"); ImGui::InputScalar("input u8", ImGuiDataType_U8, &u8_v, inputs_step ? &u8_one : NULL, NULL, "%u", flags);
ImGui::InputScalar("input s32 hex", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%04X"); ImGui::InputScalar("input s16", ImGuiDataType_S16, &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d", flags);
ImGui::InputScalar("input u32", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u"); ImGui::InputScalar("input u16", ImGuiDataType_U16, &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u", flags);
ImGui::InputScalar("input u32 hex", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X"); ImGui::InputScalar("input s32", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d", flags);
ImGui::InputScalar("input s64", ImGuiDataType_S64, &s64_v, inputs_step ? &s64_one : NULL); ImGui::InputScalar("input s32 hex", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%04X", flags);
ImGui::InputScalar("input u64", ImGuiDataType_U64, &u64_v, inputs_step ? &u64_one : NULL); ImGui::InputScalar("input u32", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u", flags);
ImGui::InputScalar("input float", ImGuiDataType_Float, &f32_v, inputs_step ? &f32_one : NULL); ImGui::InputScalar("input u32 hex", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", flags);
ImGui::InputScalar("input double", ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL); ImGui::InputScalar("input s64", ImGuiDataType_S64, &s64_v, inputs_step ? &s64_one : NULL, NULL, NULL, flags);
ImGui::InputScalar("input u64", ImGuiDataType_U64, &u64_v, inputs_step ? &u64_one : NULL, NULL, NULL, flags);
ImGui::InputScalar("input float", ImGuiDataType_Float, &f32_v, inputs_step ? &f32_one : NULL, NULL, NULL, flags);
ImGui::InputScalar("input double", ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL, NULL, NULL, flags);
ImGui::TreePop(); ImGui::TreePop();
} }
@ -3875,7 +3879,7 @@ static void ShowDemoWindowPopups()
static int item = 1; static int item = 1;
static float color[4] = { 0.4f, 0.7f, 0.0f, 0.5f }; static float color[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
ImGui::ColorEdit4("color", color); ImGui::ColorEdit4("Color", color);
if (ImGui::Button("Add another modal..")) if (ImGui::Button("Add another modal.."))
ImGui::OpenPopup("Stacked 2"); ImGui::OpenPopup("Stacked 2");
@ -3887,6 +3891,7 @@ static void ShowDemoWindowPopups()
if (ImGui::BeginPopupModal("Stacked 2", &unused_open)) if (ImGui::BeginPopupModal("Stacked 2", &unused_open))
{ {
ImGui::Text("Hello from Stacked The Second!"); ImGui::Text("Hello from Stacked The Second!");
ImGui::ColorEdit4("Color", color); // Allow opening another nested popup
if (ImGui::Button("Close")) if (ImGui::Button("Close"))
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
ImGui::EndPopup(); ImGui::EndPopup();
@ -6295,7 +6300,7 @@ static void ShowDemoWindowInputs()
ImGui::RadioButton("ImGuiInputFlags_RouteAlways", &route_type, ImGuiInputFlags_RouteAlways); ImGui::RadioButton("ImGuiInputFlags_RouteAlways", &route_type, ImGuiInputFlags_RouteAlways);
ImGuiInputFlags flags = route_type | route_options; // Merged flags ImGuiInputFlags flags = route_type | route_options; // Merged flags
if (route_type != ImGuiInputFlags_RouteGlobal) if (route_type != ImGuiInputFlags_RouteGlobal)
route_options &= ~(ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused); flags &= ~(ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused);
ImGui::SeparatorText("Using SetNextItemShortcut()"); ImGui::SeparatorText("Using SetNextItemShortcut()");
ImGui::Text("Ctrl+S"); ImGui::Text("Ctrl+S");
@ -6768,7 +6773,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f"); ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
int window_menu_button_position = style.WindowMenuButtonPosition + 1; int window_menu_button_position = style.WindowMenuButtonPosition + 1;
if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0")) if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0"))
style.WindowMenuButtonPosition = window_menu_button_position - 1; style.WindowMenuButtonPosition = (ImGuiDir)(window_menu_button_position - 1);
ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0"); ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0");
ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f");
ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content."); ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content.");
@ -6793,7 +6798,8 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
} }
ImGui::SeparatorText("Misc"); ImGui::SeparatorText("Misc");
ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f"); ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured)."); ImGui::SliderFloat2("DisplayWindowPadding", (float*)&style.DisplayWindowPadding, 0.0f, 30.0f, "%.0f"); ImGui::SameLine(); HelpMarker("Apply to regular windows: amount which we enforce to keep visible when moving near edges of your screen.");
ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f"); ImGui::SameLine(); HelpMarker("Apply to every windows, menus, popups, tooltips: amount where we avoid displaying contents. Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
ImGui::EndTabItem(); ImGui::EndTabItem();
} }

View File

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

View File

@ -1,4 +1,4 @@
// dear imgui, v1.90.7 // dear imgui, v1.90.9 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.
@ -14,8 +14,8 @@ Index of this file:
// [SECTION] Macros // [SECTION] Macros
// [SECTION] Generic helpers // [SECTION] Generic helpers
// [SECTION] ImDrawList support // [SECTION] ImDrawList support
// [SECTION] Widgets support: flags, enums, data structures
// [SECTION] Data types support // [SECTION] Data types support
// [SECTION] Widgets support: flags, enums, data structures
// [SECTION] Popup support // [SECTION] Popup support
// [SECTION] Inputs support // [SECTION] Inputs support
// [SECTION] Clipper support // [SECTION] Clipper support
@ -348,6 +348,7 @@ namespace ImStb
// - Helper: ImPool<> // - Helper: ImPool<>
// - Helper: ImChunkStream<> // - Helper: ImChunkStream<>
// - Helper: ImGuiTextIndex // - Helper: ImGuiTextIndex
// - Helper: ImGuiStorage
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Helpers: Hashing // Helpers: Hashing
@ -472,7 +473,7 @@ template<typename T> static inline T ImSubClampOverflow(T a, T b, T mn, T mx)
// - Misc maths helpers // - Misc maths helpers
static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x < rhs.x ? lhs.x : rhs.x, lhs.y < rhs.y ? lhs.y : rhs.y); } static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x < rhs.x ? lhs.x : rhs.x, lhs.y < rhs.y ? lhs.y : rhs.y); }
static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x >= rhs.x ? lhs.x : rhs.x, lhs.y >= rhs.y ? lhs.y : rhs.y); } static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x >= rhs.x ? lhs.x : rhs.x, lhs.y >= rhs.y ? lhs.y : rhs.y); }
static inline ImVec2 ImClamp(const ImVec2& v, const ImVec2& mn, ImVec2 mx) { return ImVec2((v.x < mn.x) ? mn.x : (v.x > mx.x) ? mx.x : v.x, (v.y < mn.y) ? mn.y : (v.y > mx.y) ? mx.y : v.y); } static inline ImVec2 ImClamp(const ImVec2& v, const ImVec2&mn, const ImVec2&mx) { return ImVec2((v.x < mn.x) ? mn.x : (v.x > mx.x) ? mx.x : v.x, (v.y < mn.y) ? mn.y : (v.y > mx.y) ? mx.y : v.y); }
static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t) { return ImVec2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t); } static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t) { return ImVec2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t); }
static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); } static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); }
static inline ImVec4 ImLerp(const ImVec4& a, const ImVec4& b, float t) { return ImVec4(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t); } static inline ImVec4 ImLerp(const ImVec4& a, const ImVec4& b, float t) { return ImVec4(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t); }
@ -722,7 +723,7 @@ struct ImChunkStream
void swap(ImChunkStream<T>& rhs) { rhs.Buf.swap(Buf); } void swap(ImChunkStream<T>& rhs) { rhs.Buf.swap(Buf); }
}; };
// Helper: ImGuiTextIndex<> // Helper: ImGuiTextIndex
// Maintain a line index for a text buffer. This is a strong candidate to be moved into the public API. // Maintain a line index for a text buffer. This is a strong candidate to be moved into the public API.
struct ImGuiTextIndex struct ImGuiTextIndex
{ {
@ -736,6 +737,8 @@ struct ImGuiTextIndex
void append(const char* base, int old_size, int new_size); void append(const char* base, int old_size, int new_size);
}; };
// Helper: ImGuiStorage
IMGUI_API ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStoragePair* in_end, ImGuiID key);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] ImDrawList support // [SECTION] ImDrawList support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -798,6 +801,40 @@ struct ImDrawDataBuilder
ImDrawDataBuilder() { memset(this, 0, sizeof(*this)); } ImDrawDataBuilder() { memset(this, 0, sizeof(*this)); }
}; };
//-----------------------------------------------------------------------------
// [SECTION] Data types support
//-----------------------------------------------------------------------------
struct ImGuiDataVarInfo
{
ImGuiDataType Type;
ImU32 Count; // 1+
ImU32 Offset; // Offset in parent structure
void* GetVarPtr(void* parent) const { return (void*)((unsigned char*)parent + Offset); }
};
struct ImGuiDataTypeStorage
{
ImU8 Data[8]; // Opaque storage to fit any data up to ImGuiDataType_COUNT
};
// Type information associated to one ImGuiDataType. Retrieve with DataTypeGetInfo().
struct ImGuiDataTypeInfo
{
size_t Size; // Size in bytes
const char* Name; // Short descriptive name for the type, for debugging
const char* PrintFmt; // Default printf format for the type
const char* ScanFmt; // Default scanf format for the type
};
// Extend ImGuiDataType_
enum ImGuiDataTypePrivate_
{
ImGuiDataType_String = ImGuiDataType_COUNT + 1,
ImGuiDataType_Pointer,
ImGuiDataType_ID,
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Widgets support: flags, enums, data structures // [SECTION] Widgets support: flags, enums, data structures
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1177,6 +1214,7 @@ enum ImGuiNextItemDataFlags_
ImGuiNextItemDataFlags_HasWidth = 1 << 0, ImGuiNextItemDataFlags_HasWidth = 1 << 0,
ImGuiNextItemDataFlags_HasOpen = 1 << 1, ImGuiNextItemDataFlags_HasOpen = 1 << 1,
ImGuiNextItemDataFlags_HasShortcut = 1 << 2, ImGuiNextItemDataFlags_HasShortcut = 1 << 2,
ImGuiNextItemDataFlags_HasRefVal = 1 << 3,
}; };
struct ImGuiNextItemData struct ImGuiNextItemData
@ -1189,7 +1227,8 @@ struct ImGuiNextItemData
ImGuiKeyChord Shortcut; // Set by SetNextItemShortcut() ImGuiKeyChord Shortcut; // Set by SetNextItemShortcut()
ImGuiInputFlags ShortcutFlags; // Set by SetNextItemShortcut() ImGuiInputFlags ShortcutFlags; // Set by SetNextItemShortcut()
bool OpenVal; // Set by SetNextItemOpen() bool OpenVal; // Set by SetNextItemOpen()
ImGuiCond OpenCond : 8; ImU8 OpenCond; // Set by SetNextItemOpen()
ImGuiDataTypeStorage RefVal; // Not exposed yet, for ImGuiInputTextFlags_ParseEmptyAsRefVal
ImGuiNextItemData() { memset(this, 0, sizeof(*this)); SelectionUserData = -1; } ImGuiNextItemData() { memset(this, 0, sizeof(*this)); SelectionUserData = -1; }
inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()! inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()!
@ -1243,7 +1282,8 @@ struct ImGuiWindowStackData
{ {
ImGuiWindow* Window; ImGuiWindow* Window;
ImGuiLastItemData ParentLastItemDataBackup; ImGuiLastItemData ParentLastItemDataBackup;
ImGuiStackSizes StackSizesOnBegin; // Store size of various stacks for asserting ImGuiStackSizes StackSizesOnBegin; // Store size of various stacks for asserting
bool DisabledOverrideReenable; // Non-child window override disabled flag
}; };
struct ImGuiShrinkWidthItem struct ImGuiShrinkWidthItem
@ -1262,40 +1302,6 @@ struct ImGuiPtrOrIndex
ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; } ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; }
}; };
//-----------------------------------------------------------------------------
// [SECTION] Data types support
//-----------------------------------------------------------------------------
struct ImGuiDataVarInfo
{
ImGuiDataType Type;
ImU32 Count; // 1+
ImU32 Offset; // Offset in parent structure
void* GetVarPtr(void* parent) const { return (void*)((unsigned char*)parent + Offset); }
};
struct ImGuiDataTypeTempStorage
{
ImU8 Data[8]; // Can fit any data up to ImGuiDataType_COUNT
};
// Type information associated to one ImGuiDataType. Retrieve with DataTypeGetInfo().
struct ImGuiDataTypeInfo
{
size_t Size; // Size in bytes
const char* Name; // Short descriptive name for the type, for debugging
const char* PrintFmt; // Default printf format for the type
const char* ScanFmt; // Default scanf format for the type
};
// Extend ImGuiDataType_
enum ImGuiDataTypePrivate_
{
ImGuiDataType_String = ImGuiDataType_COUNT + 1,
ImGuiDataType_Pointer,
ImGuiDataType_ID,
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Popup support // [SECTION] Popup support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1582,6 +1588,7 @@ enum ImGuiNavLayer
ImGuiNavLayer_COUNT ImGuiNavLayer_COUNT
}; };
// Storage for navigation query/results
struct ImGuiNavItemData struct ImGuiNavItemData
{ {
ImGuiWindow* Window; // Init,Move // Best candidate window (result->ItemWindow->RootWindowForNav == request->Window) ImGuiWindow* Window; // Init,Move // Best candidate window (result->ItemWindow->RootWindowForNav == request->Window)
@ -1598,6 +1605,7 @@ struct ImGuiNavItemData
void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; } void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; }
}; };
// Storage for PushFocusScope()
struct ImGuiFocusScopeData struct ImGuiFocusScopeData
{ {
ImGuiID ID; ImGuiID ID;
@ -1963,10 +1971,11 @@ struct ImGuiContext
ImGuiID DebugHookIdInfo; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by ID Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line] ImGuiID DebugHookIdInfo; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by ID Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line]
ImGuiID HoveredId; // Hovered widget, filled during the frame ImGuiID HoveredId; // Hovered widget, filled during the frame
ImGuiID HoveredIdPreviousFrame; ImGuiID HoveredIdPreviousFrame;
bool HoveredIdAllowOverlap;
bool HoveredIdDisabled; // At least one widget passed the rect test, but has been discarded by disabled flag or popup inhibit. May be true even if HoveredId == 0.
float HoveredIdTimer; // Measure contiguous hovering time float HoveredIdTimer; // Measure contiguous hovering time
float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active
bool HoveredIdAllowOverlap;
bool HoveredIdIsDisabled; // At least one widget passed the rect test, but has been discarded by disabled flag or popup inhibit. May be true even if HoveredId == 0.
bool ItemUnclipByLog; // Disable ItemAdd() clipping, essentially a memory-locality friendly copy of LogEnabled
ImGuiID ActiveId; // Active widget ImGuiID ActiveId; // Active widget
ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame) ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame)
float ActiveIdTimer; float ActiveIdTimer;
@ -2033,11 +2042,11 @@ struct ImGuiContext
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow' ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
ImGuiID NavId; // Focused item for navigation ImGuiID NavId; // Focused item for navigation
ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope) ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope)
ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem() ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem()
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0 ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat) ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
ImGuiActivateFlags NavActivateFlags; ImGuiActivateFlags NavActivateFlags;
ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
ImGuiID NavHighlightActivatedId; ImGuiID NavHighlightActivatedId;
float NavHighlightActivatedTimer; float NavHighlightActivatedTimer;
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest). ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
@ -2150,6 +2159,7 @@ struct ImGuiContext
ImGuiInputTextDeactivatedState InputTextDeactivatedState; ImGuiInputTextDeactivatedState InputTextDeactivatedState;
ImFont InputTextPasswordFont; ImFont InputTextPasswordFont;
ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
int BeginMenuDepth; int BeginMenuDepth;
int BeginComboDepth; int BeginComboDepth;
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
@ -2162,13 +2172,14 @@ 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.
float ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage?
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?
bool DragCurrentAccumDirty; bool DragCurrentAccumDirty;
float DragCurrentAccum; // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings float DragCurrentAccum; // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings
float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio
float ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage?
float DisabledAlphaBackup; // Backup for style.Alpha for BeginDisabled() float DisabledAlphaBackup; // Backup for style.Alpha for BeginDisabled()
short DisabledStackSize; short DisabledStackSize;
short LockMarkEdited; short LockMarkEdited;
@ -2271,8 +2282,9 @@ struct ImGuiContext
DebugHookIdInfo = 0; DebugHookIdInfo = 0;
HoveredId = HoveredIdPreviousFrame = 0; HoveredId = HoveredIdPreviousFrame = 0;
HoveredIdAllowOverlap = false; HoveredIdAllowOverlap = false;
HoveredIdDisabled = false; HoveredIdIsDisabled = false;
HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f; HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
ItemUnclipByLog = false;
ActiveId = 0; ActiveId = 0;
ActiveIdIsAlive = 0; ActiveIdIsAlive = 0;
ActiveIdTimer = 0.0f; ActiveIdTimer = 0.0f;
@ -2370,19 +2382,21 @@ struct ImGuiContext
MouseStationaryTimer = 0.0f; MouseStationaryTimer = 0.0f;
TempInputId = 0; TempInputId = 0;
memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue));
BeginMenuDepth = BeginComboDepth = 0; BeginMenuDepth = BeginComboDepth = 0;
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_; ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
ColorEditCurrentID = ColorEditSavedID = 0; ColorEditCurrentID = ColorEditSavedID = 0;
ColorEditSavedHue = ColorEditSavedSat = 0.0f; ColorEditSavedHue = ColorEditSavedSat = 0.0f;
ColorEditSavedColor = 0; ColorEditSavedColor = 0;
WindowResizeRelativeMode = false; WindowResizeRelativeMode = false;
ScrollbarSeekMode = 0;
ScrollbarClickDeltaToGrabCenter = 0.0f;
SliderGrabClickOffset = 0.0f; SliderGrabClickOffset = 0.0f;
SliderCurrentAccum = 0.0f; SliderCurrentAccum = 0.0f;
SliderCurrentAccumDirty = false; SliderCurrentAccumDirty = false;
DragCurrentAccumDirty = false; DragCurrentAccumDirty = false;
DragCurrentAccum = 0.0f; DragCurrentAccum = 0.0f;
DragSpeedDefaultRatio = 1.0f / 100.0f; DragSpeedDefaultRatio = 1.0f / 100.0f;
ScrollbarClickDeltaToGrabCenter = 0.0f;
DisabledAlphaBackup = 0.0f; DisabledAlphaBackup = 0.0f;
DisabledStackSize = 0; DisabledStackSize = 0;
LockMarkEdited = 0; LockMarkEdited = 0;
@ -2507,12 +2521,14 @@ struct IMGUI_API ImGuiWindow
ImVec2 WindowPadding; // Window padding at the time of Begin(). ImVec2 WindowPadding; // Window padding at the time of Begin().
float WindowRounding; // Window rounding at the time of Begin(). May be clamped lower to avoid rendering artifacts with title bar, menu bar etc. float WindowRounding; // Window rounding at the time of Begin(). May be clamped lower to avoid rendering artifacts with title bar, menu bar etc.
float WindowBorderSize; // Window border size at the time of Begin(). float WindowBorderSize; // Window border size at the time of Begin().
float TitleBarHeight, MenuBarHeight;
float DecoOuterSizeX1, DecoOuterSizeY1; // Left/Up offsets. Sum of non-scrolling outer decorations (X1 generally == 0.0f. Y1 generally = TitleBarHeight + MenuBarHeight). Locked during Begin(). float DecoOuterSizeX1, DecoOuterSizeY1; // Left/Up offsets. Sum of non-scrolling outer decorations (X1 generally == 0.0f. Y1 generally = TitleBarHeight + MenuBarHeight). Locked during Begin().
float DecoOuterSizeX2, DecoOuterSizeY2; // Right/Down offsets (X2 generally == ScrollbarSize.x, Y2 == ScrollbarSizes.y). float DecoOuterSizeX2, DecoOuterSizeY2; // Right/Down offsets (X2 generally == ScrollbarSize.x, Y2 == ScrollbarSizes.y).
float DecoInnerSizeX1, DecoInnerSizeY1; // Applied AFTER/OVER InnerRect. Specialized for Tables as they use specialized form of clipping and frozen rows/columns are inside InnerRect (and not part of regular decoration sizes). float DecoInnerSizeX1, DecoInnerSizeY1; // Applied AFTER/OVER InnerRect. Specialized for Tables as they use specialized form of clipping and frozen rows/columns are inside InnerRect (and not part of regular decoration sizes).
int NameBufLen; // Size of buffer storing Name. May be larger than strlen(Name)! int NameBufLen; // Size of buffer storing Name. May be larger than strlen(Name)!
ImGuiID MoveId; // == window->GetID("#MOVE") ImGuiID MoveId; // == window->GetID("#MOVE")
ImGuiID ChildId; // ID of corresponding item in parent window (for navigation to return from child window to parent window) ImGuiID ChildId; // ID of corresponding item in parent window (for navigation to return from child window to parent window)
ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
ImVec2 Scroll; ImVec2 Scroll;
ImVec2 ScrollMax; ImVec2 ScrollMax;
ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change)
@ -2539,7 +2555,6 @@ struct IMGUI_API ImGuiWindow
short BeginOrderWithinParent; // Begin() order within immediate parent window, if we are a child window. Otherwise 0. short BeginOrderWithinParent; // Begin() order within immediate parent window, if we are a child window. Otherwise 0.
short BeginOrderWithinContext; // Begin() order within entire imgui context. This is mostly used for debugging submission order related issues. short BeginOrderWithinContext; // Begin() order within entire imgui context. This is mostly used for debugging submission order related issues.
short FocusOrder; // Order within WindowsFocusOrder[], altered when windows are focused. short FocusOrder; // Order within WindowsFocusOrder[], altered when windows are focused.
ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
ImS8 AutoFitFramesX, AutoFitFramesY; ImS8 AutoFitFramesX, AutoFitFramesY;
bool AutoFitOnlyGrows; bool AutoFitOnlyGrows;
ImGuiDir AutoPosLastDirection; ImGuiDir AutoPosLastDirection;
@ -2608,10 +2623,8 @@ public:
// We don't use g.FontSize because the window may be != g.CurrentWindow. // We don't use g.FontSize because the window may be != g.CurrentWindow.
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
float CalcFontSize() const { ImGuiContext& g = *Ctx; float scale = g.FontBaseSize * FontWindowScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; } float CalcFontSize() const { ImGuiContext& g = *Ctx; float scale = g.FontBaseSize * FontWindowScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; }
float TitleBarHeight() const { ImGuiContext& g = *Ctx; return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + g.Style.FramePadding.y * 2.0f; } ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight)); }
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight; return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight); }
float MenuBarHeight() const { ImGuiContext& g = *Ctx; return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontSize() + g.Style.FramePadding.y * 2.0f : 0.0f; }
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); }
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -2992,7 +3005,7 @@ namespace ImGui
{ {
// Windows // Windows
// We should always have a CurrentWindow in the stack (there is an implicit "Debug" window) // We should always have a CurrentWindow in the stack (there is an implicit "Debug" window)
// If this ever crash because g.CurrentWindow is NULL it means that either // If this ever crashes because g.CurrentWindow is NULL, it means that either:
// - ImGui::NewFrame() has never been called, which is illegal. // - ImGui::NewFrame() has never been called, which is illegal.
// - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal. // - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; } inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; }
@ -3124,6 +3137,8 @@ namespace ImGui
IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);
IMGUI_API void PopItemFlag(); IMGUI_API void PopItemFlag();
IMGUI_API const ImGuiDataVarInfo* GetStyleVarInfo(ImGuiStyleVar idx); IMGUI_API const ImGuiDataVarInfo* GetStyleVarInfo(ImGuiStyleVar idx);
IMGUI_API void BeginDisabledOverrideReenable();
IMGUI_API void EndDisabledOverrideReenable();
// Logging/Capture // Logging/Capture
IMGUI_API void LogBegin(ImGuiLogType type, int auto_open_depth); // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name. IMGUI_API void LogBegin(ImGuiLogType type, int auto_open_depth); // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name.
@ -3131,16 +3146,16 @@ namespace ImGui
IMGUI_API void LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end = NULL); IMGUI_API void LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end = NULL);
IMGUI_API void LogSetNextTextDecoration(const char* prefix, const char* suffix); IMGUI_API void LogSetNextTextDecoration(const char* prefix, const char* suffix);
// Popups, Modals, Tooltips // Childs
IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags); IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags);
// Popups, Modals
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags);
IMGUI_API void OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None); IMGUI_API void OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None);
IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup); IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup);
IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup); IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup);
IMGUI_API void ClosePopupsExceptModals(); IMGUI_API void ClosePopupsExceptModals();
IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags); IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags);
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
IMGUI_API bool BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
IMGUI_API bool BeginTooltipHidden();
IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window); IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window);
IMGUI_API ImGuiWindow* GetTopMostPopupModal(); IMGUI_API ImGuiWindow* GetTopMostPopupModal();
IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal(); IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal();
@ -3148,6 +3163,10 @@ namespace ImGui
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window); IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy); IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
// Tooltips
IMGUI_API bool BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
IMGUI_API bool BeginTooltipHidden();
// Menus // Menus
IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags); IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags);
IMGUI_API bool BeginMenuEx(const char* label, const char* icon, bool enabled = true); IMGUI_API bool BeginMenuEx(const char* label, const char* icon, bool enabled = true);
@ -3450,7 +3469,7 @@ namespace ImGui
IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type); IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type);
IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format); IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format);
IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg_1, const void* arg_2); IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg_1, const void* arg_2);
IMGUI_API bool DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format); IMGUI_API bool DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format, void* p_data_when_empty = NULL);
IMGUI_API int DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2); IMGUI_API int DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2);
IMGUI_API bool DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max); IMGUI_API bool DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max);
@ -3461,6 +3480,7 @@ namespace ImGui
IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL); IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL);
inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); } inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); }
inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active
IMGUI_API void SetNextItemRefVal(ImGuiDataType data_type, void* p_data);
// Color // Color
IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags); IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags);
@ -3492,6 +3512,7 @@ namespace ImGui
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));
IMGUI_API void DebugTextUnformattedWithLocateItem(const char* line_begin, const char* line_end);
IMGUI_API void DebugLocateItem(ImGuiID target_id); // Call sparingly: only 1 at the same time! IMGUI_API void DebugLocateItem(ImGuiID target_id); // Call sparingly: only 1 at the same time!
IMGUI_API void DebugLocateItemOnHover(ImGuiID target_id); // Only call on reaction to a mouse Hover: because only 1 at the same time! IMGUI_API void DebugLocateItemOnHover(ImGuiID target_id); // Only call on reaction to a mouse Hover: because only 1 at the same time!
IMGUI_API void DebugLocateItemResolveWithLastItem(); IMGUI_API void DebugLocateItemResolveWithLastItem();

View File

@ -1,4 +1,4 @@
// dear imgui, v1.90.7 // dear imgui, v1.90.9 WIP
// (tables and columns code) // (tables and columns code)
/* /*
@ -437,6 +437,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
// For non-scrolling tables, WorkRect == OuterRect == InnerRect. // For non-scrolling tables, WorkRect == OuterRect == InnerRect.
// But at this point we do NOT have a correct value for .Max.y (unless a height has been explicitly passed in). It will only be updated in EndTable(). // But at this point we do NOT have a correct value for .Max.y (unless a height has been explicitly passed in). It will only be updated in EndTable().
table->WorkRect = table->OuterRect = table->InnerRect = outer_rect; table->WorkRect = table->OuterRect = table->InnerRect = outer_rect;
table->HasScrollbarYPrev = table->HasScrollbarYCurr = false;
} }
// Push a standardized ID for both child-using and not-child-using tables // Push a standardized ID for both child-using and not-child-using tables
@ -1490,9 +1491,13 @@ void ImGui::EndTable()
} }
else if (temp_data->UserOuterSize.x <= 0.0f) else if (temp_data->UserOuterSize.x <= 0.0f)
{ {
const float decoration_size = table->TempData->AngledHeadersExtraWidth + ((table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f); // Some references for this: #7651 + tests "table_reported_size", "table_reported_size_outer" equivalent Y block
outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth + decoration_size - temp_data->UserOuterSize.x); // - Checking for ImGuiTableFlags_ScrollX/ScrollY flag makes us a frame ahead when disabling those flags.
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth)); // - FIXME-TABLE: Would make sense to pre-compute expected scrollbar visibility/sizes to generally save a frame of feedback.
const float inner_content_max_x = table->OuterRect.Min.x + table->ColumnsAutoFitWidth; // Slightly misleading name but used for code symmetry with inner_content_max_y
const float decoration_size = table->TempData->AngledHeadersExtraWidth + ((table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.x : 0.0f);
outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, inner_content_max_x + decoration_size - temp_data->UserOuterSize.x);
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, inner_content_max_x + decoration_size));
} }
else else
{ {
@ -1500,9 +1505,9 @@ void ImGui::EndTable()
} }
if (temp_data->UserOuterSize.y <= 0.0f) if (temp_data->UserOuterSize.y <= 0.0f)
{ {
const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.y : 0.0f; const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.y : 0.0f;
outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - temp_data->UserOuterSize.y); outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - temp_data->UserOuterSize.y);
outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y)); outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y + decoration_size));
} }
else else
{ {
@ -2795,7 +2800,7 @@ ImGuiTableSortSpecs* ImGui::TableGetSortSpecs()
static inline ImGuiSortDirection TableGetColumnAvailSortDirection(ImGuiTableColumn* column, int n) static inline ImGuiSortDirection TableGetColumnAvailSortDirection(ImGuiTableColumn* column, int n)
{ {
IM_ASSERT(n < column->SortDirectionsAvailCount); IM_ASSERT(n < column->SortDirectionsAvailCount);
return (column->SortDirectionsAvailList >> (n << 1)) & 0x03; return (ImGuiSortDirection)((column->SortDirectionsAvailList >> (n << 1)) & 0x03);
} }
// Fix sort direction if currently set on a value which is unavailable (e.g. activating NoSortAscending/NoSortDescending) // Fix sort direction if currently set on a value which is unavailable (e.g. activating NoSortAscending/NoSortDescending)
@ -2949,7 +2954,7 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
sort_spec->ColumnUserID = column->UserID; sort_spec->ColumnUserID = column->UserID;
sort_spec->ColumnIndex = (ImGuiTableColumnIdx)column_n; sort_spec->ColumnIndex = (ImGuiTableColumnIdx)column_n;
sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder; sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder;
sort_spec->SortDirection = column->SortDirection; sort_spec->SortDirection = (ImGuiSortDirection)column->SortDirection;
} }
table->SortSpecs.Specs = sort_specs; table->SortSpecs.Specs = sort_specs;

View File

@ -1,4 +1,4 @@
// dear imgui, v1.90.7 // dear imgui, v1.90.9 WIP
// (widgets code) // (widgets code)
/* /*
@ -488,7 +488,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
// Default only reacts to left mouse button // Default only reacts to left mouse button
if ((flags & ImGuiButtonFlags_MouseButtonMask_) == 0) if ((flags & ImGuiButtonFlags_MouseButtonMask_) == 0)
flags |= ImGuiButtonFlags_MouseButtonDefault_; flags |= ImGuiButtonFlags_MouseButtonLeft;
// Default behavior requires click + release inside bounding box // Default behavior requires click + release inside bounding box
if ((flags & ImGuiButtonFlags_PressedOnMask_) == 0) if ((flags & ImGuiButtonFlags_PressedOnMask_) == 0)
@ -916,10 +916,10 @@ void ImGui::Scrollbar(ImGuiAxis axis)
if (!window->ScrollbarX) if (!window->ScrollbarX)
rounding_corners |= ImDrawFlags_RoundCornersBottomRight; rounding_corners |= ImDrawFlags_RoundCornersBottomRight;
} }
float size_avail = window->InnerRect.Max[axis] - window->InnerRect.Min[axis]; float size_visible = window->InnerRect.Max[axis] - window->InnerRect.Min[axis];
float size_contents = window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f; float size_contents = window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f;
ImS64 scroll = (ImS64)window->Scroll[axis]; ImS64 scroll = (ImS64)window->Scroll[axis];
ScrollbarEx(bb, id, axis, &scroll, (ImS64)size_avail, (ImS64)size_contents, rounding_corners); ScrollbarEx(bb, id, axis, &scroll, (ImS64)size_visible, (ImS64)size_contents, rounding_corners);
window->Scroll[axis] = (float)scroll; window->Scroll[axis] = (float)scroll;
} }
@ -929,7 +929,7 @@ void ImGui::Scrollbar(ImGuiAxis axis)
// - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar // - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar
// - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal. // - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal.
// Still, the code should probably be made simpler.. // Still, the code should probably be made simpler..
bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 size_avail_v, ImS64 size_contents_v, ImDrawFlags flags) bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 size_visible_v, ImS64 size_contents_v, ImDrawFlags flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
@ -959,9 +959,9 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
// Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount) // Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount)
// But we maintain a minimum size in pixel to allow for the user to still aim inside. // But we maintain a minimum size in pixel to allow for the user to still aim inside.
IM_ASSERT(ImMax(size_contents_v, size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers. IM_ASSERT(ImMax(size_contents_v, size_visible_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers.
const ImS64 win_size_v = ImMax(ImMax(size_contents_v, size_avail_v), (ImS64)1); const ImS64 win_size_v = ImMax(ImMax(size_contents_v, size_visible_v), (ImS64)1);
const float grab_h_pixels = ImClamp(scrollbar_size_v * ((float)size_avail_v / (float)win_size_v), style.GrabMinSize, scrollbar_size_v); const float grab_h_pixels = ImClamp(scrollbar_size_v * ((float)size_visible_v / (float)win_size_v), style.GrabMinSize, scrollbar_size_v);
const float grab_h_norm = grab_h_pixels / scrollbar_size_v; const float grab_h_norm = grab_h_pixels / scrollbar_size_v;
// Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar(). // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().
@ -970,7 +970,7 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
ItemAdd(bb_frame, id, NULL, ImGuiItemFlags_NoNav); ItemAdd(bb_frame, id, NULL, ImGuiItemFlags_NoNav);
ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus);
const ImS64 scroll_max = ImMax((ImS64)1, size_contents_v - size_avail_v); const ImS64 scroll_max = ImMax((ImS64)1, size_contents_v - size_visible_v);
float scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max); float scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max);
float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; // Grab position in normalized space float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; // Grab position in normalized space
if (held && allow_interaction && grab_h_norm < 1.0f) if (held && allow_interaction && grab_h_norm < 1.0f)
@ -981,29 +981,39 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
// Click position in scrollbar normalized space (0.0f->1.0f) // Click position in scrollbar normalized space (0.0f->1.0f)
const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v); const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v);
bool seek_absolute = false; 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 calculate the distance between mouse and the center of the grab
seek_absolute = (clicked_v_norm < grab_v_norm || clicked_v_norm > grab_v_norm + grab_h_norm); g.ScrollbarSeekMode = (short)held_dir;
if (seek_absolute) g.ScrollbarClickDeltaToGrabCenter = (g.ScrollbarSeekMode == 0.0f) ? clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f : 0.0f;
g.ScrollbarClickDeltaToGrabCenter = 0.0f;
else
g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f;
} }
// 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)
// It is ok to modify Scroll here because we are being called in Begin() after the calculation of ContentSize and before setting up our starting position // It is ok to modify Scroll here because we are being called in Begin() after the calculation of ContentSize and before setting up our starting position
const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm)); if (g.ScrollbarSeekMode == 0)
*p_scroll_v = (ImS64)(scroll_v_norm * scroll_max); {
// Absolute seeking
const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm));
*p_scroll_v = (ImS64)(scroll_v_norm * scroll_max);
}
else
{
// Page by page
if (IsMouseClicked(ImGuiMouseButton_Left, ImGuiInputFlags_Repeat) && held_dir == g.ScrollbarSeekMode)
{
float page_dir = (g.ScrollbarSeekMode > 0.0f) ? +1.0f : -1.0f;
*p_scroll_v = ImClamp(*p_scroll_v + (ImS64)(page_dir * size_visible_v), (ImS64)0, scroll_max);
}
}
// Update values for rendering // Update values for rendering
scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max); scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max);
grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
// Update distance to grab now that we have seek'ed and saturated // Update distance to grab now that we have seek'ed and saturated
if (seek_absolute) //if (seek_absolute)
g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f; // g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f;
} }
// Render // Render
@ -1942,28 +1952,30 @@ bool ImGui::Combo(const char* label, int* current_item, const char* (*getter)(vo
return false; return false;
// Display items // Display items
// FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed)
bool value_changed = false; bool value_changed = false;
for (int i = 0; i < items_count; i++) ImGuiListClipper clipper;
{ clipper.Begin(items_count);
const char* item_text = getter(user_data, i); clipper.IncludeItemByIndex(*current_item);
if (item_text == NULL) while (clipper.Step())
item_text = "*Unknown item*"; for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
PushID(i);
const bool item_selected = (i == *current_item);
if (Selectable(item_text, item_selected) && *current_item != i)
{ {
value_changed = true; const char* item_text = getter(user_data, i);
*current_item = i; if (item_text == NULL)
item_text = "*Unknown item*";
PushID(i);
const bool item_selected = (i == *current_item);
if (Selectable(item_text, item_selected) && *current_item != i)
{
value_changed = true;
*current_item = i;
}
if (item_selected)
SetItemDefaultFocus();
PopID();
} }
if (item_selected)
SetItemDefaultFocus();
PopID();
}
EndCombo(); EndCombo();
if (value_changed) if (value_changed)
MarkItemEdited(g.LastItemData.ID); MarkItemEdited(g.LastItemData.ID);
@ -2129,17 +2141,24 @@ void ImGui::DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const
// User can input math operators (e.g. +100) to edit a numerical values. // User can input math operators (e.g. +100) to edit a numerical values.
// NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess.. // NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess..
bool ImGui::DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format) bool ImGui::DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format, void* p_data_when_empty)
{ {
// Copy the value in an opaque buffer so we can compare at the end of the function if it changed at all.
const ImGuiDataTypeInfo* type_info = DataTypeGetInfo(data_type);
ImGuiDataTypeStorage data_backup;
memcpy(&data_backup, p_data, type_info->Size);
while (ImCharIsBlankA(*buf)) while (ImCharIsBlankA(*buf))
buf++; buf++;
if (!buf[0]) if (!buf[0])
{
if (p_data_when_empty != NULL)
{
memcpy(p_data, p_data_when_empty, type_info->Size);
return memcmp(&data_backup, p_data, type_info->Size) != 0;
}
return false; return false;
}
// Copy the value in an opaque buffer so we can compare at the end of the function if it changed at all.
const ImGuiDataTypeInfo* type_info = DataTypeGetInfo(data_type);
ImGuiDataTypeTempStorage data_backup;
memcpy(&data_backup, p_data, type_info->Size);
// Sanitize format // Sanitize format
// - For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf // - For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf
@ -3474,11 +3493,11 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
{ {
// Backup old value // Backup old value
size_t data_type_size = type_info->Size; size_t data_type_size = type_info->Size;
ImGuiDataTypeTempStorage data_backup; ImGuiDataTypeStorage data_backup;
memcpy(&data_backup, p_data, data_type_size); memcpy(&data_backup, p_data, data_type_size);
// Apply new value (or operations) then clamp // Apply new value (or operations) then clamp
DataTypeApplyFromText(data_buf, data_type, p_data, format); DataTypeApplyFromText(data_buf, data_type, p_data, format, NULL);
if (p_clamp_min || p_clamp_max) if (p_clamp_min || p_clamp_max)
{ {
if (p_clamp_min && p_clamp_max && DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0) if (p_clamp_min && p_clamp_max && DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0)
@ -3494,6 +3513,13 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
return value_changed; return value_changed;
} }
void ImGui::SetNextItemRefVal(ImGuiDataType data_type, void* p_data)
{
ImGuiContext& g = *GImGui;
g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasRefVal;
memcpy(&g.NextItemData.RefVal, p_data, DataTypeGetInfo(data_type)->Size);
}
// Note: p_data, p_step, p_step_fast are _pointers_ to a memory address holding the data. For an Input widget, p_step and p_step_fast are optional. // Note: p_data, p_step, p_step_fast are _pointers_ to a memory address holding the data. For an Input widget, p_step and p_step_fast are optional.
// Read code of e.g. InputFloat(), InputInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. // Read code of e.g. InputFloat(), InputInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly.
bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags) bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags)
@ -3508,8 +3534,13 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
if (format == NULL) if (format == NULL)
format = DataTypeGetInfo(data_type)->PrintFmt; format = DataTypeGetInfo(data_type)->PrintFmt;
void* p_data_default = (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasRefVal) ? &g.NextItemData.RefVal : &g.DataTypeZeroValue;
char buf[64]; char buf[64];
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format); if ((flags & ImGuiInputTextFlags_DisplayEmptyRefVal) && DataTypeCompare(data_type, p_data, p_data_default) == 0)
buf[0] = 0;
else
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format);
flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string. flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
flags |= (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint; flags |= (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
@ -3518,7 +3549,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
if (p_step == NULL) if (p_step == NULL)
{ {
if (InputText(label, buf, IM_ARRAYSIZE(buf), flags)) if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format); value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
} }
else else
{ {
@ -3528,7 +3559,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
PushID(label); PushID(label);
SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2)); SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format); value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Inputable); IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Inputable);
// Step buttons // Step buttons
@ -6500,7 +6531,7 @@ void ImGui::SetNextItemOpen(bool is_open, ImGuiCond cond)
return; return;
g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasOpen; g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasOpen;
g.NextItemData.OpenVal = is_open; g.NextItemData.OpenVal = is_open;
g.NextItemData.OpenCond = cond ? cond : ImGuiCond_Always; g.NextItemData.OpenCond = (ImU8)(cond ? cond : ImGuiCond_Always);
} }
// CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag). // CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag).
@ -7016,6 +7047,7 @@ bool ImGui::ListBox(const char* label, int* current_item, const char* (*getter)(
bool value_changed = false; bool value_changed = false;
ImGuiListClipper clipper; ImGuiListClipper clipper;
clipper.Begin(items_count, GetTextLineHeightWithSpacing()); // We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to. clipper.Begin(items_count, GetTextLineHeightWithSpacing()); // We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to.
clipper.IncludeItemByIndex(*current_item);
while (clipper.Step()) while (clipper.Step())
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
{ {
@ -7534,7 +7566,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
// Menu inside an horizontal menu bar // Menu inside an horizontal menu bar
// Selectable extend their highlight by half ItemSpacing in each direction. // Selectable extend their highlight by half ItemSpacing in each direction.
// For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin() // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin()
popup_pos = ImVec2(pos.x - 1.0f - IM_TRUNC(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight()); popup_pos = ImVec2(pos.x - 1.0f - IM_TRUNC(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight);
window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * 0.5f); window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * 0.5f);
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
float w = label_size.x; float w = label_size.x;
@ -8300,7 +8332,7 @@ ImGuiTabItem* ImGui::TabBarFindTabByOrder(ImGuiTabBar* tab_bar, int order)
ImGuiTabItem* ImGui::TabBarGetCurrentTab(ImGuiTabBar* tab_bar) ImGuiTabItem* ImGui::TabBarGetCurrentTab(ImGuiTabBar* tab_bar)
{ {
if (tab_bar->LastTabItemIdx <= 0 || tab_bar->LastTabItemIdx >= tab_bar->Tabs.Size) if (tab_bar->LastTabItemIdx < 0 || tab_bar->LastTabItemIdx >= tab_bar->Tabs.Size)
return NULL; return NULL;
return &tab_bar->Tabs[tab_bar->LastTabItemIdx]; return &tab_bar->Tabs[tab_bar->LastTabItemIdx];
} }