diff --git a/3rdparty/dear-imgui/imgui.cpp b/3rdparty/dear-imgui/imgui.cpp index 13c1a8029..247f8dddb 100644 --- a/3rdparty/dear-imgui/imgui.cpp +++ b/3rdparty/dear-imgui/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.7 +// dear imgui, v1.90.9 WIP // (main code and documentation) // 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. 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): - old: CaptureKeyboardFromApp(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 -static ImGuiStorage::ImGuiStoragePair* LowerBound(ImVector& data, ImGuiID key) +ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStoragePair* in_end, ImGuiID key) { - ImGuiStorage::ImGuiStoragePair* first = data.Data; - ImGuiStorage::ImGuiStoragePair* last = data.Data + data.Size; - size_t count = (size_t)(last - first); - while (count > 0) + ImGuiStoragePair* in_p = in_begin; + for (size_t count = (size_t)(in_end - in_p); count > 0; ) { size_t count2 = count >> 1; - ImGuiStorage::ImGuiStoragePair* mid = first + count2; + ImGuiStoragePair* mid = in_p + count2; if (mid->key < key) { - first = ++mid; + in_p = ++mid; count -= count2 + 1; } else @@ -2521,7 +2522,7 @@ static ImGuiStorage::ImGuiStoragePair* LowerBound(ImVector&>(Data), key); + ImGuiStoragePair* it = ImLowerBound(const_cast(Data.Data), const_cast(Data.Data + Data.Size), key); if (it == Data.end() || it->key != key) return default_val; 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 { - ImGuiStoragePair* it = LowerBound(const_cast&>(Data), key); + ImGuiStoragePair* it = ImLowerBound(const_cast(Data.Data), const_cast(Data.Data + Data.Size), key); if (it == Data.end() || it->key != key) return default_val; return it->val_f; @@ -2563,7 +2564,7 @@ float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const void* ImGuiStorage::GetVoidPtr(ImGuiID key) const { - ImGuiStoragePair* it = LowerBound(const_cast&>(Data), key); + ImGuiStoragePair* it = ImLowerBound(const_cast(Data.Data), const_cast(Data.Data + Data.Size), key); if (it == Data.end() || it->key != key) return NULL; 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. 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) it = Data.insert(it, ImGuiStoragePair(key, default_val)); return &it->val_i; @@ -2585,7 +2586,7 @@ bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool 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) it = Data.insert(it, ImGuiStoragePair(key, default_val)); return &it->val_f; @@ -2593,7 +2594,7 @@ float* ImGuiStorage::GetFloatRef(ImGuiID key, float 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) it = Data.insert(it, ImGuiStoragePair(key, default_val)); 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) 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) Data.insert(it, ImGuiStoragePair(key, val)); else @@ -2616,7 +2617,7 @@ void ImGuiStorage::SetBool(ImGuiID key, bool 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) Data.insert(it, ImGuiStoragePair(key, val)); else @@ -2625,7 +2626,7 @@ void ImGuiStorage::SetFloat(ImGuiID key, float 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) Data.insert(it, ImGuiStoragePair(key, val)); 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. if (!(item_flags & ImGuiItemFlags_NoWindowHoverableCheck) && !IsWindowContentHoverable(window, ImGuiHoveredFlags_None)) { - g.HoveredIdDisabled = true; + g.HoveredIdIsDisabled = true; return false; } @@ -4207,7 +4208,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag // Release active id if turning disabled if (g.ActiveId == id && id != 0) ClearActiveID(); - g.HoveredIdDisabled = true; + g.HoveredIdIsDisabled = true; return false; } @@ -4239,7 +4240,7 @@ bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id) ImGuiWindow* window = g.CurrentWindow; if (!bb.Overlaps(window->ClipRect)) if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId)) - if (!g.LogEnabled) + if (!g.ItemUnclipByLog) return true; return false; } @@ -4510,7 +4511,7 @@ void ImGui::UpdateMouseMovingWindowEndFrame() g.MovingWindow = NULL; // 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; } else if (root_window == NULL && g.NavWindow != NULL) @@ -4704,7 +4705,7 @@ void ImGui::NewFrame() g.HoveredIdPreviousFrame = g.HoveredId; g.HoveredId = 0; g.HoveredIdAllowOverlap = false; - g.HoveredIdDisabled = false; + g.HoveredIdIsDisabled = false; // Clear ActiveID if the item is not alive anymore. // 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 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; } @@ -5990,7 +5991,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si ImRect clamp_rect = visibility_rect; const bool window_move_from_title_bar = g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar); 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 size_target(FLT_MAX, FLT_MAX); @@ -6189,7 +6190,7 @@ static inline void ClampWindowPos(ImGuiWindow* window, const ImRect& visibility_ ImGuiContext& g = *GImGui; ImVec2 size_for_clamping = window->Size; 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); } @@ -6225,7 +6226,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window) } 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); } } @@ -6270,7 +6271,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar } if (override_alpha) 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 @@ -6564,6 +6565,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window_stack_data.Window = window; window_stack_data.ParentLastItemDataBackup = g.LastItemData; window_stack_data.StackSizesOnBegin.SetToContextState(&g); + window_stack_data.DisabledOverrideReenable = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0; g.CurrentWindowStack.push_back(window_stack_data); if (flags & ImGuiWindowFlags_ChildMenu) g.BeginMenuDepth++; @@ -6650,6 +6652,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // [EXPERIMENTAL] Skip Refresh mode 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() 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. 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->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. // 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; window->DecoOuterSizeX1 = 0.0f; window->DecoOuterSizeX2 = 0.0f; - window->DecoOuterSizeY1 = window->TitleBarHeight() + window->MenuBarHeight(); + window->DecoOuterSizeY1 = window->TitleBarHeight + window->MenuBarHeight; window->DecoOuterSizeY2 = 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->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) - 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); // 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!"); 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. if (window->Flags & ImGuiWindowFlags_ChildWindow) @@ -7259,6 +7267,8 @@ void ImGui::End() if (!window->SkipRefresh) PopClipRect(); // Inner window clip rectangle PopFocusScope(); + if (window_stack_data.DisabledOverrideReenable && window->RootWindow == window) + EndDisabledOverrideReenable(); if (window->SkipRefresh) { @@ -7274,12 +7284,12 @@ void ImGui::End() ErrorCheckUsingSetCursorPosToExtendParentBoundaries(); // Pop from window stack - g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup; + g.LastItemData = window_stack_data.ParentLastItemDataBackup; if (window->Flags & ImGuiWindowFlags_ChildMenu) g.BeginMenuDepth--; if (window->Flags & ImGuiWindowFlags_Popup) g.BeginPopupStack.pop_back(); - g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithContextState(&g); + window_stack_data.StackSizesOnBegin.CompareWithContextState(&g); g.CurrentWindowStack.pop_back(); 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 (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 : "", blocking_modal->Name); 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; } @@ -7523,7 +7537,7 @@ void ImGui::BeginDisabled(bool disabled) } if (was_disabled || 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++; } @@ -7540,6 +7554,29 @@ void ImGui::EndDisabled() 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) { PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); @@ -8870,7 +8907,7 @@ bool ImGui::IsMouseDown(ImGuiMouseButton button, ImGuiID owner_id) 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) @@ -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. 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() @@ -9884,10 +9921,6 @@ static void ImGui::ErrorCheckNewFrameSanityChecks() 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."); #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() @@ -9995,7 +10028,13 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044 { 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) { @@ -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 // 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) +IM_MSVC_RUNTIME_CHECKS_OFF bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags) { ImGuiContext& g = *GImGui; @@ -10136,15 +10176,12 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu #endif // Clipping test - // (this is a modified copy of IsClippedEx() so we can reuse the is_rect_visible value) - //const bool is_clipped = IsClippedEx(bb, id); - //if (is_clipped) - // return false; + // (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') // 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); if (!is_rect_visible) if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId)) - if (!g.LogEnabled) + if (!g.ItemUnclipByLog) return false; // [DEBUG] @@ -10171,7 +10208,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect; return true; } - +IM_MSVC_RUNTIME_CHECKS_RESTORE //----------------------------------------------------------------------------- // [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. // See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different. // THIS IS IN THE PERFORMANCE CRITICAL PATH. +IM_MSVC_RUNTIME_CHECKS_OFF void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) { ImGuiContext& g = *GImGui; @@ -10243,6 +10281,7 @@ void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) SameLine(); } +IM_MSVC_RUNTIME_CHECKS_RESTORE // Gets back to previous line and continue with horizontal layout // offset_from_start_x == 0 : follow right after previous item @@ -11196,8 +11235,8 @@ void ImGui::CloseCurrentPopup() window->DC.NavHideHighlightOneFrame = true; } -// Attention! BeginPopup() adds default flags which BeginPopupEx()! -bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags) +// Attention! BeginPopup() adds default flags when calling BeginPopupEx()! +bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags) { ImGuiContext& g = *GImGui; if (!IsPopupOpen(id, ImGuiPopupFlags_None)) @@ -11207,13 +11246,12 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags) } 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 else 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, flags); + bool is_open = Begin(name, NULL, extra_window_flags | ImGuiWindowFlags_Popup); if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display) EndPopup(); @@ -13096,6 +13134,8 @@ bool ImGui::IsDragDropActive() void ImGui::ClearDragDrop() { ImGuiContext& g = *GImGui; + if (g.DragDropActive) + IMGUI_DEBUG_LOG_ACTIVEID("[dragdrop] ClearDragDrop()\n"); g.DragDropActive = false; g.DragDropPayload.Clear(); g.DragDropAcceptFlags = ImGuiDragDropFlags_None; @@ -13134,7 +13174,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) bool source_drag_active = false; ImGuiID source_id = 0; ImGuiID source_parent_id = 0; - if (!(flags & ImGuiDragDropFlags_SourceExtern)) + if ((flags & ImGuiDragDropFlags_SourceExtern) == 0) { source_id = g.LastItemData.ID; if (source_id != 0) @@ -13196,43 +13236,44 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) } 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(); - ImGuiPayload& payload = g.DragDropPayload; - payload.SourceId = source_id; - payload.SourceParentId = source_parent_id; - g.DragDropActive = true; - g.DragDropSourceFlags = flags; - g.DragDropMouseButton = mouse_button; - if (payload.SourceId == g.ActiveId) - 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; + IM_ASSERT(source_id != 0); + ClearDragDrop(); + IMGUI_DEBUG_LOG_ACTIVEID("[dragdrop] BeginDragDropSource() DragDropActive = true, source_id = %08X\n", source_id); + ImGuiPayload& payload = g.DragDropPayload; + payload.SourceId = source_id; + payload.SourceParentId = source_parent_id; + g.DragDropActive = true; + g.DragDropSourceFlags = flags; + g.DragDropMouseButton = mouse_button; + if (payload.SourceId == g.ActiveId) + g.ActiveIdNoClearOnFocusLoss = 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() @@ -13543,7 +13584,7 @@ void ImGui::LogBegin(ImGuiLogType type, int auto_open_depth) IM_ASSERT(g.LogEnabled == false); IM_ASSERT(g.LogFile == NULL); IM_ASSERT(g.LogBuffer.empty()); - g.LogEnabled = true; + g.LogEnabled = g.ItemUnclipByLog = true; g.LogType = type; g.LogNextPrefix = g.LogNextSuffix = NULL; g.LogDepthRef = window->DC.TreeDepth; @@ -13642,7 +13683,7 @@ void ImGui::LogFinish() break; } - g.LogEnabled = false; + g.LogEnabled = g.ItemUnclipByLog = false; g.LogType = ImGuiLogType_None; g.LogFile = NULL; 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())) 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. TreePop(); } @@ -15568,8 +15609,11 @@ void ImGui::DebugLogV(const char* fmt, va_list args) if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTTY) IMGUI_DEBUG_PRINTF("%s", g.DebugLogBuf.begin() + old_size); #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) - 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 } @@ -15637,25 +15681,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open) clipper.Begin(g.DebugLogIndex.size()); while (clipper.Step()) for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; 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; - } - } + DebugTextUnformattedWithLocateItem(g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no), g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no)); g.DebugLogFlags = backup_log_flags; if (GetScrollY() >= GetScrollMaxY()) SetScrollHereY(1.0f); @@ -15664,6 +15690,28 @@ void ImGui::ShowDebugLogWindow(bool* p_open) 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) //----------------------------------------------------------------------------- diff --git a/3rdparty/dear-imgui/imgui.h b/3rdparty/dear-imgui/imgui.h index 572cae804..c48fd4c75 100644 --- a/3rdparty/dear-imgui/imgui.h +++ b/3rdparty/dear-imgui/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.7 +// dear imgui, v1.90.9 WIP // (headers) // Help: @@ -27,8 +27,8 @@ // Library Version // (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_NUM 19070 +#define IMGUI_VERSION "1.90.9 WIP" +#define IMGUI_VERSION_NUM 19081 #define IMGUI_HAS_TABLE /* @@ -143,6 +143,17 @@ Index of this file: // [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 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) @@ -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 ImGuiPlatformImeData; // Platform IME data for io.SetPlatformImeDataFn() function. 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 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 @@ -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 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. +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 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 ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions 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 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 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) #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 // (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. @@ -1082,28 +1083,37 @@ enum ImGuiChildFlags_ // (Those are per-item flags. There are shared flags in ImGuiIO: io.ConfigInputTextCursorBlink and io.ConfigInputTextEnterKeepActive) enum ImGuiInputTextFlags_ { + // Basic filters (also see ImGuiInputTextFlags_CallbackCharFilter) ImGuiInputTextFlags_None = 0, ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/ ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef - ImGuiInputTextFlags_CharsUppercase = 1 << 2, // Turn a..z into A..Z - ImGuiInputTextFlags_CharsNoBlank = 1 << 3, // Filter out spaces, tabs - ImGuiInputTextFlags_AutoSelectAll = 1 << 4, // Select entire text when first taking mouse focus - 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) - ImGuiInputTextFlags_CallbackHistory = 1 << 7, // Callback on pressing Up/Down arrows (for history handling) - ImGuiInputTextFlags_CallbackAlways = 1 << 8, // Callback on each iteration. User code may query cursor position, modify text buffer. - 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_AllowTabInput = 1 << 10, // Pressing TAB input a '\t' character into the text field - 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 - ImGuiInputTextFlags_AlwaysOverwrite = 1 << 13, // Overwrite mode - ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode - ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*' + ImGuiInputTextFlags_CharsScientific = 1 << 2, // Allow 0123456789.+-*/eE (Scientific notation input) + ImGuiInputTextFlags_CharsUppercase = 1 << 3, // Turn a..z into A..Z + ImGuiInputTextFlags_CharsNoBlank = 1 << 4, // Filter out spaces, tabs + + // Inputs + ImGuiInputTextFlags_AllowTabInput = 1 << 5, // Pressing TAB input a '\t' character into the text field + 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_EscapeClearsAll = 1 << 7, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert) + 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). + + // Other options + ImGuiInputTextFlags_ReadOnly = 1 << 9, // Read-only mode + ImGuiInputTextFlags_Password = 1 << 10, // Password mode, display all characters as '*', disable copy + 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_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) - 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_EscapeClearsAll = 1 << 20, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert) + + // Callback features + ImGuiInputTextFlags_CallbackCompletion = 1 << 17, // Callback on pressing TAB (for completion handling) + 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 //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_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_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_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. @@ -1314,7 +1324,7 @@ enum ImGuiDataType_ }; // A cardinal direction -enum ImGuiDir_ +enum ImGuiDir : int { ImGuiDir_None = -1, ImGuiDir_Left = 0, @@ -1325,7 +1335,7 @@ enum ImGuiDir_ }; // A sorting direction -enum ImGuiSortDirection_ +enum ImGuiSortDirection : ImU8 { ImGuiSortDirection_None = 0, 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_MouseButtonRight = 1 << 1, // React on right mouse button ImGuiButtonFlags_MouseButtonMiddle = 1 << 2, // React on center mouse button - - // [Internal] - ImGuiButtonFlags_MouseButtonMask_ = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle, - ImGuiButtonFlags_MouseButtonDefault_ = ImGuiButtonFlags_MouseButtonLeft, + ImGuiButtonFlags_MouseButtonMask_ = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle, // [Internal] + //ImGuiButtonFlags_MouseButtonDefault_ = ImGuiButtonFlags_MouseButtonLeft, }; // 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) 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) - ImGuiSortDirection SortDirection : 8; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending + ImGuiSortDirection SortDirection; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending ImGuiTableColumnSortSpecs() { memset(this, 0, sizeof(*this)); } }; @@ -2073,9 +2081,9 @@ struct ImGuiStyle 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 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 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! - float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later. + ImVec2 DisplayWindowPadding; // Apply to regular windows: amount which we enforce to keep visible when moving near edges of your screen. + 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). 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 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). @@ -2453,6 +2461,16 @@ struct ImGuiTextBuffer 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 // 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) @@ -2464,15 +2482,6 @@ struct ImGuiTextBuffer struct ImGuiStorage { // [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 Data; // - 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(); // 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); + +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + //typedef ::ImGuiStoragePair ImGuiStoragePair; // 1.90.8: moved type outside struct +#endif }; // Helper: Manually clip large list of items. @@ -3256,7 +3269,7 @@ namespace ImGui static inline void PopAllowKeyboardFocus() { PopTabStop(); } // 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) - // 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! //static inline ImGuiKey GetKeyIndex(ImGuiKey key) { IM_ASSERT(key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END); return key; } diff --git a/3rdparty/dear-imgui/imgui_demo.cpp b/3rdparty/dear-imgui/imgui_demo.cpp index 92f4291c8..b2f0f4a14 100644 --- a/3rdparty/dear-imgui/imgui_demo.cpp +++ b/3rdparty/dear-imgui/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.7 +// dear imgui, v1.90.9 WIP // (demo code) // Help: @@ -2273,20 +2273,24 @@ static void ShowDemoWindowWidgets() IMGUI_DEMO_MARKER("Widgets/Data Types/Inputs"); static bool inputs_step = true; + static ImGuiInputTextFlags flags = ImGuiInputTextFlags_None; ImGui::SeparatorText("Inputs"); ImGui::Checkbox("Show step buttons", &inputs_step); - ImGui::InputScalar("input s8", ImGuiDataType_S8, &s8_v, inputs_step ? &s8_one : NULL, NULL, "%d"); - ImGui::InputScalar("input u8", ImGuiDataType_U8, &u8_v, inputs_step ? &u8_one : NULL, NULL, "%u"); - ImGui::InputScalar("input s16", ImGuiDataType_S16, &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d"); - ImGui::InputScalar("input u16", ImGuiDataType_U16, &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u"); - ImGui::InputScalar("input s32", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d"); - ImGui::InputScalar("input s32 hex", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%04X"); - ImGui::InputScalar("input u32", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u"); - ImGui::InputScalar("input u32 hex", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X"); - ImGui::InputScalar("input s64", ImGuiDataType_S64, &s64_v, inputs_step ? &s64_one : NULL); - ImGui::InputScalar("input u64", ImGuiDataType_U64, &u64_v, inputs_step ? &u64_one : NULL); - ImGui::InputScalar("input float", ImGuiDataType_Float, &f32_v, inputs_step ? &f32_one : NULL); - ImGui::InputScalar("input double", ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL); + ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly); + ImGui::CheckboxFlags("ImGuiInputTextFlags_ParseEmptyRefVal", &flags, ImGuiInputTextFlags_ParseEmptyRefVal); + ImGui::CheckboxFlags("ImGuiInputTextFlags_DisplayEmptyRefVal", &flags, ImGuiInputTextFlags_DisplayEmptyRefVal); + ImGui::InputScalar("input s8", ImGuiDataType_S8, &s8_v, inputs_step ? &s8_one : NULL, NULL, "%d", flags); + ImGui::InputScalar("input u8", ImGuiDataType_U8, &u8_v, inputs_step ? &u8_one : NULL, NULL, "%u", flags); + ImGui::InputScalar("input s16", ImGuiDataType_S16, &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d", flags); + ImGui::InputScalar("input u16", ImGuiDataType_U16, &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u", flags); + ImGui::InputScalar("input s32", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d", flags); + ImGui::InputScalar("input s32 hex", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%04X", flags); + ImGui::InputScalar("input u32", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u", flags); + ImGui::InputScalar("input u32 hex", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", flags); + 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(); } @@ -3875,7 +3879,7 @@ static void ShowDemoWindowPopups() static int item = 1; static float color[4] = { 0.4f, 0.7f, 0.0f, 0.5f }; 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..")) ImGui::OpenPopup("Stacked 2"); @@ -3887,6 +3891,7 @@ static void ShowDemoWindowPopups() if (ImGui::BeginPopupModal("Stacked 2", &unused_open)) { ImGui::Text("Hello from Stacked The Second!"); + ImGui::ColorEdit4("Color", color); // Allow opening another nested popup if (ImGui::Button("Close")) ImGui::CloseCurrentPopup(); ImGui::EndPopup(); @@ -6295,7 +6300,7 @@ static void ShowDemoWindowInputs() ImGui::RadioButton("ImGuiInputFlags_RouteAlways", &route_type, ImGuiInputFlags_RouteAlways); ImGuiInputFlags flags = route_type | route_options; // Merged flags 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::Text("Ctrl+S"); @@ -6768,7 +6773,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f"); int window_menu_button_position = style.WindowMenuButtonPosition + 1; 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::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); 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::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(); } diff --git a/3rdparty/dear-imgui/imgui_draw.cpp b/3rdparty/dear-imgui/imgui_draw.cpp index b96691133..171889f2c 100644 --- a/3rdparty/dear-imgui/imgui_draw.cpp +++ b/3rdparty/dear-imgui/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.7 +// dear imgui, v1.90.9 WIP // (drawing and font code) /* diff --git a/3rdparty/dear-imgui/imgui_internal.h b/3rdparty/dear-imgui/imgui_internal.h index f2ac5ad00..244cda1a2 100644 --- a/3rdparty/dear-imgui/imgui_internal.h +++ b/3rdparty/dear-imgui/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.7 +// dear imgui, v1.90.9 WIP // (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. @@ -14,8 +14,8 @@ Index of this file: // [SECTION] Macros // [SECTION] Generic helpers // [SECTION] ImDrawList support -// [SECTION] Widgets support: flags, enums, data structures // [SECTION] Data types support +// [SECTION] Widgets support: flags, enums, data structures // [SECTION] Popup support // [SECTION] Inputs support // [SECTION] Clipper support @@ -348,6 +348,7 @@ namespace ImStb // - Helper: ImPool<> // - Helper: ImChunkStream<> // - Helper: ImGuiTextIndex +// - Helper: ImGuiStorage //----------------------------------------------------------------------------- // Helpers: Hashing @@ -472,7 +473,7 @@ template static inline T ImSubClampOverflow(T a, T b, T mn, T mx) // - 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 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, 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); } @@ -722,7 +723,7 @@ struct ImChunkStream void swap(ImChunkStream& 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. struct ImGuiTextIndex { @@ -736,6 +737,8 @@ struct ImGuiTextIndex 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 //----------------------------------------------------------------------------- @@ -798,6 +801,40 @@ struct ImDrawDataBuilder 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 //----------------------------------------------------------------------------- @@ -1177,6 +1214,7 @@ enum ImGuiNextItemDataFlags_ ImGuiNextItemDataFlags_HasWidth = 1 << 0, ImGuiNextItemDataFlags_HasOpen = 1 << 1, ImGuiNextItemDataFlags_HasShortcut = 1 << 2, + ImGuiNextItemDataFlags_HasRefVal = 1 << 3, }; struct ImGuiNextItemData @@ -1189,7 +1227,8 @@ struct ImGuiNextItemData ImGuiKeyChord Shortcut; // Set by SetNextItemShortcut() ImGuiInputFlags ShortcutFlags; // Set by SetNextItemShortcut() 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; } inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()! @@ -1243,7 +1282,8 @@ struct ImGuiWindowStackData { ImGuiWindow* Window; 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 @@ -1262,40 +1302,6 @@ struct ImGuiPtrOrIndex 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 //----------------------------------------------------------------------------- @@ -1582,6 +1588,7 @@ enum ImGuiNavLayer ImGuiNavLayer_COUNT }; +// Storage for navigation query/results struct ImGuiNavItemData { 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; } }; +// Storage for PushFocusScope() struct ImGuiFocusScopeData { 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 HoveredId; // Hovered widget, filled during the frame 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 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 ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame) float ActiveIdTimer; @@ -2033,11 +2042,11 @@ struct ImGuiContext ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow' 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) - ImVector 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 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) ImGuiActivateFlags NavActivateFlags; + ImVector NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain. ImGuiID NavHighlightActivatedId; float NavHighlightActivatedTimer; ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest). @@ -2150,6 +2159,7 @@ struct ImGuiContext ImGuiInputTextDeactivatedState InputTextDeactivatedState; ImFont InputTextPasswordFont; ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc. + ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types int BeginMenuDepth; int BeginComboDepth; ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets @@ -2162,13 +2172,14 @@ struct ImGuiContext ImGuiComboPreviewData ComboPreviewData; ImRect WindowResizeBorderExpectedRect; // Expected border rect, switch to relative edit if moving 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 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 DragCurrentAccumDirty; 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 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? float DisabledAlphaBackup; // Backup for style.Alpha for BeginDisabled() short DisabledStackSize; short LockMarkEdited; @@ -2271,8 +2282,9 @@ struct ImGuiContext DebugHookIdInfo = 0; HoveredId = HoveredIdPreviousFrame = 0; HoveredIdAllowOverlap = false; - HoveredIdDisabled = false; + HoveredIdIsDisabled = false; HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f; + ItemUnclipByLog = false; ActiveId = 0; ActiveIdIsAlive = 0; ActiveIdTimer = 0.0f; @@ -2370,19 +2382,21 @@ struct ImGuiContext MouseStationaryTimer = 0.0f; TempInputId = 0; + memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue)); BeginMenuDepth = BeginComboDepth = 0; ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_; ColorEditCurrentID = ColorEditSavedID = 0; ColorEditSavedHue = ColorEditSavedSat = 0.0f; ColorEditSavedColor = 0; WindowResizeRelativeMode = false; + ScrollbarSeekMode = 0; + ScrollbarClickDeltaToGrabCenter = 0.0f; SliderGrabClickOffset = 0.0f; SliderCurrentAccum = 0.0f; SliderCurrentAccumDirty = false; DragCurrentAccumDirty = false; DragCurrentAccum = 0.0f; DragSpeedDefaultRatio = 1.0f / 100.0f; - ScrollbarClickDeltaToGrabCenter = 0.0f; DisabledAlphaBackup = 0.0f; DisabledStackSize = 0; LockMarkEdited = 0; @@ -2507,12 +2521,14 @@ struct IMGUI_API ImGuiWindow 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 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 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). int NameBufLen; // Size of buffer storing Name. May be larger than strlen(Name)! 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 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 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) @@ -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 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. - 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; bool AutoFitOnlyGrows; ImGuiDir AutoPosLastDirection; @@ -2608,10 +2623,8 @@ public: // 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); } 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())); } - 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()); } + 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); } }; //----------------------------------------------------------------------------- @@ -2992,7 +3005,7 @@ namespace ImGui { // Windows // 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. // - 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; } @@ -3124,6 +3137,8 @@ namespace ImGui IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); IMGUI_API void PopItemFlag(); IMGUI_API const ImGuiDataVarInfo* GetStyleVarInfo(ImGuiStyleVar idx); + IMGUI_API void BeginDisabledOverrideReenable(); + IMGUI_API void EndDisabledOverrideReenable(); // 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. @@ -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 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); + + // 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 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 ClosePopupsExceptModals(); 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 ImGuiWindow* GetTopMostPopupModal(); IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal(); @@ -3148,6 +3163,10 @@ namespace ImGui 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); + // Tooltips + IMGUI_API bool BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags); + IMGUI_API bool BeginTooltipHidden(); + // Menus 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); @@ -3450,7 +3469,7 @@ namespace ImGui 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 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 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); 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 + IMGUI_API void SetNextItemRefVal(ImGuiDataType data_type, void* p_data); // Color 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 DebugDrawLineExtents(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 DebugLocateItemOnHover(ImGuiID target_id); // Only call on reaction to a mouse Hover: because only 1 at the same time! IMGUI_API void DebugLocateItemResolveWithLastItem(); diff --git a/3rdparty/dear-imgui/imgui_tables.cpp b/3rdparty/dear-imgui/imgui_tables.cpp index 10daf40f4..778d27afd 100644 --- a/3rdparty/dear-imgui/imgui_tables.cpp +++ b/3rdparty/dear-imgui/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.7 +// dear imgui, v1.90.9 WIP // (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. // 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->HasScrollbarYPrev = table->HasScrollbarYCurr = false; } // 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) { - const float decoration_size = table->TempData->AngledHeadersExtraWidth + ((table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f); - outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth + decoration_size - temp_data->UserOuterSize.x); - outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth)); + // Some references for this: #7651 + tests "table_reported_size", "table_reported_size_outer" equivalent Y block + // - Checking for ImGuiTableFlags_ScrollX/ScrollY flag makes us a frame ahead when disabling those flags. + // - 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 { @@ -1500,9 +1505,9 @@ void ImGui::EndTable() } 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.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 { @@ -2795,7 +2800,7 @@ ImGuiTableSortSpecs* ImGui::TableGetSortSpecs() static inline ImGuiSortDirection TableGetColumnAvailSortDirection(ImGuiTableColumn* column, int n) { 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) @@ -2949,7 +2954,7 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table) sort_spec->ColumnUserID = column->UserID; sort_spec->ColumnIndex = (ImGuiTableColumnIdx)column_n; sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder; - sort_spec->SortDirection = column->SortDirection; + sort_spec->SortDirection = (ImGuiSortDirection)column->SortDirection; } table->SortSpecs.Specs = sort_specs; diff --git a/3rdparty/dear-imgui/imgui_widgets.cpp b/3rdparty/dear-imgui/imgui_widgets.cpp index 2ece50ec5..4d83d9ccc 100644 --- a/3rdparty/dear-imgui/imgui_widgets.cpp +++ b/3rdparty/dear-imgui/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.7 +// dear imgui, v1.90.9 WIP // (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 if ((flags & ImGuiButtonFlags_MouseButtonMask_) == 0) - flags |= ImGuiButtonFlags_MouseButtonDefault_; + flags |= ImGuiButtonFlags_MouseButtonLeft; // Default behavior requires click + release inside bounding box if ((flags & ImGuiButtonFlags_PressedOnMask_) == 0) @@ -916,10 +916,10 @@ void ImGui::Scrollbar(ImGuiAxis axis) if (!window->ScrollbarX) 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; 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; } @@ -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 handle both horizontal and vertical scrollbars, which makes the terminology not ideal. // 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; 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) // 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. - const ImS64 win_size_v = ImMax(ImMax(size_contents_v, size_avail_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); + 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_visible_v), (ImS64)1); + 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; // 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); 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 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) @@ -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) 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) { // 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); - if (seek_absolute) - g.ScrollbarClickDeltaToGrabCenter = 0.0f; - else - g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f; + g.ScrollbarSeekMode = (short)held_dir; + g.ScrollbarClickDeltaToGrabCenter = (g.ScrollbarSeekMode == 0.0f) ? clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f : 0.0f; } // Apply scroll (p_scroll_v will generally point on one member of window->Scroll) // 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)); - *p_scroll_v = (ImS64)(scroll_v_norm * scroll_max); + if (g.ScrollbarSeekMode == 0) + { + // 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 scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max); 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 - if (seek_absolute) - g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f; + //if (seek_absolute) + // g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f; } // Render @@ -1942,28 +1952,30 @@ bool ImGui::Combo(const char* label, int* current_item, const char* (*getter)(vo return false; // 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; - for (int i = 0; i < items_count; i++) - { - const char* item_text = getter(user_data, 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) + ImGuiListClipper clipper; + clipper.Begin(items_count); + clipper.IncludeItemByIndex(*current_item); + while (clipper.Step()) + for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { - value_changed = true; - *current_item = i; + const char* item_text = getter(user_data, 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(); - if (value_changed) 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. // 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)) buf++; 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; - - // 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 // - 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 size_t data_type_size = type_info->Size; - ImGuiDataTypeTempStorage data_backup; + ImGuiDataTypeStorage data_backup; memcpy(&data_backup, p_data, data_type_size); // 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 && 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; } +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. // 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) @@ -3508,8 +3534,13 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data if (format == NULL) format = DataTypeGetInfo(data_type)->PrintFmt; + void* p_data_default = (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasRefVal) ? &g.NextItemData.RefVal : &g.DataTypeZeroValue; + 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)ImGuiInputTextFlags_LocalizeDecimalPoint; @@ -3518,7 +3549,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data if (p_step == NULL) { 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 { @@ -3528,7 +3559,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data PushID(label); 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 - 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); // Step buttons @@ -6500,7 +6531,7 @@ void ImGui::SetNextItemOpen(bool is_open, ImGuiCond cond) return; g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasOpen; 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). @@ -7016,6 +7047,7 @@ bool ImGui::ListBox(const char* label, int* current_item, const char* (*getter)( bool value_changed = false; 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.IncludeItemByIndex(*current_item); while (clipper.Step()) 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 // 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() - 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); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); float w = label_size.x; @@ -8300,7 +8332,7 @@ ImGuiTabItem* ImGui::TabBarFindTabByOrder(ImGuiTabBar* tab_bar, int order) 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 &tab_bar->Tabs[tab_bar->LastTabItemIdx]; }