From 63c60285225c32e339fb34157afe8c9c1c3f37aa Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sat, 3 Aug 2024 23:49:47 +0200 Subject: [PATCH] build: Updated ImGui to v1.91.0 --- lib/third_party/fmt | 2 +- .../ColorTextEditor/source/TextEditor.cpp | 6 +- lib/third_party/imgui/cimgui/include/cimgui.h | 730 +++--- .../imgui/cimgui/source/cimgui.cpp | 526 +++-- lib/third_party/imgui/imgui/include/imgui.h | 330 ++- .../imgui/imgui/include/imgui_internal.h | 212 +- lib/third_party/imgui/imgui/source/imgui.cpp | 427 ++-- .../imgui/imgui/source/imgui_demo.cpp | 2041 +++++++++++++++-- .../imgui/imgui/source/imgui_draw.cpp | 5 +- .../imgui/imgui/source/imgui_tables.cpp | 55 +- .../imgui/imgui/source/imgui_widgets.cpp | 1431 ++++++++++-- .../content/views/view_pattern_editor.hpp | 2 +- .../content/views/view_command_palette.cpp | 6 +- .../source/content/views/view_hex_editor.cpp | 2 +- .../source/content/views/view_settings.cpp | 2 +- .../ui/include/popups/popup_file_chooser.hpp | 2 +- 16 files changed, 4619 insertions(+), 1160 deletions(-) diff --git a/lib/third_party/fmt b/lib/third_party/fmt index 0041a40c1..0c9fce2ff 160000 --- a/lib/third_party/fmt +++ b/lib/third_party/fmt @@ -1 +1 @@ -Subproject commit 0041a40c1350ba702d475b9c4ad62da77caea164 +Subproject commit 0c9fce2ffefecfdce794e1859584e25877b7b592 diff --git a/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp b/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp index bc91a8a98..3c734fb25 100644 --- a/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp +++ b/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp @@ -834,7 +834,7 @@ void TextEditor::Render() { assert(mLineBuffer.empty()); - auto contentSize = ImGui::GetWindowContentRegionMax() - ImVec2(0,mTopMargin); + auto contentSize = ImGui::GetCurrentWindowRead()->ContentRegionRect.Max - ImGui::GetWindowPos() - ImVec2(0,mTopMargin); auto drawList = ImGui::GetWindowDrawList(); float longest(mTextStart); @@ -1164,7 +1164,7 @@ void TextEditor::Render(const char *aTitle, const ImVec2 &aSize, bool aBorder) { if (mHandleKeyboardInputs) { HandleKeyboardInputs(); - ImGui::PushTabStop(true); + ImGui::PushItemFlag(ImGuiItemFlags_NoTabStop, false); } if (mHandleMouseInputs) @@ -1174,7 +1174,7 @@ void TextEditor::Render(const char *aTitle, const ImVec2 &aSize, bool aBorder) { Render(); if (mHandleKeyboardInputs) - ImGui::PopTabStop(); + ImGui::PopItemFlag(); if (!mIgnoreImGuiChild) ImGui::EndChild(); diff --git a/lib/third_party/imgui/cimgui/include/cimgui.h b/lib/third_party/imgui/cimgui/include/cimgui.h index cc5b4e685..e46205a5d 100644 --- a/lib/third_party/imgui/cimgui/include/cimgui.h +++ b/lib/third_party/imgui/cimgui/include/cimgui.h @@ -1,5 +1,5 @@ //This file is automatically generated by generator.lua from https://github.com/cimgui/cimgui -//based on imgui.h file version "1.90.4" 19040 from Dear ImGui https://github.com/ocornut/imgui +//based on imgui.h file version "1.91.0" 19100 from Dear ImGui https://github.com/ocornut/imgui //with imgui_internal.h api //docking branch #ifndef CIMGUI_INCLUDED @@ -60,13 +60,18 @@ typedef struct ImGuiIO ImGuiIO; typedef struct ImGuiInputTextCallbackData ImGuiInputTextCallbackData; typedef struct ImGuiKeyData ImGuiKeyData; typedef struct ImGuiListClipper ImGuiListClipper; +typedef struct ImGuiMultiSelectIO ImGuiMultiSelectIO; typedef struct ImGuiOnceUponAFrame ImGuiOnceUponAFrame; typedef struct ImGuiPayload ImGuiPayload; typedef struct ImGuiPlatformIO ImGuiPlatformIO; typedef struct ImGuiPlatformMonitor ImGuiPlatformMonitor; typedef struct ImGuiPlatformImeData ImGuiPlatformImeData; +typedef struct ImGuiSelectionBasicStorage ImGuiSelectionBasicStorage; +typedef struct ImGuiSelectionExternalStorage ImGuiSelectionExternalStorage; +typedef struct ImGuiSelectionRequest ImGuiSelectionRequest; typedef struct ImGuiSizeCallbackData ImGuiSizeCallbackData; typedef struct ImGuiStorage ImGuiStorage; +typedef struct ImGuiStoragePair ImGuiStoragePair; typedef struct ImGuiStyle ImGuiStyle; typedef struct ImGuiTableSortSpecs ImGuiTableSortSpecs; typedef struct ImGuiTableColumnSortSpecs ImGuiTableColumnSortSpecs; @@ -77,6 +82,7 @@ typedef struct ImGuiWindowClass ImGuiWindowClass; typedef struct ImBitVector ImBitVector; typedef struct ImRect ImRect; typedef struct ImDrawDataBuilder ImDrawDataBuilder; +typedef struct ImGuiBoxSelectState ImGuiBoxSelectState; typedef struct ImGuiColorMod ImGuiColorMod; typedef struct ImGuiContextHook ImGuiContextHook; typedef struct ImGuiDataVarInfo ImGuiDataVarInfo; @@ -91,8 +97,9 @@ typedef struct ImGuiInputTextDeactivateData ImGuiInputTextDeactivateData; typedef struct ImGuiLastItemData ImGuiLastItemData; typedef struct ImGuiLocEntry ImGuiLocEntry; typedef struct ImGuiMenuColumns ImGuiMenuColumns; +typedef struct ImGuiMultiSelectState ImGuiMultiSelectState; +typedef struct ImGuiMultiSelectTempData ImGuiMultiSelectTempData; typedef struct ImGuiNavItemData ImGuiNavItemData; -typedef struct ImGuiNavTreeNodeData ImGuiNavTreeNodeData; typedef struct ImGuiMetricsConfig ImGuiMetricsConfig; typedef struct ImGuiNextWindowData ImGuiNextWindowData; typedef struct ImGuiNextItemData ImGuiNextItemData; @@ -102,22 +109,33 @@ typedef struct ImGuiPopupData ImGuiPopupData; typedef struct ImGuiSettingsHandler ImGuiSettingsHandler; typedef struct ImGuiStackSizes ImGuiStackSizes; typedef struct ImGuiStyleMod ImGuiStyleMod; -typedef struct ImGuiStyleShadowTexConfig ImGuiStyleShadowTexConfig; typedef struct ImGuiTabBar ImGuiTabBar; typedef struct ImGuiTabItem ImGuiTabItem; typedef struct ImGuiTable ImGuiTable; +typedef struct ImGuiTableHeaderData ImGuiTableHeaderData; typedef struct ImGuiTableColumn ImGuiTableColumn; typedef struct ImGuiTableInstanceData ImGuiTableInstanceData; typedef struct ImGuiTableTempData ImGuiTableTempData; typedef struct ImGuiTableSettings ImGuiTableSettings; typedef struct ImGuiTableColumnsSettings ImGuiTableColumnsSettings; +typedef struct ImGuiTreeNodeStackData ImGuiTreeNodeStackData; typedef struct ImGuiTypingSelectState ImGuiTypingSelectState; typedef struct ImGuiTypingSelectRequest ImGuiTypingSelectRequest; typedef struct ImGuiWindow ImGuiWindow; +typedef struct ImGuiWindowDockStyle ImGuiWindowDockStyle; typedef struct ImGuiWindowTempData ImGuiWindowTempData; typedef struct ImGuiWindowSettings ImGuiWindowSettings; typedef struct ImVector_const_charPtr {int Size;int Capacity;const char** Data;} ImVector_const_charPtr; +typedef unsigned int ImGuiID; +typedef signed char ImS8; +typedef unsigned char ImU8; +typedef signed short ImS16; +typedef unsigned short ImU16; +typedef signed int ImS32; +typedef unsigned int ImU32; +typedef signed long long ImS64; +typedef unsigned long long ImU64; struct ImDrawChannel; struct ImDrawCmd; struct ImDrawData; @@ -137,13 +155,18 @@ struct ImGuiIO; struct ImGuiInputTextCallbackData; struct ImGuiKeyData; struct ImGuiListClipper; +struct ImGuiMultiSelectIO; struct ImGuiOnceUponAFrame; struct ImGuiPayload; struct ImGuiPlatformIO; struct ImGuiPlatformMonitor; struct ImGuiPlatformImeData; +struct ImGuiSelectionBasicStorage; +struct ImGuiSelectionExternalStorage; +struct ImGuiSelectionRequest; struct ImGuiSizeCallbackData; struct ImGuiStorage; +struct ImGuiStoragePair; struct ImGuiStyle; struct ImGuiTableSortSpecs; struct ImGuiTableColumnSortSpecs; @@ -154,10 +177,8 @@ struct ImGuiWindowClass; typedef int ImGuiCol; typedef int ImGuiCond; typedef int ImGuiDataType; -typedef int ImGuiDir; typedef int ImGuiMouseButton; typedef int ImGuiMouseCursor; -typedef int ImGuiSortDirection; typedef int ImGuiStyleVar; typedef int ImGuiTableBgTarget; typedef int ImDrawFlags; @@ -173,9 +194,12 @@ typedef int ImGuiDockNodeFlags; typedef int ImGuiDragDropFlags; typedef int ImGuiFocusedFlags; typedef int ImGuiHoveredFlags; +typedef int ImGuiInputFlags; typedef int ImGuiInputTextFlags; +typedef int ImGuiItemFlags; typedef int ImGuiKeyChord; typedef int ImGuiPopupFlags; +typedef int ImGuiMultiSelectFlags; typedef int ImGuiSelectableFlags; typedef int ImGuiSliderFlags; typedef int ImGuiTabBarFlags; @@ -187,18 +211,11 @@ typedef int ImGuiTreeNodeFlags; typedef int ImGuiViewportFlags; typedef int ImGuiWindowFlags; typedef void* ImTextureID; -typedef unsigned int ImGuiID; -typedef signed char ImS8; -typedef unsigned char ImU8; -typedef signed short ImS16; -typedef unsigned short ImU16; -typedef signed int ImS32; -typedef unsigned int ImU32; -typedef signed long long ImS64; -typedef unsigned long long ImU64; +typedef unsigned short ImDrawIdx; typedef unsigned int ImWchar32; typedef unsigned short ImWchar16; typedef ImWchar16 ImWchar; +typedef ImS64 ImGuiSelectionUserData; typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); typedef void* (*ImGuiMemAllocFunc)(size_t sz, void* user_data); @@ -238,7 +255,6 @@ typedef enum { ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, ImGuiWindowFlags_NoDecoration = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse, ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, - ImGuiWindowFlags_NavFlattened = 1 << 23, ImGuiWindowFlags_ChildWindow = 1 << 24, ImGuiWindowFlags_Tooltip = 1 << 25, ImGuiWindowFlags_Popup = 1 << 26, @@ -256,30 +272,41 @@ typedef enum { ImGuiChildFlags_AutoResizeY = 1 << 5, ImGuiChildFlags_AlwaysAutoResize = 1 << 6, ImGuiChildFlags_FrameStyle = 1 << 7, + ImGuiChildFlags_NavFlattened = 1 << 8, }ImGuiChildFlags_; +typedef enum { + ImGuiItemFlags_None = 0, + ImGuiItemFlags_NoTabStop = 1 << 0, + ImGuiItemFlags_NoNav = 1 << 1, + ImGuiItemFlags_NoNavDefaultFocus = 1 << 2, + ImGuiItemFlags_ButtonRepeat = 1 << 3, + ImGuiItemFlags_AutoClosePopups = 1 << 4, +}ImGuiItemFlags_; typedef enum { ImGuiInputTextFlags_None = 0, ImGuiInputTextFlags_CharsDecimal = 1 << 0, ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, - ImGuiInputTextFlags_CharsUppercase = 1 << 2, - ImGuiInputTextFlags_CharsNoBlank = 1 << 3, - ImGuiInputTextFlags_AutoSelectAll = 1 << 4, - ImGuiInputTextFlags_EnterReturnsTrue = 1 << 5, - ImGuiInputTextFlags_CallbackCompletion = 1 << 6, - ImGuiInputTextFlags_CallbackHistory = 1 << 7, - ImGuiInputTextFlags_CallbackAlways = 1 << 8, - ImGuiInputTextFlags_CallbackCharFilter = 1 << 9, - ImGuiInputTextFlags_AllowTabInput = 1 << 10, - ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11, - ImGuiInputTextFlags_NoHorizontalScroll = 1 << 12, - ImGuiInputTextFlags_AlwaysOverwrite = 1 << 13, - ImGuiInputTextFlags_ReadOnly = 1 << 14, - ImGuiInputTextFlags_Password = 1 << 15, + ImGuiInputTextFlags_CharsScientific = 1 << 2, + ImGuiInputTextFlags_CharsUppercase = 1 << 3, + ImGuiInputTextFlags_CharsNoBlank = 1 << 4, + ImGuiInputTextFlags_AllowTabInput = 1 << 5, + ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, + ImGuiInputTextFlags_EscapeClearsAll = 1 << 7, + ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8, + ImGuiInputTextFlags_ReadOnly = 1 << 9, + ImGuiInputTextFlags_Password = 1 << 10, + ImGuiInputTextFlags_AlwaysOverwrite = 1 << 11, + ImGuiInputTextFlags_AutoSelectAll = 1 << 12, + ImGuiInputTextFlags_ParseEmptyRefVal = 1 << 13, + ImGuiInputTextFlags_DisplayEmptyRefVal = 1 << 14, + ImGuiInputTextFlags_NoHorizontalScroll = 1 << 15, ImGuiInputTextFlags_NoUndoRedo = 1 << 16, - ImGuiInputTextFlags_CharsScientific = 1 << 17, - ImGuiInputTextFlags_CallbackResize = 1 << 18, - ImGuiInputTextFlags_CallbackEdit = 1 << 19, - ImGuiInputTextFlags_EscapeClearsAll = 1 << 20, + ImGuiInputTextFlags_CallbackCompletion = 1 << 17, + ImGuiInputTextFlags_CallbackHistory = 1 << 18, + ImGuiInputTextFlags_CallbackAlways = 1 << 19, + ImGuiInputTextFlags_CallbackCharFilter = 1 << 20, + ImGuiInputTextFlags_CallbackResize = 1 << 21, + ImGuiInputTextFlags_CallbackEdit = 1 << 22, }ImGuiInputTextFlags_; typedef enum { ImGuiTreeNodeFlags_None = 0, @@ -296,8 +323,9 @@ typedef enum { ImGuiTreeNodeFlags_FramePadding = 1 << 10, ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, - ImGuiTreeNodeFlags_SpanAllColumns = 1 << 13, - ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 14, + ImGuiTreeNodeFlags_SpanTextWidth = 1 << 13, + ImGuiTreeNodeFlags_SpanAllColumns = 1 << 14, + ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 15, ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog, }ImGuiTreeNodeFlags_; typedef enum { @@ -316,11 +344,12 @@ typedef enum { }ImGuiPopupFlags_; typedef enum { ImGuiSelectableFlags_None = 0, - ImGuiSelectableFlags_DontClosePopups = 1 << 0, + ImGuiSelectableFlags_NoAutoClosePopups = 1 << 0, ImGuiSelectableFlags_SpanAllColumns = 1 << 1, ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, ImGuiSelectableFlags_Disabled = 1 << 3, ImGuiSelectableFlags_AllowOverlap = 1 << 4, + ImGuiSelectableFlags_Highlight = 1 << 5, }ImGuiSelectableFlags_; typedef enum { ImGuiComboFlags_None = 0, @@ -342,8 +371,9 @@ typedef enum { ImGuiTabBarFlags_NoCloseWithMiddleMouseButton = 1 << 3, ImGuiTabBarFlags_NoTabListScrollingButtons = 1 << 4, ImGuiTabBarFlags_NoTooltip = 1 << 5, - ImGuiTabBarFlags_FittingPolicyResizeDown = 1 << 6, - ImGuiTabBarFlags_FittingPolicyScroll = 1 << 7, + ImGuiTabBarFlags_DrawSelectedOverline = 1 << 6, + ImGuiTabBarFlags_FittingPolicyResizeDown = 1 << 7, + ImGuiTabBarFlags_FittingPolicyScroll = 1 << 8, ImGuiTabBarFlags_FittingPolicyMask_ = ImGuiTabBarFlags_FittingPolicyResizeDown | ImGuiTabBarFlags_FittingPolicyScroll, ImGuiTabBarFlags_FittingPolicyDefault_ = ImGuiTabBarFlags_FittingPolicyResizeDown, }ImGuiTabBarFlags_; @@ -408,7 +438,9 @@ typedef enum { ImGuiDragDropFlags_SourceNoHoldToOpenOthers = 1 << 2, ImGuiDragDropFlags_SourceAllowNullID = 1 << 3, ImGuiDragDropFlags_SourceExtern = 1 << 4, - ImGuiDragDropFlags_SourceAutoExpirePayload = 1 << 5, + ImGuiDragDropFlags_PayloadAutoExpire = 1 << 5, + ImGuiDragDropFlags_PayloadNoCrossContext = 1 << 6, + ImGuiDragDropFlags_PayloadNoCrossProcess = 1 << 7, ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, ImGuiDragDropFlags_AcceptNoPreviewTooltip = 1 << 12, @@ -425,21 +457,22 @@ typedef enum { ImGuiDataType_U64, ImGuiDataType_Float, ImGuiDataType_Double, + ImGuiDataType_Bool, ImGuiDataType_COUNT }ImGuiDataType_; typedef enum { - ImGuiDir_None = -1, - ImGuiDir_Left = 0, - ImGuiDir_Right = 1, - ImGuiDir_Up = 2, - ImGuiDir_Down = 3, - ImGuiDir_COUNT -}ImGuiDir_; +ImGuiDir_None=-1, +ImGuiDir_Left=0, +ImGuiDir_Right=1, +ImGuiDir_Up=2, +ImGuiDir_Down=3, +ImGuiDir_COUNT=4, +}ImGuiDir; typedef enum { - ImGuiSortDirection_None = 0, - ImGuiSortDirection_Ascending = 1, - ImGuiSortDirection_Descending = 2 -}ImGuiSortDirection_; +ImGuiSortDirection_None=0, +ImGuiSortDirection_Ascending=1, +ImGuiSortDirection_Descending=2, +}ImGuiSortDirection; typedef enum { ImGuiKey_None=0, ImGuiKey_Tab=512, @@ -602,14 +635,26 @@ ImGuiMod_Ctrl=1 << 12, ImGuiMod_Shift=1 << 13, ImGuiMod_Alt=1 << 14, ImGuiMod_Super=1 << 15, -ImGuiMod_Shortcut=1 << 11, -ImGuiMod_Mask_=0xF800, +ImGuiMod_Mask_=0xF000, ImGuiKey_NamedKey_BEGIN=512, ImGuiKey_NamedKey_END=ImGuiKey_COUNT, ImGuiKey_NamedKey_COUNT=ImGuiKey_NamedKey_END - ImGuiKey_NamedKey_BEGIN, ImGuiKey_KeysData_SIZE=ImGuiKey_NamedKey_COUNT, ImGuiKey_KeysData_OFFSET=ImGuiKey_NamedKey_BEGIN, }ImGuiKey; +typedef enum { + ImGuiInputFlags_None = 0, + ImGuiInputFlags_Repeat = 1 << 0, + ImGuiInputFlags_RouteActive = 1 << 10, + ImGuiInputFlags_RouteFocused = 1 << 11, + ImGuiInputFlags_RouteGlobal = 1 << 12, + ImGuiInputFlags_RouteAlways = 1 << 13, + ImGuiInputFlags_RouteOverFocused = 1 << 14, + ImGuiInputFlags_RouteOverActive = 1 << 15, + ImGuiInputFlags_RouteUnlessBgFocused = 1 << 16, + ImGuiInputFlags_RouteFromRootWindow = 1 << 17, + ImGuiInputFlags_Tooltip = 1 << 18, +}ImGuiInputFlags_; typedef enum { ImGuiConfigFlags_None = 0, ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, @@ -618,7 +663,8 @@ typedef enum { ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, ImGuiConfigFlags_NoMouse = 1 << 4, ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, - ImGuiConfigFlags_DockingEnable = 1 << 6, + ImGuiConfigFlags_NoKeyboard = 1 << 6, + ImGuiConfigFlags_DockingEnable = 1 << 7, ImGuiConfigFlags_ViewportsEnable = 1 << 10, ImGuiConfigFlags_DpiEnableScaleViewports= 1 << 14, ImGuiConfigFlags_DpiEnableScaleFonts = 1 << 15, @@ -669,11 +715,13 @@ typedef enum { ImGuiCol_ResizeGrip, ImGuiCol_ResizeGripHovered, ImGuiCol_ResizeGripActive, - ImGuiCol_Tab, ImGuiCol_TabHovered, - ImGuiCol_TabActive, - ImGuiCol_TabUnfocused, - ImGuiCol_TabUnfocusedActive, + ImGuiCol_Tab, + ImGuiCol_TabSelected, + ImGuiCol_TabSelectedOverline, + ImGuiCol_TabDimmed, + ImGuiCol_TabDimmedSelected, + ImGuiCol_TabDimmedSelectedOverline, ImGuiCol_DockingPreview, ImGuiCol_DockingEmptyBg, ImGuiCol_PlotLines, @@ -685,14 +733,14 @@ typedef enum { ImGuiCol_TableBorderLight, ImGuiCol_TableRowBg, ImGuiCol_TableRowBgAlt, + ImGuiCol_TextLink, ImGuiCol_TextSelectedBg, ImGuiCol_DragDropTarget, ImGuiCol_NavHighlight, ImGuiCol_NavWindowingHighlight, ImGuiCol_NavWindowingDimBg, ImGuiCol_ModalWindowDimBg, - ImGuiCol_WindowShadow, - ImGuiCol_COUNT + ImGuiCol_COUNT, }ImGuiCol_; typedef enum { ImGuiStyleVar_Alpha, @@ -718,7 +766,11 @@ typedef enum { ImGuiStyleVar_GrabMinSize, ImGuiStyleVar_GrabRounding, ImGuiStyleVar_TabRounding, + ImGuiStyleVar_TabBorderSize, ImGuiStyleVar_TabBarBorderSize, + ImGuiStyleVar_TabBarOverlineSize, + ImGuiStyleVar_TableAngledHeadersAngle, + ImGuiStyleVar_TableAngledHeadersTextAlign, ImGuiStyleVar_ButtonTextAlign, ImGuiStyleVar_SelectableTextAlign, ImGuiStyleVar_SeparatorTextBorderSize, @@ -733,7 +785,6 @@ typedef enum { ImGuiButtonFlags_MouseButtonRight = 1 << 1, ImGuiButtonFlags_MouseButtonMiddle = 1 << 2, ImGuiButtonFlags_MouseButtonMask_ = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle, - ImGuiButtonFlags_MouseButtonDefault_ = ImGuiButtonFlags_MouseButtonLeft, }ImGuiButtonFlags_; typedef enum { ImGuiColorEditFlags_None = 0, @@ -772,6 +823,7 @@ typedef enum { ImGuiSliderFlags_Logarithmic = 1 << 5, ImGuiSliderFlags_NoRoundToFormat = 1 << 6, ImGuiSliderFlags_NoInput = 1 << 7, + ImGuiSliderFlags_WrapAround = 1 << 8, ImGuiSliderFlags_InvalidMask_ = 0x7000000F, }ImGuiSliderFlags_; typedef enum { @@ -896,7 +948,7 @@ struct ImGuiTableColumnSortSpecs ImGuiID ColumnUserID; ImS16 ColumnIndex; ImS16 SortOrder; - ImGuiSortDirection SortDirection : 8; + ImGuiSortDirection SortDirection; }; struct ImGuiStyle { @@ -930,7 +982,9 @@ struct ImGuiStyle float TabBorderSize; float TabMinWidthForCloseButton; float TabBarBorderSize; + float TabBarOverlineSize; float TableAngledHeadersAngle; + ImVec2 TableAngledHeadersTextAlign; ImGuiDir ColorButtonPosition; ImVec2 ButtonTextAlign; ImVec2 SelectableTextAlign; @@ -946,9 +1000,6 @@ struct ImGuiStyle bool AntiAliasedFill; float CurveTessellationTol; float CircleTessellationMaxError; - float WindowShadowSize; - float WindowShadowOffsetDist; - float WindowShadowOffsetAngle; ImVec4 Colors[ImGuiCol_COUNT]; float HoverStationaryDelay; float HoverDelayShort; @@ -990,6 +1041,7 @@ struct ImGuiIO bool ConfigViewportsNoDefaultParent; bool MouseDrawCursor; bool ConfigMacOSXBehaviors; + bool ConfigNavSwapGamepadButtons; bool ConfigInputTrickleEventQueue; bool ConfigInputTextCursorBlink; bool ConfigInputTextEnterKeepActive; @@ -1015,7 +1067,9 @@ struct ImGuiIO const char* (*GetClipboardTextFn)(void* user_data); void (*SetClipboardTextFn)(void* user_data, const char* text); void* ClipboardUserData; - void (*SetPlatformImeDataFn)(ImGuiViewport* viewport, ImGuiPlatformImeData* data); + bool (*PlatformOpenInShellFn)(ImGuiContext* ctx, const char* path); + void* PlatformOpenInShellUserData; + void (*PlatformSetImeDataFn)(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); ImWchar PlatformLocaleDecimalPoint; bool WantCaptureMouse; bool WantCaptureKeyboard; @@ -1055,6 +1109,7 @@ struct ImGuiIO bool MouseDownOwned[5]; bool MouseDownOwnedUnlessPopupClose[5]; bool MouseWheelRequestAxisSwap; + bool MouseCtrlLeftAsRightClick; float MouseDownDuration[5]; float MouseDownDurationPrev[5]; ImVec2 MouseDragMaxDistanceAbs[5]; @@ -1141,18 +1196,15 @@ struct ImGuiTextBuffer }; struct ImGuiStoragePair { - ImGuiID key; - union { int val_i; float val_f; void* val_p; }; + ImGuiID key; + union { int val_i; float val_f; void* val_p; }; }; -typedef struct ImGuiStoragePair ImGuiStoragePair; - typedef struct ImVector_ImGuiStoragePair {int Size;int Capacity;ImGuiStoragePair* Data;} ImVector_ImGuiStoragePair; struct ImGuiStorage { ImVector_ImGuiStoragePair Data; }; -typedef struct ImGuiStoragePair ImGuiStoragePair; struct ImGuiListClipper { ImGuiContext* Ctx; @@ -1161,12 +1213,70 @@ struct ImGuiListClipper int ItemsCount; float ItemsHeight; float StartPosY; + double StartSeekOffsetY; void* TempData; }; struct ImColor { ImVec4 Value; }; +typedef enum { + ImGuiMultiSelectFlags_None = 0, + ImGuiMultiSelectFlags_SingleSelect = 1 << 0, + ImGuiMultiSelectFlags_NoSelectAll = 1 << 1, + ImGuiMultiSelectFlags_NoRangeSelect = 1 << 2, + ImGuiMultiSelectFlags_NoAutoSelect = 1 << 3, + ImGuiMultiSelectFlags_NoAutoClear = 1 << 4, + ImGuiMultiSelectFlags_NoAutoClearOnReselect = 1 << 5, + ImGuiMultiSelectFlags_BoxSelect1d = 1 << 6, + ImGuiMultiSelectFlags_BoxSelect2d = 1 << 7, + ImGuiMultiSelectFlags_BoxSelectNoScroll = 1 << 8, + ImGuiMultiSelectFlags_ClearOnEscape = 1 << 9, + ImGuiMultiSelectFlags_ClearOnClickVoid = 1 << 10, + ImGuiMultiSelectFlags_ScopeWindow = 1 << 11, + ImGuiMultiSelectFlags_ScopeRect = 1 << 12, + ImGuiMultiSelectFlags_SelectOnClick = 1 << 13, + ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 14, + ImGuiMultiSelectFlags_NavWrapX = 1 << 16, +}ImGuiMultiSelectFlags_; +typedef struct ImVector_ImGuiSelectionRequest {int Size;int Capacity;ImGuiSelectionRequest* Data;} ImVector_ImGuiSelectionRequest; + +struct ImGuiMultiSelectIO +{ + ImVector_ImGuiSelectionRequest Requests; + ImGuiSelectionUserData RangeSrcItem; + ImGuiSelectionUserData NavIdItem; + bool NavIdSelected; + bool RangeSrcReset; + int ItemsCount; +}; +typedef enum { + ImGuiSelectionRequestType_None = 0, + ImGuiSelectionRequestType_SetAll, + ImGuiSelectionRequestType_SetRange, +}ImGuiSelectionRequestType; +struct ImGuiSelectionRequest +{ + ImGuiSelectionRequestType Type; + bool Selected; + ImS8 RangeDirection; + ImGuiSelectionUserData RangeFirstItem; + ImGuiSelectionUserData RangeLastItem; +}; +struct ImGuiSelectionBasicStorage +{ + int Size; + bool PreserveOrder; + void* UserData; + ImGuiID (*AdapterIndexToStorageId)(ImGuiSelectionBasicStorage* self, int idx); + int _SelectionOrder; + ImGuiStorage _Storage; +}; +struct ImGuiSelectionExternalStorage +{ + void* UserData; + void (*AdapterSetItemSelected)(ImGuiSelectionExternalStorage* self, int idx, bool selected); +}; typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd); struct ImDrawCmd { @@ -1193,12 +1303,12 @@ struct ImDrawCmdHeader }; typedef struct ImVector_ImDrawCmd {int Size;int Capacity;ImDrawCmd* Data;} ImVector_ImDrawCmd; -typedef struct ImVector_unsigned_int {int Size;int Capacity;unsigned int* Data;} ImVector_unsigned_int; +typedef struct ImVector_ImDrawIdx {int Size;int Capacity;ImDrawIdx* Data;} ImVector_ImDrawIdx; struct ImDrawChannel { ImVector_ImDrawCmd _CmdBuffer; - ImVector_unsigned_int _IdxBuffer; + ImVector_ImDrawIdx _IdxBuffer; }; typedef struct ImVector_ImDrawChannel {int Size;int Capacity;ImDrawChannel* Data;} ImVector_ImDrawChannel; @@ -1223,7 +1333,6 @@ typedef enum { ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight, ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone, - ImDrawFlags_ShadowCutOutShapeBackground = 1 << 9, }ImDrawFlags_; typedef enum { ImDrawListFlags_None = 0, @@ -1234,29 +1343,29 @@ typedef enum { }ImDrawListFlags_; typedef struct ImVector_ImDrawVert {int Size;int Capacity;ImDrawVert* Data;} ImVector_ImDrawVert; +typedef struct ImVector_ImVec2 {int Size;int Capacity;ImVec2* Data;} ImVector_ImVec2; + typedef struct ImVector_ImVec4 {int Size;int Capacity;ImVec4* Data;} ImVector_ImVec4; typedef struct ImVector_ImTextureID {int Size;int Capacity;ImTextureID* Data;} ImVector_ImTextureID; -typedef struct ImVector_ImVec2 {int Size;int Capacity;ImVec2* Data;} ImVector_ImVec2; - struct ImDrawList { ImVector_ImDrawCmd CmdBuffer; - ImVector_unsigned_int IdxBuffer; + ImVector_ImDrawIdx IdxBuffer; ImVector_ImDrawVert VtxBuffer; ImDrawListFlags Flags; unsigned int _VtxCurrentIdx; ImDrawListSharedData* _Data; - const char* _OwnerName; ImDrawVert* _VtxWritePtr; - unsigned int* _IdxWritePtr; - ImVector_ImVec4 _ClipRectStack; - ImVector_ImTextureID _TextureIdStack; + ImDrawIdx* _IdxWritePtr; ImVector_ImVec2 _Path; ImDrawCmdHeader _CmdHeader; ImDrawListSplitter _Splitter; + ImVector_ImVec4 _ClipRectStack; + ImVector_ImTextureID _TextureIdStack; float _FringeScale; + const char* _OwnerName; }; typedef struct ImVector_ImDrawListPtr {int Size;int Capacity;ImDrawList** Data;} ImVector_ImDrawListPtr; @@ -1272,15 +1381,6 @@ struct ImDrawData ImVec2 FramebufferScale; ImGuiViewport* OwnerViewport; }; -typedef struct ImFontAtlasShadowTexConfig ImFontAtlasShadowTexConfig; -struct ImFontAtlasShadowTexConfig -{ - int TexCornerSize; - int TexEdgeSize; - float TexFalloffPower; - float TexDistanceFieldOffset; - bool TexBlur; -}; struct ImFontConfig { void* FontData; @@ -1365,9 +1465,6 @@ struct ImFontAtlas unsigned int FontBuilderFlags; int PackIdMouseCursors; int PackIdLines; - int ShadowRectIds[2]; - ImVec4 ShadowRectUvs[10]; - ImFontAtlasShadowTexConfig ShadowTexConfig; }; typedef struct ImVector_float {int Size;int Capacity;float* Data;} ImVector_float; @@ -1481,6 +1578,7 @@ struct ImBitVector; struct ImRect; struct ImDrawDataBuilder; struct ImDrawListSharedData; +struct ImGuiBoxSelectState; struct ImGuiColorMod; struct ImGuiContext; struct ImGuiContextHook; @@ -1496,8 +1594,9 @@ struct ImGuiInputTextDeactivateData; struct ImGuiLastItemData; struct ImGuiLocEntry; struct ImGuiMenuColumns; +struct ImGuiMultiSelectState; +struct ImGuiMultiSelectTempData; struct ImGuiNavItemData; -struct ImGuiNavTreeNodeData; struct ImGuiMetricsConfig; struct ImGuiNextWindowData; struct ImGuiNextItemData; @@ -1507,18 +1606,20 @@ struct ImGuiPopupData; struct ImGuiSettingsHandler; struct ImGuiStackSizes; struct ImGuiStyleMod; -struct ImGuiStyleShadowTexConfig; struct ImGuiTabBar; struct ImGuiTabItem; struct ImGuiTable; +struct ImGuiTableHeaderData; struct ImGuiTableColumn; struct ImGuiTableInstanceData; struct ImGuiTableTempData; struct ImGuiTableSettings; struct ImGuiTableColumnsSettings; +struct ImGuiTreeNodeStackData; struct ImGuiTypingSelectState; struct ImGuiTypingSelectRequest; struct ImGuiWindow; +struct ImGuiWindowDockStyle; struct ImGuiWindowTempData; struct ImGuiWindowSettings; typedef int ImGuiDataAuthority; @@ -1526,8 +1627,6 @@ typedef int ImGuiLayoutType; typedef int ImGuiActivateFlags; typedef int ImGuiDebugLogFlags; typedef int ImGuiFocusRequestFlags; -typedef int ImGuiInputFlags; -typedef int ImGuiItemFlags; typedef int ImGuiItemStatusFlags; typedef int ImGuiOldColumnFlags; typedef int ImGuiNavHighlightFlags; @@ -1539,6 +1638,7 @@ typedef int ImGuiSeparatorFlags; typedef int ImGuiTextFlags; typedef int ImGuiTooltipFlags; typedef int ImGuiTypingSelectFlags; +typedef int ImGuiWindowRefreshFlags; typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...); extern ImGuiContext* GImGui; typedef struct StbUndoRecord StbUndoRecord; @@ -1616,6 +1716,7 @@ struct ImDrawListSharedData ImVec2 TexUvWhitePixel; ImFont* Font; float FontSize; + float FontScale; float CurveTessellationTol; float CircleSegmentMaxError; ImVec4 ClipRectFullscreen; @@ -1625,29 +1726,46 @@ struct ImDrawListSharedData float ArcFastRadiusCutoff; ImU8 CircleSegmentCounts[64]; const ImVec4* TexUvLines; - int* ShadowRectIds; - const ImVec4* ShadowRectUvs; }; struct ImDrawDataBuilder { ImVector_ImDrawListPtr* Layers[2]; ImVector_ImDrawListPtr LayerData1; }; +struct ImGuiDataVarInfo +{ + ImGuiDataType Type; + ImU32 Count; + ImU32 Offset; +}; +typedef struct ImGuiDataTypeStorage ImGuiDataTypeStorage; +struct ImGuiDataTypeStorage +{ + ImU8 Data[8]; +}; +struct ImGuiDataTypeInfo +{ + size_t Size; + const char* Name; + const char* PrintFmt; + const char* ScanFmt; +}; typedef enum { - ImGuiItemFlags_None = 0, - ImGuiItemFlags_NoTabStop = 1 << 0, - ImGuiItemFlags_ButtonRepeat = 1 << 1, - ImGuiItemFlags_Disabled = 1 << 2, - ImGuiItemFlags_NoNav = 1 << 3, - ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, - ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, - ImGuiItemFlags_MixedValue = 1 << 6, - ImGuiItemFlags_ReadOnly = 1 << 7, - ImGuiItemFlags_NoWindowHoverableCheck = 1 << 8, - ImGuiItemFlags_AllowOverlap = 1 << 9, - ImGuiItemFlags_Inputable = 1 << 10, - ImGuiItemFlags_HasSelectionUserData = 1 << 11, -}ImGuiItemFlags_; + ImGuiDataType_String = ImGuiDataType_COUNT + 1, + ImGuiDataType_Pointer, + ImGuiDataType_ID, +}ImGuiDataTypePrivate_; +typedef enum { + ImGuiItemFlags_Disabled = 1 << 10, + ImGuiItemFlags_ReadOnly = 1 << 11, + ImGuiItemFlags_MixedValue = 1 << 12, + ImGuiItemFlags_NoWindowHoverableCheck = 1 << 13, + ImGuiItemFlags_AllowOverlap = 1 << 14, + ImGuiItemFlags_Inputable = 1 << 20, + ImGuiItemFlags_HasSelectionUserData = 1 << 21, + ImGuiItemFlags_IsMultiSelect = 1 << 22, + ImGuiItemFlags_Default_ = ImGuiItemFlags_AutoClosePopups, +}ImGuiItemFlagsPrivate_; typedef enum { ImGuiItemStatusFlags_None = 0, ImGuiItemStatusFlags_HoveredRect = 1 << 0, @@ -1660,11 +1778,7 @@ typedef enum { ImGuiItemStatusFlags_HoveredWindow = 1 << 7, ImGuiItemStatusFlags_Visible = 1 << 8, ImGuiItemStatusFlags_HasClipRect = 1 << 9, - ImGuiItemStatusFlags_Openable = 1 << 20, - ImGuiItemStatusFlags_Opened = 1 << 21, - ImGuiItemStatusFlags_Checkable = 1 << 22, - ImGuiItemStatusFlags_Checked = 1 << 23, - ImGuiItemStatusFlags_Inputable = 1 << 24, + ImGuiItemStatusFlags_HasShortcut = 1 << 10, }ImGuiItemStatusFlags_; typedef enum { ImGuiHoveredFlags_DelayMask_ = ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay, @@ -1675,6 +1789,7 @@ typedef enum { ImGuiInputTextFlags_Multiline = 1 << 26, ImGuiInputTextFlags_NoMarkEdited = 1 << 27, ImGuiInputTextFlags_MergedItem = 1 << 28, + ImGuiInputTextFlags_LocalizeDecimalPoint= 1 << 29, }ImGuiInputTextFlagsPrivate_; typedef enum { ImGuiButtonFlags_PressedOnClick = 1 << 4, @@ -1715,8 +1830,8 @@ typedef enum { ImGuiSelectableFlags_NoSetKeyOwner = 1 << 27, }ImGuiSelectableFlagsPrivate_; typedef enum { - ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 20, - ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 21, + ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 28, + ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 29, }ImGuiTreeNodeFlagsPrivate_; typedef enum { ImGuiSeparatorFlags_None = 0, @@ -1831,6 +1946,12 @@ struct ImGuiInputTextState int ReloadSelectionStart; int ReloadSelectionEnd; }; +typedef enum { + ImGuiWindowRefreshFlags_None = 0, + ImGuiWindowRefreshFlags_TryToAvoidRefresh = 1 << 0, + ImGuiWindowRefreshFlags_RefreshOnHover = 1 << 1, + ImGuiWindowRefreshFlags_RefreshOnFocus = 1 << 2, +}ImGuiWindowRefreshFlags_; typedef enum { ImGuiNextWindowDataFlags_None = 0, ImGuiNextWindowDataFlags_HasPos = 1 << 0, @@ -1842,9 +1963,10 @@ typedef enum { ImGuiNextWindowDataFlags_HasBgAlpha = 1 << 6, ImGuiNextWindowDataFlags_HasScroll = 1 << 7, ImGuiNextWindowDataFlags_HasChildFlags = 1 << 8, - ImGuiNextWindowDataFlags_HasViewport = 1 << 9, - ImGuiNextWindowDataFlags_HasDock = 1 << 10, - ImGuiNextWindowDataFlags_HasWindowClass = 1 << 11, + ImGuiNextWindowDataFlags_HasRefreshPolicy = 1 << 9, + ImGuiNextWindowDataFlags_HasViewport = 1 << 10, + ImGuiNextWindowDataFlags_HasDock = 1 << 11, + ImGuiNextWindowDataFlags_HasWindowClass = 1 << 12, }ImGuiNextWindowDataFlags_; struct ImGuiNextWindowData { @@ -1869,23 +1991,29 @@ struct ImGuiNextWindowData ImGuiID DockId; ImGuiWindowClass WindowClass; ImVec2 MenuBarOffsetMinVal; + ImGuiWindowRefreshFlags RefreshFlagsVal; }; -typedef ImS64 ImGuiSelectionUserData; typedef enum { ImGuiNextItemDataFlags_None = 0, ImGuiNextItemDataFlags_HasWidth = 1 << 0, ImGuiNextItemDataFlags_HasOpen = 1 << 1, ImGuiNextItemDataFlags_HasShortcut = 1 << 2, + ImGuiNextItemDataFlags_HasRefVal = 1 << 3, + ImGuiNextItemDataFlags_HasStorageID = 1 << 4, }ImGuiNextItemDataFlags_; struct ImGuiNextItemData { ImGuiNextItemDataFlags Flags; ImGuiItemFlags ItemFlags; + ImGuiID FocusScopeId; ImGuiSelectionUserData SelectionUserData; float Width; ImGuiKeyChord Shortcut; + ImGuiInputFlags ShortcutFlags; bool OpenVal; - ImGuiCond OpenCond : 8; + ImU8 OpenCond; + ImGuiDataTypeStorage RefVal; + ImGuiID StorageId; }; struct ImGuiLastItemData { @@ -1896,10 +2024,12 @@ struct ImGuiLastItemData ImRect NavRect; ImRect DisplayRect; ImRect ClipRect; + ImGuiKeyChord Shortcut; }; -struct ImGuiNavTreeNodeData +struct ImGuiTreeNodeStackData { ImGuiID ID; + ImGuiTreeNodeFlags TreeFlags; ImGuiItemFlags InFlags; ImRect NavRect; }; @@ -1921,6 +2051,7 @@ struct ImGuiWindowStackData ImGuiWindow* Window; ImGuiLastItemData ParentLastItemDataBackup; ImGuiStackSizes StackSizesOnBegin; + bool DisabledOverrideReenable; }; typedef struct ImGuiShrinkWidthItem ImGuiShrinkWidthItem; struct ImGuiShrinkWidthItem @@ -1935,29 +2066,6 @@ struct ImGuiPtrOrIndex void* Ptr; int Index; }; -struct ImGuiDataVarInfo -{ - ImGuiDataType Type; - ImU32 Count; - ImU32 Offset; -}; -typedef struct ImGuiDataTypeTempStorage ImGuiDataTypeTempStorage; -struct ImGuiDataTypeTempStorage -{ - ImU8 Data[8]; -}; -struct ImGuiDataTypeInfo -{ - size_t Size; - const char* Name; - const char* PrintFmt; - const char* ScanFmt; -}; -typedef enum { - ImGuiDataType_String = ImGuiDataType_COUNT + 1, - ImGuiDataType_Pointer, - ImGuiDataType_ID, -}ImGuiDataTypePrivate_; typedef enum { ImGuiPopupPositionPolicy_Default, ImGuiPopupPositionPolicy_ComboBox, @@ -1967,7 +2075,7 @@ struct ImGuiPopupData { ImGuiID PopupId; ImGuiWindow* Window; - ImGuiWindow* BackupNavWindow; + ImGuiWindow* RestoreNavWindow; int ParentNavLayer; int OpenFrameCount; ImGuiID OpenParentId; @@ -1993,7 +2101,6 @@ typedef enum { ImGuiInputSource_Mouse, ImGuiInputSource_Keyboard, ImGuiInputSource_Gamepad, - ImGuiInputSource_Clipboard, ImGuiInputSource_COUNT }ImGuiInputSource; typedef struct ImGuiInputEventMousePos ImGuiInputEventMousePos; @@ -2071,8 +2178,6 @@ struct ImGuiKeyOwnerData bool LockUntilRelease; }; typedef enum { - ImGuiInputFlags_None = 0, - ImGuiInputFlags_Repeat = 1 << 0, ImGuiInputFlags_RepeatRateDefault = 1 << 1, ImGuiInputFlags_RepeatRateNavMove = 1 << 2, ImGuiInputFlags_RepeatRateNavTweak = 1 << 3, @@ -2080,28 +2185,24 @@ typedef enum { ImGuiInputFlags_RepeatUntilKeyModsChange = 1 << 5, ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone = 1 << 6, ImGuiInputFlags_RepeatUntilOtherKeyPress = 1 << 7, - ImGuiInputFlags_CondHovered = 1 << 8, - ImGuiInputFlags_CondActive = 1 << 9, + ImGuiInputFlags_LockThisFrame = 1 << 20, + ImGuiInputFlags_LockUntilRelease = 1 << 21, + ImGuiInputFlags_CondHovered = 1 << 22, + ImGuiInputFlags_CondActive = 1 << 23, ImGuiInputFlags_CondDefault_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, - ImGuiInputFlags_LockThisFrame = 1 << 10, - ImGuiInputFlags_LockUntilRelease = 1 << 11, - ImGuiInputFlags_RouteFocused = 1 << 12, - ImGuiInputFlags_RouteGlobalLow = 1 << 13, - ImGuiInputFlags_RouteGlobal = 1 << 14, - ImGuiInputFlags_RouteGlobalHigh = 1 << 15, - ImGuiInputFlags_RouteAlways = 1 << 16, - ImGuiInputFlags_RouteUnlessBgFocused= 1 << 17, ImGuiInputFlags_RepeatRateMask_ = ImGuiInputFlags_RepeatRateDefault | ImGuiInputFlags_RepeatRateNavMove | ImGuiInputFlags_RepeatRateNavTweak, ImGuiInputFlags_RepeatUntilMask_ = ImGuiInputFlags_RepeatUntilRelease | ImGuiInputFlags_RepeatUntilKeyModsChange | ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone | ImGuiInputFlags_RepeatUntilOtherKeyPress, ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_, ImGuiInputFlags_CondMask_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, - ImGuiInputFlags_RouteMask_ = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteGlobalLow | ImGuiInputFlags_RouteGlobalHigh, + ImGuiInputFlags_RouteTypeMask_ = ImGuiInputFlags_RouteActive | ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteAlways, + ImGuiInputFlags_RouteOptionsMask_ = ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused | ImGuiInputFlags_RouteFromRootWindow, ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_, ImGuiInputFlags_SupportedByIsMouseClicked = ImGuiInputFlags_Repeat, - ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteMask_ | ImGuiInputFlags_RouteAlways | ImGuiInputFlags_RouteUnlessBgFocused, + ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteTypeMask_ | ImGuiInputFlags_RouteOptionsMask_, + ImGuiInputFlags_SupportedBySetNextItemShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteTypeMask_ | ImGuiInputFlags_RouteOptionsMask_ | ImGuiInputFlags_Tooltip, ImGuiInputFlags_SupportedBySetKeyOwner = ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease, ImGuiInputFlags_SupportedBySetItemKeyOwner = ImGuiInputFlags_SupportedBySetKeyOwner | ImGuiInputFlags_CondMask_, -}ImGuiInputFlags_; +}ImGuiInputFlagsPrivate_; typedef struct ImGuiListClipperRange ImGuiListClipperRange; struct ImGuiListClipperRange { @@ -2166,6 +2267,7 @@ typedef enum { ImGuiNavMoveFlags_Activate = 1 << 12, ImGuiNavMoveFlags_NoSelect = 1 << 13, ImGuiNavMoveFlags_NoSetNavHighlight = 1 << 14, + ImGuiNavMoveFlags_NoClearActiveId = 1 << 15, }ImGuiNavMoveFlags_; typedef enum { ImGuiNavLayer_Main = 0, @@ -2179,10 +2281,10 @@ struct ImGuiNavItemData ImGuiID FocusScopeId; ImRect RectRel; ImGuiItemFlags InFlags; - ImGuiSelectionUserData SelectionUserData; float DistBox; float DistCenter; float DistAxial; + ImGuiSelectionUserData SelectionUserData; }; typedef struct ImGuiFocusScopeData ImGuiFocusScopeData; struct ImGuiFocusScopeData @@ -2248,6 +2350,54 @@ struct ImGuiOldColumns ImVector_ImGuiOldColumnData Columns; ImDrawListSplitter Splitter; }; +struct ImGuiBoxSelectState +{ + ImGuiID ID; + bool IsActive; + bool IsStarting; + bool IsStartedFromVoid; + bool IsStartedSetNavIdOnce; + bool RequestClear; + ImGuiKeyChord KeyMods : 16; + ImVec2 StartPosRel; + ImVec2 EndPosRel; + ImVec2 ScrollAccum; + ImGuiWindow* Window; + bool UnclipMode; + ImRect UnclipRect; + ImRect BoxSelectRectPrev; + ImRect BoxSelectRectCurr; +}; +struct ImGuiMultiSelectTempData +{ + ImGuiMultiSelectIO IO; + ImGuiMultiSelectState* Storage; + ImGuiID FocusScopeId; + ImGuiMultiSelectFlags Flags; + ImVec2 ScopeRectMin; + ImVec2 BackupCursorMaxPos; + ImGuiSelectionUserData LastSubmittedItem; + ImGuiID BoxSelectId; + ImGuiKeyChord KeyMods; + ImS8 LoopRequestSetAll; + bool IsEndIO; + bool IsFocused; + bool IsKeyboardSetRange; + bool NavIdPassedBy; + bool RangeSrcPassedBy; + bool RangeDstPassedBy; +}; +struct ImGuiMultiSelectState +{ + ImGuiWindow* Window; + ImGuiID ID; + int LastFrameActive; + int LastSelectionSize; + ImS8 RangeSelected; + ImS8 NavIdSelected; + ImGuiSelectionUserData RangeSrcItem; + ImGuiSelectionUserData NavIdItem; +}; typedef enum { ImGuiDockNodeFlags_DockSpace = 1 << 10, ImGuiDockNodeFlags_CentralNode = 1 << 11, @@ -2328,14 +2478,15 @@ struct ImGuiDockNode }; typedef enum { ImGuiWindowDockStyleCol_Text, - ImGuiWindowDockStyleCol_Tab, ImGuiWindowDockStyleCol_TabHovered, - ImGuiWindowDockStyleCol_TabActive, - ImGuiWindowDockStyleCol_TabUnfocused, - ImGuiWindowDockStyleCol_TabUnfocusedActive, + ImGuiWindowDockStyleCol_TabFocused, + ImGuiWindowDockStyleCol_TabSelected, + ImGuiWindowDockStyleCol_TabSelectedOverline, + ImGuiWindowDockStyleCol_TabDimmed, + ImGuiWindowDockStyleCol_TabDimmedSelected, + ImGuiWindowDockStyleCol_TabDimmedSelectedOverline, ImGuiWindowDockStyleCol_COUNT }ImGuiWindowDockStyleCol; -typedef struct ImGuiWindowDockStyle ImGuiWindowDockStyle; struct ImGuiWindowDockStyle { ImU32 Colors[ImGuiWindowDockStyleCol_COUNT]; @@ -2413,10 +2564,11 @@ ImGuiLocKey_TableResetOrder=4, ImGuiLocKey_WindowingMainMenuBar=5, ImGuiLocKey_WindowingPopup=6, ImGuiLocKey_WindowingUntitled=7, -ImGuiLocKey_DockingHideTabBar=8, -ImGuiLocKey_DockingHoldShiftToDock=9, -ImGuiLocKey_DockingDragToUndockOrMoveNode=10, -ImGuiLocKey_COUNT=11, +ImGuiLocKey_CopyLink=8, +ImGuiLocKey_DockingHideTabBar=9, +ImGuiLocKey_DockingHoldShiftToDock=10, +ImGuiLocKey_DockingDragToUndockOrMoveNode=11, +ImGuiLocKey_COUNT=12, }ImGuiLocKey; struct ImGuiLocEntry { @@ -2518,7 +2670,7 @@ typedef struct ImVector_ImGuiGroupData {int Size;int Capacity;ImGuiGroupData* Da typedef struct ImVector_ImGuiPopupData {int Size;int Capacity;ImGuiPopupData* Data;} ImVector_ImGuiPopupData; -typedef struct ImVector_ImGuiNavTreeNodeData {int Size;int Capacity;ImGuiNavTreeNodeData* Data;} ImVector_ImGuiNavTreeNodeData; +typedef struct ImVector_ImGuiTreeNodeStackData {int Size;int Capacity;ImGuiTreeNodeStackData* Data;} ImVector_ImGuiTreeNodeStackData; typedef struct ImVector_ImGuiViewportPPtr {int Size;int Capacity;ImGuiViewportP** Data;} ImVector_ImGuiViewportPPtr; @@ -2540,6 +2692,12 @@ typedef struct ImVector_ImGuiPtrOrIndex {int Size;int Capacity;ImGuiPtrOrIndex* typedef struct ImVector_ImGuiShrinkWidthItem {int Size;int Capacity;ImGuiShrinkWidthItem* Data;} ImVector_ImGuiShrinkWidthItem; +typedef struct ImVector_ImGuiMultiSelectTempData {int Size;int Capacity;ImGuiMultiSelectTempData* Data;} ImVector_ImGuiMultiSelectTempData; + +typedef struct ImVector_ImGuiMultiSelectState {int Size;int Capacity;ImGuiMultiSelectState* Data;} ImVector_ImGuiMultiSelectState; + +typedef struct ImPool_ImGuiMultiSelectState {ImVector_ImGuiMultiSelectState Buf;ImGuiStorage Map;ImPoolIdx FreeIdx;ImPoolIdx AliveCount;} ImPool_ImGuiMultiSelectState; + typedef struct ImVector_ImGuiID {int Size;int Capacity;ImGuiID* Data;} ImVector_ImGuiID; typedef struct ImVector_ImGuiSettingsHandler {int Size;int Capacity;ImGuiSettingsHandler* Data;} ImVector_ImGuiSettingsHandler; @@ -2562,6 +2720,8 @@ struct ImGuiContext ImFont* Font; float FontSize; float FontBaseSize; + float FontScale; + float CurrentDpiScale; ImDrawListSharedData DrawListSharedData; double Time; int FrameCount; @@ -2574,6 +2734,7 @@ struct ImGuiContext bool GcCompactAll; bool TestEngineHookItems; void* TestEngine; + char ContextName[16]; ImVector_ImGuiInputEvent InputEventsQueue; ImVector_ImGuiInputEvent InputEventsTrail; ImGuiMouseSource InputEventsNextMouseSource; @@ -2589,6 +2750,7 @@ struct ImGuiContext ImGuiWindow* CurrentWindow; ImGuiWindow* HoveredWindow; ImGuiWindow* HoveredWindowUnderMovingWindow; + ImGuiWindow* HoveredWindowBeforeClear; ImGuiWindow* MovingWindow; ImGuiWindow* WheelingWindow; ImVec2 WheelingWindowRefMousePos; @@ -2600,10 +2762,11 @@ struct ImGuiContext ImGuiID DebugHookIdInfo; ImGuiID HoveredId; ImGuiID HoveredIdPreviousFrame; - bool HoveredIdAllowOverlap; - bool HoveredIdDisabled; float HoveredIdTimer; float HoveredIdNotActiveTimer; + bool HoveredIdAllowOverlap; + bool HoveredIdIsDisabled; + bool ItemUnclipByLog; ImGuiID ActiveId; ImGuiID ActiveIdIsAlive; float ActiveIdTimer; @@ -2649,9 +2812,8 @@ struct ImGuiContext ImVector_ImGuiGroupData GroupStack; ImVector_ImGuiPopupData OpenPopupStack; ImVector_ImGuiPopupData BeginPopupStack; - ImVector_ImGuiNavTreeNodeData NavTreeNodeStack; + ImVector_ImGuiTreeNodeStackData TreeNodeStack; ImVector_ImGuiViewportPPtr Viewports; - float CurrentDpiScale; ImGuiViewportP* CurrentViewport; ImGuiViewportP* MouseViewport; ImGuiViewportP* MouseLastHoveredViewport; @@ -2664,20 +2826,17 @@ struct ImGuiContext ImGuiWindow* NavWindow; ImGuiID NavId; ImGuiID NavFocusScopeId; - ImVector_ImGuiFocusScopeData NavFocusRoute; + ImGuiNavLayer NavLayer; ImGuiID NavActivateId; ImGuiID NavActivateDownId; ImGuiID NavActivatePressedId; ImGuiActivateFlags NavActivateFlags; + ImVector_ImGuiFocusScopeData NavFocusRoute; ImGuiID NavHighlightActivatedId; float NavHighlightActivatedTimer; - ImGuiID NavJustMovedToId; - ImGuiID NavJustMovedToFocusScopeId; - ImGuiKeyChord NavJustMovedToKeyMods; ImGuiID NavNextActivateId; ImGuiActivateFlags NavNextActivateFlags; ImGuiInputSource NavInputSource; - ImGuiNavLayer NavLayer; ImGuiSelectionUserData NavLastValidSelectionUserData; bool NavIdIsAlive; bool NavMousePosDirty; @@ -2705,6 +2864,12 @@ struct ImGuiContext ImGuiNavItemData NavMoveResultLocalVisible; ImGuiNavItemData NavMoveResultOther; ImGuiNavItemData NavTabbingResultFirst; + ImGuiID NavJustMovedFromFocusScopeId; + ImGuiID NavJustMovedToId; + ImGuiID NavJustMovedToFocusScopeId; + ImGuiKeyChord NavJustMovedToKeyMods; + bool NavJustMovedToIsTabbing; + bool NavJustMovedToHasSelectionData; ImGuiKeyChord ConfigNavWindowingKeyNext; ImGuiKeyChord ConfigNavWindowingKeyPrev; ImGuiWindow* NavWindowingTarget; @@ -2748,6 +2913,11 @@ struct ImGuiContext ImPool_ImGuiTabBar TabBars; ImVector_ImGuiPtrOrIndex CurrentTabBarStack; ImVector_ImGuiShrinkWidthItem ShrinkWidthBuffer; + ImGuiBoxSelectState BoxSelectState; + ImGuiMultiSelectTempData* CurrentMultiSelect; + int MultiSelectTempDataStacked; + ImVector_ImGuiMultiSelectTempData MultiSelectTempData; + ImPool_ImGuiMultiSelectState MultiSelectStorage; ImGuiID HoverItemDelayId; ImGuiID HoverItemDelayIdPreviousFrame; float HoverItemDelayTimer; @@ -2761,6 +2931,7 @@ struct ImGuiContext ImGuiInputTextDeactivatedState InputTextDeactivatedState; ImFont InputTextPasswordFont; ImGuiID TempInputId; + ImGuiDataTypeStorage DataTypeZeroValue; int BeginMenuDepth; int BeginComboDepth; ImGuiColorEditFlags ColorEditOptions; @@ -2773,13 +2944,14 @@ struct ImGuiContext ImGuiComboPreviewData ComboPreviewData; ImRect WindowResizeBorderExpectedRect; bool WindowResizeRelativeMode; + short ScrollbarSeekMode; + float ScrollbarClickDeltaToGrabCenter; float SliderGrabClickOffset; float SliderCurrentAccum; bool SliderCurrentAccumDirty; bool DragCurrentAccumDirty; float DragCurrentAccum; float DragSpeedDefaultRatio; - float ScrollbarClickDeltaToGrabCenter; float DisabledAlphaBackup; short DisabledStackSize; short LockMarkEdited; @@ -2867,7 +3039,7 @@ struct ImGuiWindowTempData ImVec2 MenuBarOffset; ImGuiMenuColumns MenuColumns; int TreeDepth; - ImU32 TreeJumpToParentOnPopMask; + ImU32 TreeHasStackDataDepthMask; ImVector_ImGuiWindowPtr ChildWindows; ImGuiStorage* StateStorage; ImGuiOldColumns* CurrentColumns; @@ -2903,6 +3075,7 @@ struct ImGuiWindow ImVec2 WindowPadding; float WindowRounding; float WindowBorderSize; + float TitleBarHeight, MenuBarHeight; float DecoOuterSizeX1, DecoOuterSizeY1; float DecoOuterSizeX2, DecoOuterSizeY2; float DecoInnerSizeX1, DecoInnerSizeY1; @@ -2910,6 +3083,7 @@ struct ImGuiWindow ImGuiID MoveId; ImGuiID TabId; ImGuiID ChildId; + ImGuiID PopupId; ImVec2 Scroll; ImVec2 ScrollMax; ImVec2 ScrollTarget; @@ -2924,6 +3098,7 @@ struct ImGuiWindow bool Collapsed; bool WantCollapseToggle; bool SkipItems; + bool SkipRefresh; bool Appearing; bool Hidden; bool IsFallbackWindow; @@ -2936,7 +3111,6 @@ struct ImGuiWindow short BeginOrderWithinParent; short BeginOrderWithinContext; short FocusOrder; - ImGuiID PopupId; ImS8 AutoFitFramesX, AutoFitFramesY; bool AutoFitOnlyGrows; ImGuiDir AutoPosLastDirection; @@ -3117,6 +3291,13 @@ struct ImGuiTableCellData ImU32 BgColor; ImGuiTableColumnIdx Column; }; +struct ImGuiTableHeaderData +{ + ImGuiTableColumnIdx Index; + ImU32 TextColor; + ImU32 BgColor0; + ImU32 BgColor1; +}; struct ImGuiTableInstanceData { ImGuiID TableInstanceID; @@ -3251,11 +3432,14 @@ struct ImGuiTable bool MemoryCompacted; bool HostSkipItems; }; +typedef struct ImVector_ImGuiTableHeaderData {int Size;int Capacity;ImGuiTableHeaderData* Data;} ImVector_ImGuiTableHeaderData; + struct ImGuiTableTempData { int TableIndex; float LastTimeActive; float AngledHeadersExtraWidth; + ImVector_ImGuiTableHeaderData AngledHeadersRequests; ImVec2 UserOuterSize; ImDrawListSplitter DrawSplitter; ImRect HostBackupWorkRect; @@ -3303,7 +3487,6 @@ typedef union SDL_Event SDL_Event; #endif // CIMGUI_DEFINE_ENUMS_AND_STRUCTS #ifndef CIMGUI_DEFINE_ENUMS_AND_STRUCTS -typedef struct ImGuiStoragePair ImGuiStoragePair; typedef struct ImGuiTextFilter::ImGuiTextRange ImGuiTextRange; typedef ImStb::STB_TexteditState STB_TexteditState; typedef ImStb::StbTexteditRow StbTexteditRow; @@ -3311,6 +3494,7 @@ typedef ImStb::StbUndoRecord StbUndoRecord; typedef ImStb::StbUndoState StbUndoState; typedef ImChunkStream ImChunkStream_ImGuiTableSettings; typedef ImChunkStream ImChunkStream_ImGuiWindowSettings; +typedef ImPool ImPool_ImGuiMultiSelectState; typedef ImPool ImPool_ImGuiTabBar; typedef ImPool ImPool_ImGuiTable; typedef ImSpan ImSpan_ImGuiTableCellData; @@ -3318,6 +3502,7 @@ typedef ImSpan ImSpan_ImGuiTableColumn; typedef ImSpan ImSpan_ImGuiTableColumnIdx; typedef ImVector ImVector_ImDrawChannel; typedef ImVector ImVector_ImDrawCmd; +typedef ImVector ImVector_ImDrawIdx; typedef ImVector ImVector_ImDrawListPtr; typedef ImVector ImVector_ImDrawVert; typedef ImVector ImVector_ImFontPtr; @@ -3336,12 +3521,13 @@ typedef ImVector ImVector_ImGuiItemFlags; typedef ImVector ImVector_ImGuiKeyRoutingData; typedef ImVector ImVector_ImGuiListClipperData; typedef ImVector ImVector_ImGuiListClipperRange; -typedef ImVector ImVector_ImGuiNavTreeNodeData; +typedef ImVector ImVector_ImGuiMultiSelectTempData; typedef ImVector ImVector_ImGuiOldColumnData; typedef ImVector ImVector_ImGuiOldColumns; typedef ImVector ImVector_ImGuiPlatformMonitor; typedef ImVector ImVector_ImGuiPopupData; typedef ImVector ImVector_ImGuiPtrOrIndex; +typedef ImVector ImVector_ImGuiSelectionRequest; typedef ImVector ImVector_ImGuiSettingsHandler; typedef ImVector ImVector_ImGuiShrinkWidthItem; typedef ImVector ImVector_ImGuiStackLevelInfo; @@ -3349,9 +3535,11 @@ typedef ImVector ImVector_ImGuiStoragePair; typedef ImVector ImVector_ImGuiStyleMod; typedef ImVector ImVector_ImGuiTabItem; typedef ImVector ImVector_ImGuiTableColumnSortSpecs; +typedef ImVector ImVector_ImGuiTableHeaderData; typedef ImVector ImVector_ImGuiTableInstanceData; typedef ImVector ImVector_ImGuiTableTempData; typedef ImVector ImVector_ImGuiTextRange; +typedef ImVector ImVector_ImGuiTreeNodeStackData; typedef ImVector ImVector_ImGuiViewportPtr; typedef ImVector ImVector_ImGuiViewportPPtr; typedef ImVector ImVector_ImGuiWindowPtr; @@ -3366,7 +3554,6 @@ typedef ImVector ImVector_const_charPtr; typedef ImVector ImVector_float; typedef ImVector ImVector_int; typedef ImVector ImVector_unsigned_char; -typedef ImVector ImVector_unsigned_int; #endif //CIMGUI_DEFINE_ENUMS_AND_STRUCTS CIMGUI_API ImVec2* ImVec2_ImVec2_Nil(void); CIMGUI_API void ImVec2_destroy(ImVec2* self); @@ -3431,10 +3618,6 @@ CIMGUI_API void igSetWindowPos_Str(const char* name,const ImVec2 pos,ImGuiCond c CIMGUI_API void igSetWindowSize_Str(const char* name,const ImVec2 size,ImGuiCond cond); CIMGUI_API void igSetWindowCollapsed_Str(const char* name,bool collapsed,ImGuiCond cond); CIMGUI_API void igSetWindowFocus_Str(const char* name); -CIMGUI_API void igGetContentRegionAvail(ImVec2 *pOut); -CIMGUI_API void igGetContentRegionMax(ImVec2 *pOut); -CIMGUI_API void igGetWindowContentRegionMin(ImVec2 *pOut); -CIMGUI_API void igGetWindowContentRegionMax(ImVec2 *pOut); CIMGUI_API float igGetScrollX(void); CIMGUI_API float igGetScrollY(void); CIMGUI_API void igSetScrollX_Float(float scroll_x); @@ -3453,10 +3636,8 @@ CIMGUI_API void igPopStyleColor(int count); CIMGUI_API void igPushStyleVar_Float(ImGuiStyleVar idx,float val); CIMGUI_API void igPushStyleVar_Vec2(ImGuiStyleVar idx,const ImVec2 val); CIMGUI_API void igPopStyleVar(int count); -CIMGUI_API void igPushTabStop(bool tab_stop); -CIMGUI_API void igPopTabStop(void); -CIMGUI_API void igPushButtonRepeat(bool repeat); -CIMGUI_API void igPopButtonRepeat(void); +CIMGUI_API void igPushItemFlag(ImGuiItemFlags option,bool enabled); +CIMGUI_API void igPopItemFlag(void); CIMGUI_API void igPushItemWidth(float item_width); CIMGUI_API void igPopItemWidth(void); CIMGUI_API void igSetNextItemWidth(float item_width); @@ -3472,6 +3653,7 @@ CIMGUI_API ImU32 igGetColorU32_U32(ImU32 col,float alpha_mul); CIMGUI_API const ImVec4* igGetStyleColorVec4(ImGuiCol idx); CIMGUI_API void igGetCursorScreenPos(ImVec2 *pOut); CIMGUI_API void igSetCursorScreenPos(const ImVec2 pos); +CIMGUI_API void igGetContentRegionAvail(ImVec2 *pOut); CIMGUI_API void igGetCursorPos(ImVec2 *pOut); CIMGUI_API float igGetCursorPosX(void); CIMGUI_API float igGetCursorPosY(void); @@ -3501,6 +3683,7 @@ CIMGUI_API void igPopID(void); CIMGUI_API ImGuiID igGetID_Str(const char* str_id); CIMGUI_API ImGuiID igGetID_StrStr(const char* str_id_begin,const char* str_id_end); CIMGUI_API ImGuiID igGetID_Ptr(const void* ptr_id); +CIMGUI_API ImGuiID igGetID_Int(int int_id); CIMGUI_API void igTextUnformatted(const char* text,const char* text_end); CIMGUI_API void igText(const char* fmt,...); CIMGUI_API void igTextV(const char* fmt,va_list args); @@ -3526,6 +3709,8 @@ CIMGUI_API bool igRadioButton_Bool(const char* label,bool active); CIMGUI_API bool igRadioButton_IntPtr(const char* label,int* v,int v_button); CIMGUI_API void igProgressBar(float fraction,const ImVec2 size_arg,const char* overlay); CIMGUI_API void igBullet(void); +CIMGUI_API bool igTextLink(const char* label); +CIMGUI_API void igTextLinkOpenURL(const char* label,const char* url); CIMGUI_API void igImage(ImTextureID user_texture_id,const ImVec2 image_size,const ImVec2 uv0,const ImVec2 uv1,const ImVec4 tint_col,const ImVec4 border_col); CIMGUI_API bool igImageButton(const char* str_id,ImTextureID user_texture_id,const ImVec2 image_size,const ImVec2 uv0,const ImVec2 uv1,const ImVec4 bg_col,const ImVec4 tint_col); CIMGUI_API bool igBeginCombo(const char* label,const char* preview_value,ImGuiComboFlags flags); @@ -3596,8 +3781,13 @@ CIMGUI_API float igGetTreeNodeToLabelSpacing(void); CIMGUI_API bool igCollapsingHeader_TreeNodeFlags(const char* label,ImGuiTreeNodeFlags flags); CIMGUI_API bool igCollapsingHeader_BoolPtr(const char* label,bool* p_visible,ImGuiTreeNodeFlags flags); CIMGUI_API void igSetNextItemOpen(bool is_open,ImGuiCond cond); +CIMGUI_API void igSetNextItemStorageID(ImGuiID storage_id); CIMGUI_API bool igSelectable_Bool(const char* label,bool selected,ImGuiSelectableFlags flags,const ImVec2 size); CIMGUI_API bool igSelectable_BoolPtr(const char* label,bool* p_selected,ImGuiSelectableFlags flags,const ImVec2 size); +CIMGUI_API ImGuiMultiSelectIO* igBeginMultiSelect(ImGuiMultiSelectFlags flags,int selection_size,int items_count); +CIMGUI_API ImGuiMultiSelectIO* igEndMultiSelect(void); +CIMGUI_API void igSetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data); +CIMGUI_API bool igIsItemToggledSelection(void); CIMGUI_API bool igBeginListBox(const char* label,const ImVec2 size); CIMGUI_API void igEndListBox(void); CIMGUI_API bool igListBox_Str_arr(const char* label,int* current_item,const char* const items[],int items_count,int height_in_items); @@ -3636,7 +3826,7 @@ CIMGUI_API bool igBeginPopupContextItem(const char* str_id,ImGuiPopupFlags popup CIMGUI_API bool igBeginPopupContextWindow(const char* str_id,ImGuiPopupFlags popup_flags); CIMGUI_API bool igBeginPopupContextVoid(const char* str_id,ImGuiPopupFlags popup_flags); CIMGUI_API bool igIsPopupOpen_Str(const char* str_id,ImGuiPopupFlags flags); -CIMGUI_API bool igBeginTable(const char* str_id,int column,ImGuiTableFlags flags,const ImVec2 outer_size,float inner_width); +CIMGUI_API bool igBeginTable(const char* str_id,int columns,ImGuiTableFlags flags,const ImVec2 outer_size,float inner_width); CIMGUI_API void igEndTable(void); CIMGUI_API void igTableNextRow(ImGuiTableRowFlags row_flags,float min_row_height); CIMGUI_API bool igTableNextColumn(void); @@ -3653,6 +3843,7 @@ CIMGUI_API int igTableGetRowIndex(void); CIMGUI_API const char* igTableGetColumnName_Int(int column_n); CIMGUI_API ImGuiTableColumnFlags igTableGetColumnFlags(int column_n); CIMGUI_API void igTableSetColumnEnabled(int column_n,bool v); +CIMGUI_API int igTableGetHoveredColumn(void); CIMGUI_API void igTableSetBgColor(ImGuiTableBgTarget target,ImU32 color,int column_n); CIMGUI_API void igColumns(int count,const char* id,bool border); CIMGUI_API void igNextColumn(void); @@ -3668,7 +3859,7 @@ CIMGUI_API bool igBeginTabItem(const char* label,bool* p_open,ImGuiTabItemFlags CIMGUI_API void igEndTabItem(void); CIMGUI_API bool igTabItemButton(const char* label,ImGuiTabItemFlags flags); CIMGUI_API void igSetTabItemClosed(const char* tab_or_docked_window_label); -CIMGUI_API ImGuiID igDockSpace(ImGuiID id,const ImVec2 size,ImGuiDockNodeFlags flags,const ImGuiWindowClass* window_class); +CIMGUI_API ImGuiID igDockSpace(ImGuiID dockspace_id,const ImVec2 size,ImGuiDockNodeFlags flags,const ImGuiWindowClass* window_class); CIMGUI_API ImGuiID igDockSpaceOverViewport(ImGuiID dockspace_id,const ImGuiViewport* viewport,ImGuiDockNodeFlags flags,const ImGuiWindowClass* window_class); CIMGUI_API void igSetNextWindowDockID(ImGuiID dock_id,ImGuiCond cond); CIMGUI_API void igSetNextWindowClass(const ImGuiWindowClass* window_class); @@ -3712,9 +3903,7 @@ CIMGUI_API void igGetItemRectMin(ImVec2 *pOut); CIMGUI_API void igGetItemRectMax(ImVec2 *pOut); CIMGUI_API void igGetItemRectSize(ImVec2 *pOut); CIMGUI_API ImGuiViewport* igGetMainViewport(void); -CIMGUI_API ImDrawList* igGetBackgroundDrawList_Nil(void); -CIMGUI_API ImDrawList* igGetForegroundDrawList_Nil(void); -CIMGUI_API ImDrawList* igGetBackgroundDrawList_ViewportPtr(ImGuiViewport* viewport); +CIMGUI_API ImDrawList* igGetBackgroundDrawList(ImGuiViewport* viewport); CIMGUI_API ImDrawList* igGetForegroundDrawList_ViewportPtr(ImGuiViewport* viewport); CIMGUI_API bool igIsRectVisible_Nil(const ImVec2 size); CIMGUI_API bool igIsRectVisible_Vec2(const ImVec2 rect_min,const ImVec2 rect_max); @@ -3736,6 +3925,9 @@ CIMGUI_API bool igIsKeyChordPressed_Nil(ImGuiKeyChord key_chord); CIMGUI_API int igGetKeyPressedAmount(ImGuiKey key,float repeat_delay,float rate); CIMGUI_API const char* igGetKeyName(ImGuiKey key); CIMGUI_API void igSetNextFrameWantCaptureKeyboard(bool want_capture_keyboard); +CIMGUI_API bool igShortcut_Nil(ImGuiKeyChord key_chord,ImGuiInputFlags flags); +CIMGUI_API void igSetNextItemShortcut(ImGuiKeyChord key_chord,ImGuiInputFlags flags); +CIMGUI_API void igSetItemKeyOwner_Nil(ImGuiKey key); CIMGUI_API bool igIsMouseDown_Nil(ImGuiMouseButton button); CIMGUI_API bool igIsMouseClicked_Bool(ImGuiMouseButton button,bool repeat); CIMGUI_API bool igIsMouseReleased_Nil(ImGuiMouseButton button); @@ -3762,6 +3954,8 @@ CIMGUI_API void igDebugTextEncoding(const char* text); CIMGUI_API void igDebugFlashStyleColor(ImGuiCol idx); CIMGUI_API void igDebugStartItemPicker(void); CIMGUI_API bool igDebugCheckVersionAndDataLayout(const char* version_str,size_t sz_io,size_t sz_style,size_t sz_vec2,size_t sz_vec4,size_t sz_drawvert,size_t sz_drawidx); +CIMGUI_API void igDebugLog(const char* fmt,...); +CIMGUI_API void igDebugLogV(const char* fmt,va_list args); CIMGUI_API void igSetAllocatorFunctions(ImGuiMemAllocFunc alloc_func,ImGuiMemFreeFunc free_func,void* user_data); CIMGUI_API void igGetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func,ImGuiMemFreeFunc* p_free_func,void** p_user_data); CIMGUI_API void* igMemAlloc(size_t size); @@ -3794,6 +3988,7 @@ CIMGUI_API void ImGuiIO_SetKeyEventNativeData(ImGuiIO* self,ImGuiKey key,int nat CIMGUI_API void ImGuiIO_SetAppAcceptingEvents(ImGuiIO* self,bool accepting_events); CIMGUI_API void ImGuiIO_ClearEventsQueue(ImGuiIO* self); CIMGUI_API void ImGuiIO_ClearInputKeys(ImGuiIO* self); +CIMGUI_API void ImGuiIO_ClearInputMouse(ImGuiIO* self); CIMGUI_API ImGuiIO* ImGuiIO_ImGuiIO(void); CIMGUI_API void ImGuiIO_destroy(ImGuiIO* self); CIMGUI_API ImGuiInputTextCallbackData* ImGuiInputTextCallbackData_ImGuiInputTextCallbackData(void); @@ -3862,6 +4057,7 @@ CIMGUI_API void ImGuiListClipper_End(ImGuiListClipper* self); CIMGUI_API bool ImGuiListClipper_Step(ImGuiListClipper* self); CIMGUI_API void ImGuiListClipper_IncludeItemByIndex(ImGuiListClipper* self,int item_index); CIMGUI_API void ImGuiListClipper_IncludeItemsByIndex(ImGuiListClipper* self,int item_begin,int item_end); +CIMGUI_API void ImGuiListClipper_SeekCursorForItem(ImGuiListClipper* self,int item_index); CIMGUI_API ImColor* ImColor_ImColor_Nil(void); CIMGUI_API void ImColor_destroy(ImColor* self); CIMGUI_API ImColor* ImColor_ImColor_Float(float r,float g,float b,float a); @@ -3870,6 +4066,18 @@ CIMGUI_API ImColor* ImColor_ImColor_Int(int r,int g,int b,int a); CIMGUI_API ImColor* ImColor_ImColor_U32(ImU32 rgba); CIMGUI_API void ImColor_SetHSV(ImColor* self,float h,float s,float v,float a); CIMGUI_API void ImColor_HSV(ImColor *pOut,float h,float s,float v,float a); +CIMGUI_API ImGuiSelectionBasicStorage* ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage(void); +CIMGUI_API void ImGuiSelectionBasicStorage_destroy(ImGuiSelectionBasicStorage* self); +CIMGUI_API void ImGuiSelectionBasicStorage_ApplyRequests(ImGuiSelectionBasicStorage* self,ImGuiMultiSelectIO* ms_io); +CIMGUI_API bool ImGuiSelectionBasicStorage_Contains(ImGuiSelectionBasicStorage* self,ImGuiID id); +CIMGUI_API void ImGuiSelectionBasicStorage_Clear(ImGuiSelectionBasicStorage* self); +CIMGUI_API void ImGuiSelectionBasicStorage_Swap(ImGuiSelectionBasicStorage* self,ImGuiSelectionBasicStorage* r); +CIMGUI_API void ImGuiSelectionBasicStorage_SetItemSelected(ImGuiSelectionBasicStorage* self,ImGuiID id,bool selected); +CIMGUI_API bool ImGuiSelectionBasicStorage_GetNextSelectedItem(ImGuiSelectionBasicStorage* self,void** opaque_it,ImGuiID* out_id); +CIMGUI_API ImGuiID ImGuiSelectionBasicStorage_GetStorageIdFromIndex(ImGuiSelectionBasicStorage* self,int idx); +CIMGUI_API ImGuiSelectionExternalStorage* ImGuiSelectionExternalStorage_ImGuiSelectionExternalStorage(void); +CIMGUI_API void ImGuiSelectionExternalStorage_destroy(ImGuiSelectionExternalStorage* self); +CIMGUI_API void ImGuiSelectionExternalStorage_ApplyRequests(ImGuiSelectionExternalStorage* self,ImGuiMultiSelectIO* ms_io); CIMGUI_API ImDrawCmd* ImDrawCmd_ImDrawCmd(void); CIMGUI_API void ImDrawCmd_destroy(ImDrawCmd* self); CIMGUI_API ImTextureID ImDrawCmd_GetTexID(ImDrawCmd* self); @@ -3901,29 +4109,27 @@ CIMGUI_API void ImDrawList_AddCircle(ImDrawList* self,const ImVec2 center,float CIMGUI_API void ImDrawList_AddCircleFilled(ImDrawList* self,const ImVec2 center,float radius,ImU32 col,int num_segments); CIMGUI_API void ImDrawList_AddNgon(ImDrawList* self,const ImVec2 center,float radius,ImU32 col,int num_segments,float thickness); CIMGUI_API void ImDrawList_AddNgonFilled(ImDrawList* self,const ImVec2 center,float radius,ImU32 col,int num_segments); -CIMGUI_API void ImDrawList_AddEllipse(ImDrawList* self,const ImVec2 center,ImVec2 radius,ImU32 col,float rot,int num_segments,float thickness); -CIMGUI_API void ImDrawList_AddEllipseFilled(ImDrawList* self,const ImVec2 center,ImVec2 radius,ImU32 col,float rot,int num_segments); +CIMGUI_API void ImDrawList_AddEllipse(ImDrawList* self,const ImVec2 center,const ImVec2 radius,ImU32 col,float rot,int num_segments,float thickness); +CIMGUI_API void ImDrawList_AddEllipseFilled(ImDrawList* self,const ImVec2 center,const ImVec2 radius,ImU32 col,float rot,int num_segments); CIMGUI_API void ImDrawList_AddText_Vec2(ImDrawList* self,const ImVec2 pos,ImU32 col,const char* text_begin,const char* text_end); CIMGUI_API void ImDrawList_AddText_FontPtr(ImDrawList* self,const ImFont* font,float font_size,const ImVec2 pos,ImU32 col,const char* text_begin,const char* text_end,float wrap_width,const ImVec4* cpu_fine_clip_rect); -CIMGUI_API void ImDrawList_AddPolyline(ImDrawList* self,const ImVec2* points,int num_points,ImU32 col,ImDrawFlags flags,float thickness); -CIMGUI_API void ImDrawList_AddConvexPolyFilled(ImDrawList* self,const ImVec2* points,int num_points,ImU32 col); CIMGUI_API void ImDrawList_AddBezierCubic(ImDrawList* self,const ImVec2 p1,const ImVec2 p2,const ImVec2 p3,const ImVec2 p4,ImU32 col,float thickness,int num_segments); CIMGUI_API void ImDrawList_AddBezierQuadratic(ImDrawList* self,const ImVec2 p1,const ImVec2 p2,const ImVec2 p3,ImU32 col,float thickness,int num_segments); +CIMGUI_API void ImDrawList_AddPolyline(ImDrawList* self,const ImVec2* points,int num_points,ImU32 col,ImDrawFlags flags,float thickness); +CIMGUI_API void ImDrawList_AddConvexPolyFilled(ImDrawList* self,const ImVec2* points,int num_points,ImU32 col); +CIMGUI_API void ImDrawList_AddConcavePolyFilled(ImDrawList* self,const ImVec2* points,int num_points,ImU32 col); CIMGUI_API void ImDrawList_AddImage(ImDrawList* self,ImTextureID user_texture_id,const ImVec2 p_min,const ImVec2 p_max,const ImVec2 uv_min,const ImVec2 uv_max,ImU32 col); CIMGUI_API void ImDrawList_AddImageQuad(ImDrawList* self,ImTextureID user_texture_id,const ImVec2 p1,const ImVec2 p2,const ImVec2 p3,const ImVec2 p4,const ImVec2 uv1,const ImVec2 uv2,const ImVec2 uv3,const ImVec2 uv4,ImU32 col); CIMGUI_API void ImDrawList_AddImageRounded(ImDrawList* self,ImTextureID user_texture_id,const ImVec2 p_min,const ImVec2 p_max,const ImVec2 uv_min,const ImVec2 uv_max,ImU32 col,float rounding,ImDrawFlags flags); -CIMGUI_API void ImDrawList_AddShadowRect(ImDrawList* self,const ImVec2 obj_min,const ImVec2 obj_max,ImU32 shadow_col,float shadow_thickness,const ImVec2 shadow_offset,ImDrawFlags flags,float obj_rounding); -CIMGUI_API void ImDrawList_AddShadowCircle(ImDrawList* self,const ImVec2 obj_center,float obj_radius,ImU32 shadow_col,float shadow_thickness,const ImVec2 shadow_offset,ImDrawFlags flags,int obj_num_segments); -CIMGUI_API void ImDrawList_AddShadowConvexPoly(ImDrawList* self,const ImVec2* points,int points_count,ImU32 shadow_col,float shadow_thickness,const ImVec2 shadow_offset,ImDrawFlags flags); -CIMGUI_API void ImDrawList_AddShadowNGon(ImDrawList* self,const ImVec2 obj_center,float obj_radius,ImU32 shadow_col,float shadow_thickness,const ImVec2 shadow_offset,ImDrawFlags flags,int obj_num_segments); CIMGUI_API void ImDrawList_PathClear(ImDrawList* self); CIMGUI_API void ImDrawList_PathLineTo(ImDrawList* self,const ImVec2 pos); CIMGUI_API void ImDrawList_PathLineToMergeDuplicate(ImDrawList* self,const ImVec2 pos); CIMGUI_API void ImDrawList_PathFillConvex(ImDrawList* self,ImU32 col); +CIMGUI_API void ImDrawList_PathFillConcave(ImDrawList* self,ImU32 col); CIMGUI_API void ImDrawList_PathStroke(ImDrawList* self,ImU32 col,ImDrawFlags flags,float thickness); CIMGUI_API void ImDrawList_PathArcTo(ImDrawList* self,const ImVec2 center,float radius,float a_min,float a_max,int num_segments); CIMGUI_API void ImDrawList_PathArcToFast(ImDrawList* self,const ImVec2 center,float radius,int a_min_of_12,int a_max_of_12); -CIMGUI_API void ImDrawList_PathEllipticalArcTo(ImDrawList* self,const ImVec2 center,ImVec2 radius,float rot,float a_min,float a_max,int num_segments); +CIMGUI_API void ImDrawList_PathEllipticalArcTo(ImDrawList* self,const ImVec2 center,const ImVec2 radius,float rot,float a_min,float a_max,int num_segments); CIMGUI_API void ImDrawList_PathBezierCubicCurveTo(ImDrawList* self,const ImVec2 p2,const ImVec2 p3,const ImVec2 p4,int num_segments); CIMGUI_API void ImDrawList_PathBezierQuadraticCurveTo(ImDrawList* self,const ImVec2 p2,const ImVec2 p3,int num_segments); CIMGUI_API void ImDrawList_PathRect(ImDrawList* self,const ImVec2 rect_min,const ImVec2 rect_max,float rounding,ImDrawFlags flags); @@ -3939,7 +4145,7 @@ CIMGUI_API void ImDrawList_PrimRect(ImDrawList* self,const ImVec2 a,const ImVec2 CIMGUI_API void ImDrawList_PrimRectUV(ImDrawList* self,const ImVec2 a,const ImVec2 b,const ImVec2 uv_a,const ImVec2 uv_b,ImU32 col); CIMGUI_API void ImDrawList_PrimQuadUV(ImDrawList* self,const ImVec2 a,const ImVec2 b,const ImVec2 c,const ImVec2 d,const ImVec2 uv_a,const ImVec2 uv_b,const ImVec2 uv_c,const ImVec2 uv_d,ImU32 col); CIMGUI_API void ImDrawList_PrimWriteVtx(ImDrawList* self,const ImVec2 pos,const ImVec2 uv,ImU32 col); -CIMGUI_API void ImDrawList_PrimWriteIdx(ImDrawList* self,unsigned int idx); +CIMGUI_API void ImDrawList_PrimWriteIdx(ImDrawList* self,ImDrawIdx idx); CIMGUI_API void ImDrawList_PrimVtx(ImDrawList* self,const ImVec2 pos,const ImVec2 uv,ImU32 col); CIMGUI_API void ImDrawList__ResetForNewFrame(ImDrawList* self); CIMGUI_API void ImDrawList__ClearFreeMemory(ImDrawList* self); @@ -3957,14 +4163,6 @@ CIMGUI_API void ImDrawData_Clear(ImDrawData* self); CIMGUI_API void ImDrawData_AddDrawList(ImDrawData* self,ImDrawList* draw_list); CIMGUI_API void ImDrawData_DeIndexAllBuffers(ImDrawData* self); CIMGUI_API void ImDrawData_ScaleClipRects(ImDrawData* self,const ImVec2 fb_scale); -CIMGUI_API ImFontAtlasShadowTexConfig* ImFontAtlasShadowTexConfig_ImFontAtlasShadowTexConfig(void); -CIMGUI_API void ImFontAtlasShadowTexConfig_destroy(ImFontAtlasShadowTexConfig* self); -CIMGUI_API void ImFontAtlasShadowTexConfig_SetupDefaults(ImFontAtlasShadowTexConfig* self); -CIMGUI_API int ImFontAtlasShadowTexConfig_GetRectTexPadding(ImFontAtlasShadowTexConfig* self); -CIMGUI_API int ImFontAtlasShadowTexConfig_CalcRectTexSize(ImFontAtlasShadowTexConfig* self); -CIMGUI_API int ImFontAtlasShadowTexConfig_GetConvexTexPadding(ImFontAtlasShadowTexConfig* self); -CIMGUI_API int ImFontAtlasShadowTexConfig_CalcConvexTexWidth(ImFontAtlasShadowTexConfig* self); -CIMGUI_API int ImFontAtlasShadowTexConfig_CalcConvexTexHeight(ImFontAtlasShadowTexConfig* self); CIMGUI_API ImFontConfig* ImFontConfig_ImFontConfig(void); CIMGUI_API void ImFontConfig_destroy(ImFontConfig* self); CIMGUI_API ImFontGlyphRangesBuilder* ImFontGlyphRangesBuilder_ImFontGlyphRangesBuilder(void); @@ -4038,10 +4236,9 @@ CIMGUI_API ImGuiPlatformMonitor* ImGuiPlatformMonitor_ImGuiPlatformMonitor(void) CIMGUI_API void ImGuiPlatformMonitor_destroy(ImGuiPlatformMonitor* self); CIMGUI_API ImGuiPlatformImeData* ImGuiPlatformImeData_ImGuiPlatformImeData(void); CIMGUI_API void ImGuiPlatformImeData_destroy(ImGuiPlatformImeData* self); -CIMGUI_API ImGuiKey igGetKeyIndex(ImGuiKey key); CIMGUI_API ImGuiID igImHashData(const void* data,size_t data_size,ImGuiID seed); CIMGUI_API ImGuiID igImHashStr(const char* data,size_t data_size,ImGuiID seed); -CIMGUI_API void igImQsort(void* base,size_t count,size_t size_of_element,int(*compare_func)(const void*,const void*)); +CIMGUI_API void igImQsort(void* base,size_t count,size_t size_of_element,int(*compare_func)(void const*,void const*)); CIMGUI_API ImU32 igImAlphaBlendColors(ImU32 col_a,ImU32 col_b); CIMGUI_API bool igImIsPowerOfTwo_Int(int v); CIMGUI_API bool igImIsPowerOfTwo_U64(ImU64 v); @@ -4061,6 +4258,7 @@ CIMGUI_API const ImWchar* igImStrbolW(const ImWchar* buf_mid_line,const ImWchar* CIMGUI_API char igImToUpper(char c); CIMGUI_API bool igImCharIsBlankA(char c); CIMGUI_API bool igImCharIsBlankW(unsigned int c); +CIMGUI_API bool igImCharIsXdigitA(char c); CIMGUI_API int igImFormatString(char* buf,size_t buf_size,const char* fmt,...); CIMGUI_API int igImFormatStringV(char* buf,size_t buf_size,const char* fmt,va_list args); CIMGUI_API void igImFormatStringToTempBuffer(const char** out_buf,const char** out_buf_end,const char* fmt,...); @@ -4079,6 +4277,7 @@ CIMGUI_API int igImTextCountCharsFromUtf8(const char* in_text,const char* in_tex CIMGUI_API int igImTextCountUtf8BytesFromChar(const char* in_text,const char* in_text_end); CIMGUI_API int igImTextCountUtf8BytesFromStr(const ImWchar* in_text,const ImWchar* in_text_end); CIMGUI_API const char* igImTextFindPreviousUtf8Codepoint(const char* in_text_start,const char* in_text_curr); +CIMGUI_API int igImTextCountLines(const char* in_text,const char* in_text_end); CIMGUI_API ImFileHandle igImFileOpen(const char* filename,const char* mode); CIMGUI_API bool igImFileClose(ImFileHandle file); CIMGUI_API ImU64 igImFileGetSize(ImFileHandle file); @@ -4098,14 +4297,13 @@ CIMGUI_API float igImRsqrt_Float(float x); CIMGUI_API double igImRsqrt_double(double x); CIMGUI_API void igImMin(ImVec2 *pOut,const ImVec2 lhs,const ImVec2 rhs); CIMGUI_API void igImMax(ImVec2 *pOut,const ImVec2 lhs,const ImVec2 rhs); -CIMGUI_API void igImClamp(ImVec2 *pOut,const ImVec2 v,const ImVec2 mn,ImVec2 mx); +CIMGUI_API void igImClamp(ImVec2 *pOut,const ImVec2 v,const ImVec2 mn,const ImVec2 mx); CIMGUI_API void igImLerp_Vec2Float(ImVec2 *pOut,const ImVec2 a,const ImVec2 b,float t); CIMGUI_API void igImLerp_Vec2Vec2(ImVec2 *pOut,const ImVec2 a,const ImVec2 b,const ImVec2 t); CIMGUI_API void igImLerp_Vec4(ImVec4 *pOut,const ImVec4 a,const ImVec4 b,float t); CIMGUI_API float igImSaturate(float f); CIMGUI_API float igImLengthSqr_Vec2(const ImVec2 lhs); CIMGUI_API float igImLengthSqr_Vec4(const ImVec4 lhs); -CIMGUI_API float igImLength(const ImVec2 lhs,float fail_value); CIMGUI_API float igImInvLength(const ImVec2 lhs,float fail_value); CIMGUI_API float igImTrunc_Float(float f); CIMGUI_API void igImTrunc_Vec2(ImVec2 *pOut,const ImVec2 v); @@ -4115,6 +4313,7 @@ CIMGUI_API int igImModPositive(int a,int b); CIMGUI_API float igImDot(const ImVec2 a,const ImVec2 b); CIMGUI_API void igImRotate(ImVec2 *pOut,const ImVec2 v,float cos_a,float sin_a); CIMGUI_API float igImLinearSweep(float current,float target,float speed); +CIMGUI_API float igImLinearRemapClamp(float s0,float s1,float d0,float d1,float x); CIMGUI_API void igImMul(ImVec2 *pOut,const ImVec2 lhs,const ImVec2 rhs); CIMGUI_API bool igImIsFloatAboveGuaranteedIntegerPrecision(float f); CIMGUI_API float igImExponentialMovingAverage(float avg,float sample,int n); @@ -4127,6 +4326,7 @@ CIMGUI_API bool igImTriangleContainsPoint(const ImVec2 a,const ImVec2 b,const Im CIMGUI_API void igImTriangleClosestPoint(ImVec2 *pOut,const ImVec2 a,const ImVec2 b,const ImVec2 c,const ImVec2 p); CIMGUI_API void igImTriangleBarycentricCoords(const ImVec2 a,const ImVec2 b,const ImVec2 c,const ImVec2 p,float* out_u,float* out_v,float* out_w); CIMGUI_API float igImTriangleArea(const ImVec2 a,const ImVec2 b,const ImVec2 c); +CIMGUI_API bool igImTriangleIsClockwise(const ImVec2 a,const ImVec2 b,const ImVec2 c); CIMGUI_API ImVec1* ImVec1_ImVec1_Nil(void); CIMGUI_API void ImVec1_destroy(ImVec1* self); CIMGUI_API ImVec1* ImVec1_ImVec1_Float(float _x); @@ -4180,11 +4380,13 @@ CIMGUI_API int ImGuiTextIndex_size(ImGuiTextIndex* self); CIMGUI_API const char* ImGuiTextIndex_get_line_begin(ImGuiTextIndex* self,const char* base,int n); CIMGUI_API const char* ImGuiTextIndex_get_line_end(ImGuiTextIndex* self,const char* base,int n); CIMGUI_API void ImGuiTextIndex_append(ImGuiTextIndex* self,const char* base,int old_size,int new_size); +CIMGUI_API ImGuiStoragePair* igImLowerBound(ImGuiStoragePair* in_begin,ImGuiStoragePair* in_end,ImGuiID key); CIMGUI_API ImDrawListSharedData* ImDrawListSharedData_ImDrawListSharedData(void); CIMGUI_API void ImDrawListSharedData_destroy(ImDrawListSharedData* self); CIMGUI_API void ImDrawListSharedData_SetCircleTessellationMaxError(ImDrawListSharedData* self,float max_error); CIMGUI_API ImDrawDataBuilder* ImDrawDataBuilder_ImDrawDataBuilder(void); CIMGUI_API void ImDrawDataBuilder_destroy(ImDrawDataBuilder* self); +CIMGUI_API void* ImGuiDataVarInfo_GetVarPtr(ImGuiDataVarInfo* self,void* parent); CIMGUI_API ImGuiStyleMod* ImGuiStyleMod_ImGuiStyleMod_Int(ImGuiStyleVar idx,int v); CIMGUI_API void ImGuiStyleMod_destroy(ImGuiStyleMod* self); CIMGUI_API ImGuiStyleMod* ImGuiStyleMod_ImGuiStyleMod_Float(ImGuiStyleVar idx,float v); @@ -4232,7 +4434,6 @@ CIMGUI_API void ImGuiStackSizes_CompareWithContextState(ImGuiStackSizes* self,Im CIMGUI_API ImGuiPtrOrIndex* ImGuiPtrOrIndex_ImGuiPtrOrIndex_Ptr(void* ptr); CIMGUI_API void ImGuiPtrOrIndex_destroy(ImGuiPtrOrIndex* self); CIMGUI_API ImGuiPtrOrIndex* ImGuiPtrOrIndex_ImGuiPtrOrIndex_Int(int index); -CIMGUI_API void* ImGuiDataVarInfo_GetVarPtr(ImGuiDataVarInfo* self,void* parent); CIMGUI_API ImGuiPopupData* ImGuiPopupData_ImGuiPopupData(void); CIMGUI_API void ImGuiPopupData_destroy(ImGuiPopupData* self); CIMGUI_API ImGuiInputEvent* ImGuiInputEvent_ImGuiInputEvent(void); @@ -4259,6 +4460,14 @@ CIMGUI_API ImGuiOldColumnData* ImGuiOldColumnData_ImGuiOldColumnData(void); CIMGUI_API void ImGuiOldColumnData_destroy(ImGuiOldColumnData* self); CIMGUI_API ImGuiOldColumns* ImGuiOldColumns_ImGuiOldColumns(void); CIMGUI_API void ImGuiOldColumns_destroy(ImGuiOldColumns* self); +CIMGUI_API ImGuiBoxSelectState* ImGuiBoxSelectState_ImGuiBoxSelectState(void); +CIMGUI_API void ImGuiBoxSelectState_destroy(ImGuiBoxSelectState* self); +CIMGUI_API ImGuiMultiSelectTempData* ImGuiMultiSelectTempData_ImGuiMultiSelectTempData(void); +CIMGUI_API void ImGuiMultiSelectTempData_destroy(ImGuiMultiSelectTempData* self); +CIMGUI_API void ImGuiMultiSelectTempData_Clear(ImGuiMultiSelectTempData* self); +CIMGUI_API void ImGuiMultiSelectTempData_ClearIO(ImGuiMultiSelectTempData* self); +CIMGUI_API ImGuiMultiSelectState* ImGuiMultiSelectState_ImGuiMultiSelectState(void); +CIMGUI_API void ImGuiMultiSelectState_destroy(ImGuiMultiSelectState* self); CIMGUI_API ImGuiDockNode* ImGuiDockNode_ImGuiDockNode(ImGuiID id); CIMGUI_API void ImGuiDockNode_destroy(ImGuiDockNode* self); CIMGUI_API bool ImGuiDockNode_IsRootNode(ImGuiDockNode* self); @@ -4307,9 +4516,7 @@ CIMGUI_API ImGuiID ImGuiWindow_GetID_Int(ImGuiWindow* self,int n); CIMGUI_API ImGuiID ImGuiWindow_GetIDFromRectangle(ImGuiWindow* self,const ImRect r_abs); CIMGUI_API void ImGuiWindow_Rect(ImRect *pOut,ImGuiWindow* self); CIMGUI_API float ImGuiWindow_CalcFontSize(ImGuiWindow* self); -CIMGUI_API float ImGuiWindow_TitleBarHeight(ImGuiWindow* self); CIMGUI_API void ImGuiWindow_TitleBarRect(ImRect *pOut,ImGuiWindow* self); -CIMGUI_API float ImGuiWindow_MenuBarHeight(ImGuiWindow* self); CIMGUI_API void ImGuiWindow_MenuBarRect(ImRect *pOut,ImGuiWindow* self); CIMGUI_API ImGuiTabItem* ImGuiTabItem_ImGuiTabItem(void); CIMGUI_API void ImGuiTabItem_destroy(ImGuiTabItem* self); @@ -4333,6 +4540,7 @@ CIMGUI_API ImGuiWindow* igGetCurrentWindow(void); CIMGUI_API ImGuiWindow* igFindWindowByID(ImGuiID id); CIMGUI_API ImGuiWindow* igFindWindowByName(const char* name); CIMGUI_API void igUpdateWindowParentAndRootLinks(ImGuiWindow* window,ImGuiWindowFlags flags,ImGuiWindow* parent_window); +CIMGUI_API void igUpdateWindowSkipRefresh(ImGuiWindow* window); CIMGUI_API void igCalcWindowNextAutoFitSize(ImVec2 *pOut,ImGuiWindow* window); CIMGUI_API bool igIsWindowChildOf(ImGuiWindow* window,ImGuiWindow* potential_parent,bool popup_hierarchy,bool dock_hierarchy); CIMGUI_API bool igIsWindowWithinBeginStackOf(ImGuiWindow* window,ImGuiWindow* potential_parent); @@ -4347,6 +4555,7 @@ CIMGUI_API void igSetWindowParentWindowForFocusRoute(ImGuiWindow* window,ImGuiWi CIMGUI_API void igWindowRectAbsToRel(ImRect *pOut,ImGuiWindow* window,const ImRect r); CIMGUI_API void igWindowRectRelToAbs(ImRect *pOut,ImGuiWindow* window,const ImRect r); CIMGUI_API void igWindowPosRelToAbs(ImVec2 *pOut,ImGuiWindow* window,const ImVec2 p); +CIMGUI_API void igWindowPosAbsToRel(ImVec2 *pOut,ImGuiWindow* window,const ImVec2 p); CIMGUI_API void igFocusWindow(ImGuiWindow* window,ImGuiFocusRequestFlags flags); CIMGUI_API void igFocusTopMostWindowUnderOne(ImGuiWindow* under_this_window,ImGuiWindow* ignore_window,ImGuiViewport* filter_viewport,ImGuiFocusRequestFlags flags); CIMGUI_API void igBringWindowToFocusFront(ImGuiWindow* window); @@ -4355,6 +4564,7 @@ CIMGUI_API void igBringWindowToDisplayBack(ImGuiWindow* window); CIMGUI_API void igBringWindowToDisplayBehind(ImGuiWindow* window,ImGuiWindow* above_window); CIMGUI_API int igFindWindowDisplayIndex(ImGuiWindow* window); CIMGUI_API ImGuiWindow* igFindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* window); +CIMGUI_API void igSetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags); CIMGUI_API void igSetCurrentFont(ImFont* font); CIMGUI_API ImFont* igGetDefaultFont(void); CIMGUI_API ImDrawList* igGetForegroundDrawList_WindowPtr(ImGuiWindow* window); @@ -4363,6 +4573,7 @@ CIMGUI_API void igInitialize(void); CIMGUI_API void igShutdown(void); CIMGUI_API void igUpdateInputEvents(bool trickle_fast_inputs); CIMGUI_API void igUpdateHoveredWindowAndCaptureFlags(void); +CIMGUI_API void igFindHoveredWindowEx(const ImVec2 pos,bool find_first_and_in_any_viewport,ImGuiWindow** out_hovered_window,ImGuiWindow** out_hovered_window_under_moving_window); CIMGUI_API void igStartMouseMovingWindow(ImGuiWindow* window); CIMGUI_API void igStartMouseMovingWindowOrNode(ImGuiWindow* window,ImGuiDockNode* node,bool undock); CIMGUI_API void igUpdateMouseMovingWindowNewFrame(void); @@ -4421,31 +4632,29 @@ CIMGUI_API void igSetLastItemData(ImGuiID item_id,ImGuiItemFlags in_flags,ImGuiI CIMGUI_API void igCalcItemSize(ImVec2 *pOut,ImVec2 size,float default_w,float default_h); CIMGUI_API float igCalcWrapWidthForPos(const ImVec2 pos,float wrap_pos_x); CIMGUI_API void igPushMultiItemsWidths(int components,float width_full); -CIMGUI_API bool igIsItemToggledSelection(void); -CIMGUI_API void igGetContentRegionMaxAbs(ImVec2 *pOut); CIMGUI_API void igShrinkWidths(ImGuiShrinkWidthItem* items,int count,float width_excess); -CIMGUI_API void igPushItemFlag(ImGuiItemFlags option,bool enabled); -CIMGUI_API void igPopItemFlag(void); CIMGUI_API const ImGuiDataVarInfo* igGetStyleVarInfo(ImGuiStyleVar idx); +CIMGUI_API void igBeginDisabledOverrideReenable(void); +CIMGUI_API void igEndDisabledOverrideReenable(void); CIMGUI_API void igLogBegin(ImGuiLogType type,int auto_open_depth); CIMGUI_API void igLogToBuffer(int auto_open_depth); CIMGUI_API void igLogRenderedText(const ImVec2* ref_pos,const char* text,const char* text_end); CIMGUI_API void igLogSetNextTextDecoration(const char* prefix,const char* suffix); CIMGUI_API bool igBeginChildEx(const char* name,ImGuiID id,const ImVec2 size_arg,ImGuiChildFlags child_flags,ImGuiWindowFlags window_flags); +CIMGUI_API bool igBeginPopupEx(ImGuiID id,ImGuiWindowFlags extra_window_flags); CIMGUI_API void igOpenPopupEx(ImGuiID id,ImGuiPopupFlags popup_flags); CIMGUI_API void igClosePopupToLevel(int remaining,bool restore_focus_to_window_under_popup); CIMGUI_API void igClosePopupsOverWindow(ImGuiWindow* ref_window,bool restore_focus_to_window_under_popup); CIMGUI_API void igClosePopupsExceptModals(void); CIMGUI_API bool igIsPopupOpen_ID(ImGuiID id,ImGuiPopupFlags popup_flags); -CIMGUI_API bool igBeginPopupEx(ImGuiID id,ImGuiWindowFlags extra_flags); -CIMGUI_API bool igBeginTooltipEx(ImGuiTooltipFlags tooltip_flags,ImGuiWindowFlags extra_window_flags); -CIMGUI_API bool igBeginTooltipHidden(void); CIMGUI_API void igGetPopupAllowedExtentRect(ImRect *pOut,ImGuiWindow* window); CIMGUI_API ImGuiWindow* igGetTopMostPopupModal(void); CIMGUI_API ImGuiWindow* igGetTopMostAndVisiblePopupModal(void); CIMGUI_API ImGuiWindow* igFindBlockingModal(ImGuiWindow* window); CIMGUI_API void igFindBestWindowPosForPopup(ImVec2 *pOut,ImGuiWindow* window); CIMGUI_API void igFindBestWindowPosForPopupEx(ImVec2 *pOut,const ImVec2 ref_pos,const ImVec2 size,ImGuiDir* last_dir,const ImRect r_outer,const ImRect r_avoid,ImGuiPopupPositionPolicy policy); +CIMGUI_API bool igBeginTooltipEx(ImGuiTooltipFlags tooltip_flags,ImGuiWindowFlags extra_window_flags); +CIMGUI_API bool igBeginTooltipHidden(void); CIMGUI_API bool igBeginViewportSideBar(const char* name,ImGuiViewport* viewport,ImGuiDir dir,float size,ImGuiWindowFlags window_flags); CIMGUI_API bool igBeginMenuEx(const char* label,const char* icon,bool enabled); CIMGUI_API bool igMenuItemEx(const char* label,const char* icon,const char* shortcut,bool selected,bool enabled); @@ -4458,7 +4667,7 @@ CIMGUI_API bool igNavMoveRequestButNoResultYet(void); CIMGUI_API void igNavMoveRequestSubmit(ImGuiDir move_dir,ImGuiDir clip_dir,ImGuiNavMoveFlags move_flags,ImGuiScrollFlags scroll_flags); CIMGUI_API void igNavMoveRequestForward(ImGuiDir move_dir,ImGuiDir clip_dir,ImGuiNavMoveFlags move_flags,ImGuiScrollFlags scroll_flags); CIMGUI_API void igNavMoveRequestResolveWithLastItem(ImGuiNavItemData* result); -CIMGUI_API void igNavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result,ImGuiNavTreeNodeData* tree_node_data); +CIMGUI_API void igNavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result,ImGuiTreeNodeStackData* tree_node_data); CIMGUI_API void igNavMoveRequestCancel(void); CIMGUI_API void igNavMoveRequestApplyResult(void); CIMGUI_API void igNavMoveRequestTryWrapping(ImGuiWindow* window,ImGuiNavMoveFlags move_flags); @@ -4496,20 +4705,19 @@ CIMGUI_API bool igIsActiveIdUsingNavDir(ImGuiDir dir); CIMGUI_API ImGuiID igGetKeyOwner(ImGuiKey key); CIMGUI_API void igSetKeyOwner(ImGuiKey key,ImGuiID owner_id,ImGuiInputFlags flags); CIMGUI_API void igSetKeyOwnersForKeyChord(ImGuiKeyChord key,ImGuiID owner_id,ImGuiInputFlags flags); -CIMGUI_API void igSetItemKeyOwner(ImGuiKey key,ImGuiInputFlags flags); +CIMGUI_API void igSetItemKeyOwner_InputFlags(ImGuiKey key,ImGuiInputFlags flags); CIMGUI_API bool igTestKeyOwner(ImGuiKey key,ImGuiID owner_id); CIMGUI_API ImGuiKeyOwnerData* igGetKeyOwnerData(ImGuiContext* ctx,ImGuiKey key); CIMGUI_API bool igIsKeyDown_ID(ImGuiKey key,ImGuiID owner_id); -CIMGUI_API bool igIsKeyPressed_ID(ImGuiKey key,ImGuiID owner_id,ImGuiInputFlags flags); +CIMGUI_API bool igIsKeyPressed_InputFlags(ImGuiKey key,ImGuiInputFlags flags,ImGuiID owner_id); CIMGUI_API bool igIsKeyReleased_ID(ImGuiKey key,ImGuiID owner_id); +CIMGUI_API bool igIsKeyChordPressed_InputFlags(ImGuiKeyChord key_chord,ImGuiInputFlags flags,ImGuiID owner_id); CIMGUI_API bool igIsMouseDown_ID(ImGuiMouseButton button,ImGuiID owner_id); -CIMGUI_API bool igIsMouseClicked_ID(ImGuiMouseButton button,ImGuiID owner_id,ImGuiInputFlags flags); +CIMGUI_API bool igIsMouseClicked_InputFlags(ImGuiMouseButton button,ImGuiInputFlags flags,ImGuiID owner_id); CIMGUI_API bool igIsMouseReleased_ID(ImGuiMouseButton button,ImGuiID owner_id); CIMGUI_API bool igIsMouseDoubleClicked_ID(ImGuiMouseButton button,ImGuiID owner_id); -CIMGUI_API bool igIsKeyChordPressed_ID(ImGuiKeyChord key_chord,ImGuiID owner_id,ImGuiInputFlags flags); -CIMGUI_API void igSetNextItemShortcut(ImGuiKeyChord key_chord); -CIMGUI_API bool igShortcut(ImGuiKeyChord key_chord,ImGuiID owner_id,ImGuiInputFlags flags); -CIMGUI_API bool igSetShortcutRouting(ImGuiKeyChord key_chord,ImGuiID owner_id,ImGuiInputFlags flags); +CIMGUI_API bool igShortcut_ID(ImGuiKeyChord key_chord,ImGuiInputFlags flags,ImGuiID owner_id); +CIMGUI_API bool igSetShortcutRouting(ImGuiKeyChord key_chord,ImGuiInputFlags flags,ImGuiID owner_id); CIMGUI_API bool igTestShortcutRouting(ImGuiKeyChord key_chord,ImGuiID owner_id); CIMGUI_API ImGuiKeyRoutingData* igGetShortcutRoutingData(ImGuiKeyChord key_chord); CIMGUI_API void igDockContextInitialize(ImGuiContext* ctx); @@ -4566,6 +4774,14 @@ CIMGUI_API ImGuiTypingSelectRequest* igGetTypingSelectRequest(ImGuiTypingSelectF CIMGUI_API int igTypingSelectFindMatch(ImGuiTypingSelectRequest* req,int items_count,const char*(*get_item_name_func)(void*,int),void* user_data,int nav_item_idx); CIMGUI_API int igTypingSelectFindNextSingleCharMatch(ImGuiTypingSelectRequest* req,int items_count,const char*(*get_item_name_func)(void*,int),void* user_data,int nav_item_idx); CIMGUI_API int igTypingSelectFindBestLeadingMatch(ImGuiTypingSelectRequest* req,int items_count,const char*(*get_item_name_func)(void*,int),void* user_data); +CIMGUI_API bool igBeginBoxSelect(const ImRect scope_rect,ImGuiWindow* window,ImGuiID box_select_id,ImGuiMultiSelectFlags ms_flags); +CIMGUI_API void igEndBoxSelect(const ImRect scope_rect,ImGuiMultiSelectFlags ms_flags); +CIMGUI_API void igMultiSelectItemHeader(ImGuiID id,bool* p_selected,ImGuiButtonFlags* p_button_flags); +CIMGUI_API void igMultiSelectItemFooter(ImGuiID id,bool* p_selected,bool* p_pressed); +CIMGUI_API void igMultiSelectAddSetAll(ImGuiMultiSelectTempData* ms,bool selected); +CIMGUI_API void igMultiSelectAddSetRange(ImGuiMultiSelectTempData* ms,bool selected,int range_dir,ImGuiSelectionUserData first_item,ImGuiSelectionUserData last_item); +CIMGUI_API ImGuiBoxSelectState* igGetBoxSelectState(ImGuiID id); +CIMGUI_API ImGuiMultiSelectState* igGetMultiSelectState(ImGuiID id); CIMGUI_API void igSetWindowClipRectBeforeSetChannel(ImGuiWindow* window,const ImRect clip_rect); CIMGUI_API void igBeginColumns(const char* str_id,int count,ImGuiOldColumnFlags flags); CIMGUI_API void igEndColumns(void); @@ -4579,13 +4795,12 @@ CIMGUI_API float igGetColumnNormFromOffset(const ImGuiOldColumns* columns,float CIMGUI_API void igTableOpenContextMenu(int column_n); CIMGUI_API void igTableSetColumnWidth(int column_n,float width); CIMGUI_API void igTableSetColumnSortDirection(int column_n,ImGuiSortDirection sort_direction,bool append_to_sort_specs); -CIMGUI_API int igTableGetHoveredColumn(void); CIMGUI_API int igTableGetHoveredRow(void); CIMGUI_API float igTableGetHeaderRowHeight(void); CIMGUI_API float igTableGetHeaderAngledMaxLabelWidth(void); CIMGUI_API void igTablePushBackgroundChannel(void); CIMGUI_API void igTablePopBackgroundChannel(void); -CIMGUI_API void igTableAngledHeadersRowEx(ImGuiID row_id, float angle,float max_label_width, const ImGuiTableHeaderData *data, int data_count); +CIMGUI_API void igTableAngledHeadersRowEx(ImGuiID row_id,float angle,float max_label_width,const ImGuiTableHeaderData* data,int data_count); CIMGUI_API ImGuiTable* igGetCurrentTable(void); CIMGUI_API ImGuiTable* igTableFindByID(ImGuiID id); CIMGUI_API bool igBeginTableEx(const char* name,ImGuiID id,int columns_count,ImGuiTableFlags flags,const ImVec2 outer_size,float inner_width); @@ -4688,13 +4903,13 @@ CIMGUI_API bool igSliderBehavior(const ImRect bb,ImGuiID id,ImGuiDataType data_t CIMGUI_API bool igSplitterBehavior(const ImRect bb,ImGuiID id,ImGuiAxis axis,float* size1,float* size2,float min_size1,float min_size2,float hover_extend,float hover_visibility_delay,ImU32 bg_col); CIMGUI_API bool igTreeNodeBehavior(ImGuiID id,ImGuiTreeNodeFlags flags,const char* label,const char* label_end); CIMGUI_API void igTreePushOverrideID(ImGuiID id); -CIMGUI_API void igTreeNodeSetOpen(ImGuiID id,bool open); -CIMGUI_API bool igTreeNodeUpdateNextOpen(ImGuiID id,ImGuiTreeNodeFlags flags); -CIMGUI_API void igSetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data); +CIMGUI_API bool igTreeNodeGetOpen(ImGuiID storage_id); +CIMGUI_API void igTreeNodeSetOpen(ImGuiID storage_id,bool open); +CIMGUI_API bool igTreeNodeUpdateNextOpen(ImGuiID storage_id,ImGuiTreeNodeFlags flags); CIMGUI_API const ImGuiDataTypeInfo* igDataTypeGetInfo(ImGuiDataType data_type); CIMGUI_API int igDataTypeFormatString(char* buf,int buf_size,ImGuiDataType data_type,const void* p_data,const char* format); CIMGUI_API void igDataTypeApplyOp(ImGuiDataType data_type,int op,void* output,const void* arg_1,const void* arg_2); -CIMGUI_API bool igDataTypeApplyFromText(const char* buf,ImGuiDataType data_type,void* p_data,const char* format); +CIMGUI_API bool igDataTypeApplyFromText(const char* buf,ImGuiDataType data_type,void* p_data,const char* format,void* p_data_when_empty); CIMGUI_API int igDataTypeCompare(ImGuiDataType data_type,const void* arg_1,const void* arg_2); CIMGUI_API bool igDataTypeClamp(ImGuiDataType data_type,void* p_data,const void* p_min,const void* p_max); CIMGUI_API bool igInputTextEx(const char* label,const char* hint,char* buf,int buf_size,const ImVec2 size_arg,ImGuiInputTextFlags flags,ImGuiInputTextCallback callback,void* user_data); @@ -4703,6 +4918,7 @@ CIMGUI_API bool igTempInputText(const ImRect bb,ImGuiID id,const char* label,cha CIMGUI_API bool igTempInputScalar(const ImRect bb,ImGuiID id,const char* label,ImGuiDataType data_type,void* p_data,const char* format,const void* p_clamp_min,const void* p_clamp_max); CIMGUI_API bool igTempInputIsActive(ImGuiID id); CIMGUI_API ImGuiInputTextState* igGetInputTextState(ImGuiID id); +CIMGUI_API void igSetNextItemRefVal(ImGuiDataType data_type,void* p_data); CIMGUI_API void igColorTooltip(const char* text,const float* col,ImGuiColorEditFlags flags); CIMGUI_API void igColorEditOptionsPopup(const float* col,ImGuiColorEditFlags flags); CIMGUI_API void igColorPickerOptionsPopup(const float* ref_col,ImGuiColorEditFlags flags); @@ -4713,8 +4929,6 @@ CIMGUI_API void igShadeVertsTransformPos(ImDrawList* draw_list,int vert_start_id CIMGUI_API void igGcCompactTransientMiscBuffers(void); CIMGUI_API void igGcCompactTransientWindowBuffers(ImGuiWindow* window); CIMGUI_API void igGcAwakeTransientWindowBuffers(ImGuiWindow* window); -CIMGUI_API void igDebugLog(const char* fmt,...); -CIMGUI_API void igDebugLogV(const char* fmt,va_list args); CIMGUI_API void igDebugAllocHook(ImGuiDebugAllocInfo* info,int frame_count,void* ptr,size_t size); CIMGUI_API void igErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback,void* user_data); CIMGUI_API void igErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback,void* user_data); @@ -4722,6 +4936,7 @@ CIMGUI_API void igErrorCheckUsingSetCursorPosToExtendParentBoundaries(void); CIMGUI_API void igDebugDrawCursorPos(ImU32 col); CIMGUI_API void igDebugDrawLineExtents(ImU32 col); CIMGUI_API void igDebugDrawItemRect(ImU32 col); +CIMGUI_API void igDebugTextUnformattedWithLocateItem(const char* line_begin,const char* line_end); CIMGUI_API void igDebugLocateItem(ImGuiID target_id); CIMGUI_API void igDebugLocateItemOnHover(ImGuiID target_id); CIMGUI_API void igDebugLocateItemResolveWithLastItem(void); @@ -4742,13 +4957,16 @@ CIMGUI_API void igDebugNodeTable(ImGuiTable* table); CIMGUI_API void igDebugNodeTableSettings(ImGuiTableSettings* settings); CIMGUI_API void igDebugNodeInputTextState(ImGuiInputTextState* state); CIMGUI_API void igDebugNodeTypingSelectState(ImGuiTypingSelectState* state); +CIMGUI_API void igDebugNodeMultiSelectState(ImGuiMultiSelectState* state); CIMGUI_API void igDebugNodeWindow(ImGuiWindow* window,const char* label); CIMGUI_API void igDebugNodeWindowSettings(ImGuiWindowSettings* settings); CIMGUI_API void igDebugNodeWindowsList(ImVector_ImGuiWindowPtr* windows,const char* label); CIMGUI_API void igDebugNodeWindowsListByBeginStackParent(ImGuiWindow** windows,int windows_size,ImGuiWindow* parent_in_begin_stack); CIMGUI_API void igDebugNodeViewport(ImGuiViewportP* viewport); +CIMGUI_API void igDebugNodePlatformMonitor(ImGuiPlatformMonitor* monitor,const char* label,int idx); CIMGUI_API void igDebugRenderKeyboardPreview(ImDrawList* draw_list); CIMGUI_API void igDebugRenderViewportThumbnail(ImDrawList* draw_list,ImGuiViewportP* viewport,const ImRect bb); +CIMGUI_API const ImFontBuilderIO* igImFontAtlasGetBuilderForStbTruetype(void); CIMGUI_API void igImFontAtlasUpdateConfigDataPointers(ImFontAtlas* atlas); CIMGUI_API void igImFontAtlasBuildInit(ImFontAtlas* atlas); CIMGUI_API void igImFontAtlasBuildSetupFont(ImFontAtlas* atlas,ImFont* font,ImFontConfig* font_config,float ascent,float descent); @@ -4758,10 +4976,6 @@ CIMGUI_API void igImFontAtlasBuildRender8bppRectFromString(ImFontAtlas* atlas,in CIMGUI_API void igImFontAtlasBuildRender32bppRectFromString(ImFontAtlas* atlas,int x,int y,int w,int h,const char* in_str,char in_marker_char,unsigned int in_marker_pixel_value); CIMGUI_API void igImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256],float in_multiply_factor); CIMGUI_API void igImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256],unsigned char* pixels,int x,int y,int w,int h,int stride); -CIMGUI_API void igImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx,ImGuiID id,const ImRect bb,const ImGuiLastItemData* item_data); -CIMGUI_API void igImGuiTestEngineHook_ItemInfo(ImGuiContext* ctx,ImGuiID id,const char* label,ImGuiItemStatusFlags flags); -CIMGUI_API void igImGuiTestEngineHook_Log(ImGuiContext* ctx,const char* fmt,...); -CIMGUI_API const char* igImGuiTestEngine_FindItemDebugLabel(ImGuiContext* ctx,ImGuiID id); /////////////////////////hand written functions @@ -4780,6 +4994,10 @@ CIMGUI_API void ImVector_ImWchar_destroy(ImVector_ImWchar* self); CIMGUI_API void ImVector_ImWchar_Init(ImVector_ImWchar* p); CIMGUI_API void ImVector_ImWchar_UnInit(ImVector_ImWchar* p); +#ifdef IMGUI_HAS_DOCK +CIMGUI_API void ImGuiPlatformIO_Set_Platform_GetWindowPos(ImGuiPlatformIO* platform_io, void(*user_callback)(ImGuiViewport* vp, ImVec2* out_pos)); +CIMGUI_API void ImGuiPlatformIO_Set_Platform_GetWindowSize(ImGuiPlatformIO* platform_io, void(*user_callback)(ImGuiViewport* vp, ImVec2* out_size)); +#endif #endif //CIMGUI_INCLUDED diff --git a/lib/third_party/imgui/cimgui/source/cimgui.cpp b/lib/third_party/imgui/cimgui/source/cimgui.cpp index 719c6c3f5..06f423005 100644 --- a/lib/third_party/imgui/cimgui/source/cimgui.cpp +++ b/lib/third_party/imgui/cimgui/source/cimgui.cpp @@ -1,5 +1,5 @@ //This file is automatically generated by generator.lua from https://github.com/cimgui/cimgui -//based on imgui.h file version "1.90.4" 19040 from Dear ImGui https://github.com/ocornut/imgui +//based on imgui.h file version "1.91.0" 19100 from Dear ImGui https://github.com/ocornut/imgui //with imgui_internal.h api //docking branch #ifdef IMGUI_ENABLE_FREETYPE @@ -11,10 +11,10 @@ #error "IMGUI_FREETYPE should not be defined without freetype generated cimgui" #endif #endif -#ifdef IMGUI_ENABLE_FREETYPE -#include "./imgui/misc/freetype/imgui_freetype.h" -#endif #include "imgui.h" +#ifdef IMGUI_ENABLE_FREETYPE +#include "misc/freetype/imgui_freetype.h" +#endif #include "imgui_internal.h" #include "cimgui.h" @@ -272,22 +272,6 @@ CIMGUI_API void igSetWindowFocus_Str(const char* name) { return ImGui::SetWindowFocus(name); } -CIMGUI_API void igGetContentRegionAvail(ImVec2 *pOut) -{ - *pOut = ImGui::GetContentRegionAvail(); -} -CIMGUI_API void igGetContentRegionMax(ImVec2 *pOut) -{ - *pOut = ImGui::GetContentRegionMax(); -} -CIMGUI_API void igGetWindowContentRegionMin(ImVec2 *pOut) -{ - *pOut = ImGui::GetWindowContentRegionMin(); -} -CIMGUI_API void igGetWindowContentRegionMax(ImVec2 *pOut) -{ - *pOut = ImGui::GetWindowContentRegionMax(); -} CIMGUI_API float igGetScrollX() { return ImGui::GetScrollX(); @@ -360,21 +344,13 @@ CIMGUI_API void igPopStyleVar(int count) { return ImGui::PopStyleVar(count); } -CIMGUI_API void igPushTabStop(bool tab_stop) +CIMGUI_API void igPushItemFlag(ImGuiItemFlags option,bool enabled) { - return ImGui::PushTabStop(tab_stop); + return ImGui::PushItemFlag(option,enabled); } -CIMGUI_API void igPopTabStop() +CIMGUI_API void igPopItemFlag() { - return ImGui::PopTabStop(); -} -CIMGUI_API void igPushButtonRepeat(bool repeat) -{ - return ImGui::PushButtonRepeat(repeat); -} -CIMGUI_API void igPopButtonRepeat() -{ - return ImGui::PopButtonRepeat(); + return ImGui::PopItemFlag(); } CIMGUI_API void igPushItemWidth(float item_width) { @@ -436,6 +412,10 @@ CIMGUI_API void igSetCursorScreenPos(const ImVec2 pos) { return ImGui::SetCursorScreenPos(pos); } +CIMGUI_API void igGetContentRegionAvail(ImVec2 *pOut) +{ + *pOut = ImGui::GetContentRegionAvail(); +} CIMGUI_API void igGetCursorPos(ImVec2 *pOut) { *pOut = ImGui::GetCursorPos(); @@ -552,6 +532,10 @@ CIMGUI_API ImGuiID igGetID_Ptr(const void* ptr_id) { return ImGui::GetID(ptr_id); } +CIMGUI_API ImGuiID igGetID_Int(int int_id) +{ + return ImGui::GetID(int_id); +} CIMGUI_API void igTextUnformatted(const char* text,const char* text_end) { return ImGui::TextUnformatted(text,text_end); @@ -670,6 +654,14 @@ CIMGUI_API void igBullet() { return ImGui::Bullet(); } +CIMGUI_API bool igTextLink(const char* label) +{ + return ImGui::TextLink(label); +} +CIMGUI_API void igTextLinkOpenURL(const char* label,const char* url) +{ + return ImGui::TextLinkOpenURL(label,url); +} CIMGUI_API void igImage(ImTextureID user_texture_id,const ImVec2 image_size,const ImVec2 uv0,const ImVec2 uv1,const ImVec4 tint_col,const ImVec4 border_col) { return ImGui::Image(user_texture_id,image_size,uv0,uv1,tint_col,border_col); @@ -966,6 +958,10 @@ CIMGUI_API void igSetNextItemOpen(bool is_open,ImGuiCond cond) { return ImGui::SetNextItemOpen(is_open,cond); } +CIMGUI_API void igSetNextItemStorageID(ImGuiID storage_id) +{ + return ImGui::SetNextItemStorageID(storage_id); +} CIMGUI_API bool igSelectable_Bool(const char* label,bool selected,ImGuiSelectableFlags flags,const ImVec2 size) { return ImGui::Selectable(label,selected,flags,size); @@ -974,6 +970,22 @@ CIMGUI_API bool igSelectable_BoolPtr(const char* label,bool* p_selected,ImGuiSel { return ImGui::Selectable(label,p_selected,flags,size); } +CIMGUI_API ImGuiMultiSelectIO* igBeginMultiSelect(ImGuiMultiSelectFlags flags,int selection_size,int items_count) +{ + return ImGui::BeginMultiSelect(flags,selection_size,items_count); +} +CIMGUI_API ImGuiMultiSelectIO* igEndMultiSelect() +{ + return ImGui::EndMultiSelect(); +} +CIMGUI_API void igSetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data) +{ + return ImGui::SetNextItemSelectionUserData(selection_user_data); +} +CIMGUI_API bool igIsItemToggledSelection() +{ + return ImGui::IsItemToggledSelection(); +} CIMGUI_API bool igBeginListBox(const char* label,const ImVec2 size) { return ImGui::BeginListBox(label,size); @@ -1132,9 +1144,9 @@ CIMGUI_API bool igIsPopupOpen_Str(const char* str_id,ImGuiPopupFlags flags) { return ImGui::IsPopupOpen(str_id,flags); } -CIMGUI_API bool igBeginTable(const char* str_id,int column,ImGuiTableFlags flags,const ImVec2 outer_size,float inner_width) +CIMGUI_API bool igBeginTable(const char* str_id,int columns,ImGuiTableFlags flags,const ImVec2 outer_size,float inner_width) { - return ImGui::BeginTable(str_id,column,flags,outer_size,inner_width); + return ImGui::BeginTable(str_id,columns,flags,outer_size,inner_width); } CIMGUI_API void igEndTable() { @@ -1200,6 +1212,10 @@ CIMGUI_API void igTableSetColumnEnabled(int column_n,bool v) { return ImGui::TableSetColumnEnabled(column_n,v); } +CIMGUI_API int igTableGetHoveredColumn() +{ + return ImGui::TableGetHoveredColumn(); +} CIMGUI_API void igTableSetBgColor(ImGuiTableBgTarget target,ImU32 color,int column_n) { return ImGui::TableSetBgColor(target,color,column_n); @@ -1260,11 +1276,11 @@ CIMGUI_API void igSetTabItemClosed(const char* tab_or_docked_window_label) { return ImGui::SetTabItemClosed(tab_or_docked_window_label); } -CIMGUI_API ImGuiID igDockSpace(ImGuiID id,const ImVec2 size,ImGuiDockNodeFlags flags,const ImGuiWindowClass* window_class) +CIMGUI_API ImGuiID igDockSpace(ImGuiID dockspace_id,const ImVec2 size,ImGuiDockNodeFlags flags,const ImGuiWindowClass* window_class) { - return ImGui::DockSpace(id,size,flags,window_class); + return ImGui::DockSpace(dockspace_id,size,flags,window_class); } -CIMGUI_API ImGuiID igDockSpaceOverViewport(ImGuiID dockspace_id, const ImGuiViewport* viewport,ImGuiDockNodeFlags flags,const ImGuiWindowClass* window_class) +CIMGUI_API ImGuiID igDockSpaceOverViewport(ImGuiID dockspace_id,const ImGuiViewport* viewport,ImGuiDockNodeFlags flags,const ImGuiWindowClass* window_class) { return ImGui::DockSpaceOverViewport(dockspace_id,viewport,flags,window_class); } @@ -1436,15 +1452,7 @@ CIMGUI_API ImGuiViewport* igGetMainViewport() { return ImGui::GetMainViewport(); } -CIMGUI_API ImDrawList* igGetBackgroundDrawList_Nil() -{ - return ImGui::GetBackgroundDrawList(); -} -CIMGUI_API ImDrawList* igGetForegroundDrawList_Nil() -{ - return ImGui::GetForegroundDrawList(); -} -CIMGUI_API ImDrawList* igGetBackgroundDrawList_ViewportPtr(ImGuiViewport* viewport) +CIMGUI_API ImDrawList* igGetBackgroundDrawList(ImGuiViewport* viewport) { return ImGui::GetBackgroundDrawList(viewport); } @@ -1532,6 +1540,18 @@ CIMGUI_API void igSetNextFrameWantCaptureKeyboard(bool want_capture_keyboard) { return ImGui::SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } +CIMGUI_API bool igShortcut_Nil(ImGuiKeyChord key_chord,ImGuiInputFlags flags) +{ + return ImGui::Shortcut(key_chord,flags); +} +CIMGUI_API void igSetNextItemShortcut(ImGuiKeyChord key_chord,ImGuiInputFlags flags) +{ + return ImGui::SetNextItemShortcut(key_chord,flags); +} +CIMGUI_API void igSetItemKeyOwner_Nil(ImGuiKey key) +{ + return ImGui::SetItemKeyOwner(key); +} CIMGUI_API bool igIsMouseDown_Nil(ImGuiMouseButton button) { return ImGui::IsMouseDown(button); @@ -1636,6 +1656,17 @@ CIMGUI_API bool igDebugCheckVersionAndDataLayout(const char* version_str,size_t { return ImGui::DebugCheckVersionAndDataLayout(version_str,sz_io,sz_style,sz_vec2,sz_vec4,sz_drawvert,sz_drawidx); } +CIMGUI_API void igDebugLog(const char* fmt,...) +{ + va_list args; + va_start(args, fmt); + ImGui::DebugLogV(fmt,args); + va_end(args); +} +CIMGUI_API void igDebugLogV(const char* fmt,va_list args) +{ + return ImGui::DebugLogV(fmt,args); +} CIMGUI_API void igSetAllocatorFunctions(ImGuiMemAllocFunc alloc_func,ImGuiMemFreeFunc free_func,void* user_data) { return ImGui::SetAllocatorFunctions(alloc_func,free_func,user_data); @@ -1764,6 +1795,10 @@ CIMGUI_API void ImGuiIO_ClearInputKeys(ImGuiIO* self) { return self->ClearInputKeys(); } +CIMGUI_API void ImGuiIO_ClearInputMouse(ImGuiIO* self) +{ + return self->ClearInputMouse(); +} CIMGUI_API ImGuiIO* ImGuiIO_ImGuiIO(void) { return IM_NEW(ImGuiIO)(); @@ -2036,6 +2071,10 @@ CIMGUI_API void ImGuiListClipper_IncludeItemsByIndex(ImGuiListClipper* self,int { return self->IncludeItemsByIndex(item_begin,item_end); } +CIMGUI_API void ImGuiListClipper_SeekCursorForItem(ImGuiListClipper* self,int item_index) +{ + return self->SeekCursorForItem(item_index); +} CIMGUI_API ImColor* ImColor_ImColor_Nil(void) { return IM_NEW(ImColor)(); @@ -2068,6 +2107,54 @@ CIMGUI_API void ImColor_HSV(ImColor *pOut,float h,float s,float v,float a) { *pOut = ImColor::HSV(h,s,v,a); } +CIMGUI_API ImGuiSelectionBasicStorage* ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage(void) +{ + return IM_NEW(ImGuiSelectionBasicStorage)(); +} +CIMGUI_API void ImGuiSelectionBasicStorage_destroy(ImGuiSelectionBasicStorage* self) +{ + IM_DELETE(self); +} +CIMGUI_API void ImGuiSelectionBasicStorage_ApplyRequests(ImGuiSelectionBasicStorage* self,ImGuiMultiSelectIO* ms_io) +{ + return self->ApplyRequests(ms_io); +} +CIMGUI_API bool ImGuiSelectionBasicStorage_Contains(ImGuiSelectionBasicStorage* self,ImGuiID id) +{ + return self->Contains(id); +} +CIMGUI_API void ImGuiSelectionBasicStorage_Clear(ImGuiSelectionBasicStorage* self) +{ + return self->Clear(); +} +CIMGUI_API void ImGuiSelectionBasicStorage_Swap(ImGuiSelectionBasicStorage* self,ImGuiSelectionBasicStorage* r) +{ + return self->Swap(*r); +} +CIMGUI_API void ImGuiSelectionBasicStorage_SetItemSelected(ImGuiSelectionBasicStorage* self,ImGuiID id,bool selected) +{ + return self->SetItemSelected(id,selected); +} +CIMGUI_API bool ImGuiSelectionBasicStorage_GetNextSelectedItem(ImGuiSelectionBasicStorage* self,void** opaque_it,ImGuiID* out_id) +{ + return self->GetNextSelectedItem(opaque_it,out_id); +} +CIMGUI_API ImGuiID ImGuiSelectionBasicStorage_GetStorageIdFromIndex(ImGuiSelectionBasicStorage* self,int idx) +{ + return self->GetStorageIdFromIndex(idx); +} +CIMGUI_API ImGuiSelectionExternalStorage* ImGuiSelectionExternalStorage_ImGuiSelectionExternalStorage(void) +{ + return IM_NEW(ImGuiSelectionExternalStorage)(); +} +CIMGUI_API void ImGuiSelectionExternalStorage_destroy(ImGuiSelectionExternalStorage* self) +{ + IM_DELETE(self); +} +CIMGUI_API void ImGuiSelectionExternalStorage_ApplyRequests(ImGuiSelectionExternalStorage* self,ImGuiMultiSelectIO* ms_io) +{ + return self->ApplyRequests(ms_io); +} CIMGUI_API ImDrawCmd* ImDrawCmd_ImDrawCmd(void) { return IM_NEW(ImDrawCmd)(); @@ -2192,11 +2279,11 @@ CIMGUI_API void ImDrawList_AddNgonFilled(ImDrawList* self,const ImVec2 center,fl { return self->AddNgonFilled(center,radius,col,num_segments); } -CIMGUI_API void ImDrawList_AddEllipse(ImDrawList* self,const ImVec2 center,ImVec2 radius,ImU32 col,float rot,int num_segments,float thickness) +CIMGUI_API void ImDrawList_AddEllipse(ImDrawList* self,const ImVec2 center,const ImVec2 radius,ImU32 col,float rot,int num_segments,float thickness) { return self->AddEllipse(center,radius,col,rot,num_segments,thickness); } -CIMGUI_API void ImDrawList_AddEllipseFilled(ImDrawList* self,const ImVec2 center,ImVec2 radius,ImU32 col,float rot,int num_segments) +CIMGUI_API void ImDrawList_AddEllipseFilled(ImDrawList* self,const ImVec2 center,const ImVec2 radius,ImU32 col,float rot,int num_segments) { return self->AddEllipseFilled(center,radius,col,rot,num_segments); } @@ -2208,6 +2295,14 @@ CIMGUI_API void ImDrawList_AddText_FontPtr(ImDrawList* self,const ImFont* font,f { return self->AddText(font,font_size,pos,col,text_begin,text_end,wrap_width,cpu_fine_clip_rect); } +CIMGUI_API void ImDrawList_AddBezierCubic(ImDrawList* self,const ImVec2 p1,const ImVec2 p2,const ImVec2 p3,const ImVec2 p4,ImU32 col,float thickness,int num_segments) +{ + return self->AddBezierCubic(p1,p2,p3,p4,col,thickness,num_segments); +} +CIMGUI_API void ImDrawList_AddBezierQuadratic(ImDrawList* self,const ImVec2 p1,const ImVec2 p2,const ImVec2 p3,ImU32 col,float thickness,int num_segments) +{ + return self->AddBezierQuadratic(p1,p2,p3,col,thickness,num_segments); +} CIMGUI_API void ImDrawList_AddPolyline(ImDrawList* self,const ImVec2* points,int num_points,ImU32 col,ImDrawFlags flags,float thickness) { return self->AddPolyline(points,num_points,col,flags,thickness); @@ -2216,13 +2311,9 @@ CIMGUI_API void ImDrawList_AddConvexPolyFilled(ImDrawList* self,const ImVec2* po { return self->AddConvexPolyFilled(points,num_points,col); } -CIMGUI_API void ImDrawList_AddBezierCubic(ImDrawList* self,const ImVec2 p1,const ImVec2 p2,const ImVec2 p3,const ImVec2 p4,ImU32 col,float thickness,int num_segments) +CIMGUI_API void ImDrawList_AddConcavePolyFilled(ImDrawList* self,const ImVec2* points,int num_points,ImU32 col) { - return self->AddBezierCubic(p1,p2,p3,p4,col,thickness,num_segments); -} -CIMGUI_API void ImDrawList_AddBezierQuadratic(ImDrawList* self,const ImVec2 p1,const ImVec2 p2,const ImVec2 p3,ImU32 col,float thickness,int num_segments) -{ - return self->AddBezierQuadratic(p1,p2,p3,col,thickness,num_segments); + return self->AddConcavePolyFilled(points,num_points,col); } CIMGUI_API void ImDrawList_AddImage(ImDrawList* self,ImTextureID user_texture_id,const ImVec2 p_min,const ImVec2 p_max,const ImVec2 uv_min,const ImVec2 uv_max,ImU32 col) { @@ -2236,22 +2327,6 @@ CIMGUI_API void ImDrawList_AddImageRounded(ImDrawList* self,ImTextureID user_tex { return self->AddImageRounded(user_texture_id,p_min,p_max,uv_min,uv_max,col,rounding,flags); } -CIMGUI_API void ImDrawList_AddShadowRect(ImDrawList* self,const ImVec2 obj_min,const ImVec2 obj_max,ImU32 shadow_col,float shadow_thickness,const ImVec2 shadow_offset,ImDrawFlags flags,float obj_rounding) -{ - return self->AddShadowRect(obj_min,obj_max,shadow_col,shadow_thickness,shadow_offset,flags,obj_rounding); -} -CIMGUI_API void ImDrawList_AddShadowCircle(ImDrawList* self,const ImVec2 obj_center,float obj_radius,ImU32 shadow_col,float shadow_thickness,const ImVec2 shadow_offset,ImDrawFlags flags,int obj_num_segments) -{ - return self->AddShadowCircle(obj_center,obj_radius,shadow_col,shadow_thickness,shadow_offset,flags,obj_num_segments); -} -CIMGUI_API void ImDrawList_AddShadowConvexPoly(ImDrawList* self,const ImVec2* points,int points_count,ImU32 shadow_col,float shadow_thickness,const ImVec2 shadow_offset,ImDrawFlags flags) -{ - return self->AddShadowConvexPoly(points,points_count,shadow_col,shadow_thickness,shadow_offset,flags); -} -CIMGUI_API void ImDrawList_AddShadowNGon(ImDrawList* self,const ImVec2 obj_center,float obj_radius,ImU32 shadow_col,float shadow_thickness,const ImVec2 shadow_offset,ImDrawFlags flags,int obj_num_segments) -{ - return self->AddShadowNGon(obj_center,obj_radius,shadow_col,shadow_thickness,shadow_offset,flags,obj_num_segments); -} CIMGUI_API void ImDrawList_PathClear(ImDrawList* self) { return self->PathClear(); @@ -2268,6 +2343,10 @@ CIMGUI_API void ImDrawList_PathFillConvex(ImDrawList* self,ImU32 col) { return self->PathFillConvex(col); } +CIMGUI_API void ImDrawList_PathFillConcave(ImDrawList* self,ImU32 col) +{ + return self->PathFillConcave(col); +} CIMGUI_API void ImDrawList_PathStroke(ImDrawList* self,ImU32 col,ImDrawFlags flags,float thickness) { return self->PathStroke(col,flags,thickness); @@ -2280,7 +2359,7 @@ CIMGUI_API void ImDrawList_PathArcToFast(ImDrawList* self,const ImVec2 center,fl { return self->PathArcToFast(center,radius,a_min_of_12,a_max_of_12); } -CIMGUI_API void ImDrawList_PathEllipticalArcTo(ImDrawList* self,const ImVec2 center,ImVec2 radius,float rot,float a_min,float a_max,int num_segments) +CIMGUI_API void ImDrawList_PathEllipticalArcTo(ImDrawList* self,const ImVec2 center,const ImVec2 radius,float rot,float a_min,float a_max,int num_segments) { return self->PathEllipticalArcTo(center,radius,rot,a_min,a_max,num_segments); } @@ -2344,7 +2423,7 @@ CIMGUI_API void ImDrawList_PrimWriteVtx(ImDrawList* self,const ImVec2 pos,const { return self->PrimWriteVtx(pos,uv,col); } -CIMGUI_API void ImDrawList_PrimWriteIdx(ImDrawList* self,unsigned int idx) +CIMGUI_API void ImDrawList_PrimWriteIdx(ImDrawList* self,ImDrawIdx idx) { return self->PrimWriteIdx(idx); } @@ -2416,38 +2495,6 @@ CIMGUI_API void ImDrawData_ScaleClipRects(ImDrawData* self,const ImVec2 fb_scale { return self->ScaleClipRects(fb_scale); } -CIMGUI_API ImFontAtlasShadowTexConfig* ImFontAtlasShadowTexConfig_ImFontAtlasShadowTexConfig(void) -{ - return IM_NEW(ImFontAtlasShadowTexConfig)(); -} -CIMGUI_API void ImFontAtlasShadowTexConfig_destroy(ImFontAtlasShadowTexConfig* self) -{ - IM_DELETE(self); -} -CIMGUI_API void ImFontAtlasShadowTexConfig_SetupDefaults(ImFontAtlasShadowTexConfig* self) -{ - return self->SetupDefaults(); -} -CIMGUI_API int ImFontAtlasShadowTexConfig_GetRectTexPadding(ImFontAtlasShadowTexConfig* self) -{ - return self->GetRectTexPadding(); -} -CIMGUI_API int ImFontAtlasShadowTexConfig_CalcRectTexSize(ImFontAtlasShadowTexConfig* self) -{ - return self->CalcRectTexSize(); -} -CIMGUI_API int ImFontAtlasShadowTexConfig_GetConvexTexPadding(ImFontAtlasShadowTexConfig* self) -{ - return self->GetConvexTexPadding(); -} -CIMGUI_API int ImFontAtlasShadowTexConfig_CalcConvexTexWidth(ImFontAtlasShadowTexConfig* self) -{ - return self->CalcConvexTexWidth(); -} -CIMGUI_API int ImFontAtlasShadowTexConfig_CalcConvexTexHeight(ImFontAtlasShadowTexConfig* self) -{ - return self->CalcConvexTexHeight(); -} CIMGUI_API ImFontConfig* ImFontConfig_ImFontConfig(void) { return IM_NEW(ImFontConfig)(); @@ -2748,7 +2795,7 @@ CIMGUI_API ImGuiID igImHashStr(const char* data,size_t data_size,ImGuiID seed) { return ImHashStr(data,data_size,seed); } -CIMGUI_API void igImQsort(void* base,size_t count,size_t size_of_element,int(*compare_func)(const void*,const void*)) +CIMGUI_API void igImQsort(void* base,size_t count,size_t size_of_element,int(*compare_func)(void const*,void const*)) { return ImQsort(base,count,size_of_element,compare_func); } @@ -2828,6 +2875,10 @@ CIMGUI_API bool igImCharIsBlankW(unsigned int c) { return ImCharIsBlankW(c); } +CIMGUI_API bool igImCharIsXdigitA(char c) +{ + return ImCharIsXdigitA(c); +} CIMGUI_API int igImFormatString(char* buf,size_t buf_size,const char* fmt,...) { va_list args; @@ -2907,6 +2958,10 @@ CIMGUI_API const char* igImTextFindPreviousUtf8Codepoint(const char* in_text_sta { return ImTextFindPreviousUtf8Codepoint(in_text_start,in_text_curr); } +CIMGUI_API int igImTextCountLines(const char* in_text,const char* in_text_end) +{ + return ImTextCountLines(in_text,in_text_end); +} CIMGUI_API ImFileHandle igImFileOpen(const char* filename,const char* mode) { return ImFileOpen(filename,mode); @@ -2983,7 +3038,7 @@ CIMGUI_API void igImMax(ImVec2 *pOut,const ImVec2 lhs,const ImVec2 rhs) { *pOut = ImMax(lhs,rhs); } -CIMGUI_API void igImClamp(ImVec2 *pOut,const ImVec2 v,const ImVec2 mn,ImVec2 mx) +CIMGUI_API void igImClamp(ImVec2 *pOut,const ImVec2 v,const ImVec2 mn,const ImVec2 mx) { *pOut = ImClamp(v,mn,mx); } @@ -3011,10 +3066,6 @@ CIMGUI_API float igImLengthSqr_Vec4(const ImVec4 lhs) { return ImLengthSqr(lhs); } -CIMGUI_API float igImLength(const ImVec2 lhs,float fail_value) -{ - return ImLength(lhs,fail_value); -} CIMGUI_API float igImInvLength(const ImVec2 lhs,float fail_value) { return ImInvLength(lhs,fail_value); @@ -3051,6 +3102,10 @@ CIMGUI_API float igImLinearSweep(float current,float target,float speed) { return ImLinearSweep(current,target,speed); } +CIMGUI_API float igImLinearRemapClamp(float s0,float s1,float d0,float d1,float x) +{ + return ImLinearRemapClamp(s0,s1,d0,d1,x); +} CIMGUI_API void igImMul(ImVec2 *pOut,const ImVec2 lhs,const ImVec2 rhs) { *pOut = ImMul(lhs,rhs); @@ -3099,6 +3154,10 @@ CIMGUI_API float igImTriangleArea(const ImVec2 a,const ImVec2 b,const ImVec2 c) { return ImTriangleArea(a,b,c); } +CIMGUI_API bool igImTriangleIsClockwise(const ImVec2 a,const ImVec2 b,const ImVec2 c) +{ + return ImTriangleIsClockwise(a,b,c); +} CIMGUI_API ImVec1* ImVec1_ImVec1_Nil(void) { return IM_NEW(ImVec1)(); @@ -3311,6 +3370,10 @@ CIMGUI_API void ImGuiTextIndex_append(ImGuiTextIndex* self,const char* base,int { return self->append(base,old_size,new_size); } +CIMGUI_API ImGuiStoragePair* igImLowerBound(ImGuiStoragePair* in_begin,ImGuiStoragePair* in_end,ImGuiID key) +{ + return ImLowerBound(in_begin,in_end,key); +} CIMGUI_API ImDrawListSharedData* ImDrawListSharedData_ImDrawListSharedData(void) { return IM_NEW(ImDrawListSharedData)(); @@ -3331,6 +3394,10 @@ CIMGUI_API void ImDrawDataBuilder_destroy(ImDrawDataBuilder* self) { IM_DELETE(self); } +CIMGUI_API void* ImGuiDataVarInfo_GetVarPtr(ImGuiDataVarInfo* self,void* parent) +{ + return self->GetVarPtr(parent); +} CIMGUI_API ImGuiStyleMod* ImGuiStyleMod_ImGuiStyleMod_Int(ImGuiStyleVar idx,int v) { return IM_NEW(ImGuiStyleMod)(idx,v); @@ -3519,10 +3586,6 @@ CIMGUI_API ImGuiPtrOrIndex* ImGuiPtrOrIndex_ImGuiPtrOrIndex_Int(int index) { return IM_NEW(ImGuiPtrOrIndex)(index); } -CIMGUI_API void* ImGuiDataVarInfo_GetVarPtr(ImGuiDataVarInfo* self,void* parent) -{ - return self->GetVarPtr(parent); -} CIMGUI_API ImGuiPopupData* ImGuiPopupData_ImGuiPopupData(void) { return IM_NEW(ImGuiPopupData)(); @@ -3627,6 +3690,38 @@ CIMGUI_API void ImGuiOldColumns_destroy(ImGuiOldColumns* self) { IM_DELETE(self); } +CIMGUI_API ImGuiBoxSelectState* ImGuiBoxSelectState_ImGuiBoxSelectState(void) +{ + return IM_NEW(ImGuiBoxSelectState)(); +} +CIMGUI_API void ImGuiBoxSelectState_destroy(ImGuiBoxSelectState* self) +{ + IM_DELETE(self); +} +CIMGUI_API ImGuiMultiSelectTempData* ImGuiMultiSelectTempData_ImGuiMultiSelectTempData(void) +{ + return IM_NEW(ImGuiMultiSelectTempData)(); +} +CIMGUI_API void ImGuiMultiSelectTempData_destroy(ImGuiMultiSelectTempData* self) +{ + IM_DELETE(self); +} +CIMGUI_API void ImGuiMultiSelectTempData_Clear(ImGuiMultiSelectTempData* self) +{ + return self->Clear(); +} +CIMGUI_API void ImGuiMultiSelectTempData_ClearIO(ImGuiMultiSelectTempData* self) +{ + return self->ClearIO(); +} +CIMGUI_API ImGuiMultiSelectState* ImGuiMultiSelectState_ImGuiMultiSelectState(void) +{ + return IM_NEW(ImGuiMultiSelectState)(); +} +CIMGUI_API void ImGuiMultiSelectState_destroy(ImGuiMultiSelectState* self) +{ + IM_DELETE(self); +} CIMGUI_API ImGuiDockNode* ImGuiDockNode_ImGuiDockNode(ImGuiID id) { return IM_NEW(ImGuiDockNode)(id); @@ -3819,18 +3914,10 @@ CIMGUI_API float ImGuiWindow_CalcFontSize(ImGuiWindow* self) { return self->CalcFontSize(); } -CIMGUI_API float ImGuiWindow_TitleBarHeight(ImGuiWindow* self) -{ - return self->TitleBarHeight; -} CIMGUI_API void ImGuiWindow_TitleBarRect(ImRect *pOut,ImGuiWindow* self) { *pOut = self->TitleBarRect(); } -CIMGUI_API float ImGuiWindow_MenuBarHeight(ImGuiWindow* self) -{ - return self->MenuBarHeight; -} CIMGUI_API void ImGuiWindow_MenuBarRect(ImRect *pOut,ImGuiWindow* self) { *pOut = self->MenuBarRect(); @@ -3923,6 +4010,10 @@ CIMGUI_API void igUpdateWindowParentAndRootLinks(ImGuiWindow* window,ImGuiWindow { return ImGui::UpdateWindowParentAndRootLinks(window,flags,parent_window); } +CIMGUI_API void igUpdateWindowSkipRefresh(ImGuiWindow* window) +{ + return ImGui::UpdateWindowSkipRefresh(window); +} CIMGUI_API void igCalcWindowNextAutoFitSize(ImVec2 *pOut,ImGuiWindow* window) { *pOut = ImGui::CalcWindowNextAutoFitSize(window); @@ -3979,6 +4070,10 @@ CIMGUI_API void igWindowPosRelToAbs(ImVec2 *pOut,ImGuiWindow* window,const ImVec { *pOut = ImGui::WindowPosRelToAbs(window,p); } +CIMGUI_API void igWindowPosAbsToRel(ImVec2 *pOut,ImGuiWindow* window,const ImVec2 p) +{ + *pOut = ImGui::WindowPosAbsToRel(window,p); +} CIMGUI_API void igFocusWindow(ImGuiWindow* window,ImGuiFocusRequestFlags flags) { return ImGui::FocusWindow(window,flags); @@ -4011,6 +4106,10 @@ CIMGUI_API ImGuiWindow* igFindBottomMostVisibleWindowWithinBeginStack(ImGuiWindo { return ImGui::FindBottomMostVisibleWindowWithinBeginStack(window); } +CIMGUI_API void igSetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags) +{ + return ImGui::SetNextWindowRefreshPolicy(flags); +} CIMGUI_API void igSetCurrentFont(ImFont* font) { return ImGui::SetCurrentFont(font); @@ -4043,6 +4142,10 @@ CIMGUI_API void igUpdateHoveredWindowAndCaptureFlags() { return ImGui::UpdateHoveredWindowAndCaptureFlags(); } +CIMGUI_API void igFindHoveredWindowEx(const ImVec2 pos,bool find_first_and_in_any_viewport,ImGuiWindow** out_hovered_window,ImGuiWindow** out_hovered_window_under_moving_window) +{ + return ImGui::FindHoveredWindowEx(pos,find_first_and_in_any_viewport,out_hovered_window,out_hovered_window_under_moving_window); +} CIMGUI_API void igStartMouseMovingWindow(ImGuiWindow* window) { return ImGui::StartMouseMovingWindow(window); @@ -4275,30 +4378,22 @@ CIMGUI_API void igPushMultiItemsWidths(int components,float width_full) { return ImGui::PushMultiItemsWidths(components,width_full); } -CIMGUI_API bool igIsItemToggledSelection() -{ - return ImGui::IsItemToggledSelection(); -} -CIMGUI_API void igGetContentRegionMaxAbs(ImVec2 *pOut) -{ - *pOut = ImGui::GetContentRegionMaxAbs(); -} CIMGUI_API void igShrinkWidths(ImGuiShrinkWidthItem* items,int count,float width_excess) { return ImGui::ShrinkWidths(items,count,width_excess); } -CIMGUI_API void igPushItemFlag(ImGuiItemFlags option,bool enabled) -{ - return ImGui::PushItemFlag(option,enabled); -} -CIMGUI_API void igPopItemFlag() -{ - return ImGui::PopItemFlag(); -} CIMGUI_API const ImGuiDataVarInfo* igGetStyleVarInfo(ImGuiStyleVar idx) { return ImGui::GetStyleVarInfo(idx); } +CIMGUI_API void igBeginDisabledOverrideReenable() +{ + return ImGui::BeginDisabledOverrideReenable(); +} +CIMGUI_API void igEndDisabledOverrideReenable() +{ + return ImGui::EndDisabledOverrideReenable(); +} CIMGUI_API void igLogBegin(ImGuiLogType type,int auto_open_depth) { return ImGui::LogBegin(type,auto_open_depth); @@ -4319,6 +4414,10 @@ CIMGUI_API bool igBeginChildEx(const char* name,ImGuiID id,const ImVec2 size_arg { return ImGui::BeginChildEx(name,id,size_arg,child_flags,window_flags); } +CIMGUI_API bool igBeginPopupEx(ImGuiID id,ImGuiWindowFlags extra_window_flags) +{ + return ImGui::BeginPopupEx(id,extra_window_flags); +} CIMGUI_API void igOpenPopupEx(ImGuiID id,ImGuiPopupFlags popup_flags) { return ImGui::OpenPopupEx(id,popup_flags); @@ -4339,18 +4438,6 @@ CIMGUI_API bool igIsPopupOpen_ID(ImGuiID id,ImGuiPopupFlags popup_flags) { return ImGui::IsPopupOpen(id,popup_flags); } -CIMGUI_API bool igBeginPopupEx(ImGuiID id,ImGuiWindowFlags extra_flags) -{ - return ImGui::BeginPopupEx(id,extra_flags); -} -CIMGUI_API bool igBeginTooltipEx(ImGuiTooltipFlags tooltip_flags,ImGuiWindowFlags extra_window_flags) -{ - return ImGui::BeginTooltipEx(tooltip_flags,extra_window_flags); -} -CIMGUI_API bool igBeginTooltipHidden() -{ - return ImGui::BeginTooltipHidden(); -} CIMGUI_API void igGetPopupAllowedExtentRect(ImRect *pOut,ImGuiWindow* window) { *pOut = ImGui::GetPopupAllowedExtentRect(window); @@ -4375,6 +4462,14 @@ CIMGUI_API void igFindBestWindowPosForPopupEx(ImVec2 *pOut,const ImVec2 ref_pos, { *pOut = ImGui::FindBestWindowPosForPopupEx(ref_pos,size,last_dir,r_outer,r_avoid,policy); } +CIMGUI_API bool igBeginTooltipEx(ImGuiTooltipFlags tooltip_flags,ImGuiWindowFlags extra_window_flags) +{ + return ImGui::BeginTooltipEx(tooltip_flags,extra_window_flags); +} +CIMGUI_API bool igBeginTooltipHidden() +{ + return ImGui::BeginTooltipHidden(); +} CIMGUI_API bool igBeginViewportSideBar(const char* name,ImGuiViewport* viewport,ImGuiDir dir,float size,ImGuiWindowFlags window_flags) { return ImGui::BeginViewportSideBar(name,viewport,dir,size,window_flags); @@ -4423,7 +4518,7 @@ CIMGUI_API void igNavMoveRequestResolveWithLastItem(ImGuiNavItemData* result) { return ImGui::NavMoveRequestResolveWithLastItem(result); } -CIMGUI_API void igNavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result,ImGuiNavTreeNodeData* tree_node_data) +CIMGUI_API void igNavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result,ImGuiTreeNodeStackData* tree_node_data) { return ImGui::NavMoveRequestResolveWithPastTreeNode(result,tree_node_data); } @@ -4575,7 +4670,7 @@ CIMGUI_API void igSetKeyOwnersForKeyChord(ImGuiKeyChord key,ImGuiID owner_id,ImG { return ImGui::SetKeyOwnersForKeyChord(key,owner_id,flags); } -CIMGUI_API void igSetItemKeyOwner(ImGuiKey key,ImGuiInputFlags flags) +CIMGUI_API void igSetItemKeyOwner_InputFlags(ImGuiKey key,ImGuiInputFlags flags) { return ImGui::SetItemKeyOwner(key,flags); } @@ -4591,21 +4686,25 @@ CIMGUI_API bool igIsKeyDown_ID(ImGuiKey key,ImGuiID owner_id) { return ImGui::IsKeyDown(key,owner_id); } -CIMGUI_API bool igIsKeyPressed_ID(ImGuiKey key,ImGuiID owner_id,ImGuiInputFlags flags) +CIMGUI_API bool igIsKeyPressed_InputFlags(ImGuiKey key,ImGuiInputFlags flags,ImGuiID owner_id) { - return ImGui::IsKeyPressed(key,owner_id,flags); + return ImGui::IsKeyPressed(key,flags,owner_id); } CIMGUI_API bool igIsKeyReleased_ID(ImGuiKey key,ImGuiID owner_id) { return ImGui::IsKeyReleased(key,owner_id); } +CIMGUI_API bool igIsKeyChordPressed_InputFlags(ImGuiKeyChord key_chord,ImGuiInputFlags flags,ImGuiID owner_id) +{ + return ImGui::IsKeyChordPressed(key_chord,flags,owner_id); +} CIMGUI_API bool igIsMouseDown_ID(ImGuiMouseButton button,ImGuiID owner_id) { return ImGui::IsMouseDown(button,owner_id); } -CIMGUI_API bool igIsMouseClicked_ID(ImGuiMouseButton button,ImGuiID owner_id,ImGuiInputFlags flags) +CIMGUI_API bool igIsMouseClicked_InputFlags(ImGuiMouseButton button,ImGuiInputFlags flags,ImGuiID owner_id) { - return ImGui::IsMouseClicked(button,owner_id,flags); + return ImGui::IsMouseClicked(button,flags,owner_id); } CIMGUI_API bool igIsMouseReleased_ID(ImGuiMouseButton button,ImGuiID owner_id) { @@ -4615,21 +4714,13 @@ CIMGUI_API bool igIsMouseDoubleClicked_ID(ImGuiMouseButton button,ImGuiID owner_ { return ImGui::IsMouseDoubleClicked(button,owner_id); } -CIMGUI_API bool igIsKeyChordPressed_ID(ImGuiKeyChord key_chord,ImGuiID owner_id,ImGuiInputFlags flags) +CIMGUI_API bool igShortcut_ID(ImGuiKeyChord key_chord,ImGuiInputFlags flags,ImGuiID owner_id) { - return ImGui::IsKeyChordPressed(key_chord,owner_id,flags); + return ImGui::Shortcut(key_chord,flags,owner_id); } -CIMGUI_API void igSetNextItemShortcut(ImGuiKeyChord key_chord) +CIMGUI_API bool igSetShortcutRouting(ImGuiKeyChord key_chord,ImGuiInputFlags flags,ImGuiID owner_id) { - return ImGui::SetNextItemShortcut(key_chord); -} -CIMGUI_API bool igShortcut(ImGuiKeyChord key_chord,ImGuiID owner_id,ImGuiInputFlags flags) -{ - return ImGui::Shortcut(key_chord,owner_id,flags); -} -CIMGUI_API bool igSetShortcutRouting(ImGuiKeyChord key_chord,ImGuiID owner_id,ImGuiInputFlags flags) -{ - return ImGui::SetShortcutRouting(key_chord,owner_id,flags); + return ImGui::SetShortcutRouting(key_chord,flags,owner_id); } CIMGUI_API bool igTestShortcutRouting(ImGuiKeyChord key_chord,ImGuiID owner_id) { @@ -4855,6 +4946,38 @@ CIMGUI_API int igTypingSelectFindBestLeadingMatch(ImGuiTypingSelectRequest* req, { return ImGui::TypingSelectFindBestLeadingMatch(req,items_count,get_item_name_func,user_data); } +CIMGUI_API bool igBeginBoxSelect(const ImRect scope_rect,ImGuiWindow* window,ImGuiID box_select_id,ImGuiMultiSelectFlags ms_flags) +{ + return ImGui::BeginBoxSelect(scope_rect,window,box_select_id,ms_flags); +} +CIMGUI_API void igEndBoxSelect(const ImRect scope_rect,ImGuiMultiSelectFlags ms_flags) +{ + return ImGui::EndBoxSelect(scope_rect,ms_flags); +} +CIMGUI_API void igMultiSelectItemHeader(ImGuiID id,bool* p_selected,ImGuiButtonFlags* p_button_flags) +{ + return ImGui::MultiSelectItemHeader(id,p_selected,p_button_flags); +} +CIMGUI_API void igMultiSelectItemFooter(ImGuiID id,bool* p_selected,bool* p_pressed) +{ + return ImGui::MultiSelectItemFooter(id,p_selected,p_pressed); +} +CIMGUI_API void igMultiSelectAddSetAll(ImGuiMultiSelectTempData* ms,bool selected) +{ + return ImGui::MultiSelectAddSetAll(ms,selected); +} +CIMGUI_API void igMultiSelectAddSetRange(ImGuiMultiSelectTempData* ms,bool selected,int range_dir,ImGuiSelectionUserData first_item,ImGuiSelectionUserData last_item) +{ + return ImGui::MultiSelectAddSetRange(ms,selected,range_dir,first_item,last_item); +} +CIMGUI_API ImGuiBoxSelectState* igGetBoxSelectState(ImGuiID id) +{ + return ImGui::GetBoxSelectState(id); +} +CIMGUI_API ImGuiMultiSelectState* igGetMultiSelectState(ImGuiID id) +{ + return ImGui::GetMultiSelectState(id); +} CIMGUI_API void igSetWindowClipRectBeforeSetChannel(ImGuiWindow* window,const ImRect clip_rect) { return ImGui::SetWindowClipRectBeforeSetChannel(window,clip_rect); @@ -4907,10 +5030,6 @@ CIMGUI_API void igTableSetColumnSortDirection(int column_n,ImGuiSortDirection so { return ImGui::TableSetColumnSortDirection(column_n,sort_direction,append_to_sort_specs); } -CIMGUI_API int igTableGetHoveredColumn() -{ - return ImGui::TableGetHoveredColumn(); -} CIMGUI_API int igTableGetHoveredRow() { return ImGui::TableGetHoveredRow(); @@ -4931,7 +5050,7 @@ CIMGUI_API void igTablePopBackgroundChannel() { return ImGui::TablePopBackgroundChannel(); } -CIMGUI_API void igTableAngledHeadersRowEx(ImGuiID row_id, float angle,float max_label_width, const ImGuiTableHeaderData *data, int data_count) +CIMGUI_API void igTableAngledHeadersRowEx(ImGuiID row_id,float angle,float max_label_width,const ImGuiTableHeaderData* data,int data_count) { return ImGui::TableAngledHeadersRowEx(row_id,angle,max_label_width,data,data_count); } @@ -5343,17 +5462,17 @@ CIMGUI_API void igTreePushOverrideID(ImGuiID id) { return ImGui::TreePushOverrideID(id); } -CIMGUI_API void igTreeNodeSetOpen(ImGuiID id,bool open) +CIMGUI_API bool igTreeNodeGetOpen(ImGuiID storage_id) { - return ImGui::TreeNodeSetOpen(id,open); + return ImGui::TreeNodeGetOpen(storage_id); } -CIMGUI_API bool igTreeNodeUpdateNextOpen(ImGuiID id,ImGuiTreeNodeFlags flags) +CIMGUI_API void igTreeNodeSetOpen(ImGuiID storage_id,bool open) { - return ImGui::TreeNodeUpdateNextOpen(id,flags); + return ImGui::TreeNodeSetOpen(storage_id,open); } -CIMGUI_API void igSetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data) +CIMGUI_API bool igTreeNodeUpdateNextOpen(ImGuiID storage_id,ImGuiTreeNodeFlags flags) { - return ImGui::SetNextItemSelectionUserData(selection_user_data); + return ImGui::TreeNodeUpdateNextOpen(storage_id,flags); } CIMGUI_API const ImGuiDataTypeInfo* igDataTypeGetInfo(ImGuiDataType data_type) { @@ -5367,9 +5486,9 @@ CIMGUI_API void igDataTypeApplyOp(ImGuiDataType data_type,int op,void* output,co { return ImGui::DataTypeApplyOp(data_type,op,output,arg_1,arg_2); } -CIMGUI_API bool igDataTypeApplyFromText(const char* buf,ImGuiDataType data_type,void* p_data,const char* format) +CIMGUI_API bool igDataTypeApplyFromText(const char* buf,ImGuiDataType data_type,void* p_data,const char* format,void* p_data_when_empty) { - return ImGui::DataTypeApplyFromText(buf,data_type,p_data,format); + return ImGui::DataTypeApplyFromText(buf,data_type,p_data,format,p_data_when_empty); } CIMGUI_API int igDataTypeCompare(ImGuiDataType data_type,const void* arg_1,const void* arg_2) { @@ -5403,6 +5522,10 @@ CIMGUI_API ImGuiInputTextState* igGetInputTextState(ImGuiID id) { return ImGui::GetInputTextState(id); } +CIMGUI_API void igSetNextItemRefVal(ImGuiDataType data_type,void* p_data) +{ + return ImGui::SetNextItemRefVal(data_type,p_data); +} CIMGUI_API void igColorTooltip(const char* text,const float* col,ImGuiColorEditFlags flags) { return ImGui::ColorTooltip(text,col,flags); @@ -5443,17 +5566,6 @@ CIMGUI_API void igGcAwakeTransientWindowBuffers(ImGuiWindow* window) { return ImGui::GcAwakeTransientWindowBuffers(window); } -CIMGUI_API void igDebugLog(const char* fmt,...) -{ - va_list args; - va_start(args, fmt); - ImGui::DebugLogV(fmt,args); - va_end(args); -} -CIMGUI_API void igDebugLogV(const char* fmt,va_list args) -{ - return ImGui::DebugLogV(fmt,args); -} CIMGUI_API void igDebugAllocHook(ImGuiDebugAllocInfo* info,int frame_count,void* ptr,size_t size) { return ImGui::DebugAllocHook(info,frame_count,ptr,size); @@ -5482,6 +5594,10 @@ CIMGUI_API void igDebugDrawItemRect(ImU32 col) { return ImGui::DebugDrawItemRect(col); } +CIMGUI_API void igDebugTextUnformattedWithLocateItem(const char* line_begin,const char* line_end) +{ + return ImGui::DebugTextUnformattedWithLocateItem(line_begin,line_end); +} CIMGUI_API void igDebugLocateItem(ImGuiID target_id) { return ImGui::DebugLocateItem(target_id); @@ -5562,6 +5678,10 @@ CIMGUI_API void igDebugNodeTypingSelectState(ImGuiTypingSelectState* state) { return ImGui::DebugNodeTypingSelectState(state); } +CIMGUI_API void igDebugNodeMultiSelectState(ImGuiMultiSelectState* state) +{ + return ImGui::DebugNodeMultiSelectState(state); +} CIMGUI_API void igDebugNodeWindow(ImGuiWindow* window,const char* label) { return ImGui::DebugNodeWindow(window,label); @@ -5582,6 +5702,10 @@ CIMGUI_API void igDebugNodeViewport(ImGuiViewportP* viewport) { return ImGui::DebugNodeViewport(viewport); } +CIMGUI_API void igDebugNodePlatformMonitor(ImGuiPlatformMonitor* monitor,const char* label,int idx) +{ + return ImGui::DebugNodePlatformMonitor(monitor,label,idx); +} CIMGUI_API void igDebugRenderKeyboardPreview(ImDrawList* draw_list) { return ImGui::DebugRenderKeyboardPreview(draw_list); @@ -5626,22 +5750,6 @@ CIMGUI_API void igImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[2 { return ImFontAtlasBuildMultiplyRectAlpha8(table,pixels,x,y,w,h,stride); } -CIMGUI_API void igImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx,ImGuiID id,const ImRect bb,const ImGuiLastItemData* item_data) -{ - return ImGuiTestEngineHook_ItemAdd(ctx,id,bb,item_data); -} -CIMGUI_API void igImGuiTestEngineHook_ItemInfo(ImGuiContext* ctx,ImGuiID id,const char* label,ImGuiItemStatusFlags flags) -{ - return ImGuiTestEngineHook_ItemInfo(ctx,id,label,flags); -} -CIMGUI_API void igImGuiTestEngineHook_Log(ImGuiContext* ctx,const char* fmt,...) -{ - -} -CIMGUI_API const char* igImGuiTestEngine_FindItemDebugLabel(ImGuiContext* ctx,ImGuiID id) -{ - return ImGuiTestEngine_FindItemDebugLabel(ctx,id); -} @@ -5715,7 +5823,7 @@ CimguiStorage& GetCimguiStorage() ImGuiIO& io = ImGui::GetIO(); if (io.BackendLanguageUserData == NULL) { - io.BackendLanguageUserData = new CimguiStorage(); + io.BackendLanguageUserData = IM_NEW(CimguiStorage)(); } return *(CimguiStorage*)io.BackendLanguageUserData; diff --git a/lib/third_party/imgui/imgui/include/imgui.h b/lib/third_party/imgui/imgui/include/imgui.h index a6dacbb5e..a16f8f3f2 100644 --- a/lib/third_party/imgui/imgui/include/imgui.h +++ b/lib/third_party/imgui/imgui/include/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.9 +// dear imgui, v1.91.0 // (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.9" -#define IMGUI_VERSION_NUM 19090 +#define IMGUI_VERSION "1.91.0" +#define IMGUI_VERSION_NUM 19100 #define IMGUI_HAS_TABLE #define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_DOCK // Docking WIP branch @@ -41,11 +41,12 @@ Index of this file: // [SECTION] Dear ImGui end-user API functions // [SECTION] Flags & Enumerations // [SECTION] Tables API flags and structures (ImGuiTableFlags, ImGuiTableColumnFlags, ImGuiTableRowFlags, ImGuiTableBgTarget, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs) -// [SECTION] Helpers: Memory allocations macros, ImVector<> +// [SECTION] Helpers: Debug log, Memory allocations macros, ImVector<> // [SECTION] ImGuiStyle // [SECTION] ImGuiIO // [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiWindowClass, ImGuiPayload) // [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor) +// [SECTION] Multi-Select API flags and structures (ImGuiMultiSelectFlags, ImGuiMultiSelectIO, ImGuiSelectionRequest, ImGuiSelectionBasicStorage, ImGuiSelectionExternalStorage) // [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData) // [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont) // [SECTION] Viewports (ImGuiViewportFlags, ImGuiViewport) @@ -176,11 +177,15 @@ struct ImGuiIO; // Main configuration and I/O between your a struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use) struct ImGuiKeyData; // Storage for ImGuiIO and IsKeyDown(), IsKeyPressed() etc functions. struct ImGuiListClipper; // Helper to manually clip large list of items +struct ImGuiMultiSelectIO; // Structure to interact with a BeginMultiSelect()/EndMultiSelect() block struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame struct ImGuiPayload; // User data payload for drag and drop operations struct ImGuiPlatformIO; // Multi-viewport support: interface for Platform/Renderer backends + viewports to render struct ImGuiPlatformMonitor; // Multi-viewport support: user-provided bounds for each connected monitor/display. Used when positioning popups and tooltips to avoid them straddling monitors -struct ImGuiPlatformImeData; // Platform IME data for io.SetPlatformImeDataFn() function. +struct ImGuiPlatformImeData; // Platform IME data for io.PlatformSetImeDataFn() function. +struct ImGuiSelectionBasicStorage; // Optional helper to store multi-selection state + apply multi-selection requests. +struct ImGuiSelectionExternalStorage;//Optional helper to apply multi-selection requests to existing randomly accessible storage. +struct ImGuiSelectionRequest; // A selection request (stored in ImGuiMultiSelectIO) struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use) struct ImGuiStorage; // Helper for key->value storage (container sorted by key) struct ImGuiStoragePair; // Helper for key->value storage (pair) @@ -230,8 +235,10 @@ typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: f typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc. typedef int ImGuiInputFlags; // -> enum ImGuiInputFlags_ // Flags: for Shortcut(), SetNextItemShortcut() typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline() +typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag(), shared by all items typedef int ImGuiKeyChord; // -> ImGuiKey | ImGuiMod_XXX // Flags: for IsKeyChordPressed(), Shortcut() etc. an ImGuiKey optionally OR-ed with one or more ImGuiMod_XXX values. typedef int ImGuiPopupFlags; // -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen() +typedef int ImGuiMultiSelectFlags; // -> enum ImGuiMultiSelectFlags_// Flags: for BeginMultiSelect() typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable() typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc. typedef int ImGuiTabBarFlags; // -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar() @@ -267,6 +274,11 @@ typedef ImWchar32 ImWchar; typedef ImWchar16 ImWchar; #endif +// Multi-Selection item index or identifier when using BeginMultiSelect() +// - Used by SetNextItemSelectionUserData() + and inside ImGuiMultiSelectIO structure. +// - Most users are likely to use this store an item INDEX but this may be used to store a POINTER/ID as well. Read comments near ImGuiMultiSelectIO for details. +typedef ImS64 ImGuiSelectionUserData; + // Callback and functions types typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); // Callback function for ImGui::InputText() typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); // Callback function for ImGui::SetNextWindowSizeConstraints() @@ -387,10 +399,10 @@ namespace ImGui IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags=0); // is current window hovered and hoverable (e.g. not blocked by a popup/modal)? See ImGuiHoveredFlags_ for options. IMPORTANT: If you are trying to check whether your mouse should be dispatched to Dear ImGui or to your underlying app, you should not use this function! Use the 'io.WantCaptureMouse' boolean for that! Refer to FAQ entry "How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?" for details. IMGUI_API ImDrawList* GetWindowDrawList(); // get draw list associated to the current window, to append your own drawing primitives IMGUI_API float GetWindowDpiScale(); // get DPI scale currently associated to the current window's viewport. - IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (note: it is unlikely you need to use this. Consider using current layout pos instead, GetCursorScreenPos()) - IMGUI_API ImVec2 GetWindowSize(); // get current window size (note: it is unlikely you need to use this. Consider using GetCursorScreenPos() and e.g. GetContentRegionAvail() instead) - IMGUI_API float GetWindowWidth(); // get current window width (shortcut for GetWindowSize().x) - IMGUI_API float GetWindowHeight(); // get current window height (shortcut for GetWindowSize().y) + IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (IT IS UNLIKELY YOU EVER NEED TO USE THIS. Consider always using GetCursorScreenPos() and GetContentRegionAvail() instead) + IMGUI_API ImVec2 GetWindowSize(); // get current window size (IT IS UNLIKELY YOU EVER NEED TO USE THIS. Consider always using GetCursorScreenPos() and GetContentRegionAvail() instead) + IMGUI_API float GetWindowWidth(); // get current window width (IT IS UNLIKELY YOU EVER NEED TO USE THIS). Shortcut for GetWindowSize().x. + IMGUI_API float GetWindowHeight(); // get current window height (IT IS UNLIKELY YOU EVER NEED TO USE THIS). Shortcut for GetWindowSize().y. IMGUI_API ImGuiViewport*GetWindowViewport(); // get viewport currently associated to the current window. // Window manipulation @@ -414,14 +426,6 @@ namespace ImGui IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / top-most. use NULL to remove focus. - // Content region - // - Retrieve available space from a given point. GetContentRegionAvail() is frequently useful. - // - Those functions are bound to be redesigned (they are confusing, incomplete and the Min/Max return values are in local window coordinates which increases confusion) - IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos() - IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates - IMGUI_API ImVec2 GetWindowContentRegionMin(); // content boundaries min for the full window (roughly (0,0)-Scroll), in window coordinates - IMGUI_API ImVec2 GetWindowContentRegionMax(); // content boundaries max for the full window (roughly (0,0)+Size-Scroll) where Size can be overridden with SetNextWindowContentSize(), in window coordinates - // Windows Scrolling // - Any change of Scroll will be applied at the beginning of next frame in the first call to Begin(). // - You may instead use SetNextWindowScroll() prior to calling Begin() to avoid this delay, as an alternative to using SetScrollX()/SetScrollY(). @@ -445,10 +449,8 @@ namespace ImGui IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); // modify a style float variable. always use this if you modify the style after NewFrame(). IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); // modify a style ImVec2 variable. always use this if you modify the style after NewFrame(). IMGUI_API void PopStyleVar(int count = 1); - IMGUI_API void PushTabStop(bool tab_stop); // == tab stop enable. Allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets - IMGUI_API void PopTabStop(); - IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame. - IMGUI_API void PopButtonRepeat(); + IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); // modify specified shared item flag, e.g. PushItemFlag(ImGuiItemFlags_NoTabStop, true) + IMGUI_API void PopItemFlag(); // Parameters stacks (current window) IMGUI_API void PushItemWidth(float item_width); // push width of items for common large "item+label" widgets. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -FLT_MIN always align width to the right side). @@ -472,19 +474,22 @@ namespace ImGui // - By "cursor" we mean the current output position. // - The typical widget behavior is to output themselves at the current cursor position, then move the cursor one line down. // - You can call SameLine() between widgets to undo the last carriage return and output at the right of the preceding widget. + // - YOU CAN DO 99% OF WHAT YOU NEED WITH ONLY GetCursorScreenPos() and GetContentRegionAvail(). // - Attention! We currently have inconsistencies between window-local and absolute positions we will aim to fix with future API: // - Absolute coordinate: GetCursorScreenPos(), SetCursorScreenPos(), all ImDrawList:: functions. -> this is the preferred way forward. - // - Window-local coordinates: SameLine(), GetCursorPos(), SetCursorPos(), GetCursorStartPos(), GetContentRegionMax(), GetWindowContentRegion*(), PushTextWrapPos() - // - GetCursorScreenPos() = GetCursorPos() + GetWindowPos(). GetWindowPos() is almost only ever useful to convert from window-local to absolute coordinates. - IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute coordinates (prefer using this, also more useful to work with ImDrawList API). - IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute coordinates - IMGUI_API ImVec2 GetCursorPos(); // [window-local] cursor position in window coordinates (relative to window position) + // - Window-local coordinates: SameLine(offset), GetCursorPos(), SetCursorPos(), GetCursorStartPos(), PushTextWrapPos() + // - Window-local coordinates: GetContentRegionMax(), GetWindowContentRegionMin(), GetWindowContentRegionMax() --> all obsoleted. YOU DON'T NEED THEM. + // - GetCursorScreenPos() = GetCursorPos() + GetWindowPos(). GetWindowPos() is almost only ever useful to convert from window-local to absolute coordinates. Try not to use it. + IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position, absolute coordinates. THIS IS YOUR BEST FRIEND (prefer using this rather than GetCursorPos(), also more useful to work with ImDrawList API). + IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position, absolute coordinates. THIS IS YOUR BEST FRIEND. + IMGUI_API ImVec2 GetContentRegionAvail(); // available space from current position. THIS IS YOUR BEST FRIEND. + IMGUI_API ImVec2 GetCursorPos(); // [window-local] cursor position in window-local coordinates. This is not your best friend. IMGUI_API float GetCursorPosX(); // [window-local] " IMGUI_API float GetCursorPosY(); // [window-local] " IMGUI_API void SetCursorPos(const ImVec2& local_pos); // [window-local] " IMGUI_API void SetCursorPosX(float local_x); // [window-local] " IMGUI_API void SetCursorPosY(float local_y); // [window-local] " - IMGUI_API ImVec2 GetCursorStartPos(); // [window-local] initial cursor position, in window coordinates + IMGUI_API ImVec2 GetCursorStartPos(); // [window-local] initial cursor position, in window-local coordinates. Call GetCursorScreenPos() after Begin() to get the absolute coordinates version. // Other layout functions IMGUI_API void Separator(); // separator, generally horizontal. inside a menu bar or in horizontal layout mode, this becomes a vertical separator. @@ -521,6 +526,7 @@ namespace ImGui IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end); IMGUI_API ImGuiID GetID(const void* ptr_id); + IMGUI_API ImGuiID GetID(int int_id); // Widgets: Text IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Roughly equivalent to Text("%s", text) but: A) doesn't require null terminated string if 'text_end' is specified, B) it's faster, no memory copy is done, no buffer size limits, recommended for long chunks of text. @@ -552,6 +558,8 @@ namespace ImGui IMGUI_API bool RadioButton(const char* label, int* v, int v_button); // shortcut to handle the above pattern when value is an integer IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-FLT_MIN, 0), const char* overlay = NULL); IMGUI_API void Bullet(); // draw a small circle + keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses + IMGUI_API bool TextLink(const char* label); // hyperlink text button, return true when clicked + IMGUI_API void TextLinkOpenURL(const char* label, const char* url = NULL); // hyperlink text button, automatically open file/url when clicked // Widgets: Images // - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples @@ -662,6 +670,7 @@ namespace ImGui IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). IMGUI_API bool CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags = 0); // when 'p_visible != NULL': if '*p_visible==true' display an additional small close button on upper right of the header which will set the bool to false when clicked, if '*p_visible==false' don't display the header. IMGUI_API void SetNextItemOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state. + IMGUI_API void SetNextItemStorageID(ImGuiID storage_id); // set id to use for open/close storage (default to same as item id). // Widgets: Selectables // - A selectable highlights when hovered, and can display another color when selected. @@ -669,6 +678,18 @@ namespace ImGui IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper. + // Multi-selection system for Selectable(), Checkbox(), TreeNode() functions [BETA] + // - This enables standard multi-selection/range-selection idioms (CTRL+Mouse/Keyboard, SHIFT+Mouse/Keyboard, etc.) in a way that also allow a clipper to be used. + // - ImGuiSelectionUserData is often used to store your item index within the current view (but may store something else). + // - Read comments near ImGuiMultiSelectIO for instructions/details and see 'Demo->Widgets->Selection State & Multi-Select' for demo. + // - TreeNode() is technically supported but... using this correctly is more complicated. You need some sort of linear/random access to your tree, + // which is suited to advanced trees setups already implementing filters and clipper. We will work simplifying the current demo. + // - 'selection_size' and 'items_count' parameters are optional and used by a few features. If they are costly for you to compute, you may avoid them. + IMGUI_API ImGuiMultiSelectIO* BeginMultiSelect(ImGuiMultiSelectFlags flags, int selection_size = -1, int items_count = -1); + IMGUI_API ImGuiMultiSelectIO* EndMultiSelect(); + IMGUI_API void SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data); + IMGUI_API bool IsItemToggledSelection(); // Was the last item selection state toggled? Useful if you need the per-item information _before_ reaching EndMultiSelect(). We only returns toggle _event_ in order to handle clipping correctly. + // Widgets: List Boxes // - This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label. // - You can submit contents and manage your selection state however you want it, by creating e.g. Selectable() or any other items. @@ -989,6 +1010,14 @@ namespace ImGui IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags = 0); IMGUI_API void SetNextItemShortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags = 0); + // Inputs Utilities: Key/Input Ownership [BETA] + // - One common use case would be to allow your items to disable standard inputs behaviors such + // as Tab or Alt key handling, Mouse Wheel scrolling, etc. + // e.g. Button(...); SetItemKeyOwner(ImGuiKey_MouseWheelY); to make hovering/activating a button disable wheel for scrolling. + // - Reminder ImGuiKey enum include access to mouse buttons and gamepad, so key ownership can apply to them. + // - Many related features are still in imgui_internal.h. For instance, most IsKeyXXX()/IsMouseXXX() functions have an owner-id-aware version. + IMGUI_API void SetItemKeyOwner(ImGuiKey key); // Set key owner to last item ID if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'. + // Inputs Utilities: Mouse specific // - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right. // - You can also use regular integer: it is forever guaranteed that 0=Left, 1=Right, 2=Middle. @@ -1030,6 +1059,10 @@ namespace ImGui IMGUI_API void DebugFlashStyleColor(ImGuiCol idx); IMGUI_API void DebugStartItemPicker(); IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro. +#ifndef IMGUI_DISABLE_DEBUG_TOOLS + IMGUI_API void DebugLog(const char* fmt, ...) IM_FMTARGS(1); // Call via IMGUI_DEBUG_LOG() for maximum stripping in caller code! + IMGUI_API void DebugLogV(const char* fmt, va_list args) IM_FMTLIST(1); +#endif // Memory Allocators // - Those functions are not reliant on the current context. @@ -1095,7 +1128,7 @@ enum ImGuiWindowFlags_ // Obsolete names #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 30, // Obsoleted in 1.90: Use ImGuiChildFlags_AlwaysUseWindowPadding in BeginChild() call. + ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 30, // Obsoleted in 1.90.0: Use ImGuiChildFlags_AlwaysUseWindowPadding in BeginChild() call. ImGuiWindowFlags_NavFlattened = 1 << 31, // Obsoleted in 1.90.9: Use ImGuiChildFlags_NavFlattened in BeginChild() call. #endif }; @@ -1120,7 +1153,19 @@ enum ImGuiChildFlags_ ImGuiChildFlags_AutoResizeY = 1 << 5, // Enable auto-resizing height. Read "IMPORTANT: Size measurement" details above. ImGuiChildFlags_AlwaysAutoResize = 1 << 6, // Combined with AutoResizeX/AutoResizeY. Always measure size even when child is hidden, always return true, always disable clipping optimization! NOT RECOMMENDED. ImGuiChildFlags_FrameStyle = 1 << 7, // Style the child window like a framed item: use FrameBg, FrameRounding, FrameBorderSize, FramePadding instead of ChildBg, ChildRounding, ChildBorderSize, WindowPadding. - ImGuiChildFlags_NavFlattened = 1 << 8, // Share focus scope, allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows. + ImGuiChildFlags_NavFlattened = 1 << 8, // [BETA] Share focus scope, allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows. +}; + +// Flags for ImGui::PushItemFlag() +// (Those are shared by all items) +enum ImGuiItemFlags_ +{ + ImGuiItemFlags_None = 0, // (Default) + ImGuiItemFlags_NoTabStop = 1 << 0, // false // Disable keyboard tabbing. This is a "lighter" version of ImGuiItemFlags_NoNav. + ImGuiItemFlags_NoNav = 1 << 1, // false // Disable any form of focusing (keyboard/gamepad directional navigation and SetKeyboardFocusHere() calls). + ImGuiItemFlags_NoNavDefaultFocus = 1 << 2, // false // Disable item being a candidate for default focus (e.g. used by title bar items). + ImGuiItemFlags_ButtonRepeat = 1 << 3, // false // Any button-like behavior will have repeat mode enabled (based on io.KeyRepeatDelay and io.KeyRepeatRate values). Note that you can also call IsItemActive() after any button to tell if it is being held. + ImGuiItemFlags_AutoClosePopups = 1 << 4, // true // MenuItem()/Selectable() automatically close their parent popup window. }; // Flags for ImGui::InputText() @@ -1220,14 +1265,16 @@ enum ImGuiPopupFlags_ enum ImGuiSelectableFlags_ { ImGuiSelectableFlags_None = 0, - ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this doesn't close parent popup window + ImGuiSelectableFlags_NoAutoClosePopups = 1 << 0, // Clicking this doesn't close parent popup window (overrides ImGuiItemFlags_AutoClosePopups) ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Frame will span all columns of its container table (text will still fit in current column) ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, // Generate press events on double clicks too ImGuiSelectableFlags_Disabled = 1 << 3, // Cannot be selected, display grayed out text ImGuiSelectableFlags_AllowOverlap = 1 << 4, // (WIP) Hit testing to allow subsequent widgets to overlap this one + ImGuiSelectableFlags_Highlight = 1 << 5, // Make the item be displayed as if it is hovered #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - ImGuiSelectableFlags_AllowItemOverlap = ImGuiSelectableFlags_AllowOverlap, // Renamed in 1.89.7 + ImGuiSelectableFlags_DontClosePopups = ImGuiSelectableFlags_NoAutoClosePopups, // Renamed in 1.91.0 + ImGuiSelectableFlags_AllowItemOverlap = ImGuiSelectableFlags_AllowOverlap, // Renamed in 1.89.7 #endif }; @@ -1392,6 +1439,7 @@ enum ImGuiDataType_ ImGuiDataType_U64, // unsigned long long / unsigned __int64 ImGuiDataType_Float, // float ImGuiDataType_Double, // double + ImGuiDataType_Bool, // bool (provided for user convenience, not supported by scalar widgets) ImGuiDataType_COUNT }; @@ -1687,6 +1735,7 @@ enum ImGuiCol_ ImGuiCol_TableBorderLight, // Table inner borders (prefer using Alpha=1.0 here) ImGuiCol_TableRowBg, // Table row background (even rows) ImGuiCol_TableRowBgAlt, // Table row background (odd rows) + ImGuiCol_TextLink, // Hyperlink color ImGuiCol_TextSelectedBg, ImGuiCol_DragDropTarget, // Rectangle highlighting a drop target ImGuiCol_NavHighlight, // Gamepad/keyboard: current highlighted item @@ -1739,6 +1788,7 @@ enum ImGuiStyleVar_ ImGuiStyleVar_TabRounding, // float TabRounding ImGuiStyleVar_TabBorderSize, // float TabBorderSize ImGuiStyleVar_TabBarBorderSize, // float TabBarBorderSize + ImGuiStyleVar_TabBarOverlineSize, // float TabBarOverlineSize ImGuiStyleVar_TableAngledHeadersAngle, // float TableAngledHeadersAngle ImGuiStyleVar_TableAngledHeadersTextAlign,// ImVec2 TableAngledHeadersTextAlign ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign @@ -2038,9 +2088,19 @@ struct ImGuiTableColumnSortSpecs }; //----------------------------------------------------------------------------- -// [SECTION] Helpers: Memory allocations macros, ImVector<> +// [SECTION] Helpers: Debug log, memory allocations macros, ImVector<> //----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// Debug Logging into ShowDebugLogWindow(), tty and more. +//----------------------------------------------------------------------------- + +#ifndef IMGUI_DISABLE_DEBUG_TOOLS +#define IMGUI_DEBUG_LOG(...) ImGui::DebugLog(__VA_ARGS__) +#else +#define IMGUI_DEBUG_LOG(...) ((void)0) +#endif + //----------------------------------------------------------------------------- // IM_MALLOC(), IM_FREE(), IM_NEW(), IM_PLACEMENT_NEW(), IM_DELETE() // We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax. @@ -2173,12 +2233,13 @@ struct ImGuiStyle float TabBorderSize; // Thickness of border around tabs. float TabMinWidthForCloseButton; // Minimum width for close button to appear on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected. float TabBarBorderSize; // Thickness of tab-bar separator, which takes on the tab active color to denote focus. + float TabBarOverlineSize; // Thickness of tab-bar overline, which highlights the selected tab-bar. float TableAngledHeadersAngle; // Angle of angled headers (supported values range from -50.0f degrees to +50.0f degrees). ImVec2 TableAngledHeadersTextAlign;// Alignment of angled headers within the cell ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right. ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered). ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line. - float SeparatorTextBorderSize; // Thickkness of border in SeparatorText() + float SeparatorTextBorderSize; // Thickness 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; // Apply to regular windows: amount which we enforce to keep visible when moving near edges of your screen. @@ -2263,6 +2324,7 @@ struct ImGuiIO // Miscellaneous options bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations. bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl. + bool ConfigNavSwapGamepadButtons; // = false // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout. bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates. bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting). bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will keep item active and select contents (single-line only). @@ -2322,9 +2384,15 @@ struct ImGuiIO void (*SetClipboardTextFn)(void* user_data, const char* text); void* ClipboardUserData; + // Optional: Open link/folder/file in OS Shell + // (default to use ShellExecuteA() on Windows, system() on Linux/Mac) + bool (*PlatformOpenInShellFn)(ImGuiContext* ctx, const char* path); + void* PlatformOpenInShellUserData; + // Optional: Notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME on Windows) // (default to use native imm32 api on Windows) - void (*SetPlatformImeDataFn)(ImGuiViewport* viewport, ImGuiPlatformImeData* data); + void (*PlatformSetImeDataFn)(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); + //void (*SetPlatformImeDataFn)(ImGuiViewport* viewport, ImGuiPlatformImeData* data); // [Renamed to io.PlatformSetImeDataFn in 1.91.0] // Optional: Platform locale ImWchar PlatformLocaleDecimalPoint; // '.' // [Experimental] Configure decimal point e.g. '.' or ',' useful for some languages (e.g. German), generally pulled from *localeconv()->decimal_point @@ -2686,9 +2754,10 @@ struct ImGuiListClipper int ItemsCount; // [Internal] Number of items float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it float StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed + double StartSeekOffsetY; // [Internal] Account for frozen rows in a table and initial loss of precision in very large windows. void* TempData; // [Internal] Internal data - // items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step) + // items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step, and you can call SeekCursorForItem() manually if you need) // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing(). IMGUI_API ImGuiListClipper(); IMGUI_API ~ImGuiListClipper(); @@ -2701,6 +2770,11 @@ struct ImGuiListClipper inline void IncludeItemByIndex(int item_index) { IncludeItemsByIndex(item_index, item_index + 1); } IMGUI_API void IncludeItemsByIndex(int item_begin, int item_end); // item_end is exclusive e.g. use (42, 42+1) to make item 42 never clipped. + // Seek cursor toward given item. This is automatically called while stepping. + // - The only reason to call this is: you can use ImGuiListClipper::Begin(INT_MAX) if you don't know item count ahead of time. + // - In this case, after all steps are done, you'll want to call SeekCursorForItem(item_count). + IMGUI_API void SeekCursorForItem(int item_index); + #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS inline void IncludeRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.9] inline void ForceDisplayRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.6] @@ -2781,6 +2855,154 @@ struct ImColor static ImColor HSV(float h, float s, float v, float a = 1.0f) { float r, g, b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r, g, b, a); } }; +//----------------------------------------------------------------------------- +// [SECTION] Multi-Select API flags and structures (ImGuiMultiSelectFlags, ImGuiSelectionRequestType, ImGuiSelectionRequest, ImGuiMultiSelectIO, ImGuiSelectionBasicStorage) +//----------------------------------------------------------------------------- + +// Multi-selection system +// Documentation at: https://github.com/ocornut/imgui/wiki/Multi-Select +// - Refer to 'Demo->Widgets->Selection State & Multi-Select' for demos using this. +// - This system implements standard multi-selection idioms (CTRL+Mouse/Keyboard, SHIFT+Mouse/Keyboard, etc) +// with support for clipper (skipping non-visible items), box-select and many other details. +// - Selectable(), Checkbox() are supported but custom widgets may use it as well. +// - TreeNode() is technically supported but... using this correctly is more complicated: you need some sort of linear/random access to your tree, +// which is suited to advanced trees setups also implementing filters and clipper. We will work toward simplifying and demoing it. +// - In the spirit of Dear ImGui design, your code owns actual selection data. +// This is designed to allow all kinds of selection storage you may use in your application e.g. set/map/hash. +// About ImGuiSelectionBasicStorage: +// - This is an optional helper to store a selection state and apply selection requests. +// - It is used by our demos and provided as a convenience to quickly implement multi-selection. +// Usage: +// - Identify submitted items with SetNextItemSelectionUserData(), most likely using an index into your current data-set. +// - Store and maintain actual selection data using persistent object identifiers. +// - Usage flow: +// BEGIN - (1) Call BeginMultiSelect() and retrieve the ImGuiMultiSelectIO* result. +// - (2) Honor request list (SetAll/SetRange requests) by updating your selection data. Same code as Step 6. +// - (3) [If using clipper] You need to make sure RangeSrcItem is always submitted. Calculate its index and pass to clipper.IncludeItemByIndex(). If storing indices in ImGuiSelectionUserData, a simple clipper.IncludeItemByIndex(ms_io->RangeSrcItem) call will work. +// LOOP - (4) Submit your items with SetNextItemSelectionUserData() + Selectable()/TreeNode() calls. +// END - (5) Call EndMultiSelect() and retrieve the ImGuiMultiSelectIO* result. +// - (6) Honor request list (SetAll/SetRange requests) by updating your selection data. Same code as Step 2. +// If you submit all items (no clipper), Step 2 and 3 are optional and will be handled by each item themselves. It is fine to always honor those steps. +// About ImGuiSelectionUserData: +// - This can store an application-defined identifier (e.g. index or pointer) submitted via SetNextItemSelectionUserData(). +// - In return we store them into RangeSrcItem/RangeFirstItem/RangeLastItem and other fields in ImGuiMultiSelectIO. +// - Most applications will store an object INDEX, hence the chosen name and type. Storing an index is natural, because +// SetRange requests will give you two end-points and you will need to iterate/interpolate between them to update your selection. +// - However it is perfectly possible to store a POINTER or another IDENTIFIER inside ImGuiSelectionUserData. +// Our system never assume that you identify items by indices, it never attempts to interpolate between two values. +// - If you enable ImGuiMultiSelectFlags_NoRangeSelect then it is guaranteed that you will never have to interpolate +// between two ImGuiSelectionUserData, which may be a convenient way to use part of the feature with less code work. +// - As most users will want to store an index, for convenience and to reduce confusion we use ImS64 instead of void*, +// being syntactically easier to downcast. Feel free to reinterpret_cast and store a pointer inside. + +// Flags for BeginMultiSelect() +enum ImGuiMultiSelectFlags_ +{ + ImGuiMultiSelectFlags_None = 0, + ImGuiMultiSelectFlags_SingleSelect = 1 << 0, // Disable selecting more than one item. This is available to allow single-selection code to share same code/logic if desired. It essentially disables the main purpose of BeginMultiSelect() tho! + ImGuiMultiSelectFlags_NoSelectAll = 1 << 1, // Disable CTRL+A shortcut to select all. + ImGuiMultiSelectFlags_NoRangeSelect = 1 << 2, // Disable Shift+selection mouse/keyboard support (useful for unordered 2D selection). With BoxSelect is also ensure contiguous SetRange requests are not combined into one. This allows not handling interpolation in SetRange requests. + ImGuiMultiSelectFlags_NoAutoSelect = 1 << 3, // Disable selecting items when navigating (useful for e.g. supporting range-select in a list of checkboxes). + ImGuiMultiSelectFlags_NoAutoClear = 1 << 4, // Disable clearing selection when navigating or selecting another one (generally used with ImGuiMultiSelectFlags_NoAutoSelect. useful for e.g. supporting range-select in a list of checkboxes). + ImGuiMultiSelectFlags_NoAutoClearOnReselect = 1 << 5, // Disable clearing selection when clicking/selecting an already selected item. + ImGuiMultiSelectFlags_BoxSelect1d = 1 << 6, // Enable box-selection with same width and same x pos items (e.g. full row Selectable()). Box-selection works better with little bit of spacing between items hit-box in order to be able to aim at empty space. + ImGuiMultiSelectFlags_BoxSelect2d = 1 << 7, // Enable box-selection with varying width or varying x pos items support (e.g. different width labels, or 2D layout/grid). This is slower: alters clipping logic so that e.g. horizontal movements will update selection of normally clipped items. + ImGuiMultiSelectFlags_BoxSelectNoScroll = 1 << 8, // Disable scrolling when box-selecting near edges of scope. + ImGuiMultiSelectFlags_ClearOnEscape = 1 << 9, // Clear selection when pressing Escape while scope is focused. + ImGuiMultiSelectFlags_ClearOnClickVoid = 1 << 10, // Clear selection when clicking on empty location within scope. + ImGuiMultiSelectFlags_ScopeWindow = 1 << 11, // Scope for _BoxSelect and _ClearOnClickVoid is whole window (Default). Use if BeginMultiSelect() covers a whole window or used a single time in same window. + ImGuiMultiSelectFlags_ScopeRect = 1 << 12, // Scope for _BoxSelect and _ClearOnClickVoid is rectangle encompassing BeginMultiSelect()/EndMultiSelect(). Use if BeginMultiSelect() is called multiple times in same window. + ImGuiMultiSelectFlags_SelectOnClick = 1 << 13, // Apply selection on mouse down when clicking on unselected item. (Default) + ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 14, // Apply selection on mouse release when clicking an unselected item. Allow dragging an unselected item without altering selection. + //ImGuiMultiSelectFlags_RangeSelect2d = 1 << 15, // Shift+Selection uses 2d geometry instead of linear sequence, so possible to use Shift+up/down to select vertically in grid. Analogous to what BoxSelect does. + ImGuiMultiSelectFlags_NavWrapX = 1 << 16, // [Temporary] Enable navigation wrapping on X axis. Provided as a convenience because we don't have a design for the general Nav API for this yet. When the more general feature be public we may obsolete this flag in favor of new one. +}; + +// Main IO structure returned by BeginMultiSelect()/EndMultiSelect(). +// This mainly contains a list of selection requests. +// - Use 'Demo->Tools->Debug Log->Selection' to see requests as they happen. +// - Some fields are only useful if your list is dynamic and allows deletion (getting post-deletion focus/state right is shown in the demo) +// - Below: who reads/writes each fields? 'r'=read, 'w'=write, 'ms'=multi-select code, 'app'=application/user code. +struct ImGuiMultiSelectIO +{ + //------------------------------------------// BeginMultiSelect / EndMultiSelect + ImVector Requests; // ms:w, app:r / ms:w app:r // Requests to apply to your selection data. + ImGuiSelectionUserData RangeSrcItem; // ms:w app:r / // (If using clipper) Begin: Source item (often the first selected item) must never be clipped: use clipper.IncludeItemByIndex() to ensure it is submitted. + ImGuiSelectionUserData NavIdItem; // ms:w, app:r / // (If using deletion) Last known SetNextItemSelectionUserData() value for NavId (if part of submitted items). + bool NavIdSelected; // ms:w, app:r / app:r // (If using deletion) Last known selection state for NavId (if part of submitted items). + bool RangeSrcReset; // app:w / ms:r // (If using deletion) Set before EndMultiSelect() to reset ResetSrcItem (e.g. if deleted selection). + int ItemsCount; // ms:w, app:r / app:r // 'int items_count' parameter to BeginMultiSelect() is copied here for convenience, allowing simpler calls to your ApplyRequests handler. Not used internally. +}; + +// Selection request type +enum ImGuiSelectionRequestType +{ + ImGuiSelectionRequestType_None = 0, + ImGuiSelectionRequestType_SetAll, // Request app to clear selection (if Selected==false) or select all items (if Selected==true). We cannot set RangeFirstItem/RangeLastItem as its contents is entirely up to user (not necessarily an index) + ImGuiSelectionRequestType_SetRange, // Request app to select/unselect [RangeFirstItem..RangeLastItem] items (inclusive) based on value of Selected. Only EndMultiSelect() request this, app code can read after BeginMultiSelect() and it will always be false. +}; + +// Selection request item +struct ImGuiSelectionRequest +{ + //------------------------------------------// BeginMultiSelect / EndMultiSelect + ImGuiSelectionRequestType Type; // ms:w, app:r / ms:w, app:r // Request type. You'll most often receive 1 Clear + 1 SetRange with a single-item range. + bool Selected; // ms:w, app:r / ms:w, app:r // Parameter for SetAll/SetRange requests (true = select, false = unselect) + ImS8 RangeDirection; // / ms:w app:r // Parameter for SetRange request: +1 when RangeFirstItem comes before RangeLastItem, -1 otherwise. Useful if you want to preserve selection order on a backward Shift+Click. + ImGuiSelectionUserData RangeFirstItem; // / ms:w, app:r // Parameter for SetRange request (this is generally == RangeSrcItem when shift selecting from top to bottom). + ImGuiSelectionUserData RangeLastItem; // / ms:w, app:r // Parameter for SetRange request (this is generally == RangeSrcItem when shift selecting from bottom to top). Inclusive! +}; + +// Optional helper to store multi-selection state + apply multi-selection requests. +// - Used by our demos and provided as a convenience to easily implement basic multi-selection. +// - Iterate selection with 'void* it = NULL; ImGuiID id; while (selection.GetNextSelectedItem(&it, &id)) { ... }' +// Or you can check 'if (Contains(id)) { ... }' for each possible object if their number is not too high to iterate. +// - USING THIS IS NOT MANDATORY. This is only a helper and not a required API. +// To store a multi-selection, in your application you could: +// - Use this helper as a convenience. We use our simple key->value ImGuiStorage as a std::set replacement. +// - Use your own external storage: e.g. std::set, std::vector, interval trees, intrusively stored selection etc. +// In ImGuiSelectionBasicStorage we: +// - always use indices in the multi-selection API (passed to SetNextItemSelectionUserData(), retrieved in ImGuiMultiSelectIO) +// - use the AdapterIndexToStorageId() indirection layer to abstract how persistent selection data is derived from an index. +// - use decently optimized logic to allow queries and insertion of very large selection sets. +// - do not preserve selection order. +// Many combinations are possible depending on how you prefer to store your items and how you prefer to store your selection. +// Large applications are likely to eventually want to get rid of this indirection layer and do their own thing. +// See https://github.com/ocornut/imgui/wiki/Multi-Select for details and pseudo-code using this helper. +struct ImGuiSelectionBasicStorage +{ + // Members + int Size; // // Number of selected items, maintained by this helper. + bool PreserveOrder; // = false // GetNextSelectedItem() will return ordered selection (currently implemented by two additional sorts of selection. Could be improved) + void* UserData; // = NULL // User data for use by adapter function // e.g. selection.UserData = (void*)my_items; + ImGuiID (*AdapterIndexToStorageId)(ImGuiSelectionBasicStorage* self, int idx); // e.g. selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { return ((MyItems**)self->UserData)[idx]->ID; }; + int _SelectionOrder;// [Internal] Increasing counter to store selection order + ImGuiStorage _Storage; // [Internal] Selection set. Think of this as similar to e.g. std::set. Prefer not accessing directly: iterate with GetNextSelectedItem(). + + // Methods + ImGuiSelectionBasicStorage(); + IMGUI_API void ApplyRequests(ImGuiMultiSelectIO* ms_io); // Apply selection requests coming from BeginMultiSelect() and EndMultiSelect() functions. It uses 'items_count' passed to BeginMultiSelect() + IMGUI_API bool Contains(ImGuiID id) const; // Query if an item id is in selection. + IMGUI_API void Clear(); // Clear selection + IMGUI_API void Swap(ImGuiSelectionBasicStorage& r); // Swap two selections + IMGUI_API void SetItemSelected(ImGuiID id, bool selected); // Add/remove an item from selection (generally done by ApplyRequests() function) + IMGUI_API bool GetNextSelectedItem(void** opaque_it, ImGuiID* out_id); // Iterate selection with 'void* it = NULL; ImGuiId id; while (selection.GetNextSelectedItem(&it, &id)) { ... }' + inline ImGuiID GetStorageIdFromIndex(int idx) { return AdapterIndexToStorageId(this, idx); } // Convert index to item id based on provided adapter. +}; + +// Optional helper to apply multi-selection requests to existing randomly accessible storage. +// Convenient if you want to quickly wire multi-select API on e.g. an array of bool or items storing their own selection state. +struct ImGuiSelectionExternalStorage +{ + // Members + void* UserData; // User data for use by adapter function // e.g. selection.UserData = (void*)my_items; + void (*AdapterSetItemSelected)(ImGuiSelectionExternalStorage* self, int idx, bool selected); // e.g. AdapterSetItemSelected = [](ImGuiSelectionExternalStorage* self, int idx, bool selected) { ((MyItems**)self->UserData)[idx]->Selected = selected; } + + // Methods + IMGUI_API ImGuiSelectionExternalStorage(); + IMGUI_API void ApplyRequests(ImGuiMultiSelectIO* ms_io); // Apply selection requests by using AdapterSetItemSelected() calls +}; + //----------------------------------------------------------------------------- // [SECTION] Drawing API (ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawListFlags, ImDrawList, ImDrawData) // Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList. @@ -3345,7 +3567,7 @@ struct ImFont float EllipsisCharStep; // 4 // out // Step between characters when EllipsisCount > 0 bool DirtyLookupTables; // 1 // out // float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() - float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] + float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] (unscaled) int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) ImU8 Used4kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/4096/8]; // 2 bytes if ImWchar=ImWchar16, 34 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints. @@ -3564,7 +3786,7 @@ struct ImGuiPlatformMonitor ImGuiPlatformMonitor() { MainPos = MainSize = WorkPos = WorkSize = ImVec2(0, 0); DpiScale = 1.0f; PlatformHandle = NULL; } }; -// (Optional) Support for IME (Input Method Editor) via the io.SetPlatformImeDataFn() function. +// (Optional) Support for IME (Input Method Editor) via the io.PlatformSetImeDataFn() function. struct ImGuiPlatformImeData { bool WantVisible; // A widget wants the IME to be visible @@ -3583,29 +3805,37 @@ struct ImGuiPlatformImeData #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { + // OBSOLETED in 1.91.0 (from July 2024) + static inline void PushButtonRepeat(bool repeat) { PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat); } + static inline void PopButtonRepeat() { PopItemFlag(); } + static inline void PushTabStop(bool tab_stop) { PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); } + static inline void PopTabStop() { PopItemFlag(); } + IMGUI_API ImVec2 GetContentRegionMax(); // Content boundaries max (e.g. window boundaries including scrolling, or current column boundaries). You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()! + IMGUI_API ImVec2 GetWindowContentRegionMin(); // Content boundaries min for the window (roughly (0,0)-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()! + IMGUI_API ImVec2 GetWindowContentRegionMax(); // Content boundaries max for the window (roughly (0,0)+Size-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()! // OBSOLETED in 1.90.0 (from September 2023) - static inline bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags window_flags = 0) { return BeginChild(id, size, ImGuiChildFlags_FrameStyle, window_flags); } - static inline void EndChildFrame() { EndChild(); } + static inline bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags window_flags = 0) { return BeginChild(id, size, ImGuiChildFlags_FrameStyle, window_flags); } + static inline void EndChildFrame() { EndChild(); } //static inline bool BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags window_flags){ return BeginChild(str_id, size_arg, border ? ImGuiChildFlags_Border : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Border //static inline bool BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags window_flags) { return BeginChild(id, size_arg, border ? ImGuiChildFlags_Border : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Border - static inline void ShowStackToolWindow(bool* p_open = NULL) { ShowIDStackToolWindow(p_open); } - IMGUI_API bool ListBox(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1); + static inline void ShowStackToolWindow(bool* p_open = NULL) { ShowIDStackToolWindow(p_open); } IMGUI_API bool Combo(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int popup_max_height_in_items = -1); + IMGUI_API bool ListBox(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1); // OBSOLETED in 1.89.7 (from June 2023) - IMGUI_API void SetItemAllowOverlap(); // Use SetNextItemAllowOverlap() before item. + IMGUI_API void SetItemAllowOverlap(); // Use SetNextItemAllowOverlap() before item. // OBSOLETED in 1.89.4 (from March 2023) - static inline void PushAllowKeyboardFocus(bool tab_stop) { PushTabStop(tab_stop); } - static inline void PopAllowKeyboardFocus() { PopTabStop(); } + static inline void PushAllowKeyboardFocus(bool tab_stop) { PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); } + static inline void PopAllowKeyboardFocus() { PopItemFlag(); } // 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 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; } + 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; } // Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE) //-- OBSOLETED in 1.88 (from May 2022) - //static inline void CaptureKeyboardFromApp(bool want_capture_keyboard = true) { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value. - //static inline void CaptureMouseFromApp(bool want_capture_mouse = true) { SetNextFrameWantCaptureMouse(want_capture_mouse); } // Renamed as name was misleading + removed default value. + //static inline void CaptureKeyboardFromApp(bool want_capture_keyboard = true) { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value. + //static inline void CaptureMouseFromApp(bool want_capture_mouse = true) { SetNextFrameWantCaptureMouse(want_capture_mouse); } // Renamed as name was misleading + removed default value. //-- OBSOLETED in 1.86 (from November 2021) //IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Code removed, see 1.90 for last version of the code. Calculate range of visible items for large list of evenly sized items. Prefer using ImGuiListClipper. //-- OBSOLETED in 1.85 (from August 2021) @@ -3678,8 +3908,8 @@ namespace ImGui // RENAMED and MERGED both ImGuiKey_ModXXX and ImGuiModFlags_XXX into ImGuiMod_XXX (from September 2022) // RENAMED ImGuiKeyModFlags -> ImGuiModFlags in 1.88 (from April 2022). Exceptionally commented out ahead of obscolescence schedule to reduce confusion and because they were not meant to be used in the first place. -typedef ImGuiKeyChord ImGuiModFlags; // == int. We generally use ImGuiKeyChord to mean "a ImGuiKey or-ed with any number of ImGuiMod_XXX value", but you may store only mods in there. -enum ImGuiModFlags_ { ImGuiModFlags_None = 0, ImGuiModFlags_Ctrl = ImGuiMod_Ctrl, ImGuiModFlags_Shift = ImGuiMod_Shift, ImGuiModFlags_Alt = ImGuiMod_Alt, ImGuiModFlags_Super = ImGuiMod_Super }; +//typedef ImGuiKeyChord ImGuiModFlags; // == int. We generally use ImGuiKeyChord to mean "a ImGuiKey or-ed with any number of ImGuiMod_XXX value", so you may store mods in there. +//enum ImGuiModFlags_ { ImGuiModFlags_None = 0, ImGuiModFlags_Ctrl = ImGuiMod_Ctrl, ImGuiModFlags_Shift = ImGuiMod_Shift, ImGuiModFlags_Alt = ImGuiMod_Alt, ImGuiModFlags_Super = ImGuiMod_Super }; //typedef ImGuiKeyChord ImGuiKeyModFlags; // == int //enum ImGuiKeyModFlags_ { ImGuiKeyModFlags_None = 0, ImGuiKeyModFlags_Ctrl = ImGuiMod_Ctrl, ImGuiKeyModFlags_Shift = ImGuiMod_Shift, ImGuiKeyModFlags_Alt = ImGuiMod_Alt, ImGuiKeyModFlags_Super = ImGuiMod_Super }; diff --git a/lib/third_party/imgui/imgui/include/imgui_internal.h b/lib/third_party/imgui/imgui/include/imgui_internal.h index 0530c6ce1..263926d6b 100644 --- a/lib/third_party/imgui/imgui/include/imgui_internal.h +++ b/lib/third_party/imgui/imgui/include/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.9 +// dear imgui, v1.91.0 // (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. @@ -22,6 +22,7 @@ Index of this file: // [SECTION] Navigation support // [SECTION] Typing-select support // [SECTION] Columns support +// [SECTION] Box-select support // [SECTION] Multi-select support // [SECTION] Docking support // [SECTION] Viewport support @@ -124,6 +125,7 @@ struct ImBitVector; // Store 1-bit per value struct ImRect; // An axis-aligned rectangle (2 points) struct ImDrawDataBuilder; // Helper to build a ImDrawData instance struct ImDrawListSharedData; // Data shared between all ImDrawList instances +struct ImGuiBoxSelectState; // Box-selection state (currently used by multi-selection, could potentially be used by others) struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it struct ImGuiContext; // Main Dear ImGui context struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine @@ -139,8 +141,9 @@ struct ImGuiInputTextDeactivateData;// Short term storage to backup text of a de struct ImGuiLastItemData; // Status storage for last submitted items struct ImGuiLocEntry; // A localization entry. struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only +struct ImGuiMultiSelectState; // Multi-selection persistent state (for focused selection). +struct ImGuiMultiSelectTempData; // Multi-selection temporary state (while traversing). struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result -struct ImGuiNavTreeNodeData; // Temporary storage for last TreeNode() being a Left arrow landing candidate. struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions struct ImGuiNextWindowData; // Storage for SetNextWindow** functions struct ImGuiNextItemData; // Storage for SetNextItem** functions @@ -160,6 +163,7 @@ struct ImGuiTableInstanceData; // Storage for one instance of a same table struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables. struct ImGuiTableSettings; // Storage for a table .ini settings struct ImGuiTableColumnsSettings; // Storage for a column .ini settings +struct ImGuiTreeNodeStackData; // Temporary storage for TreeNode(). struct ImGuiTypingSelectState; // Storage for GetTypingSelectRequest() struct ImGuiTypingSelectRequest; // Storage for GetTypingSelectRequest() (aimed to be public) struct ImGuiWindow; // Storage for one window @@ -177,7 +181,6 @@ typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // E typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later) typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags typedef int ImGuiFocusRequestFlags; // -> enum ImGuiFocusRequestFlags_ // Flags: for FocusWindow(); -typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag(), g.LastItemData.InFlags typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for g.LastItemData.StatusFlags typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns() typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight() @@ -398,6 +401,7 @@ IM_MSVC_RUNTIME_CHECKS_OFF static inline char ImToUpper(char c) { return (c >= 'a' && c <= 'z') ? c &= ~32 : c; } static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; } static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; } +static inline bool ImCharIsXdigitA(char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); } IM_MSVC_RUNTIME_CHECKS_RESTORE // Helpers: Formatting @@ -503,6 +507,7 @@ static inline int ImModPositive(int a, int b) static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; } static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; } +static inline float ImLinearRemapClamp(float s0, float s1, float d0, float d1, float x) { return ImSaturate((x - s0) / (s1 - s0)) * (d1 - d0) + d0; } static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } static inline bool ImIsFloatAboveGuaranteedIntegerPrecision(float f) { return f <= -16777216 || f >= 16777216; } static inline float ImExponentialMovingAverage(float avg, float sample, int n) { avg -= avg / n; avg += sample / n; return avg; } @@ -789,6 +794,7 @@ struct IMGUI_API ImDrawListSharedData ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas ImFont* Font; // Current/default font (optional, for simplified AddText overload) float FontSize; // Current/default font size (optional, for simplified AddText overload) + float FontScale; // Current/default font scale (== FontSize / Font->FontSize) float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen() @@ -856,29 +862,27 @@ enum ImGuiDataTypePrivate_ // [SECTION] Widgets support: flags, enums, data structures //----------------------------------------------------------------------------- -// Flags used by upcoming items +// Extend ImGuiItemFlags // - input: PushItemFlag() manipulates g.CurrentItemFlags, ItemAdd() calls may add extra flags. // - output: stored in g.LastItemData.InFlags -// Current window shared by all windows. -// This is going to be exposed in imgui.h when stabilized enough. -enum ImGuiItemFlags_ +enum ImGuiItemFlagsPrivate_ { // Controlled by user - ImGuiItemFlags_None = 0, - ImGuiItemFlags_NoTabStop = 1 << 0, // false // Disable keyboard tabbing. This is a "lighter" version of ImGuiItemFlags_NoNav. - ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. - ImGuiItemFlags_Disabled = 1 << 2, // false // Disable interactions but doesn't affect visuals. See BeginDisabled()/EndDisabled(). See github.com/ocornut/imgui/issues/211 - ImGuiItemFlags_NoNav = 1 << 3, // false // Disable any form of focusing (keyboard/gamepad directional navigation and SetKeyboardFocusHere() calls) - ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false // Disable item being a candidate for default focus (e.g. used by title bar items) - ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // Disable MenuItem/Selectable() automatically closing their popup window - ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets) - ImGuiItemFlags_ReadOnly = 1 << 7, // false // [ALPHA] Allow hovering interactions but underlying value is not changed. - ImGuiItemFlags_NoWindowHoverableCheck = 1 << 8, // false // Disable hoverable check in ItemHoverable() - ImGuiItemFlags_AllowOverlap = 1 << 9, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame. + ImGuiItemFlags_Disabled = 1 << 10, // false // Disable interactions (DOES NOT affect visuals, see BeginDisabled()/EndDisabled() for full disable feature, and github #211). + ImGuiItemFlags_ReadOnly = 1 << 11, // false // [ALPHA] Allow hovering interactions but underlying value is not changed. + ImGuiItemFlags_MixedValue = 1 << 12, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets) + ImGuiItemFlags_NoWindowHoverableCheck = 1 << 13, // false // Disable hoverable check in ItemHoverable() + ImGuiItemFlags_AllowOverlap = 1 << 14, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame. // Controlled by widget code - ImGuiItemFlags_Inputable = 1 << 10, // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature. - ImGuiItemFlags_HasSelectionUserData = 1 << 11, // false // Set by SetNextItemSelectionUserData() + ImGuiItemFlags_Inputable = 1 << 20, // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature. + ImGuiItemFlags_HasSelectionUserData = 1 << 21, // false // Set by SetNextItemSelectionUserData() + ImGuiItemFlags_IsMultiSelect = 1 << 22, // false // Set by SetNextItemSelectionUserData() + + ImGuiItemFlags_Default_ = ImGuiItemFlags_AutoClosePopups, // Please don't change, use PushItemFlag() instead. + + // Obsolete + //ImGuiItemFlags_SelectableDontClosePopup = !ImGuiItemFlags_AutoClosePopups, // Can't have a redirect as we inverted the behavior }; // Status flags for an already submitted item @@ -981,8 +985,8 @@ enum ImGuiSelectableFlagsPrivate_ // Extend ImGuiTreeNodeFlags_ enum ImGuiTreeNodeFlagsPrivate_ { - ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 20, - ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 21,// (FIXME-WIP) Turn Down arrow into an Up arrow, but reversed trees (#6517) + ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 28,// FIXME-WIP: Hard-coded for CollapsingHeader() + ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 29,// FIXME-WIP: Turn Down arrow into an Up arrow, but reversed trees (#6517) }; enum ImGuiSeparatorFlags_ @@ -1229,10 +1233,6 @@ struct ImGuiNextWindowData inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } }; -// Multi-Selection item index or identifier when using SetNextItemSelectionUserData()/BeginMultiSelect() -// (Most users are likely to use this store an item INDEX but this may be used to store a POINTER as well.) -typedef ImS64 ImGuiSelectionUserData; - enum ImGuiNextItemDataFlags_ { ImGuiNextItemDataFlags_None = 0, @@ -1240,13 +1240,15 @@ enum ImGuiNextItemDataFlags_ ImGuiNextItemDataFlags_HasOpen = 1 << 1, ImGuiNextItemDataFlags_HasShortcut = 1 << 2, ImGuiNextItemDataFlags_HasRefVal = 1 << 3, + ImGuiNextItemDataFlags_HasStorageID = 1 << 4, }; struct ImGuiNextItemData { ImGuiNextItemDataFlags Flags; - ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap. + ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap and ImGuiItemFlags_HasSelectionUserData. // Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem() + ImGuiID FocusScopeId; // Set by SetNextItemSelectionUserData() ImGuiSelectionUserData SelectionUserData; // Set by SetNextItemSelectionUserData() (note that NULL/0 is a valid value, we use -1 == ImGuiSelectionUserData_Invalid to mark invalid values) float Width; // Set by SetNextItemWidth() ImGuiKeyChord Shortcut; // Set by SetNextItemShortcut() @@ -1254,6 +1256,7 @@ struct ImGuiNextItemData bool OpenVal; // Set by SetNextItemOpen() ImU8 OpenCond; // Set by SetNextItemOpen() ImGuiDataTypeStorage RefVal; // Not exposed yet, for ImGuiInputTextFlags_ParseEmptyAsRefVal + ImGuiID StorageId; // Set by SetNextItemStorageID() ImGuiNextItemData() { memset(this, 0, sizeof(*this)); SelectionUserData = -1; } inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()! @@ -1275,14 +1278,16 @@ struct ImGuiLastItemData ImGuiLastItemData() { memset(this, 0, sizeof(*this)); } }; -// Store data emitted by TreeNode() for usage by TreePop() to implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere. -// This is the minimum amount of data that we need to perform the equivalent of NavApplyItemToResult() and which we can't infer in TreePop() -// Only stored when the node is a potential candidate for landing on a Left arrow jump. -struct ImGuiNavTreeNodeData +// Store data emitted by TreeNode() for usage by TreePop() +// - To implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere: store the minimum amount of data +// which we can't infer in TreePop(), to perform the equivalent of NavApplyItemToResult(). +// Only stored when the node is a potential candidate for landing on a Left arrow jump. +struct ImGuiTreeNodeStackData { ImGuiID ID; - ImGuiItemFlags InFlags; - ImRect NavRect; + ImGuiTreeNodeFlags TreeFlags; + ImGuiItemFlags InFlags; // Used for nav landing + ImRect NavRect; // Used for nav landing }; struct IMGUI_API ImGuiStackSizes @@ -1377,8 +1382,8 @@ typedef ImBitArray ImBitAr #define ImGuiKey_NavKeyboardTweakFast ImGuiMod_Shift #define ImGuiKey_NavGamepadTweakSlow ImGuiKey_GamepadL1 #define ImGuiKey_NavGamepadTweakFast ImGuiKey_GamepadR1 -#define ImGuiKey_NavGamepadActivate ImGuiKey_GamepadFaceDown -#define ImGuiKey_NavGamepadCancel ImGuiKey_GamepadFaceRight +#define ImGuiKey_NavGamepadActivate (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceRight : ImGuiKey_GamepadFaceDown) +#define ImGuiKey_NavGamepadCancel (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceDown : ImGuiKey_GamepadFaceRight) #define ImGuiKey_NavGamepadMenu ImGuiKey_GamepadFaceLeft #define ImGuiKey_NavGamepadInput ImGuiKey_GamepadFaceUp @@ -1733,6 +1738,34 @@ struct ImGuiOldColumns ImGuiOldColumns() { memset(this, 0, sizeof(*this)); } }; +//----------------------------------------------------------------------------- +// [SECTION] Box-select support +//----------------------------------------------------------------------------- + +struct ImGuiBoxSelectState +{ + // Active box-selection data (persistent, 1 active at a time) + ImGuiID ID; + bool IsActive; + bool IsStarting; + bool IsStartedFromVoid; // Starting click was not from an item. + bool IsStartedSetNavIdOnce; + bool RequestClear; + ImGuiKeyChord KeyMods : 16; // Latched key-mods for box-select logic. + ImVec2 StartPosRel; // Start position in window-contents relative space (to support scrolling) + ImVec2 EndPosRel; // End position in window-contents relative space + ImVec2 ScrollAccum; // Scrolling accumulator (to behave at high-frame spaces) + ImGuiWindow* Window; + + // Temporary/Transient data + bool UnclipMode; // (Temp/Transient, here in hot area). Set/cleared by the BeginMultiSelect()/EndMultiSelect() owning active box-select. + ImRect UnclipRect; // Rectangle where ItemAdd() clipping may be temporarily disabled. Need support by multi-select supporting widgets. + ImRect BoxSelectRectPrev; // Selection rectangle in absolute coordinates (derived every frame from BoxSelectStartPosRel and MousePos) + ImRect BoxSelectRectCurr; + + ImGuiBoxSelectState() { memset(this, 0, sizeof(*this)); } +}; + //----------------------------------------------------------------------------- // [SECTION] Multi-select support //----------------------------------------------------------------------------- @@ -1740,9 +1773,45 @@ struct ImGuiOldColumns // We always assume that -1 is an invalid value (which works for indices and pointers) #define ImGuiSelectionUserData_Invalid ((ImGuiSelectionUserData)-1) -#ifdef IMGUI_HAS_MULTI_SELECT -// -#endif // #ifdef IMGUI_HAS_MULTI_SELECT +// Temporary storage for multi-select +struct IMGUI_API ImGuiMultiSelectTempData +{ + ImGuiMultiSelectIO IO; // MUST BE FIRST FIELD. Requests are set and returned by BeginMultiSelect()/EndMultiSelect() + written to by user during the loop. + ImGuiMultiSelectState* Storage; + ImGuiID FocusScopeId; // Copied from g.CurrentFocusScopeId (unless another selection scope was pushed manually) + ImGuiMultiSelectFlags Flags; + ImVec2 ScopeRectMin; + ImVec2 BackupCursorMaxPos; + ImGuiSelectionUserData LastSubmittedItem; // Copy of last submitted item data, used to merge output ranges. + ImGuiID BoxSelectId; + ImGuiKeyChord KeyMods; + ImS8 LoopRequestSetAll; // -1: no operation, 0: clear all, 1: select all. + bool IsEndIO; // Set when switching IO from BeginMultiSelect() to EndMultiSelect() state. + bool IsFocused; // Set if currently focusing the selection scope (any item of the selection). May be used if you have custom shortcut associated to selection. + bool IsKeyboardSetRange; // Set by BeginMultiSelect() when using Shift+Navigation. Because scrolling may be affected we can't afford a frame of lag with Shift+Navigation. + bool NavIdPassedBy; + bool RangeSrcPassedBy; // Set by the item that matches RangeSrcItem. + bool RangeDstPassedBy; // Set by the item that matches NavJustMovedToId when IsSetRange is set. + + ImGuiMultiSelectTempData() { Clear(); } + void Clear() { size_t io_sz = sizeof(IO); ClearIO(); memset((void*)(&IO + 1), 0, sizeof(*this) - io_sz); } // Zero-clear except IO as we preserve IO.Requests[] buffer allocation. + void ClearIO() { IO.Requests.resize(0); IO.RangeSrcItem = IO.NavIdItem = ImGuiSelectionUserData_Invalid; IO.NavIdSelected = IO.RangeSrcReset = false; } +}; + +// Persistent storage for multi-select (as long as selection is alive) +struct IMGUI_API ImGuiMultiSelectState +{ + ImGuiWindow* Window; + ImGuiID ID; + int LastFrameActive; // Last used frame-count, for GC. + int LastSelectionSize; // Set by BeginMultiSelect() based on optional info provided by user. May be -1 if unknown. + ImS8 RangeSelected; // -1 (don't have) or true/false + ImS8 NavIdSelected; // -1 (don't have) or true/false + ImGuiSelectionUserData RangeSrcItem; // + ImGuiSelectionUserData NavIdItem; // SetNextItemSelectionUserData() value for NavId (if part of submitted items) + + ImGuiMultiSelectState() { Window = NULL; ID = 0; LastFrameActive = LastSelectionSize = 0; RangeSelected = NavIdSelected = -1; RangeSrcItem = NavIdItem = ImGuiSelectionUserData_Invalid; } +}; //----------------------------------------------------------------------------- // [SECTION] Docking support @@ -1997,6 +2066,7 @@ enum ImGuiLocKey : int ImGuiLocKey_WindowingMainMenuBar, ImGuiLocKey_WindowingPopup, ImGuiLocKey_WindowingUntitled, + ImGuiLocKey_CopyLink, ImGuiLocKey_DockingHideTabBar, ImGuiLocKey_DockingHoldShiftToDock, ImGuiLocKey_DockingDragToUndockOrMoveNode, @@ -2127,6 +2197,7 @@ struct ImGuiContext ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height. + float FontScale; // == FontSize / Font->FontSize float CurrentDpiScale; // Current window/viewport DpiScale == CurrentViewport->DpiScale ImDrawListSharedData DrawListSharedData; double Time; @@ -2211,11 +2282,9 @@ struct ImGuiContext ImGuiKeyOwnerData KeysOwnerData[ImGuiKey_NamedKey_COUNT]; ImGuiKeyRoutingTable KeysRoutingTable; ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it) - bool ActiveIdUsingAllKeyboardKeys; // Active widget will want to read all keyboard keys inputs. (FIXME: This is a shortcut for not taking ownership of 100+ keys but perhaps best to not have the inconsistency) + bool ActiveIdUsingAllKeyboardKeys; // Active widget will want to read all keyboard keys inputs. (this is a shortcut for not taking ownership of 100+ keys, frequently used by drag operations) ImGuiKeyChord DebugBreakInShortcutRouting; // Set to break in SetShortcutRouting()/Shortcut() calls. -#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO - ImU32 ActiveIdUsingNavInputMask; // If you used this. Since (IMGUI_VERSION_NUM >= 18804) : 'g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);' becomes 'SetKeyOwner(ImGuiKey_Escape, g.ActiveId) and/or SetKeyOwner(ImGuiKey_NavGamepadCancel, g.ActiveId);' -#endif + //ImU32 ActiveIdUsingNavInputMask; // [OBSOLETE] Since (IMGUI_VERSION_NUM >= 18804) : 'g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);' becomes --> 'SetKeyOwner(ImGuiKey_Escape, g.ActiveId) and/or SetKeyOwner(ImGuiKey_NavGamepadCancel, g.ActiveId);' // Next window/item data ImGuiID CurrentFocusScopeId; // Value for currently appending items == g.FocusScopeStack.back(). Not to be mistaken with g.NavFocusScopeId. @@ -2236,7 +2305,7 @@ struct ImGuiContext ImVector GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin() ImVector OpenPopupStack; // Which popups are open (persistent) ImVector BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame) - ImVector NavTreeNodeStack; // Stack for TreeNode() when a NavLeft requested is emitted. + ImVectorTreeNodeStack; // Stack for TreeNode() // Viewports ImVector Viewports; // Active viewports (always 1+, and generally 1 unless multi-viewports are enabled). Each viewports hold their copy of ImDrawData. @@ -2358,6 +2427,13 @@ struct ImGuiContext ImVector CurrentTabBarStack; ImVector ShrinkWidthBuffer; + // Multi-Select state + ImGuiBoxSelectState BoxSelectState; + ImGuiMultiSelectTempData* CurrentMultiSelect; + int MultiSelectTempDataStacked; // Temporary multi-select data size (because we leave previous instances undestructed, we generally don't use MultiSelectTempData.Size) + ImVector MultiSelectTempData; + ImPool MultiSelectStorage; + // Hover Delay system ImGuiID HoverItemDelayId; ImGuiID HoverItemDelayIdPreviousFrame; @@ -2407,7 +2483,7 @@ struct ImGuiContext // Platform support ImGuiPlatformImeData PlatformImeData; // Data updated by current frame - ImGuiPlatformImeData PlatformImeDataPrev; // Previous frame data (when changing we will call io.SetPlatformImeDataFn + ImGuiPlatformImeData PlatformImeDataPrev; // Previous frame data. When changed we call the io.PlatformSetImeDataFn() handler. ImGuiID PlatformImeViewport; // Extensions @@ -2482,7 +2558,7 @@ struct ImGuiContext ConfigFlagsCurrFrame = ConfigFlagsLastFrame = ImGuiConfigFlags_None; FontAtlasOwnedByContext = shared_font_atlas ? false : true; Font = NULL; - FontSize = FontBaseSize = CurrentDpiScale = 0.0f; + FontSize = FontBaseSize = FontScale = CurrentDpiScale = 0.0f; IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)(); Time = 0.0f; FrameCount = 0; @@ -2537,9 +2613,6 @@ struct ImGuiContext ActiveIdUsingNavDirMask = 0x00; ActiveIdUsingAllKeyboardKeys = false; -#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO - ActiveIdUsingNavInputMask = 0x00; -#endif CurrentFocusScopeId = 0; CurrentItemFlags = ImGuiItemFlags_None; @@ -2612,6 +2685,8 @@ struct ImGuiContext CurrentTable = NULL; TablesTempDataStacked = 0; CurrentTabBar = NULL; + CurrentMultiSelect = NULL; + MultiSelectTempDataStacked = 0; HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId = 0; HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f; @@ -2728,7 +2803,7 @@ struct IMGUI_API ImGuiWindowTempData ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs. ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement int TreeDepth; // Current tree depth. - ImU32 TreeJumpToParentOnPopMask; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary. + ImU32 TreeHasStackDataDepthMask; // Store whether given depth has ImGuiTreeNodeStackData data. Could be turned into a ImU64 if necessary. ImVector ChildWindows; ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state) ImGuiOldColumns* CurrentColumns; // Current columns set @@ -3295,6 +3370,7 @@ namespace ImGui inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); } inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); } inline ImVec2 WindowPosRelToAbs(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x + off.x, p.y + off.y); } + inline ImVec2 WindowPosAbsToRel(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x - off.x, p.y - off.y); } // Windows: Display Order and Focus Order IMGUI_API void FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags = 0); @@ -3375,7 +3451,7 @@ namespace ImGui //#endif // Basic Accessors - inline ImGuiItemStatusFlags GetItemStatusFlags(){ ImGuiContext& g = *GImGui; return g.LastItemData.StatusFlags; } + inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.StatusFlags; } inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.InFlags; } inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; } inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; } @@ -3401,13 +3477,9 @@ namespace ImGui IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); IMGUI_API void PushMultiItemsWidths(int components, float width_full); - IMGUI_API bool IsItemToggledSelection(); // Was the last item selection toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly) - IMGUI_API ImVec2 GetContentRegionMaxAbs(); IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess); // Parameter stacks (shared) - 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(); @@ -3456,7 +3528,7 @@ namespace ImGui IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags); IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags); IMGUI_API void NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result); - IMGUI_API void NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiNavTreeNodeData* tree_node_data); + IMGUI_API void NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiTreeNodeStackData* tree_node_data); IMGUI_API void NavMoveRequestCancel(); IMGUI_API void NavMoveRequestApplyResult(); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); @@ -3521,7 +3593,7 @@ namespace ImGui IMGUI_API ImGuiID GetKeyOwner(ImGuiKey key); IMGUI_API void SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API void SetKeyOwnersForKeyChord(ImGuiKeyChord key, ImGuiID owner_id, ImGuiInputFlags flags = 0); - IMGUI_API void SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags = 0); // Set key owner to last item if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'. + IMGUI_API void SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags); // Set key owner to last item if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'. IMGUI_API bool TestKeyOwner(ImGuiKey key, ImGuiID owner_id); // Test that key is either not owned, either owned by 'owner_id' inline ImGuiKeyOwnerData* GetKeyOwnerData(ImGuiContext* ctx, ImGuiKey key) { if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(key); IM_ASSERT(IsNamedKey(key)); return &ctx->KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN]; } @@ -3639,6 +3711,18 @@ namespace ImGui IMGUI_API int TypingSelectFindNextSingleCharMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx); IMGUI_API int TypingSelectFindBestLeadingMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data); + // Box-Select API + IMGUI_API bool BeginBoxSelect(const ImRect& scope_rect, ImGuiWindow* window, ImGuiID box_select_id, ImGuiMultiSelectFlags ms_flags); + IMGUI_API void EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flags); + + // Multi-Select API + IMGUI_API void MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags* p_button_flags); + IMGUI_API void MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed); + IMGUI_API void MultiSelectAddSetAll(ImGuiMultiSelectTempData* ms, bool selected); + IMGUI_API void MultiSelectAddSetRange(ImGuiMultiSelectTempData* ms, bool selected, int range_dir, ImGuiSelectionUserData first_item, ImGuiSelectionUserData last_item); + inline ImGuiBoxSelectState* GetBoxSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.BoxSelectState.ID == id && g.BoxSelectState.IsActive) ? &g.BoxSelectState : NULL; } + inline ImGuiMultiSelectState* GetMultiSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return g.MultiSelectStorage.GetByKey(id); } + // Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API) IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect); IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). @@ -3779,11 +3863,13 @@ namespace ImGui IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags); IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb); IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f, ImU32 bg_col = 0); + + // Widgets: Tree Nodes IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); IMGUI_API void TreePushOverrideID(ImGuiID id); - IMGUI_API void TreeNodeSetOpen(ImGuiID id, bool open); - IMGUI_API bool TreeNodeUpdateNextOpen(ImGuiID id, ImGuiTreeNodeFlags flags); // Return open state. Consume previous SetNextItemOpen() data, if any. May return true when logging. - IMGUI_API void SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data); + IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id); + IMGUI_API void TreeNodeSetOpen(ImGuiID storage_id, bool open); + IMGUI_API bool TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags); // Return open state. Consume previous SetNextItemOpen() data, if any. May return true when logging. // Template functions are instantiated in imgui_widgets.cpp for a finite number of types. // To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036). @@ -3830,12 +3916,8 @@ namespace ImGui IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window); IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window); - // Debug Log - IMGUI_API void DebugLog(const char* fmt, ...) IM_FMTARGS(1); - IMGUI_API void DebugLogV(const char* fmt, va_list args) IM_FMTLIST(1); - IMGUI_API void DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free - // Debug Tools + IMGUI_API void DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckUsingSetCursorPosToExtendParentBoundaries(); @@ -3863,11 +3945,13 @@ namespace ImGui IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings); IMGUI_API void DebugNodeInputTextState(ImGuiInputTextState* state); IMGUI_API void DebugNodeTypingSelectState(ImGuiTypingSelectState* state); + IMGUI_API void DebugNodeMultiSelectState(ImGuiMultiSelectState* state); IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label); IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings); IMGUI_API void DebugNodeWindowsList(ImVector* windows, const char* label); IMGUI_API void DebugNodeWindowsListByBeginStackParent(ImGuiWindow** windows, int windows_size, ImGuiWindow* parent_in_begin_stack); IMGUI_API void DebugNodeViewport(ImGuiViewportP* viewport); + IMGUI_API void DebugNodePlatformMonitor(ImGuiPlatformMonitor* monitor, const char* label, int idx); IMGUI_API void DebugRenderKeyboardPreview(ImDrawList* draw_list); IMGUI_API void DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb); diff --git a/lib/third_party/imgui/imgui/source/imgui.cpp b/lib/third_party/imgui/imgui/source/imgui.cpp index b77693042..21e631708 100644 --- a/lib/third_party/imgui/imgui/source/imgui.cpp +++ b/lib/third_party/imgui/imgui/source/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.9 +// dear imgui, v1.91.0 // (main code and documentation) // Help: @@ -438,6 +438,25 @@ CODE - likewise io.MousePos and GetMousePos() will use OS coordinates. If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos. + - 2024/07/25 (1.91.0) - obsoleted GetContentRegionMax(), GetWindowContentRegionMin() and GetWindowContentRegionMax(). (see #7838 on GitHub for more info) + you should never need those functions. you can do everything with GetCursorScreenPos() and GetContentRegionAvail() in a more simple way. + - instead of: GetWindowContentRegionMax().x - GetCursorPos().x + - you can use: GetContentRegionAvail().x + - instead of: GetWindowContentRegionMax().x + GetWindowPos().x + - you can use: GetCursorScreenPos().x + GetContentRegionAvail().x // when called from left edge of window + - instead of: GetContentRegionMax() + - you can use: GetContentRegionAvail() + GetCursorScreenPos() - GetWindowPos() // right edge in local coordinates + - instead of: GetWindowContentRegionMax().x - GetWindowContentRegionMin().x + - you can use: GetContentRegionAvail() // when called from left edge of window + - 2024/07/15 (1.91.0) - renamed ImGuiSelectableFlags_DontClosePopups to ImGuiSelectableFlags_NoAutoClosePopups. (#1379, #1468, #2200, #4936, #5216, #7302, #7573) + (internals: also renamed ImGuiItemFlags_SelectableDontClosePopup into ImGuiItemFlags_AutoClosePopups with inverted behaviors) + - 2024/07/15 (1.91.0) - obsoleted PushButtonRepeat()/PopButtonRepeat() in favor of using new PushItemFlag(ImGuiItemFlags_ButtonRepeat, ...)/PopItemFlag(). + - 2024/07/02 (1.91.0) - commented out obsolete ImGuiModFlags (renamed to ImGuiKeyChord in 1.89). (#4921, #456) + - commented out obsolete ImGuiModFlags_XXX values (renamed to ImGuiMod_XXX in 1.89). (#4921, #456) + - ImGuiModFlags_Ctrl -> ImGuiMod_Ctrl, ImGuiModFlags_Shift -> ImGuiMod_Shift etc. + - 2024/07/02 (1.91.0) - IO, IME: renamed platform IME hook and added explicit context for consistency and future-proofness. + - old: io.SetPlatformImeDataFn(ImGuiViewport* viewport, ImGuiPlatformImeData* data); + - new: io.PlatformSetImeDataFn(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); - 2024/06/21 (1.90.9) - BeginChild: added ImGuiChildFlags_NavFlattened as a replacement for the window flag ImGuiWindowFlags_NavFlattened: the feature only ever made sense for BeginChild() anyhow. - old: BeginChild("Name", size, 0, ImGuiWindowFlags_NavFlattened); - new: BeginChild("Name", size, ImGuiChildFlags_NavFlattened, 0); @@ -1026,7 +1045,7 @@ CODE #endif // [Windows] OS specific includes (optional) -#if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) +#if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && defined(IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) #define IMGUI_DISABLE_WIN32_FUNCTIONS #endif #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) @@ -1045,6 +1064,7 @@ CODE // The UWP and GDK Win32 API subsets don't support clipboard nor IME functions #define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS #define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS +#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS #endif #endif @@ -1097,7 +1117,7 @@ CODE #endif // Debug options -#define IMGUI_DEBUG_NAV_SCORING 0 // Display navigation scoring preview when hovering items. Display last moving direction matches when holding CTRL +#define IMGUI_DEBUG_NAV_SCORING 0 // Display navigation scoring preview when hovering items. Hold CTRL to display for all candidates. CTRL+Arrow to change last direction. #define IMGUI_DEBUG_NAV_RECTS 0 // Display the reference navigation rectangle for each window // When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch. @@ -1137,7 +1157,8 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSetti // Platform Dependents default implementation for IO functions static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx); static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text); -static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatformImeData* data); +static void PlatformSetImeDataFn_DefaultImpl(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); +static bool PlatformOpenInShellFn_DefaultImpl(ImGuiContext* ctx, const char* path); namespace ImGui { @@ -1284,12 +1305,13 @@ ImGuiStyle::ImGuiStyle() TabBorderSize = 0.0f; // Thickness of border around tabs. TabMinWidthForCloseButton = 0.0f; // Minimum width for close button to appear on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected. TabBarBorderSize = 1.0f; // Thickness of tab-bar separator, which takes on the tab active color to denote focus. + TabBarOverlineSize = 2.0f; // Thickness of tab-bar overline, which highlights the selected tab-bar. TableAngledHeadersAngle = 35.0f * (IM_PI / 180.0f); // Angle of angled headers (supported values range from -50 degrees to +50 degrees). TableAngledHeadersTextAlign = ImVec2(0.5f,0.0f);// Alignment of angled headers within the cell ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right. ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text. SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line. - SeparatorTextBorderSize = 3.0f; // Thickkness of border in SeparatorText() + SeparatorTextBorderSize = 3.0f; // Thickness of border in SeparatorText() SeparatorTextAlign = ImVec2(0.0f,0.5f);// Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center). SeparatorTextPadding = ImVec2(20.0f,3.f);// Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y. DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows. @@ -1340,6 +1362,7 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor) LogSliderDeadzone = ImTrunc(LogSliderDeadzone * scale_factor); TabRounding = ImTrunc(TabRounding * scale_factor); TabMinWidthForCloseButton = (TabMinWidthForCloseButton != FLT_MAX) ? ImTrunc(TabMinWidthForCloseButton * scale_factor) : FLT_MAX; + TabBarOverlineSize = ImTrunc(TabBarOverlineSize * scale_factor); SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor); DockingSeparatorSize = ImTrunc(DockingSeparatorSize * scale_factor); DisplayWindowPadding = ImTrunc(DisplayWindowPadding * scale_factor); @@ -1392,6 +1415,7 @@ ImGuiIO::ImGuiIO() #else ConfigMacOSXBehaviors = false; #endif + ConfigNavSwapGamepadButtons = false; ConfigInputTrickleEventQueue = true; ConfigInputTextCursorBlink = true; ConfigInputTextEnterKeepActive = false; @@ -1413,6 +1437,7 @@ ImGuiIO::ImGuiIO() // Note: Initialize() will setup default clipboard/ime handlers. BackendPlatformName = BackendRendererName = NULL; BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL; + PlatformOpenInShellUserData = NULL; PlatformLocaleDecimalPoint = '.'; // Input (NB: we already have memset zero the entire structure!) @@ -2110,6 +2135,10 @@ void ImFormatStringToTempBuffer(const char** out_buf, const char** out_buf_end, va_end(args); } +// FIXME: Should rework API toward allowing multiple in-flight temp buffers (easier and safer for caller) +// by making the caller acquire a temp buffer token, with either explicit or destructor release, e.g. +// ImGuiTempBufferToken token; +// ImFormatStringToTempBuffer(token, ...); void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end, const char* fmt, va_list args) { ImGuiContext& g = *GImGui; @@ -2607,6 +2636,7 @@ ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStoragePair* in_ return in_p; } +IM_MSVC_RUNTIME_CHECKS_OFF static int IMGUI_CDECL PairComparerByID(const void* lhs, const void* rhs) { // We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that. @@ -2624,7 +2654,7 @@ void ImGuiStorage::BuildSortByKey() int ImGuiStorage::GetInt(ImGuiID key, int default_val) const { ImGuiStoragePair* it = ImLowerBound(const_cast(Data.Data), const_cast(Data.Data + Data.Size), key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) return default_val; return it->val_i; } @@ -2637,7 +2667,7 @@ bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const { ImGuiStoragePair* it = ImLowerBound(const_cast(Data.Data), const_cast(Data.Data + Data.Size), key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) return default_val; return it->val_f; } @@ -2645,7 +2675,7 @@ float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const void* ImGuiStorage::GetVoidPtr(ImGuiID key) const { ImGuiStoragePair* it = ImLowerBound(const_cast(Data.Data), const_cast(Data.Data + Data.Size), key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) return NULL; return it->val_p; } @@ -2654,7 +2684,7 @@ void* ImGuiStorage::GetVoidPtr(ImGuiID key) const int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val) { ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) it = Data.insert(it, ImGuiStoragePair(key, default_val)); return &it->val_i; } @@ -2667,7 +2697,7 @@ bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val) float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val) { ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) it = Data.insert(it, ImGuiStoragePair(key, default_val)); return &it->val_f; } @@ -2675,7 +2705,7 @@ float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val) void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val) { ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) it = Data.insert(it, ImGuiStoragePair(key, default_val)); return &it->val_p; } @@ -2684,7 +2714,7 @@ void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val) void ImGuiStorage::SetInt(ImGuiID key, int val) { ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) Data.insert(it, ImGuiStoragePair(key, val)); else it->val_i = val; @@ -2698,7 +2728,7 @@ void ImGuiStorage::SetBool(ImGuiID key, bool val) void ImGuiStorage::SetFloat(ImGuiID key, float val) { ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) Data.insert(it, ImGuiStoragePair(key, val)); else it->val_f = val; @@ -2707,7 +2737,7 @@ void ImGuiStorage::SetFloat(ImGuiID key, float val) void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val) { ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) Data.insert(it, ImGuiStoragePair(key, val)); else it->val_p = val; @@ -2718,6 +2748,7 @@ void ImGuiStorage::SetAllInt(int v) for (int i = 0; i < Data.Size; i++) Data[i].val_i = v; } +IM_MSVC_RUNTIME_CHECKS_RESTORE //----------------------------------------------------------------------------- // [SECTION] ImGuiTextFilter @@ -2785,15 +2816,15 @@ void ImGuiTextFilter::Build() bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const { - if (Filters.empty()) + if (Filters.Size == 0) return true; if (text == NULL) - text = ""; + text = text_end = ""; for (const ImGuiTextRange& f : Filters) { - if (f.empty()) + if (f.b == f.e) continue; if (f.b[0] == '-') { @@ -2960,15 +2991,6 @@ static void ImGuiListClipper_SeekCursorAndSetupPrevLine(float pos_y, float line_ } } -static void ImGuiListClipper_SeekCursorForItem(ImGuiListClipper* clipper, int item_n) -{ - // StartPosY starts from ItemsFrozen hence the subtraction - // Perform the add and multiply with double to allow seeking through larger ranges - ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData; - float pos_y = (float)((double)clipper->StartPosY + data->LossynessOffset + (double)(item_n - data->ItemsFrozen) * clipper->ItemsHeight); - ImGuiListClipper_SeekCursorAndSetupPrevLine(pos_y, clipper->ItemsHeight); -} - ImGuiListClipper::ImGuiListClipper() { memset(this, 0, sizeof(*this)); @@ -3005,6 +3027,7 @@ void ImGuiListClipper::Begin(int items_count, float items_height) data->Reset(this); data->LossynessOffset = window->DC.CursorStartPosLossyness.y; TempData = data; + StartSeekOffsetY = data->LossynessOffset; } void ImGuiListClipper::End() @@ -3015,7 +3038,7 @@ void ImGuiListClipper::End() ImGuiContext& g = *Ctx; IMGUI_DEBUG_LOG_CLIPPER("Clipper: End() in '%s'\n", g.CurrentWindow->Name); if (ItemsCount >= 0 && ItemsCount < INT_MAX && DisplayStart >= 0) - ImGuiListClipper_SeekCursorForItem(this, ItemsCount); + SeekCursorForItem(ItemsCount); // Restore temporary buffer and fix back pointers which may be invalidated when nesting IM_ASSERT(data->ListClipper == this); @@ -3039,6 +3062,17 @@ void ImGuiListClipper::IncludeItemsByIndex(int item_begin, int item_end) data->Ranges.push_back(ImGuiListClipperRange::FromIndices(item_begin, item_end)); } +// This is already called while stepping. +// The ONLY reason you may want to call this is if you passed INT_MAX to ImGuiListClipper::Begin() because you couldn't step item count beforehand. +void ImGuiListClipper::SeekCursorForItem(int item_n) +{ + // - Perform the add and multiply with double to allow seeking through larger ranges. + // - StartPosY starts from ItemsFrozen, by adding SeekOffsetY we generally cancel that out (SeekOffsetY == LossynessOffset - ItemsFrozen * ItemsHeight). + // - The reason we store SeekOffsetY instead of inferring it, is because we want to allow user to perform Seek after the last step, where ImGuiListClipperData is already done. + float pos_y = (float)((double)StartPosY + StartSeekOffsetY + (double)item_n * ItemsHeight); + ImGuiListClipper_SeekCursorAndSetupPrevLine(pos_y, ItemsHeight); +} + static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper) { ImGuiContext& g = *clipper->Ctx; @@ -3093,7 +3127,8 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper) bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision(clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y); if (affected_by_floating_point_precision) clipper->ItemsHeight = window->DC.PrevLineSize.y + g.Style.ItemSpacing.y; // FIXME: Technically wouldn't allow multi-line entries. - + if (clipper->ItemsHeight == 0.0f && clipper->ItemsCount == INT_MAX) // Accept that no item have been submitted if in indeterminate mode. + return false; IM_ASSERT(clipper->ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!"); calc_clipping = true; // If item height had to be calculated, calculate clipping afterwards. } @@ -3102,6 +3137,9 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper) const int already_submitted = clipper->DisplayEnd; if (calc_clipping) { + // Record seek offset, this is so ImGuiListClipper::Seek() can be called after ImGuiListClipperData is done + clipper->StartSeekOffsetY = (double)data->LossynessOffset - data->ItemsFrozen * (double)clipper->ItemsHeight; + if (g.LogEnabled) { // If logging is active, do not perform any clipping @@ -3122,9 +3160,27 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper) data->Ranges.push_back(ImGuiListClipperRange::FromPositions(nav_rect_abs.Min.y, nav_rect_abs.Max.y, 0, 0)); // Add visible range + float min_y = window->ClipRect.Min.y; + float max_y = window->ClipRect.Max.y; + + // Add box selection range + ImGuiBoxSelectState* bs = &g.BoxSelectState; + if (bs->IsActive && bs->Window == window) + { + // FIXME: Selectable() use of half-ItemSpacing isn't consistent in matter of layout, as ItemAdd(bb) stray above ItemSize()'s CursorPos. + // RangeSelect's BoxSelect relies on comparing overlap of previous and current rectangle and is sensitive to that. + // As a workaround we currently half ItemSpacing worth on each side. + min_y -= g.Style.ItemSpacing.y; + max_y += g.Style.ItemSpacing.y; + + // Box-select on 2D area requires different clipping. + if (bs->UnclipMode) + data->Ranges.push_back(ImGuiListClipperRange::FromPositions(bs->UnclipRect.Min.y, bs->UnclipRect.Max.y, 0, 0)); + } + const int off_min = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Up) ? -1 : 0; const int off_max = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Down) ? 1 : 0; - data->Ranges.push_back(ImGuiListClipperRange::FromPositions(window->ClipRect.Min.y, window->ClipRect.Max.y, off_min, off_max)); + data->Ranges.push_back(ImGuiListClipperRange::FromPositions(min_y, max_y, off_min, off_max)); } // Convert position ranges to item index ranges @@ -3149,7 +3205,7 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper) clipper->DisplayStart = ImMax(data->Ranges[data->StepNo].Min, already_submitted); clipper->DisplayEnd = ImMin(data->Ranges[data->StepNo].Max, clipper->ItemsCount); if (clipper->DisplayStart > already_submitted) //-V1051 - ImGuiListClipper_SeekCursorForItem(clipper, clipper->DisplayStart); + clipper->SeekCursorForItem(clipper->DisplayStart); data->StepNo++; if (clipper->DisplayStart == clipper->DisplayEnd && data->StepNo < data->Ranges.Size) continue; @@ -3159,7 +3215,7 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper) // After the last step: Let the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), // Advance the cursor to the end of the list and then returns 'false' to end the loop. if (clipper->ItemsCount < INT_MAX) - ImGuiListClipper_SeekCursorForItem(clipper, clipper->ItemsCount); + clipper->SeekCursorForItem(clipper->ItemsCount); return false; } @@ -3302,6 +3358,7 @@ static const ImGuiDataVarInfo GStyleVarInfo[] = { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBorderSize) }, // ImGuiStyleVar_TabBorderSize { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBarBorderSize) }, // ImGuiStyleVar_TabBarBorderSize + { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBarOverlineSize) }, // ImGuiStyleVar_TabBarOverlineSize { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersAngle)}, // ImGuiStyleVar_TableAngledHeadersAngle { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersTextAlign)},// ImGuiStyleVar_TableAngledHeadersTextAlign { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign @@ -3424,6 +3481,7 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx) case ImGuiCol_TableBorderLight: return "TableBorderLight"; case ImGuiCol_TableRowBg: return "TableRowBg"; case ImGuiCol_TableRowBgAlt: return "TableRowBgAlt"; + case ImGuiCol_TextLink: return "TextLink"; case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; case ImGuiCol_DragDropTarget: return "DragDropTarget"; case ImGuiCol_NavHighlight: return "NavHighlight"; @@ -3570,7 +3628,7 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con const ImFont* font = draw_list->_Data->Font; const float font_size = draw_list->_Data->FontSize; - const float font_scale = font_size / font->FontSize; + const float font_scale = draw_list->_Data->FontScale; const char* text_end_ellipsis = NULL; const float ellipsis_width = font->EllipsisWidth * font_scale; @@ -3747,7 +3805,7 @@ void ImGui::DestroyContext(ImGuiContext* ctx) IM_DELETE(ctx); } -// IMPORTANT: ###xxx suffixes must be same in ALL languages +// IMPORTANT: ###xxx suffixes must be same in ALL languages to allow for automation. static const ImGuiLocEntry GLocalizationEntriesEnUS[] = { { ImGuiLocKey_VersionStr, "Dear ImGui " IMGUI_VERSION " (" IM_STRINGIFY(IMGUI_VERSION_NUM) ")" }, @@ -3758,6 +3816,7 @@ static const ImGuiLocEntry GLocalizationEntriesEnUS[] = { ImGuiLocKey_WindowingMainMenuBar, "(Main menu bar)" }, { ImGuiLocKey_WindowingPopup, "(Popup)" }, { ImGuiLocKey_WindowingUntitled, "(Untitled)" }, + { ImGuiLocKey_CopyLink, "Copy Link###CopyLink" }, { ImGuiLocKey_DockingHideTabBar, "Hide tab bar###HideTabBar" }, { ImGuiLocKey_DockingHoldShiftToDock, "Hold SHIFT to enable Docking window." }, { ImGuiLocKey_DockingDragToUndockOrMoveNode,"Click and drag to move or undock whole node." }, @@ -3789,7 +3848,8 @@ void ImGui::Initialize() g.IO.GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations g.IO.SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; g.IO.ClipboardUserData = (void*)&g; // Default implementation use the ImGuiContext as user data (ideally those would be arguments to the function) - g.IO.SetPlatformImeDataFn = SetPlatformImeDataFn_DefaultImpl; + g.IO.PlatformOpenInShellFn = PlatformOpenInShellFn_DefaultImpl; + g.IO.PlatformSetImeDataFn = PlatformSetImeDataFn_DefaultImpl; // Create default viewport ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)(); @@ -3869,7 +3929,7 @@ void ImGui::Shutdown() g.FontStack.clear(); g.OpenPopupStack.clear(); g.BeginPopupStack.clear(); - g.NavTreeNodeStack.clear(); + g.TreeNodeStack.clear(); g.CurrentViewport = g.MouseViewport = g.MouseLastHoveredViewport = NULL; g.Viewports.clear_delete(); @@ -3884,6 +3944,9 @@ void ImGui::Shutdown() g.TablesTempData.clear_destruct(); g.DrawChannelsTempMergeBuffer.clear(); + g.MultiSelectStorage.Clear(); + g.MultiSelectTempData.clear_destruct(); + g.ClipboardHandlerData.clear(); g.MenusIdSubmittedThisFrame.clear(); g.InputTextState.ClearFreeMemory(); @@ -3989,6 +4052,7 @@ static void SetCurrentWindow(ImGuiWindow* window) if (window) { g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); + g.FontScale = g.FontSize / g.Font->FontSize; ImGui::NavUpdateCurrentWindowIsScrollPushableX(); } } @@ -3998,6 +4062,8 @@ void ImGui::GcCompactTransientMiscBuffers() ImGuiContext& g = *GImGui; g.ItemFlagsStack.clear(); g.GroupStack.clear(); + g.MultiSelectTempDataStacked = 0; + g.MultiSelectTempData.clear_destruct(); TableGcCompactSettings(); } @@ -4082,9 +4148,6 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) // (Please note that this is WIP and not all keys/inputs are thoroughly declared by all widgets yet) g.ActiveIdUsingNavDirMask = 0x00; g.ActiveIdUsingAllKeyboardKeys = false; -#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO - g.ActiveIdUsingNavInputMask = 0x00; -#endif } void ImGui::ClearActiveID() @@ -4122,7 +4185,7 @@ void ImGui::MarkItemEdited(ImGuiID id) // We accept a MarkItemEdited() on drag and drop targets (see https://github.com/ocornut/imgui/issues/1875#issuecomment-978243343) // We accept 'ActiveIdPreviousFrame == id' for InputText() returning an edit after it has been taken ActiveId away (#4714) - IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id); + IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive)); //IM_ASSERT(g.CurrentWindow->DC.LastItemId == id); g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited; @@ -4938,25 +5001,8 @@ void ImGui::NewFrame() { g.ActiveIdUsingNavDirMask = 0x00; g.ActiveIdUsingAllKeyboardKeys = false; -#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO - g.ActiveIdUsingNavInputMask = 0x00; -#endif } -#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO - if (g.ActiveId == 0) - g.ActiveIdUsingNavInputMask = 0; - else if (g.ActiveIdUsingNavInputMask != 0) - { - // If your custom widget code used: { g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel); } - // Since IMGUI_VERSION_NUM >= 18804 it should be: { SetKeyOwner(ImGuiKey_Escape, g.ActiveId); SetKeyOwner(ImGuiKey_NavGamepadCancel, g.ActiveId); } - if (g.ActiveIdUsingNavInputMask & (1 << ImGuiNavInput_Cancel)) - SetKeyOwner(ImGuiKey_Escape, g.ActiveId); - if (g.ActiveIdUsingNavInputMask & ~(1 << ImGuiNavInput_Cancel)) - IM_ASSERT(0); // Other values unsupported - } -#endif - // Record when we have been stationary as this state is preserved while over same item. // FIXME: The way this is expressed means user cannot alter HoverStationaryDelay during the frame to use varying values. // To allow this we should store HoverItemMaxStationaryTime+ID and perform the >= check in IsItemHovered() function. @@ -5075,7 +5121,8 @@ void ImGui::NewFrame() g.CurrentWindowStack.resize(0); g.BeginPopupStack.resize(0); g.ItemFlagsStack.resize(0); - g.ItemFlagsStack.push_back(ImGuiItemFlags_None); + g.ItemFlagsStack.push_back(ImGuiItemFlags_AutoClosePopups); // Default flags + g.CurrentItemFlags = g.ItemFlagsStack.back(); g.GroupStack.resize(0); // Docking @@ -5377,13 +5424,13 @@ void ImGui::EndFrame() // Notify Platform/OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) ImGuiPlatformImeData* ime_data = &g.PlatformImeData; - if (g.IO.SetPlatformImeDataFn && memcmp(ime_data, &g.PlatformImeDataPrev, sizeof(ImGuiPlatformImeData)) != 0) + if (g.IO.PlatformSetImeDataFn != NULL && memcmp(ime_data, &g.PlatformImeDataPrev, sizeof(ImGuiPlatformImeData)) != 0) { ImGuiViewport* viewport = FindViewportByID(g.PlatformImeViewport); - IMGUI_DEBUG_LOG_IO("[io] Calling io.SetPlatformImeDataFn(): WantVisible: %d, InputPos (%.2f,%.2f)\n", ime_data->WantVisible, ime_data->InputPos.x, ime_data->InputPos.y); + IMGUI_DEBUG_LOG_IO("[io] Calling io.PlatformSetImeDataFn(): WantVisible: %d, InputPos (%.2f,%.2f)\n", ime_data->WantVisible, ime_data->InputPos.x, ime_data->InputPos.y); if (viewport == NULL) viewport = GetMainViewport(); - g.IO.SetPlatformImeDataFn(viewport, ime_data); + g.IO.PlatformSetImeDataFn(&g, viewport, ime_data); } // Hide implicit/fallback "Debug" window if it hasn't been used @@ -5691,9 +5738,15 @@ bool ImGui::IsItemToggledOpen() return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true : false; } +// Call after a Selectable() or TreeNode() involved in multi-selection. +// Useful if you need the per-item information before reaching EndMultiSelect(), e.g. for rendering purpose. +// This is only meant to be called inside a BeginMultiSelect()/EndMultiSelect() block. +// (Outside of multi-select, it would be misleading/ambiguous to report this signal, as widgets +// return e.g. a pressed event and user code is in charge of altering selection in ways we cannot predict.) bool ImGui::IsItemToggledSelection() { ImGuiContext& g = *GImGui; + IM_ASSERT(g.CurrentMultiSelect != NULL); // Can only be used inside a BeginMultiSelect()/EndMultiSelect() return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true : false; } @@ -5753,7 +5806,8 @@ void ImGui::SetItemAllowOverlap() } #endif -// FIXME: It might be undesirable that this will likely disable KeyOwner-aware shortcuts systems. Consider a more fine-tuned version for the two users of this function. +// This is a shortcut for not taking ownership of 100+ keys, frequently used by drag operations. +// FIXME: It might be undesirable that this will likely disable KeyOwner-aware shortcuts systems. Consider a more fine-tuned version if needed? void ImGui::SetActiveIdUsingAllKeyboardKeys() { ImGuiContext& g = *GImGui; @@ -7634,7 +7688,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.MenuBarAppending = false; window->DC.MenuColumns.Update(style.ItemSpacing.x, window_just_activated_by_user); window->DC.TreeDepth = 0; - window->DC.TreeJumpToParentOnPopMask = 0x00; + window->DC.TreeHasStackDataDepthMask = 0x00; window->DC.ChildWindows.resize(0); window->DC.StateStorage = &window->StateStorage; window->DC.CurrentColumns = NULL; @@ -8090,12 +8144,14 @@ void ImGui::SetCurrentFont(ImFont* font) g.Font = font; g.FontBaseSize = ImMax(1.0f, g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale); g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f; + g.FontScale = g.FontSize / g.Font->FontSize; ImFontAtlas* atlas = g.Font->ContainerAtlas; g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel; g.DrawListSharedData.TexUvLines = atlas->TexUvLines; g.DrawListSharedData.Font = g.Font; g.DrawListSharedData.FontSize = g.FontSize; + g.DrawListSharedData.FontScale = g.FontScale; g.DrawListSharedData.ShadowRectIds = &atlas->ShadowRectIds[0]; g.DrawListSharedData.ShadowRectUvs = &atlas->ShadowRectUvs[0]; } @@ -8196,26 +8252,6 @@ void ImGui::EndDisabledOverrideReenable() g.Style.Alpha = g.DisabledAlphaBackup * g.Style.DisabledAlpha; } -void ImGui::PushTabStop(bool tab_stop) -{ - PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); -} - -void ImGui::PopTabStop() -{ - PopItemFlag(); -} - -void ImGui::PushButtonRepeat(bool repeat) -{ - PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat); -} - -void ImGui::PopButtonRepeat() -{ - PopItemFlag(); -} - void ImGui::PushTextWrapPos(float wrap_pos_x) { ImGuiWindow* window = GetCurrentWindow(); @@ -8696,6 +8732,7 @@ void ImGui::SetWindowFontScale(float scale) ImGuiWindow* window = GetCurrentWindow(); window->FontWindowScale = scale; g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); + g.FontScale = g.DrawListSharedData.FontScale = g.FontSize / g.Font->FontSize; } void ImGui::PushFocusScope(ImGuiID id) @@ -8856,6 +8893,7 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) // This is one of the very rare legacy case where we use ImGuiWindow methods, // it should ideally be flattened at some point but it's been used a lots by widgets. +IM_MSVC_RUNTIME_CHECKS_OFF ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) { ImGuiID seed = IDStack.back(); @@ -8995,6 +9033,13 @@ ImGuiID ImGui::GetID(const void* ptr_id) return window->GetID(ptr_id); } +ImGuiID ImGui::GetID(int int_id) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->GetID(int_id); +} +IM_MSVC_RUNTIME_CHECKS_RESTORE + //----------------------------------------------------------------------------- // [SECTION] INPUTS //----------------------------------------------------------------------------- @@ -10422,6 +10467,11 @@ void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags) } } +void ImGui::SetItemKeyOwner(ImGuiKey key) +{ + SetItemKeyOwner(key, ImGuiInputFlags_None); +} + // This is the only public API until we expose owner_id versions of the API as replacements. bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord) { @@ -10748,6 +10798,11 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'", window->Name); EndTabBar(); } + while (g.CurrentMultiSelect != NULL && g.CurrentMultiSelect->Storage->Window == window) + { + if (log_callback) log_callback(user_data, "Recovered from missing EndMultiSelect() in '%s'", window->Name); + EndMultiSelect(); + } while (window->DC.TreeDepth > 0) { if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'", window->Name); @@ -10971,9 +11026,7 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE // - GetFrameHeight() // - GetFrameHeightWithSpacing() // - GetContentRegionMax() -// - GetContentRegionMaxAbs() [Internal] // - GetContentRegionAvail(), -// - GetWindowContentRegionMin(), GetWindowContentRegionMax() // - BeginGroup() // - EndGroup() // Also see in imgui_widgets: tab bars, and in imgui_tables: tables, columns. @@ -11189,8 +11242,8 @@ float ImGui::CalcItemWidth() w = window->DC.ItemWidth; if (w < 0.0f) { - float region_max_x = GetContentRegionMaxAbs().x; - w = ImMax(1.0f, region_max_x - window->DC.CursorPos.x + w); + float region_avail_x = GetContentRegionAvail().x; + w = ImMax(1.0f, region_avail_x + w); } w = IM_TRUNC(w); return w; @@ -11202,22 +11255,19 @@ float ImGui::CalcItemWidth() // The 4.0f here may be changed to match CalcItemWidth() and/or BeginChild() (right now we have a mismatch which is harmless but undesirable) ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_w, float default_h) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - ImVec2 region_max; + ImVec2 avail; if (size.x < 0.0f || size.y < 0.0f) - region_max = GetContentRegionMaxAbs(); + avail = GetContentRegionAvail(); if (size.x == 0.0f) size.x = default_w; else if (size.x < 0.0f) - size.x = ImMax(4.0f, region_max.x - window->DC.CursorPos.x + size.x); + size.x = ImMax(4.0f, avail.x + size.x); // <-- size.x is negative here so we are subtracting if (size.y == 0.0f) size.y = default_h; else if (size.y < 0.0f) - size.y = ImMax(4.0f, region_max.y - window->DC.CursorPos.y + size.y); + size.y = ImMax(4.0f, avail.y + size.y); // <-- size.y is negative here so we are subtracting return size; } @@ -11246,33 +11296,23 @@ float ImGui::GetFrameHeightWithSpacing() return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y; } -// FIXME: All the Contents Region function are messy or misleading. WE WILL AIM TO OBSOLETE ALL OF THEM WITH A NEW "WORK RECT" API. Thanks for your patience! - -// FIXME: This is in window space (not screen space!). -ImVec2 ImGui::GetContentRegionMax() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImVec2 mx = (window->DC.CurrentColumns || g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max; - return mx - window->Pos; -} - -// [Internal] Absolute coordinate. Saner. This is not exposed until we finishing refactoring work rect features. -ImVec2 ImGui::GetContentRegionMaxAbs() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImVec2 mx = (window->DC.CurrentColumns || g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max; - return mx; -} - ImVec2 ImGui::GetContentRegionAvail() { - ImGuiWindow* window = GImGui->CurrentWindow; - return GetContentRegionMaxAbs() - window->DC.CursorPos; + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + ImVec2 mx = (window->DC.CurrentColumns || g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max; + return mx - window->DC.CursorPos; +} + +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + +// You should never need those functions. Always use GetCursorScreenPos() and GetContentRegionAvail()! +// They are bizarre local-coordinates which don't play well with scrolling. +ImVec2 ImGui::GetContentRegionMax() +{ + return GetContentRegionAvail() + GetCursorScreenPos() - GetWindowPos(); } -// In window space (not screen space!) ImVec2 ImGui::GetWindowContentRegionMin() { ImGuiWindow* window = GImGui->CurrentWindow; @@ -11284,6 +11324,7 @@ ImVec2 ImGui::GetWindowContentRegionMax() ImGuiWindow* window = GImGui->CurrentWindow; return window->ContentRegionRect.Max - window->Pos; } +#endif // Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) // Groups are currently a mishmash of functionalities which should perhaps be clarified and separated. @@ -11329,11 +11370,11 @@ void ImGui::EndGroup() if (window->DC.IsSetPos) ErrorCheckUsingSetCursorPosToExtendParentBoundaries(); - ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos)); - + // Include LastItemData.Rect.Max as a workaround for e.g. EndTable() undershooting with CursorMaxPos report. (#7543) + ImRect group_bb(group_data.BackupCursorPos, ImMax(ImMax(window->DC.CursorMaxPos, g.LastItemData.Rect.Max), group_data.BackupCursorPos)); window->DC.CursorPos = group_data.BackupCursorPos; window->DC.CursorPosPrevLine = group_data.BackupCursorPosPrevLine; - window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos); + window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, group_bb.Max); window->DC.Indent = group_data.BackupIndent; window->DC.GroupOffset = group_data.BackupGroupOffset; window->DC.CurrLineSize = group_data.BackupCurrLineSize; @@ -11348,7 +11389,7 @@ void ImGui::EndGroup() return; } - window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now. + window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now. ItemSize(group_bb.GetSize()); ItemAdd(group_bb, 0, NULL, ImGuiItemFlags_NoTabStop); @@ -12421,6 +12462,9 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result) if (dbx != 0.0f || dby != 0.0f) { // For non-overlapping boxes, use distance between boxes + // FIXME-NAV: Quadrant may be incorrect because of (1) dbx bias and (2) curr.Max.y bias applied by NavBiasScoringRect() where typically curr.Max.y==curr.Min.y + // One typical case where this happens, with style.WindowMenuButtonPosition == ImGuiDir_Right, pressing Left to navigate from Close to Collapse tends to fail. + // Also see #6344. Calling ImGetDirQuadrantFromDelta() with unbiased values may be good but side-effects are plenty. dax = dbx; day = dby; dist_axial = dist_box; @@ -12699,6 +12743,7 @@ void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavM { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindow != NULL); + //IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequestSubmit: dir %c, window \"%s\"\n", "-WENS"[move_dir + 1], g.NavWindow->Name); if (move_flags & ImGuiNavMoveFlags_IsTabbing) move_flags |= ImGuiNavMoveFlags_AllowCurrentNavId; @@ -12728,7 +12773,7 @@ void ImGui::NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result) } // Called by TreePop() to implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere -void ImGui::NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiNavTreeNodeData* tree_node_data) +void ImGui::NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiTreeNodeStackData* tree_node_data) { ImGuiContext& g = *GImGui; g.NavMoveScoringItems = false; @@ -12951,6 +12996,7 @@ static void ImGui::NavUpdate() // Process navigation init request (select first/default focus) g.NavJustMovedToId = 0; + g.NavJustMovedToFocusScopeId = g.NavJustMovedFromFocusScopeId = 0; if (g.NavInitResult.ID != 0) NavInitRequestApplyResult(); g.NavInitRequest = false; @@ -13103,6 +13149,7 @@ void ImGui::NavInitRequestApplyResult() ImGuiNavItemData* result = &g.NavInitResult; if (g.NavId != result->ID) { + g.NavJustMovedFromFocusScopeId = g.NavFocusScopeId; g.NavJustMovedToId = result->ID; g.NavJustMovedToFocusScopeId = result->FocusScopeId; g.NavJustMovedToKeyMods = 0; @@ -13361,6 +13408,7 @@ void ImGui::NavMoveRequestApplyResult() // PageUp/PageDown however sets always set NavJustMovedTo (vs Home/End which doesn't) mimicking Windows behavior. if ((g.NavId != result->ID || (g.NavMoveFlags & ImGuiNavMoveFlags_IsPageMove)) && (g.NavMoveFlags & ImGuiNavMoveFlags_NoSelect) == 0) { + g.NavJustMovedFromFocusScopeId = g.NavFocusScopeId; g.NavJustMovedToId = result->ID; g.NavJustMovedToFocusScopeId = result->FocusScopeId; g.NavJustMovedToKeyMods = g.NavMoveKeyMods; @@ -14129,7 +14177,7 @@ bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id) IM_ASSERT(g.DragDropWithinTarget == false && g.DragDropWithinSource == false); // Can't nest BeginDragDropSource() and BeginDragDropTarget() g.DragDropTargetRect = bb; - g.DragDropTargetClipRect = window->ClipRect; // May want to be overriden by user depending on use case? + g.DragDropTargetClipRect = window->ClipRect; // May want to be overridden by user depending on use case? g.DragDropTargetId = id; g.DragDropWithinTarget = true; return true; @@ -14482,10 +14530,10 @@ void ImGui::LogButtons() #endif const bool log_to_file = Button("Log To File"); SameLine(); const bool log_to_clipboard = Button("Log To Clipboard"); SameLine(); - PushTabStop(false); + PushItemFlag(ImGuiItemFlags_NoTabStop, true); SetNextItemWidth(80.0f); SliderInt("Default Depth", &g.LogDepthToExpandDefault, 0, 9, NULL); - PopTabStop(); + PopItemFlag(); PopID(); // Start logging at the end of the function so that the buttons don't appear in the log @@ -15265,6 +15313,10 @@ static void ImGui::UpdateViewportsNewFrame() g.PlatformMonitorsFullWorkRect.Add(monitor->WorkPos); g.PlatformMonitorsFullWorkRect.Add(monitor->WorkPos + monitor->WorkSize); } + else + { + g.FallbackMonitor = g.PlatformIO.Monitors[0]; + } for (ImGuiPlatformMonitor& monitor : g.PlatformIO.Monitors) { g.PlatformMonitorsFullWorkRect.Add(monitor.WorkPos); @@ -19846,6 +19898,10 @@ static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettings //----------------------------------------------------------------------------- // [SECTION] PLATFORM DEPENDENT HELPERS //----------------------------------------------------------------------------- +// - Default clipboard handlers +// - Default shell function handlers +// - Default IME handlers +//----------------------------------------------------------------------------- #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) @@ -19971,8 +20027,62 @@ static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text g.ClipboardHandlerData[(int)(text_end - text)] = 0; } +#endif // Default clipboard handlers + +//----------------------------------------------------------------------------- + +#ifndef IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS +#if defined(__APPLE__) && TARGET_OS_IPHONE +#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS #endif +#if defined(_WIN32) && defined(IMGUI_DISABLE_WIN32_FUNCTIONS) +#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS +#endif +#endif + +#ifndef IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS +#ifdef _WIN32 +#include // ShellExecuteA() +#ifdef _MSC_VER +#pragma comment(lib, "shell32") +#endif +static bool PlatformOpenInShellFn_DefaultImpl(ImGuiContext*, const char* path) +{ + return (INT_PTR)::ShellExecuteA(NULL, "open", path, NULL, NULL, SW_SHOWDEFAULT) > 32; +} +#else +#include +#include +static bool PlatformOpenInShellFn_DefaultImpl(ImGuiContext*, const char* path) +{ +#if defined(__APPLE__) + const char* args[] { "open", "--", path, NULL }; +#else + const char* args[] { "xdg-open", path, NULL }; +#endif + pid_t pid = fork(); + if (pid < 0) + return false; + if (!pid) + { + execvp(args[0], const_cast(args)); + exit(-1); + } + else + { + int status; + waitpid(pid, &status, 0); + return WEXITSTATUS(status) == 0; + } +} +#endif +#else +static bool PlatformOpenInShellFn_DefaultImpl(ImGuiContext*, const char*) { return false; } +#endif // Default shell handlers + +//----------------------------------------------------------------------------- + // Win32 API IME support (for Asian languages, etc.) #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) @@ -19981,7 +20091,7 @@ static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text #pragma comment(lib, "imm32") #endif -static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatformImeData* data) +static void PlatformSetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport* viewport, ImGuiPlatformImeData* data) { // Notify OS Input Method Editor of text input position HWND hwnd = (HWND)viewport->PlatformHandleRaw; @@ -20007,9 +20117,9 @@ static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatf #else -static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport*, ImGuiPlatformImeData*) {} +static void PlatformSetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport*, ImGuiPlatformImeData*) {} -#endif +#endif // Default IME handlers //----------------------------------------------------------------------------- // [SECTION] METRICS/DEBUGGER WINDOW @@ -20496,14 +20606,11 @@ void ImGui::ShowMetricsWindow(bool* p_open) { for (int i = 0; i < g.PlatformIO.Monitors.Size; i++) { - const ImGuiPlatformMonitor& mon = g.PlatformIO.Monitors[i]; - BulletText("Monitor #%d: DPI %.0f%%\n MainMin (%.0f,%.0f), MainMax (%.0f,%.0f), MainSize (%.0f,%.0f)\n WorkMin (%.0f,%.0f), WorkMax (%.0f,%.0f), WorkSize (%.0f,%.0f)", - i, mon.DpiScale * 100.0f, - mon.MainPos.x, mon.MainPos.y, mon.MainPos.x + mon.MainSize.x, mon.MainPos.y + mon.MainSize.y, mon.MainSize.x, mon.MainSize.y, - mon.WorkPos.x, mon.WorkPos.y, mon.WorkPos.x + mon.WorkSize.x, mon.WorkPos.y + mon.WorkSize.y, mon.WorkSize.x, mon.WorkSize.y); + DebugNodePlatformMonitor(&g.PlatformIO.Monitors[i], "Monitor", i); if (IsItemHovered()) cfg->HighlightMonitorIdx = i; } + DebugNodePlatformMonitor(&g.FallbackMonitor, "Fallback", 0); TreePop(); } @@ -20598,6 +20705,17 @@ void ImGui::ShowMetricsWindow(bool* p_open) TreePop(); } + // Details for MultiSelect + if (TreeNode("MultiSelect", "MultiSelect (%d)", g.MultiSelectStorage.GetAliveCount())) + { + ImGuiBoxSelectState* bs = &g.BoxSelectState; + BulletText("BoxSelect ID=0x%08X, Starting = %d, Active %d", bs->ID, bs->IsStarting, bs->IsActive); + for (int n = 0; n < g.MultiSelectStorage.GetMapSize(); n++) + if (ImGuiMultiSelectState* state = g.MultiSelectStorage.TryGetMapData(n)) + DebugNodeMultiSelectState(state); + TreePop(); + } + // Details for Docking #ifdef IMGUI_HAS_DOCK if (TreeNode("Docking")) @@ -20700,7 +20818,12 @@ void ImGui::ShowMetricsWindow(bool* p_open) for (int n = buf_size - 1; n >= 0; n--) { ImGuiDebugAllocEntry* entry = &info->LastEntriesBuf[(info->LastEntriesIdx - n + buf_size) % buf_size]; - BulletText("Frame %06d: %+3d ( %2d malloc, %2d free )%s", entry->FrameCount, entry->AllocCount - entry->FreeCount, entry->AllocCount, entry->FreeCount, (n == 0) ? " (most recent)" : ""); + BulletText("Frame %06d: %+3d ( %2d alloc, %2d free )", entry->FrameCount, entry->AllocCount - entry->FreeCount, entry->AllocCount, entry->FreeCount); + if (n == 0) + { + SameLine(); + Text("<- %d frames ago", g.FrameCount - entry->FrameCount); + } } TreePop(); } @@ -21409,6 +21532,14 @@ void ImGui::DebugNodeViewport(ImGuiViewportP* viewport) } } +void ImGui::DebugNodePlatformMonitor(ImGuiPlatformMonitor* monitor, const char* label, int idx) +{ + BulletText("%s %d: DPI %.0f%%\n MainMin (%.0f,%.0f), MainMax (%.0f,%.0f), MainSize (%.0f,%.0f)\n WorkMin (%.0f,%.0f), WorkMax (%.0f,%.0f), WorkSize (%.0f,%.0f)", + label, idx, monitor->DpiScale * 100.0f, + monitor->MainPos.x, monitor->MainPos.y, monitor->MainPos.x + monitor->MainSize.x, monitor->MainPos.y + monitor->MainSize.y, monitor->MainSize.x, monitor->MainSize.y, + monitor->WorkPos.x, monitor->WorkPos.y, monitor->WorkPos.x + monitor->WorkSize.x, monitor->WorkPos.y + monitor->WorkSize.y, monitor->WorkSize.x, monitor->WorkSize.y); +} + void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label) { if (window == NULL) @@ -21441,6 +21572,12 @@ void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label) (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "", (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "", (flags & ImGuiWindowFlags_NoMouseInputs)? "NoMouseInputs":"", (flags & ImGuiWindowFlags_NoNavInputs) ? "NoNavInputs" : "", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : ""); + if (flags & ImGuiWindowFlags_ChildWindow) + BulletText("ChildFlags: 0x%08X (%s%s%s%s..)", window->ChildFlags, + (window->ChildFlags & ImGuiChildFlags_Border) ? "Border " : "", + (window->ChildFlags & ImGuiChildFlags_ResizeX) ? "ResizeX " : "", + (window->ChildFlags & ImGuiChildFlags_ResizeY) ? "ResizeY " : "", + (window->ChildFlags & ImGuiChildFlags_NavFlattened) ? "NavFlattened " : ""); BulletText("WindowClassId: 0x%08X", window->WindowClass.ClassId); BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f) Scrollbar:%s%s", window->Scroll.x, window->ScrollMax.x, window->Scroll.y, window->ScrollMax.y, window->ScrollbarX ? "X" : "", window->ScrollbarY ? "Y" : ""); BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1); @@ -21560,7 +21697,7 @@ static void SameLineOrWrap(const ImVec2& size) ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImVec2 pos(window->DC.CursorPosPrevLine.x + g.Style.ItemSpacing.x, window->DC.CursorPosPrevLine.y); - if (window->ClipRect.Contains(ImRect(pos, pos + size))) + if (window->WorkRect.Contains(ImRect(pos, pos + size))) ImGui::SameLine(); } @@ -21599,7 +21736,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open) ShowDebugLogFlag("IO", ImGuiDebugLogFlags_EventIO); ShowDebugLogFlag("Nav", ImGuiDebugLogFlags_EventNav); ShowDebugLogFlag("Popup", ImGuiDebugLogFlags_EventPopup); - //ShowDebugLogFlag("Selection", ImGuiDebugLogFlags_EventSelection); + ShowDebugLogFlag("Selection", ImGuiDebugLogFlags_EventSelection); ShowDebugLogFlag("Viewport", ImGuiDebugLogFlags_EventViewport); ShowDebugLogFlag("InputRouting", ImGuiDebugLogFlags_EventInputRouting); @@ -21611,6 +21748,22 @@ void ImGui::ShowDebugLogWindow(bool* p_open) SameLine(); if (SmallButton("Copy")) SetClipboardText(g.DebugLogBuf.c_str()); + SameLine(); + if (SmallButton("Configure Outputs..")) + OpenPopup("Outputs"); + if (BeginPopup("Outputs")) + { + CheckboxFlags("OutputToTTY", &g.DebugLogFlags, ImGuiDebugLogFlags_OutputToTTY); +#ifndef IMGUI_ENABLE_TEST_ENGINE + BeginDisabled(); +#endif + CheckboxFlags("OutputToTestEngine", &g.DebugLogFlags, ImGuiDebugLogFlags_OutputToTestEngine); +#ifndef IMGUI_ENABLE_TEST_ENGINE + EndDisabled(); +#endif + EndPopup(); + } + BeginChild("##log", ImVec2(0.0f, 0.0f), ImGuiChildFlags_Border, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar); const ImGuiDebugLogFlags backup_log_flags = g.DebugLogFlags; @@ -21640,7 +21793,7 @@ void ImGui::DebugTextUnformattedWithLocateItem(const char* line_begin, const cha 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) + if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1 || ImCharIsXdigitA(p[10])) continue; ImVec2 p0 = CalcTextSize(line_begin, p); ImVec2 p1 = CalcTextSize(p, p + 10); @@ -21971,8 +22124,6 @@ void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings*) {} void ImGui::DebugNodeWindowsList(ImVector*, const char*) {} void ImGui::DebugNodeViewport(ImGuiViewportP*) {} -void ImGui::DebugLog(const char*, ...) {} -void ImGui::DebugLogV(const char*, va_list) {} void ImGui::ShowDebugLogWindow(bool*) {} void ImGui::ShowIDStackToolWindow(bool*) {} void ImGui::DebugStartItemPicker() {} diff --git a/lib/third_party/imgui/imgui/source/imgui_demo.cpp b/lib/third_party/imgui/imgui/source/imgui_demo.cpp index 44b31547a..542fd87f4 100644 --- a/lib/third_party/imgui/imgui/source/imgui_demo.cpp +++ b/lib/third_party/imgui/imgui/source/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.9 +// dear imgui, v1.91.0 // (demo code) // Help: @@ -11,7 +11,7 @@ // Get the latest version at https://github.com/ocornut/imgui // How to easily locate code? -// - Use the Item Picker to debug break in code by clicking any widgets: https://github.com/ocornut/imgui/wiki/Debug-Tools +// - Use Tools->Item Picker to debug break in code by clicking any widgets: https://github.com/ocornut/imgui/wiki/Debug-Tools // - Browse an online version the demo with code linked to hovered widgets: https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html // - Find a visible string and search for it in the code! @@ -62,6 +62,7 @@ // - 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. +// - You can search/grep for all sections listed in the index to find the section. /* @@ -69,13 +70,15 @@ Index of this file: // [SECTION] Forward Declarations // [SECTION] Helpers +// [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor & Multi-Select demos) // [SECTION] Demo Window / ShowDemoWindow() -// - ShowDemoWindow() -// - sub section: ShowDemoWindowWidgets() -// - sub section: ShowDemoWindowLayout() -// - sub section: ShowDemoWindowPopups() -// - sub section: ShowDemoWindowTables() -// - sub section: ShowDemoWindowInputs() +// [SECTION] ShowDemoWindowMenuBar() +// [SECTION] ShowDemoWindowWidgets() +// [SECTION] ShowDemoWindowMultiSelect() +// [SECTION] ShowDemoWindowLayout() +// [SECTION] ShowDemoWindowPopups() +// [SECTION] ShowDemoWindowTables() +// [SECTION] ShowDemoWindowInputs() // [SECTION] About Window / ShowAboutWindow() // [SECTION] Style Editor / ShowStyleEditor() // [SECTION] User Guide / ShowUserGuide() @@ -93,6 +96,7 @@ Index of this file: // [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering() // [SECTION] Example App: Docking, DockSpace / ShowExampleAppDockSpace() // [SECTION] Example App: Documents Handling / ShowExampleAppDocuments() +// [SECTION] Example App: Assets Browser / ShowExampleAppAssetsBrowser() */ @@ -190,20 +194,22 @@ Index of this file: #endif //----------------------------------------------------------------------------- -// [SECTION] Forward Declarations, Helpers +// [SECTION] Forward Declarations //----------------------------------------------------------------------------- #if !defined(IMGUI_DISABLE_DEMO_WINDOWS) // Forward Declarations +struct ImGuiDemoWindowData; static void ShowExampleAppMainMenuBar(); +static void ShowExampleAppAssetsBrowser(bool* p_open); static void ShowExampleAppConsole(bool* p_open); static void ShowExampleAppCustomRendering(bool* p_open); static void ShowExampleAppDockSpace(bool* p_open); static void ShowExampleAppDocuments(bool* p_open); static void ShowExampleAppLog(bool* p_open); static void ShowExampleAppLayout(bool* p_open); -static void ShowExampleAppPropertyEditor(bool* p_open); +static void ShowExampleAppPropertyEditor(bool* p_open, ImGuiDemoWindowData* demo_data); static void ShowExampleAppSimpleOverlay(bool* p_open); static void ShowExampleAppAutoResize(bool* p_open); static void ShowExampleAppConstrainedResize(bool* p_open); @@ -213,8 +219,10 @@ static void ShowExampleAppWindowTitles(bool* p_open); static void ShowExampleMenuFile(); // We split the contents of the big ShowDemoWindow() function into smaller functions -// (because the link time of very large functions grow non-linearly) -static void ShowDemoWindowWidgets(); +// (because the link time of very large functions tends to grow non-linearly) +static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data); +static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data); +static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data); static void ShowDemoWindowLayout(); static void ShowDemoWindowPopups(); static void ShowDemoWindowTables(); @@ -257,17 +265,122 @@ ImGuiDemoMarkerCallback GImGuiDemoMarkerCallback = NULL; void* GImGuiDemoMarkerCallbackUserData = NULL; #define IMGUI_DEMO_MARKER(section) do { if (GImGuiDemoMarkerCallback != NULL) GImGuiDemoMarkerCallback(__FILE__, __LINE__, section, GImGuiDemoMarkerCallbackUserData); } while (0) +//----------------------------------------------------------------------------- +// [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor etc.) +//----------------------------------------------------------------------------- + +// Simple representation for a tree +// (this is designed to be simple to understand for our demos, not to be fancy or efficient etc.) +struct ExampleTreeNode +{ + // Tree structure + char Name[28] = ""; + int UID = 0; + ExampleTreeNode* Parent = NULL; + ImVector Childs; + unsigned short IndexInParent = 0; // Maintaining this allows us to implement linear traversal more easily + + // Leaf Data + bool HasData = false; // All leaves have data + bool DataMyBool = true; + int DataMyInt = 128; + ImVec2 DataMyVec2 = ImVec2(0.0f, 3.141592f); +}; + +// Simple representation of struct metadata/serialization data. +// (this is a minimal version of what a typical advanced application may provide) +struct ExampleMemberInfo +{ + const char* Name; // Member name + ImGuiDataType DataType; // Member type + int DataCount; // Member count (1 when scalar) + int Offset; // Offset inside parent structure +}; + +// Metadata description of ExampleTreeNode struct. +static const ExampleMemberInfo ExampleTreeNodeMemberInfos[] +{ + { "MyBool", ImGuiDataType_Bool, 1, offsetof(ExampleTreeNode, DataMyBool) }, + { "MyInt", ImGuiDataType_S32, 1, offsetof(ExampleTreeNode, DataMyInt) }, + { "MyVec2", ImGuiDataType_Float, 2, offsetof(ExampleTreeNode, DataMyVec2) }, +}; + +static ExampleTreeNode* ExampleTree_CreateNode(const char* name, int uid, ExampleTreeNode* parent) +{ + ExampleTreeNode* node = IM_NEW(ExampleTreeNode); + snprintf(node->Name, IM_ARRAYSIZE(node->Name), "%s", name); + node->UID = uid; + node->Parent = parent; + node->IndexInParent = parent ? (unsigned short)parent->Childs.Size : 0; + if (parent) + parent->Childs.push_back(node); + return node; +} + +// Create example tree data +// (this allocates _many_ more times than most other code in either Dear ImGui or others demo) +static ExampleTreeNode* ExampleTree_CreateDemoTree() +{ + static const char* root_names[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pear", "Pineapple", "Strawberry", "Watermelon" }; + char name_buf[32]; + int uid = 0; + ExampleTreeNode* node_L0 = ExampleTree_CreateNode("", ++uid, NULL); + const int root_items_multiplier = 2; + for (int idx_L0 = 0; idx_L0 < IM_ARRAYSIZE(root_names) * root_items_multiplier; idx_L0++) + { + snprintf(name_buf, 32, "%s %d", root_names[idx_L0 / root_items_multiplier], idx_L0 % root_items_multiplier); + ExampleTreeNode* node_L1 = ExampleTree_CreateNode(name_buf, ++uid, node_L0); + const int number_of_childs = (int)strlen(node_L1->Name); + for (int idx_L1 = 0; idx_L1 < number_of_childs; idx_L1++) + { + snprintf(name_buf, 32, "Child %d", idx_L1); + ExampleTreeNode* node_L2 = ExampleTree_CreateNode(name_buf, ++uid, node_L1); + node_L2->HasData = true; + if (idx_L1 == 0) + { + snprintf(name_buf, 32, "Sub-child %d", 0); + ExampleTreeNode* node_L3 = ExampleTree_CreateNode(name_buf, ++uid, node_L2); + node_L3->HasData = true; + } + } + } + return node_L0; +} + //----------------------------------------------------------------------------- // [SECTION] Demo Window / ShowDemoWindow() //----------------------------------------------------------------------------- -// - ShowDemoWindow() -// - ShowDemoWindowWidgets() -// - ShowDemoWindowLayout() -// - ShowDemoWindowPopups() -// - ShowDemoWindowTables() -// - ShowDemoWindowColumns() -// - ShowDemoWindowInputs() -//----------------------------------------------------------------------------- + +// Data to be shared accross different functions of the demo. +struct ImGuiDemoWindowData +{ + // Examples Apps (accessible from the "Examples" menu) + bool ShowMainMenuBar = false; + bool ShowAppAssetsBrowser = false; + bool ShowAppConsole = false; + bool ShowAppCustomRendering = false; + bool ShowAppDocuments = false; + bool ShowAppDockSpace = false; + bool ShowAppLog = false; + bool ShowAppLayout = false; + bool ShowAppPropertyEditor = false; + bool ShowAppSimpleOverlay = false; + bool ShowAppAutoResize = false; + bool ShowAppConstrainedResize = false; + bool ShowAppFullscreen = false; + bool ShowAppLongText = false; + bool ShowAppWindowTitles = false; + + // Dear ImGui Tools (accessible from the "Tools" menu) + bool ShowMetrics = false; + bool ShowDebugLog = false; + bool ShowIDStackTool = false; + bool ShowStyleEditor = false; + bool ShowAbout = false; + + // Other data + ExampleTreeNode* DemoTree = NULL; +}; // Demonstrate most Dear ImGui features (this is big function!) // You may execute this function to experiment with the UI and understand what it does. @@ -281,58 +394,37 @@ void ImGui::ShowDemoWindow(bool* p_open) // Verify ABI compatibility between caller code and compiled version of Dear ImGui. This helps detects some build issues. IMGUI_CHECKVERSION(); - // Examples Apps (accessible from the "Examples" menu) - static bool show_app_main_menu_bar = false; - static bool show_app_console = false; - static bool show_app_custom_rendering = false; - static bool show_app_dockspace = false; - static bool show_app_documents = false; - static bool show_app_log = false; - static bool show_app_layout = false; - static bool show_app_property_editor = false; - static bool show_app_simple_overlay = false; - static bool show_app_auto_resize = false; - static bool show_app_constrained_resize = false; - static bool show_app_fullscreen = false; - static bool show_app_long_text = false; - static bool show_app_window_titles = false; + // Stored data + static ImGuiDemoWindowData demo_data; - if (show_app_main_menu_bar) ShowExampleAppMainMenuBar(); - if (show_app_dockspace) ShowExampleAppDockSpace(&show_app_dockspace); // Process the Docking app first, as explicit DockSpace() nodes needs to be submitted early (read comments near the DockSpace function) - if (show_app_documents) ShowExampleAppDocuments(&show_app_documents); // Process the Document app next, as it may also use a DockSpace() - if (show_app_console) ShowExampleAppConsole(&show_app_console); - if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering); - if (show_app_log) ShowExampleAppLog(&show_app_log); - if (show_app_layout) ShowExampleAppLayout(&show_app_layout); - if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor); - if (show_app_simple_overlay) ShowExampleAppSimpleOverlay(&show_app_simple_overlay); - if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize); - if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize); - if (show_app_fullscreen) ShowExampleAppFullscreen(&show_app_fullscreen); - if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text); - if (show_app_window_titles) ShowExampleAppWindowTitles(&show_app_window_titles); + // Examples Apps (accessible from the "Examples" menu) + if (demo_data.ShowMainMenuBar) { ShowExampleAppMainMenuBar(); } + if (demo_data.ShowAppDockSpace) { ShowExampleAppDockSpace(&demo_data.ShowAppDockSpace); } // Important: Process the Docking app first, as explicit DockSpace() nodes needs to be submitted early (read comments near the DockSpace function) + if (demo_data.ShowAppDocuments) { ShowExampleAppDocuments(&demo_data.ShowAppDocuments); } // ...process the Document app next, as it may also use a DockSpace() + if (demo_data.ShowAppAssetsBrowser) { ShowExampleAppAssetsBrowser(&demo_data.ShowAppAssetsBrowser); } + if (demo_data.ShowAppConsole) { ShowExampleAppConsole(&demo_data.ShowAppConsole); } + if (demo_data.ShowAppCustomRendering) { ShowExampleAppCustomRendering(&demo_data.ShowAppCustomRendering); } + if (demo_data.ShowAppLog) { ShowExampleAppLog(&demo_data.ShowAppLog); } + if (demo_data.ShowAppLayout) { ShowExampleAppLayout(&demo_data.ShowAppLayout); } + if (demo_data.ShowAppPropertyEditor) { ShowExampleAppPropertyEditor(&demo_data.ShowAppPropertyEditor, &demo_data); } + if (demo_data.ShowAppSimpleOverlay) { ShowExampleAppSimpleOverlay(&demo_data.ShowAppSimpleOverlay); } + if (demo_data.ShowAppAutoResize) { ShowExampleAppAutoResize(&demo_data.ShowAppAutoResize); } + if (demo_data.ShowAppConstrainedResize) { ShowExampleAppConstrainedResize(&demo_data.ShowAppConstrainedResize); } + if (demo_data.ShowAppFullscreen) { ShowExampleAppFullscreen(&demo_data.ShowAppFullscreen); } + if (demo_data.ShowAppLongText) { ShowExampleAppLongText(&demo_data.ShowAppLongText); } + if (demo_data.ShowAppWindowTitles) { ShowExampleAppWindowTitles(&demo_data.ShowAppWindowTitles); } // Dear ImGui Tools (accessible from the "Tools" menu) - static bool show_tool_metrics = false; - static bool show_tool_debug_log = false; - static bool show_tool_id_stack_tool = false; - static bool show_tool_style_editor = false; - static bool show_tool_about = false; - - if (show_tool_metrics) - ImGui::ShowMetricsWindow(&show_tool_metrics); - if (show_tool_debug_log) - ImGui::ShowDebugLogWindow(&show_tool_debug_log); - if (show_tool_id_stack_tool) - ImGui::ShowIDStackToolWindow(&show_tool_id_stack_tool); - if (show_tool_style_editor) + if (demo_data.ShowMetrics) { ImGui::ShowMetricsWindow(&demo_data.ShowMetrics); } + if (demo_data.ShowDebugLog) { ImGui::ShowDebugLogWindow(&demo_data.ShowDebugLog); } + if (demo_data.ShowIDStackTool) { ImGui::ShowIDStackToolWindow(&demo_data.ShowIDStackTool); } + if (demo_data.ShowAbout) { ImGui::ShowAboutWindow(&demo_data.ShowAbout); } + if (demo_data.ShowStyleEditor) { - ImGui::Begin("Dear ImGui Style Editor", &show_tool_style_editor); + ImGui::Begin("Dear ImGui Style Editor", &demo_data.ShowStyleEditor); ImGui::ShowStyleEditor(); ImGui::End(); } - if (show_tool_about) - ImGui::ShowAboutWindow(&show_tool_about); // Demonstrate the various window flags. Typically you would just use the default! static bool no_titlebar = false; @@ -377,68 +469,11 @@ void ImGui::ShowDemoWindow(bool* p_open) } // Most "big" widgets share a common width settings by default. See 'Demo->Layout->Widgets Width' for details. - // e.g. Use 2/3 of the space for widgets and 1/3 for labels (right align) - //ImGui::PushItemWidth(-ImGui::GetWindowWidth() * 0.35f); - // e.g. Leave a fixed amount of width for labels (by passing a negative value), the rest goes to widgets. - ImGui::PushItemWidth(ImGui::GetFontSize() * -12); + ImGui::PushItemWidth(ImGui::GetFontSize() * -12); // e.g. Leave a fixed amount of width for labels (by passing a negative value), the rest goes to widgets. + //ImGui::PushItemWidth(-ImGui::GetWindowWidth() * 0.35f); // e.g. Use 2/3 of the space for widgets and 1/3 for labels (right align) // Menu Bar - if (ImGui::BeginMenuBar()) - { - if (ImGui::BeginMenu("Menu")) - { - IMGUI_DEMO_MARKER("Menu/File"); - ShowExampleMenuFile(); - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Examples")) - { - IMGUI_DEMO_MARKER("Menu/Examples"); - ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar); - - ImGui::SeparatorText("Mini apps"); - ImGui::MenuItem("Console", NULL, &show_app_console); - ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering); - ImGui::MenuItem("Dockspace", NULL, &show_app_dockspace); - ImGui::MenuItem("Documents", NULL, &show_app_documents); - ImGui::MenuItem("Log", NULL, &show_app_log); - ImGui::MenuItem("Property editor", NULL, &show_app_property_editor); - ImGui::MenuItem("Simple layout", NULL, &show_app_layout); - ImGui::MenuItem("Simple overlay", NULL, &show_app_simple_overlay); - - ImGui::SeparatorText("Concepts"); - ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize); - ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize); - ImGui::MenuItem("Fullscreen window", NULL, &show_app_fullscreen); - ImGui::MenuItem("Long text display", NULL, &show_app_long_text); - ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles); - - ImGui::EndMenu(); - } - //if (ImGui::MenuItem("MenuItem")) {} // You can also use MenuItem() inside a menu bar! - if (ImGui::BeginMenu("Tools")) - { - IMGUI_DEMO_MARKER("Menu/Tools"); -#ifndef IMGUI_DISABLE_DEBUG_TOOLS - const bool has_debug_tools = true; -#else - const bool has_debug_tools = false; -#endif - ImGui::MenuItem("Metrics/Debugger", NULL, &show_tool_metrics, has_debug_tools); - ImGui::MenuItem("Debug Log", NULL, &show_tool_debug_log, has_debug_tools); - ImGui::MenuItem("ID Stack Tool", NULL, &show_tool_id_stack_tool, has_debug_tools); - ImGui::MenuItem("Style Editor", NULL, &show_tool_style_editor); - bool is_debugger_present = ImGui::GetIO().ConfigDebugIsDebuggerPresent; - if (ImGui::MenuItem("Item Picker", NULL, false, has_debug_tools && is_debugger_present)) - ImGui::DebugStartItemPicker(); - if (!is_debugger_present) - ImGui::SetItemTooltip("Requires io.ConfigDebugIsDebuggerPresent=true to be set.\n\nWe otherwise disable the menu option to avoid casual users crashing the application.\n\nYou can however always access the Item Picker in Metrics->Tools."); - ImGui::Separator(); - ImGui::MenuItem("About Dear ImGui", NULL, &show_tool_about); - ImGui::EndMenu(); - } - ImGui::EndMenuBar(); - } + ShowDemoWindowMenuBar(&demo_data); ImGui::Text("dear imgui says hello! (%s) (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM); ImGui::Spacing(); @@ -456,7 +491,9 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::BulletText("See the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!"); ImGui::BulletText("See comments in imgui.cpp."); ImGui::BulletText("See example applications in the examples/ folder."); - ImGui::BulletText("Read the FAQ at https://www.dearimgui.com/faq/"); + ImGui::BulletText("Read the FAQ at "); + ImGui::SameLine(0, 0); + ImGui::TextLinkOpenURL("https://www.dearimgui.com/faq/"); ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls."); ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls."); @@ -599,8 +636,9 @@ void ImGui::ShowDemoWindow(bool* p_open) IMGUI_DEMO_MARKER("Configuration/Style"); if (ImGui::TreeNode("Style")) { + ImGui::Checkbox("Style Editor", &demo_data.ShowStyleEditor); + ImGui::SameLine(); HelpMarker("The same contents can be accessed in 'Tools->Style Editor' or by calling the ShowStyleEditor() function."); - ImGui::ShowStyleEditor(); ImGui::TreePop(); ImGui::Spacing(); } @@ -647,7 +685,7 @@ void ImGui::ShowDemoWindow(bool* p_open) } // All demo contents - ShowDemoWindowWidgets(); + ShowDemoWindowWidgets(&demo_data); ShowDemoWindowLayout(); ShowDemoWindowPopups(); ShowDemoWindowTables(); @@ -658,9 +696,80 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::End(); } -static void ShowDemoWindowWidgets() +//----------------------------------------------------------------------------- +// [SECTION] ShowDemoWindowMenuBar() +//----------------------------------------------------------------------------- + +static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data) +{ + IMGUI_DEMO_MARKER("Menu"); + if (ImGui::BeginMenuBar()) + { + if (ImGui::BeginMenu("Menu")) + { + IMGUI_DEMO_MARKER("Menu/File"); + ShowExampleMenuFile(); + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Examples")) + { + IMGUI_DEMO_MARKER("Menu/Examples"); + ImGui::MenuItem("Main menu bar", NULL, &demo_data->ShowMainMenuBar); + + ImGui::SeparatorText("Mini apps"); + ImGui::MenuItem("Assets Browser", NULL, &demo_data->ShowAppAssetsBrowser); + ImGui::MenuItem("Console", NULL, &demo_data->ShowAppConsole); + ImGui::MenuItem("Custom rendering", NULL, &demo_data->ShowAppCustomRendering); + ImGui::MenuItem("Documents", NULL, &demo_data->ShowAppDocuments); + ImGui::MenuItem("Dockspace", NULL, &demo_data->ShowAppDockSpace); + ImGui::MenuItem("Log", NULL, &demo_data->ShowAppLog); + ImGui::MenuItem("Property editor", NULL, &demo_data->ShowAppPropertyEditor); + ImGui::MenuItem("Simple layout", NULL, &demo_data->ShowAppLayout); + ImGui::MenuItem("Simple overlay", NULL, &demo_data->ShowAppSimpleOverlay); + + ImGui::SeparatorText("Concepts"); + ImGui::MenuItem("Auto-resizing window", NULL, &demo_data->ShowAppAutoResize); + ImGui::MenuItem("Constrained-resizing window", NULL, &demo_data->ShowAppConstrainedResize); + ImGui::MenuItem("Fullscreen window", NULL, &demo_data->ShowAppFullscreen); + ImGui::MenuItem("Long text display", NULL, &demo_data->ShowAppLongText); + ImGui::MenuItem("Manipulating window titles", NULL, &demo_data->ShowAppWindowTitles); + + ImGui::EndMenu(); + } + //if (ImGui::MenuItem("MenuItem")) {} // You can also use MenuItem() inside a menu bar! + if (ImGui::BeginMenu("Tools")) + { + IMGUI_DEMO_MARKER("Menu/Tools"); +#ifndef IMGUI_DISABLE_DEBUG_TOOLS + const bool has_debug_tools = true; +#else + const bool has_debug_tools = false; +#endif + ImGui::MenuItem("Metrics/Debugger", NULL, &demo_data->ShowMetrics, has_debug_tools); + ImGui::MenuItem("Debug Log", NULL, &demo_data->ShowDebugLog, has_debug_tools); + ImGui::MenuItem("ID Stack Tool", NULL, &demo_data->ShowIDStackTool, has_debug_tools); + ImGui::MenuItem("Style Editor", NULL, &demo_data->ShowStyleEditor); + bool is_debugger_present = ImGui::GetIO().ConfigDebugIsDebuggerPresent; + if (ImGui::MenuItem("Item Picker", NULL, false, has_debug_tools && is_debugger_present)) + ImGui::DebugStartItemPicker(); + if (!is_debugger_present) + ImGui::SetItemTooltip("Requires io.ConfigDebugIsDebuggerPresent=true to be set.\n\nWe otherwise disable the menu option to avoid casual users crashing the application.\n\nYou can however always access the Item Picker in Metrics->Tools."); + ImGui::Separator(); + ImGui::MenuItem("About Dear ImGui", NULL, &demo_data->ShowAbout); + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); + } +} + +//----------------------------------------------------------------------------- +// [SECTION] ShowDemoWindowWidgets() +//----------------------------------------------------------------------------- + +static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) { IMGUI_DEMO_MARKER("Widgets"); + //ImGui::SetNextItemOpen(true, ImGuiCond_Once); if (!ImGui::CollapsingHeader("Widgets")) return; @@ -719,11 +828,11 @@ static void ShowDemoWindowWidgets() IMGUI_DEMO_MARKER("Widgets/Basic/Buttons (Repeating)"); static int counter = 0; float spacing = ImGui::GetStyle().ItemInnerSpacing.x; - ImGui::PushButtonRepeat(true); + ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true); if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; } ImGui::SameLine(0.0f, spacing); if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; } - ImGui::PopButtonRepeat(); + ImGui::PopItemFlag(); ImGui::SameLine(); ImGui::Text("%d", counter); @@ -1010,6 +1119,7 @@ static void ShowDemoWindowWidgets() ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &base_flags, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::SameLine(); HelpMarker("For use in Tables only."); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_AllowOverlap", &base_flags, ImGuiTreeNodeFlags_AllowOverlap); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_Framed", &base_flags, ImGuiTreeNodeFlags_Framed); ImGui::SameLine(); HelpMarker("Draw frame with background (e.g. for CollapsingHeader)"); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_NavLeftJumpsBackHere", &base_flags, ImGuiTreeNodeFlags_NavLeftJumpsBackHere); ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position); ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop); ImGui::Text("Hello!"); @@ -1042,7 +1152,7 @@ static void ShowDemoWindowWidgets() ImGui::Text("This is a drag and drop source"); ImGui::EndDragDropSource(); } - if (i == 2) + if (i == 2 && (base_flags & ImGuiTreeNodeFlags_SpanTextWidth)) { // Item 2 has an additional inline button to help demonstrate SpanTextWidth. ImGui::SameLine(); @@ -1051,6 +1161,8 @@ static void ShowDemoWindowWidgets() if (node_open) { ImGui::BulletText("Blah blah\nBlah Blah"); + ImGui::SameLine(); + ImGui::SmallButton("Button"); ImGui::TreePop(); } } @@ -1312,18 +1424,18 @@ static void ShowDemoWindowWidgets() // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively // stored in the object itself, etc.) const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; - static int item_current_idx = 0; // Here we store our selection data as an index. + static int item_selected_idx = 0; // Here we store our selection data as an index. // Pass in the preview value visible before opening the combo (it could technically be different contents or not pulled from items[]) - const char* combo_preview_value = items[item_current_idx]; + const char* combo_preview_value = items[item_selected_idx]; if (ImGui::BeginCombo("combo 1", combo_preview_value, flags)) { for (int n = 0; n < IM_ARRAYSIZE(items); n++) { - const bool is_selected = (item_current_idx == n); + const bool is_selected = (item_selected_idx == n); if (ImGui::Selectable(items[n], is_selected)) - item_current_idx = n; + item_selected_idx = n; // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) if (is_selected) @@ -1365,14 +1477,22 @@ static void ShowDemoWindowWidgets() // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively // stored in the object itself, etc.) const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; - static int item_current_idx = 0; // Here we store our selection data as an index. + static int item_selected_idx = 0; // Here we store our selected data as an index. + + static bool item_highlight = false; + int item_highlighted_idx = -1; // Here we store our highlighted data as an index. + ImGui::Checkbox("Highlight hovered item in second listbox", &item_highlight); + if (ImGui::BeginListBox("listbox 1")) { for (int n = 0; n < IM_ARRAYSIZE(items); n++) { - const bool is_selected = (item_current_idx == n); + const bool is_selected = (item_selected_idx == n); if (ImGui::Selectable(items[n], is_selected)) - item_current_idx = n; + item_selected_idx = n; + + if (item_highlight && ImGui::IsItemHovered()) + item_highlighted_idx = n; // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) if (is_selected) @@ -1388,9 +1508,10 @@ static void ShowDemoWindowWidgets() { for (int n = 0; n < IM_ARRAYSIZE(items); n++) { - const bool is_selected = (item_current_idx == n); - if (ImGui::Selectable(items[n], is_selected)) - item_current_idx = n; + bool is_selected = (item_selected_idx == n); + ImGuiSelectableFlags flags = (item_highlighted_idx == n) ? ImGuiSelectableFlags_Highlight : 0; + if (ImGui::Selectable(items[n], is_selected, flags)) + item_selected_idx = n; // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) if (is_selected) @@ -1403,6 +1524,7 @@ static void ShowDemoWindowWidgets() } IMGUI_DEMO_MARKER("Widgets/Selectables"); + //ImGui::SetNextItemOpen(true, ImGuiCond_Once); if (ImGui::TreeNode("Selectables")) { // Selectable() has 2 overloads: @@ -1424,37 +1546,6 @@ static void ShowDemoWindowWidgets() ImGui::TreePop(); } - IMGUI_DEMO_MARKER("Widgets/Selectables/Single Selection"); - if (ImGui::TreeNode("Selection State: Single Selection")) - { - static int selected = -1; - for (int n = 0; n < 5; n++) - { - char buf[32]; - sprintf(buf, "Object %d", n); - if (ImGui::Selectable(buf, selected == n)) - selected = n; - } - ImGui::TreePop(); - } - IMGUI_DEMO_MARKER("Widgets/Selectables/Multiple Selection"); - if (ImGui::TreeNode("Selection State: Multiple Selection")) - { - HelpMarker("Hold CTRL and click to select multiple items."); - static bool selection[5] = { false, false, false, false, false }; - for (int n = 0; n < 5; n++) - { - char buf[32]; - sprintf(buf, "Object %d", n); - if (ImGui::Selectable(buf, selection[n])) - { - if (!ImGui::GetIO().KeyCtrl) // Clear selection when CTRL is not held - memset(selection, 0, sizeof(selection)); - selection[n] ^= 1; - } - } - ImGui::TreePop(); - } IMGUI_DEMO_MARKER("Widgets/Selectables/Rendering more items on the same line"); if (ImGui::TreeNode("Rendering more items on the same line")) { @@ -1467,8 +1558,8 @@ static void ShowDemoWindowWidgets() ImGui::TreePop(); } - IMGUI_DEMO_MARKER("Widgets/Selectables/In columns"); - if (ImGui::TreeNode("In columns")) + IMGUI_DEMO_MARKER("Widgets/Selectables/In Tables"); + if (ImGui::TreeNode("In Tables")) { static bool selected[10] = {}; @@ -1562,6 +1653,8 @@ static void ShowDemoWindowWidgets() ImGui::TreePop(); } + ShowDemoWindowMultiSelect(demo_data); + // To wire InputText() with std::string or any other custom string type, // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file. IMGUI_DEMO_MARKER("Widgets/Text Input"); @@ -2635,7 +2728,7 @@ static void ShowDemoWindowWidgets() ImGui::BeginDisabled(true); if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button - if (item_type == 2) { ImGui::PushButtonRepeat(true); ret = ImGui::Button("ITEM: Button"); ImGui::PopButtonRepeat(); } // Testing button (with repeater) + if (item_type == 2) { ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true); ret = ImGui::Button("ITEM: Button"); ImGui::PopItemFlag(); } // Testing button (with repeater) if (item_type == 3) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); } // Testing checkbox if (item_type == 4) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); } // Testing basic item if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which handles tabbing) @@ -2853,6 +2946,977 @@ static void ShowDemoWindowWidgets() } } +static const char* ExampleNames[] = +{ + "Artichoke", "Arugula", "Asparagus", "Avocado", "Bamboo Shoots", "Bean Sprouts", "Beans", "Beet", "Belgian Endive", "Bell Pepper", + "Bitter Gourd", "Bok Choy", "Broccoli", "Brussels Sprouts", "Burdock Root", "Cabbage", "Calabash", "Capers", "Carrot", "Cassava", + "Cauliflower", "Celery", "Celery Root", "Celcuce", "Chayote", "Chinese Broccoli", "Corn", "Cucumber" +}; + +// Extra functions to add deletion support to ImGuiSelectionBasicStorage +struct ExampleSelectionWithDeletion : ImGuiSelectionBasicStorage +{ + // Find which item should be Focused after deletion. + // Call _before_ item submission. Retunr an index in the before-deletion item list, your item loop should call SetKeyboardFocusHere() on it. + // The subsequent ApplyDeletionPostLoop() code will use it to apply Selection. + // - We cannot provide this logic in core Dear ImGui because we don't have access to selection data. + // - We don't actually manipulate the ImVector<> here, only in ApplyDeletionPostLoop(), but using similar API for consistency and flexibility. + // - Important: Deletion only works if the underlying ImGuiID for your items are stable: aka not depend on their index, but on e.g. item id/ptr. + // FIXME-MULTISELECT: Doesn't take account of the possibility focus target will be moved during deletion. Need refocus or scroll offset. + int ApplyDeletionPreLoop(ImGuiMultiSelectIO* ms_io, int items_count) + { + if (Size == 0) + return -1; + + // If focused item is not selected... + const int focused_idx = (int)ms_io->NavIdItem; // Index of currently focused item + if (ms_io->NavIdSelected == false) // This is merely a shortcut, == Contains(adapter->IndexToStorage(items, focused_idx)) + { + ms_io->RangeSrcReset = true; // Request to recover RangeSrc from NavId next frame. Would be ok to reset even when NavIdSelected==true, but it would take an extra frame to recover RangeSrc when deleting a selected item. + return focused_idx; // Request to focus same item after deletion. + } + + // If focused item is selected: land on first unselected item after focused item. + for (int idx = focused_idx + 1; idx < items_count; idx++) + if (!Contains(GetStorageIdFromIndex(idx))) + return idx; + + // If focused item is selected: otherwise return last unselected item before focused item. + for (int idx = IM_MIN(focused_idx, items_count) - 1; idx >= 0; idx--) + if (!Contains(GetStorageIdFromIndex(idx))) + return idx; + + return -1; + } + + // Rewrite item list (delete items) + update selection. + // - Call after EndMultiSelect() + // - We cannot provide this logic in core Dear ImGui because we don't have access to your items, nor to selection data. + template + void ApplyDeletionPostLoop(ImGuiMultiSelectIO* ms_io, ImVector& items, int item_curr_idx_to_select) + { + // Rewrite item list (delete items) + convert old selection index (before deletion) to new selection index (after selection). + // If NavId was not part of selection, we will stay on same item. + ImVector new_items; + new_items.reserve(items.Size - Size); + int item_next_idx_to_select = -1; + for (int idx = 0; idx < items.Size; idx++) + { + if (!Contains(GetStorageIdFromIndex(idx))) + new_items.push_back(items[idx]); + if (item_curr_idx_to_select == idx) + item_next_idx_to_select = new_items.Size - 1; + } + items.swap(new_items); + + // Update selection + Clear(); + if (item_next_idx_to_select != -1 && ms_io->NavIdSelected) + SetItemSelected(GetStorageIdFromIndex(item_next_idx_to_select), true); + } +}; + +// Example: Implement dual list box storage and interface +struct ExampleDualListBox +{ + ImVector Items[2]; // ID is index into ExampleName[] + ImGuiSelectionBasicStorage Selections[2]; // Store ExampleItemId into selection + bool OptKeepSorted = true; + + void MoveAll(int src, int dst) + { + IM_ASSERT((src == 0 && dst == 1) || (src == 1 && dst == 0)); + for (ImGuiID item_id : Items[src]) + Items[dst].push_back(item_id); + Items[src].clear(); + SortItems(dst); + Selections[src].Swap(Selections[dst]); + Selections[src].Clear(); + } + void MoveSelected(int src, int dst) + { + for (int src_n = 0; src_n < Items[src].Size; src_n++) + { + ImGuiID item_id = Items[src][src_n]; + if (!Selections[src].Contains(item_id)) + continue; + Items[src].erase(&Items[src][src_n]); // FIXME-OPT: Could be implemented more optimally (rebuild src items and swap) + Items[dst].push_back(item_id); + src_n--; + } + if (OptKeepSorted) + SortItems(dst); + Selections[src].Swap(Selections[dst]); + Selections[src].Clear(); + } + void ApplySelectionRequests(ImGuiMultiSelectIO* ms_io, int side) + { + // In this example we store item id in selection (instead of item index) + Selections[side].UserData = Items[side].Data; + Selections[side].AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { ImGuiID* items = (ImGuiID*)self->UserData; return items[idx]; }; + Selections[side].ApplyRequests(ms_io); + } + static int IMGUI_CDECL CompareItemsByValue(const void* lhs, const void* rhs) + { + const int* a = (const int*)lhs; + const int* b = (const int*)rhs; + return (*a - *b) > 0 ? +1 : -1; + } + void SortItems(int n) + { + qsort(Items[n].Data, (size_t)Items[n].Size, sizeof(Items[n][0]), CompareItemsByValue); + } + void Show() + { + //ImGui::Checkbox("Sorted", &OptKeepSorted); + if (ImGui::BeginTable("split", 3, ImGuiTableFlags_None)) + { + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch); // Left side + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); // Buttons + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch); // Right side + ImGui::TableNextRow(); + + int request_move_selected = -1; + int request_move_all = -1; + float child_height_0 = 0.0f; + for (int side = 0; side < 2; side++) + { + // FIXME-MULTISELECT: Dual List Box: Add context menus + // FIXME-NAV: Using ImGuiWindowFlags_NavFlattened exhibit many issues. + ImVector& items = Items[side]; + ImGuiSelectionBasicStorage& selection = Selections[side]; + + ImGui::TableSetColumnIndex((side == 0) ? 0 : 2); + ImGui::Text("%s (%d)", (side == 0) ? "Available" : "Basket", items.Size); + + // Submit scrolling range to avoid glitches on moving/deletion + const float items_height = ImGui::GetTextLineHeightWithSpacing(); + ImGui::SetNextWindowContentSize(ImVec2(0.0f, items.Size * items_height)); + + bool child_visible; + if (side == 0) + { + // Left child is resizable + ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, ImGui::GetFrameHeightWithSpacing() * 4), ImVec2(FLT_MAX, FLT_MAX)); + child_visible = ImGui::BeginChild("0", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY); + child_height_0 = ImGui::GetWindowSize().y; + } + else + { + // Right child use same height as left one + child_visible = ImGui::BeginChild("1", ImVec2(-FLT_MIN, child_height_0), ImGuiChildFlags_FrameStyle); + } + if (child_visible) + { + ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_None; + ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, items.Size); + ApplySelectionRequests(ms_io, side); + + for (int item_n = 0; item_n < items.Size; item_n++) + { + ImGuiID item_id = items[item_n]; + bool item_is_selected = selection.Contains(item_id); + ImGui::SetNextItemSelectionUserData(item_n); + ImGui::Selectable(ExampleNames[item_id], item_is_selected, ImGuiSelectableFlags_AllowDoubleClick); + if (ImGui::IsItemFocused()) + { + // FIXME-MULTISELECT: Dual List Box: Transfer focus + if (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter)) + request_move_selected = side; + if (ImGui::IsMouseDoubleClicked(0)) // FIXME-MULTISELECT: Double-click on multi-selection? + request_move_selected = side; + } + } + + ms_io = ImGui::EndMultiSelect(); + ApplySelectionRequests(ms_io, side); + } + ImGui::EndChild(); + } + + // Buttons columns + ImGui::TableSetColumnIndex(1); + ImGui::NewLine(); + //ImVec2 button_sz = { ImGui::CalcTextSize(">>").x + ImGui::GetStyle().FramePadding.x * 2.0f, ImGui::GetFrameHeight() + padding.y * 2.0f }; + ImVec2 button_sz = { ImGui::GetFrameHeight(), ImGui::GetFrameHeight() }; + + // (Using BeginDisabled()/EndDisabled() works but feels distracting given how it is currently visualized) + if (ImGui::Button(">>", button_sz)) + request_move_all = 0; + if (ImGui::Button(">", button_sz)) + request_move_selected = 0; + if (ImGui::Button("<", button_sz)) + request_move_selected = 1; + if (ImGui::Button("<<", button_sz)) + request_move_all = 1; + + // Process requests + if (request_move_all != -1) + MoveAll(request_move_all, request_move_all ^ 1); + if (request_move_selected != -1) + MoveSelected(request_move_selected, request_move_selected ^ 1); + + // FIXME-MULTISELECT: Support action from outside + /* + if (OptKeepSorted == false) + { + ImGui::NewLine(); + if (ImGui::ArrowButton("MoveUp", ImGuiDir_Up)) {} + if (ImGui::ArrowButton("MoveDown", ImGuiDir_Down)) {} + } + */ + + ImGui::EndTable(); + } + } +}; + +//----------------------------------------------------------------------------- +// [SECTION] ShowDemoWindowMultiSelect() +//----------------------------------------------------------------------------- +// Multi-selection demos +// Also read: https://github.com/ocornut/imgui/wiki/Multi-Select +//----------------------------------------------------------------------------- + +static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data) +{ + IMGUI_DEMO_MARKER("Widgets/Selection State & Multi-Select"); + if (ImGui::TreeNode("Selection State & Multi-Select")) + { + HelpMarker("Selections can be built using Selectable(), TreeNode() or other widgets. Selection state is owned by application code/data."); + + // Without any fancy API: manage single-selection yourself. + IMGUI_DEMO_MARKER("Widgets/Selection State/Single-Select"); + if (ImGui::TreeNode("Single-Select")) + { + static int selected = -1; + for (int n = 0; n < 5; n++) + { + char buf[32]; + sprintf(buf, "Object %d", n); + if (ImGui::Selectable(buf, selected == n)) + selected = n; + } + ImGui::TreePop(); + } + + // Demonstrate implementation a most-basic form of multi-selection manually + // This doesn't support the SHIFT modifier which requires BeginMultiSelect()! + IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (manual/simplified, without BeginMultiSelect)"); + if (ImGui::TreeNode("Multi-Select (manual/simplified, without BeginMultiSelect)")) + { + HelpMarker("Hold CTRL and click to select multiple items."); + static bool selection[5] = { false, false, false, false, false }; + for (int n = 0; n < 5; n++) + { + char buf[32]; + sprintf(buf, "Object %d", n); + if (ImGui::Selectable(buf, selection[n])) + { + if (!ImGui::GetIO().KeyCtrl) // Clear selection when CTRL is not held + memset(selection, 0, sizeof(selection)); + selection[n] ^= 1; // Toggle current item + } + } + ImGui::TreePop(); + } + + // Demonstrate handling proper multi-selection using the BeginMultiSelect/EndMultiSelect API. + // SHIFT+Click w/ CTRL and other standard features are supported. + // We use the ImGuiSelectionBasicStorage helper which you may freely reimplement. + IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select"); + if (ImGui::TreeNode("Multi-Select")) + { + ImGui::Text("Supported features:"); + ImGui::BulletText("Keyboard navigation (arrows, page up/down, home/end, space)."); + ImGui::BulletText("Ctrl modifier to preserve and toggle selection."); + ImGui::BulletText("Shift modifier for range selection."); + ImGui::BulletText("CTRL+A to select all."); + ImGui::BulletText("Escape to clear selection."); + ImGui::BulletText("Click and drag to box-select."); + ImGui::Text("Tip: Use 'Demo->Tools->Debug Log->Selection' to see selection requests as they happen."); + + // Use default selection.Adapter: Pass index to SetNextItemSelectionUserData(), store index in Selection + const int ITEMS_COUNT = 50; + static ImGuiSelectionBasicStorage selection; + ImGui::Text("Selection: %d/%d", selection.Size, ITEMS_COUNT); + + // The BeginChild() has no purpose for selection logic, other that offering a scrolling region. + if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY)) + { + ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d; + ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, ITEMS_COUNT); + selection.ApplyRequests(ms_io); + + for (int n = 0; n < ITEMS_COUNT; n++) + { + char label[64]; + sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]); + bool item_is_selected = selection.Contains((ImGuiID)n); + ImGui::SetNextItemSelectionUserData(n); + ImGui::Selectable(label, item_is_selected); + } + + ms_io = ImGui::EndMultiSelect(); + selection.ApplyRequests(ms_io); + } + ImGui::EndChild(); + ImGui::TreePop(); + } + + // Demonstrate using the clipper with BeginMultiSelect()/EndMultiSelect() + IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (with clipper)"); + if (ImGui::TreeNode("Multi-Select (with clipper)")) + { + // Use default selection.Adapter: Pass index to SetNextItemSelectionUserData(), store index in Selection + static ImGuiSelectionBasicStorage selection; + + ImGui::Text("Added features:"); + ImGui::BulletText("Using ImGuiListClipper."); + + const int ITEMS_COUNT = 10000; + ImGui::Text("Selection: %d/%d", selection.Size, ITEMS_COUNT); + if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY)) + { + ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d; + ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, ITEMS_COUNT); + selection.ApplyRequests(ms_io); + + ImGuiListClipper clipper; + clipper.Begin(ITEMS_COUNT); + if (ms_io->RangeSrcItem != -1) + clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem); // Ensure RangeSrc item is not clipped. + while (clipper.Step()) + { + for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++) + { + char label[64]; + sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]); + bool item_is_selected = selection.Contains((ImGuiID)n); + ImGui::SetNextItemSelectionUserData(n); + ImGui::Selectable(label, item_is_selected); + } + } + + ms_io = ImGui::EndMultiSelect(); + selection.ApplyRequests(ms_io); + } + ImGui::EndChild(); + ImGui::TreePop(); + } + + // Demonstrate dynamic item list + deletion support using the BeginMultiSelect/EndMultiSelect API. + // In order to support Deletion without any glitches you need to: + // - (1) If items are submitted in their own scrolling area, submit contents size SetNextWindowContentSize() ahead of time to prevent one-frame readjustment of scrolling. + // - (2) Items needs to have persistent ID Stack identifier = ID needs to not depends on their index. PushID(index) = KO. PushID(item_id) = OK. This is in order to focus items reliably after a selection. + // - (3) BeginXXXX process + // - (4) Focus process + // - (5) EndXXXX process + IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (with deletion)"); + if (ImGui::TreeNode("Multi-Select (with deletion)")) + { + // Storing items data separately from selection data. + // (you may decide to store selection data inside your item (aka intrusive storage) if you don't need multiple views over same items) + // Use a custom selection.Adapter: store item identifier in Selection (instead of index) + static ImVector items; + static ExampleSelectionWithDeletion selection; + selection.UserData = (void*)&items; + selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { ImVector* p_items = (ImVector*)self->UserData; return (*p_items)[idx]; }; // Index -> ID + + ImGui::Text("Added features:"); + ImGui::BulletText("Dynamic list with Delete key support."); + ImGui::Text("Selection size: %d/%d", selection.Size, items.Size); + + // Initialize default list with 50 items + button to add/remove items. + static ImGuiID items_next_id = 0; + if (items_next_id == 0) + for (ImGuiID n = 0; n < 50; n++) + items.push_back(items_next_id++); + if (ImGui::SmallButton("Add 20 items")) { for (int n = 0; n < 20; n++) { items.push_back(items_next_id++); } } + ImGui::SameLine(); + if (ImGui::SmallButton("Remove 20 items")) { for (int n = IM_MIN(20, items.Size); n > 0; n--) { selection.SetItemSelected(items.back(), false); items.pop_back(); } } + + // (1) Extra to support deletion: Submit scrolling range to avoid glitches on deletion + const float items_height = ImGui::GetTextLineHeightWithSpacing(); + ImGui::SetNextWindowContentSize(ImVec2(0.0f, items.Size * items_height)); + + if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY)) + { + ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d; + ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, items.Size); + selection.ApplyRequests(ms_io); + + const bool want_delete = ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (selection.Size > 0); + const int item_curr_idx_to_focus = want_delete ? selection.ApplyDeletionPreLoop(ms_io, items.Size) : -1; + + for (int n = 0; n < items.Size; n++) + { + const ImGuiID item_id = items[n]; + char label[64]; + sprintf(label, "Object %05u: %s", item_id, ExampleNames[item_id % IM_ARRAYSIZE(ExampleNames)]); + + bool item_is_selected = selection.Contains(item_id); + ImGui::SetNextItemSelectionUserData(n); + ImGui::Selectable(label, item_is_selected); + if (item_curr_idx_to_focus == n) + ImGui::SetKeyboardFocusHere(-1); + } + + // Apply multi-select requests + ms_io = ImGui::EndMultiSelect(); + selection.ApplyRequests(ms_io); + if (want_delete) + selection.ApplyDeletionPostLoop(ms_io, items, item_curr_idx_to_focus); + } + ImGui::EndChild(); + ImGui::TreePop(); + } + + // Implement a Dual List Box (#6648) + IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (dual list box)"); + if (ImGui::TreeNode("Multi-Select (dual list box)")) + { + // Init default state + static ExampleDualListBox dlb; + if (dlb.Items[0].Size == 0 && dlb.Items[1].Size == 0) + for (int item_id = 0; item_id < IM_ARRAYSIZE(ExampleNames); item_id++) + dlb.Items[0].push_back((ImGuiID)item_id); + + // Show + dlb.Show(); + + ImGui::TreePop(); + } + + // Demonstrate using the clipper with BeginMultiSelect()/EndMultiSelect() + IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (in a table)"); + if (ImGui::TreeNode("Multi-Select (in a table)")) + { + static ImGuiSelectionBasicStorage selection; + + const int ITEMS_COUNT = 10000; + ImGui::Text("Selection: %d/%d", selection.Size, ITEMS_COUNT); + if (ImGui::BeginTable("##Basket", 2, ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter)) + { + ImGui::TableSetupColumn("Object"); + ImGui::TableSetupColumn("Action"); + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableHeadersRow(); + + ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d; + ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, ITEMS_COUNT); + selection.ApplyRequests(ms_io); + + ImGuiListClipper clipper; + clipper.Begin(ITEMS_COUNT); + if (ms_io->RangeSrcItem != -1) + clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem); // Ensure RangeSrc item is not clipped. + while (clipper.Step()) + { + for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++) + { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + char label[64]; + sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]); + bool item_is_selected = selection.Contains((ImGuiID)n); + ImGui::SetNextItemSelectionUserData(n); + ImGui::Selectable(label, item_is_selected, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap); + ImGui::TableNextColumn(); + ImGui::SmallButton("hello"); + } + } + + ms_io = ImGui::EndMultiSelect(); + selection.ApplyRequests(ms_io); + ImGui::EndTable(); + } + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (checkboxes)"); + if (ImGui::TreeNode("Multi-Select (checkboxes)")) + { + ImGui::Text("In a list of checkboxes (not selectable):"); + ImGui::BulletText("Using _NoAutoSelect + _NoAutoClear flags."); + ImGui::BulletText("Shift+Click to check multiple boxes."); + ImGui::BulletText("Shift+Keyboard to copy current value to other boxes."); + + // If you have an array of checkboxes, you may want to use NoAutoSelect + NoAutoClear and the ImGuiSelectionExternalStorage helper. + static bool items[20] = {}; + static ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_NoAutoSelect | ImGuiMultiSelectFlags_NoAutoClear | ImGuiMultiSelectFlags_ClearOnEscape; + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoSelect", &flags, ImGuiMultiSelectFlags_NoAutoSelect); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClear", &flags, ImGuiMultiSelectFlags_NoAutoClear); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect2d", &flags, ImGuiMultiSelectFlags_BoxSelect2d); // Cannot use ImGuiMultiSelectFlags_BoxSelect1d as checkboxes are varying width. + + if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeY)) + { + ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, -1, IM_ARRAYSIZE(items)); + ImGuiSelectionExternalStorage storage_wrapper; + storage_wrapper.UserData = (void*)items; + storage_wrapper.AdapterSetItemSelected = [](ImGuiSelectionExternalStorage* self, int n, bool selected) { bool* array = (bool*)self->UserData; array[n] = selected; }; + storage_wrapper.ApplyRequests(ms_io); + for (int n = 0; n < 20; n++) + { + char label[32]; + sprintf(label, "Item %d", n); + ImGui::SetNextItemSelectionUserData(n); + ImGui::Checkbox(label, &items[n]); + } + ms_io = ImGui::EndMultiSelect(); + storage_wrapper.ApplyRequests(ms_io); + } + ImGui::EndChild(); + + ImGui::TreePop(); + } + + // Demonstrate individual selection scopes in same window + IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (multiple scopes)"); + if (ImGui::TreeNode("Multi-Select (multiple scopes)")) + { + // Use default select: Pass index to SetNextItemSelectionUserData(), store index in Selection + const int SCOPES_COUNT = 3; + const int ITEMS_COUNT = 8; // Per scope + static ImGuiSelectionBasicStorage selections_data[SCOPES_COUNT]; + + // Use ImGuiMultiSelectFlags_ScopeRect to not affect other selections in same window. + static ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ScopeRect | ImGuiMultiSelectFlags_ClearOnEscape;// | ImGuiMultiSelectFlags_ClearOnClickVoid; + if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ScopeWindow", &flags, ImGuiMultiSelectFlags_ScopeWindow) && (flags & ImGuiMultiSelectFlags_ScopeWindow)) + flags &= ~ImGuiMultiSelectFlags_ScopeRect; + if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ScopeRect", &flags, ImGuiMultiSelectFlags_ScopeRect) && (flags & ImGuiMultiSelectFlags_ScopeRect)) + flags &= ~ImGuiMultiSelectFlags_ScopeWindow; + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnClickVoid", &flags, ImGuiMultiSelectFlags_ClearOnClickVoid); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect1d", &flags, ImGuiMultiSelectFlags_BoxSelect1d); + + for (int selection_scope_n = 0; selection_scope_n < SCOPES_COUNT; selection_scope_n++) + { + ImGui::PushID(selection_scope_n); + ImGuiSelectionBasicStorage* selection = &selections_data[selection_scope_n]; + ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection->Size, ITEMS_COUNT); + selection->ApplyRequests(ms_io); + + ImGui::SeparatorText("Selection scope"); + ImGui::Text("Selection size: %d/%d", selection->Size, ITEMS_COUNT); + + for (int n = 0; n < ITEMS_COUNT; n++) + { + char label[64]; + sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]); + bool item_is_selected = selection->Contains((ImGuiID)n); + ImGui::SetNextItemSelectionUserData(n); + ImGui::Selectable(label, item_is_selected); + } + + // Apply multi-select requests + ms_io = ImGui::EndMultiSelect(); + selection->ApplyRequests(ms_io); + ImGui::PopID(); + } + ImGui::TreePop(); + } + + // See ShowExampleAppAssetsBrowser() + if (ImGui::TreeNode("Multi-Select (tiled assets browser)")) + { + ImGui::Checkbox("Assets Browser", &demo_data->ShowAppAssetsBrowser); + ImGui::Text("(also access from 'Examples->Assets Browser' in menu)"); + ImGui::TreePop(); + } + + // Demonstrate supporting multiple-selection in a tree. + // - We don't use linear indices for selection user data, but our ExampleTreeNode* pointer directly! + // This showcase how SetNextItemSelectionUserData() never assume indices! + // - The difficulty here is to "interpolate" from RangeSrcItem to RangeDstItem in the SetAll/SetRange request. + // We want this interpolation to match what the user sees: in visible order, skipping closed nodes. + // This is implemented by our TreeGetNextNodeInVisibleOrder() user-space helper. + // - Important: In a real codebase aiming to implement full-featured selectable tree with custom filtering, you + // are more likely to build an array mapping sequential indices to visible tree nodes, since your + // filtering/search + clipping process will benefit from it. Having this will make this interpolation much easier. + // - Consider this a prototype: we are working toward simplifying some of it. + IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (trees)"); + if (ImGui::TreeNode("Multi-Select (trees)")) + { + HelpMarker( + "This is rather advanced and experimental. If you are getting started with multi-select," + "please don't start by looking at how to use it for a tree!\n\n" + "Future versions will try to simplify and formalize some of this."); + + struct ExampleTreeFuncs + { + static void DrawNode(ExampleTreeNode* node, ImGuiSelectionBasicStorage* selection) + { + ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_NavLeftJumpsBackHere; // Enable pressing left to jump to parent + if (node->Childs.Size == 0) + tree_node_flags |= ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_Leaf; + if (selection->Contains((ImGuiID)node->UID)) + tree_node_flags |= ImGuiTreeNodeFlags_Selected; + + // Using SetNextItemStorageID() to specify storage id, so we can easily peek into + // the storage holding open/close stage, using our TreeNodeGetOpen/TreeNodeSetOpen() functions. + ImGui::SetNextItemSelectionUserData((ImGuiSelectionUserData)(intptr_t)node); + ImGui::SetNextItemStorageID((ImGuiID)node->UID); + if (ImGui::TreeNodeEx(node->Name, tree_node_flags)) + { + for (ExampleTreeNode* child : node->Childs) + DrawNode(child, selection); + ImGui::TreePop(); + } + else if (ImGui::IsItemToggledOpen()) + { + TreeCloseAndUnselectChildNodes(node, selection); + } + } + + static bool TreeNodeGetOpen(ExampleTreeNode* node) + { + return ImGui::GetStateStorage()->GetBool((ImGuiID)node->UID); + } + + static void TreeNodeSetOpen(ExampleTreeNode* node, bool open) + { + ImGui::GetStateStorage()->SetBool((ImGuiID)node->UID, open); + } + + // When closing a node: 1) close and unselect all child nodes, 2) select parent if any child was selected. + // FIXME: This is currently handled by user logic but I'm hoping to eventually provide tree node + // features to do this automatically, e.g. a ImGuiTreeNodeFlags_AutoCloseChildNodes etc. + static int TreeCloseAndUnselectChildNodes(ExampleTreeNode* node, ImGuiSelectionBasicStorage* selection, int depth = 0) + { + // Recursive close (the test for depth == 0 is because we call this on a node that was just closed!) + int unselected_count = selection->Contains((ImGuiID)node->UID) ? 1 : 0; + if (depth == 0 || TreeNodeGetOpen(node)) + { + for (ExampleTreeNode* child : node->Childs) + unselected_count += TreeCloseAndUnselectChildNodes(child, selection, depth + 1); + TreeNodeSetOpen(node, false); + } + + // Select root node if any of its child was selected, otherwise unselect + selection->SetItemSelected((ImGuiID)node->UID, (depth == 0 && unselected_count > 0)); + return unselected_count; + } + + // Apply multi-selection requests + static void ApplySelectionRequests(ImGuiMultiSelectIO* ms_io, ExampleTreeNode* tree, ImGuiSelectionBasicStorage* selection) + { + for (ImGuiSelectionRequest& req : ms_io->Requests) + { + if (req.Type == ImGuiSelectionRequestType_SetAll) + { + if (req.Selected) + TreeSetAllInOpenNodes(tree, selection, req.Selected); + else + selection->Clear(); + } + else if (req.Type == ImGuiSelectionRequestType_SetRange) + { + ExampleTreeNode* first_node = (ExampleTreeNode*)(intptr_t)req.RangeFirstItem; + ExampleTreeNode* last_node = (ExampleTreeNode*)(intptr_t)req.RangeLastItem; + for (ExampleTreeNode* node = first_node; node != NULL; node = TreeGetNextNodeInVisibleOrder(node, last_node)) + selection->SetItemSelected((ImGuiID)node->UID, req.Selected); + } + } + } + + static void TreeSetAllInOpenNodes(ExampleTreeNode* node, ImGuiSelectionBasicStorage* selection, bool selected) + { + if (node->Parent != NULL) // Root node isn't visible nor selectable in our scheme + selection->SetItemSelected((ImGuiID)node->UID, selected); + if (node->Parent == NULL || TreeNodeGetOpen(node)) + for (ExampleTreeNode* child : node->Childs) + TreeSetAllInOpenNodes(child, selection, selected); + } + + // Interpolate in *user-visible order* AND only *over opened nodes*. + // If you have a sequential mapping tables (e.g. generated after a filter/search pass) this would be simpler. + // Here the tricks are that: + // - we store/maintain ExampleTreeNode::IndexInParent which allows implementing a linear iterator easily, without searches, without recursion. + // this could be replaced by a search in parent, aka 'int index_in_parent = curr_node->Parent->Childs.find_index(curr_node)' + // which would only be called when crossing from child to a parent, aka not too much. + // - we call SetNextItemStorageID() before our TreeNode() calls with an ID which doesn't relate to UI stack, + // making it easier to call TreeNodeGetOpen()/TreeNodeSetOpen() from any location. + static ExampleTreeNode* TreeGetNextNodeInVisibleOrder(ExampleTreeNode* curr_node, ExampleTreeNode* last_node) + { + // Reached last node + if (curr_node == last_node) + return NULL; + + // Recurse into childs. Query storage to tell if the node is open. + if (curr_node->Childs.Size > 0 && TreeNodeGetOpen(curr_node)) + return curr_node->Childs[0]; + + // Next sibling, then into our own parent + while (curr_node->Parent != NULL) + { + if (curr_node->IndexInParent + 1 < curr_node->Parent->Childs.Size) + return curr_node->Parent->Childs[curr_node->IndexInParent + 1]; + curr_node = curr_node->Parent; + } + return NULL; + } + + }; // ExampleTreeFuncs + + static ImGuiSelectionBasicStorage selection; + if (demo_data->DemoTree == NULL) + demo_data->DemoTree = ExampleTree_CreateDemoTree(); // Create tree once + ImGui::Text("Selection size: %d", selection.Size); + + if (ImGui::BeginChild("##Tree", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY)) + { + ExampleTreeNode* tree = demo_data->DemoTree; + ImGuiMultiSelectFlags ms_flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect2d; + ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(ms_flags, selection.Size, -1); + ExampleTreeFuncs::ApplySelectionRequests(ms_io, tree, &selection); + for (ExampleTreeNode* node : tree->Childs) + ExampleTreeFuncs::DrawNode(node, &selection); + ms_io = ImGui::EndMultiSelect(); + ExampleTreeFuncs::ApplySelectionRequests(ms_io, tree, &selection); + } + ImGui::EndChild(); + + ImGui::TreePop(); + } + + // Advanced demonstration of BeginMultiSelect() + // - Showcase clipping. + // - Showcase deletion. + // - Showcase basic drag and drop. + // - Showcase TreeNode variant (note that tree node don't expand in the demo: supporting expanding tree nodes + clipping a separate thing). + // - Showcase using inside a table. + IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (advanced)"); + //ImGui::SetNextItemOpen(true, ImGuiCond_Once); + if (ImGui::TreeNode("Multi-Select (advanced)")) + { + // Options + enum WidgetType { WidgetType_Selectable, WidgetType_TreeNode }; + static bool use_clipper = true; + static bool use_deletion = true; + static bool use_drag_drop = true; + static bool show_in_table = false; + static bool show_color_button = true; + static ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d; + static WidgetType widget_type = WidgetType_Selectable; + + if (ImGui::TreeNode("Options")) + { + if (ImGui::RadioButton("Selectables", widget_type == WidgetType_Selectable)) { widget_type = WidgetType_Selectable; } + ImGui::SameLine(); + if (ImGui::RadioButton("Tree nodes", widget_type == WidgetType_TreeNode)) { widget_type = WidgetType_TreeNode; } + ImGui::SameLine(); + HelpMarker("TreeNode() is technically supported but... using this correctly is more complicated (you need some sort of linear/random access to your tree, which is suited to advanced trees setups already implementing filters and clipper. We will work toward simplifying and demoing this.\n\nFor now the tree demo is actually a little bit meaningless because it is an empty tree with only root nodes."); + ImGui::Checkbox("Enable clipper", &use_clipper); + ImGui::Checkbox("Enable deletion", &use_deletion); + ImGui::Checkbox("Enable drag & drop", &use_drag_drop); + ImGui::Checkbox("Show in a table", &show_in_table); + ImGui::Checkbox("Show color button", &show_color_button); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_SingleSelect", &flags, ImGuiMultiSelectFlags_SingleSelect); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoSelectAll", &flags, ImGuiMultiSelectFlags_NoSelectAll); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoRangeSelect", &flags, ImGuiMultiSelectFlags_NoRangeSelect); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoSelect", &flags, ImGuiMultiSelectFlags_NoAutoSelect); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClear", &flags, ImGuiMultiSelectFlags_NoAutoClear); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClearOnReselect", &flags, ImGuiMultiSelectFlags_NoAutoClearOnReselect); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect1d", &flags, ImGuiMultiSelectFlags_BoxSelect1d); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect2d", &flags, ImGuiMultiSelectFlags_BoxSelect2d); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelectNoScroll", &flags, ImGuiMultiSelectFlags_BoxSelectNoScroll); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnEscape", &flags, ImGuiMultiSelectFlags_ClearOnEscape); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnClickVoid", &flags, ImGuiMultiSelectFlags_ClearOnClickVoid); + if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ScopeWindow", &flags, ImGuiMultiSelectFlags_ScopeWindow) && (flags & ImGuiMultiSelectFlags_ScopeWindow)) + flags &= ~ImGuiMultiSelectFlags_ScopeRect; + if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ScopeRect", &flags, ImGuiMultiSelectFlags_ScopeRect) && (flags & ImGuiMultiSelectFlags_ScopeRect)) + flags &= ~ImGuiMultiSelectFlags_ScopeWindow; + if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_SelectOnClick", &flags, ImGuiMultiSelectFlags_SelectOnClick) && (flags & ImGuiMultiSelectFlags_SelectOnClick)) + flags &= ~ImGuiMultiSelectFlags_SelectOnClickRelease; + if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_SelectOnClickRelease", &flags, ImGuiMultiSelectFlags_SelectOnClickRelease) && (flags & ImGuiMultiSelectFlags_SelectOnClickRelease)) + flags &= ~ImGuiMultiSelectFlags_SelectOnClick; + ImGui::SameLine(); HelpMarker("Allow dragging an unselected item without altering selection."); + ImGui::TreePop(); + } + + // Initialize default list with 1000 items. + // Use default selection.Adapter: Pass index to SetNextItemSelectionUserData(), store index in Selection + static ImVector items; + static int items_next_id = 0; + if (items_next_id == 0) { for (int n = 0; n < 1000; n++) { items.push_back(items_next_id++); } } + static ExampleSelectionWithDeletion selection; + static bool request_deletion_from_menu = false; // Queue deletion triggered from context menu + + ImGui::Text("Selection size: %d/%d", selection.Size, items.Size); + + const float items_height = (widget_type == WidgetType_TreeNode) ? ImGui::GetTextLineHeight() : ImGui::GetTextLineHeightWithSpacing(); + ImGui::SetNextWindowContentSize(ImVec2(0.0f, items.Size * items_height)); + if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY)) + { + ImVec2 color_button_sz(ImGui::GetFontSize(), ImGui::GetFontSize()); + if (widget_type == WidgetType_TreeNode) + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(ImGui::GetStyle().ItemSpacing.x, 0.0f)); + + ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, items.Size); + selection.ApplyRequests(ms_io); + + const bool want_delete = (ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (selection.Size > 0)) || request_deletion_from_menu; + const int item_curr_idx_to_focus = want_delete ? selection.ApplyDeletionPreLoop(ms_io, items.Size) : -1; + request_deletion_from_menu = false; + + if (show_in_table) + { + if (widget_type == WidgetType_TreeNode) + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0.0f, 0.0f)); + ImGui::BeginTable("##Split", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_NoPadOuterX); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.70f); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.30f); + //ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(ImGui::GetStyle().ItemSpacing.x, 0.0f)); + } + + ImGuiListClipper clipper; + if (use_clipper) + { + clipper.Begin(items.Size); + if (item_curr_idx_to_focus != -1) + clipper.IncludeItemByIndex(item_curr_idx_to_focus); // Ensure focused item is not clipped. + if (ms_io->RangeSrcItem != -1) + clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem); // Ensure RangeSrc item is not clipped. + } + + while (!use_clipper || clipper.Step()) + { + const int item_begin = use_clipper ? clipper.DisplayStart : 0; + const int item_end = use_clipper ? clipper.DisplayEnd : items.Size; + for (int n = item_begin; n < item_end; n++) + { + if (show_in_table) + ImGui::TableNextColumn(); + + const int item_id = items[n]; + const char* item_category = ExampleNames[item_id % IM_ARRAYSIZE(ExampleNames)]; + char label[64]; + sprintf(label, "Object %05d: %s", item_id, item_category); + + // IMPORTANT: for deletion refocus to work we need object ID to be stable, + // aka not depend on their index in the list. Here we use our persistent item_id + // instead of index to build a unique ID that will persist. + // (If we used PushID(index) instead, focus wouldn't be restored correctly after deletion). + ImGui::PushID(item_id); + + // Emit a color button, to test that Shift+LeftArrow landing on an item that is not part + // of the selection scope doesn't erroneously alter our selection. + if (show_color_button) + { + ImU32 dummy_col = (ImU32)((unsigned int)n * 0xC250B74B) | IM_COL32_A_MASK; + ImGui::ColorButton("##", ImColor(dummy_col), ImGuiColorEditFlags_NoTooltip, color_button_sz); + ImGui::SameLine(); + } + + // Submit item + bool item_is_selected = selection.Contains((ImGuiID)n); + bool item_is_open = false; + ImGui::SetNextItemSelectionUserData(n); + if (widget_type == WidgetType_Selectable) + { + ImGui::Selectable(label, item_is_selected, ImGuiSelectableFlags_None); + } + else if (widget_type == WidgetType_TreeNode) + { + ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; + if (item_is_selected) + tree_node_flags |= ImGuiTreeNodeFlags_Selected; + item_is_open = ImGui::TreeNodeEx(label, tree_node_flags); + } + + // Focus (for after deletion) + if (item_curr_idx_to_focus == n) + ImGui::SetKeyboardFocusHere(-1); + + // Drag and Drop + if (use_drag_drop && ImGui::BeginDragDropSource()) + { + // Create payload with full selection OR single unselected item. + // (the later is only possible when using ImGuiMultiSelectFlags_SelectOnClickRelease) + if (ImGui::GetDragDropPayload() == NULL) + { + ImVector payload_items; + void* it = NULL; + ImGuiID id = 0; + if (!item_is_selected) + payload_items.push_back(item_id); + else + while (selection.GetNextSelectedItem(&it, &id)) + payload_items.push_back((int)id); + ImGui::SetDragDropPayload("MULTISELECT_DEMO_ITEMS", payload_items.Data, (size_t)payload_items.size_in_bytes()); + } + + // Display payload content in tooltip + const ImGuiPayload* payload = ImGui::GetDragDropPayload(); + const int* payload_items = (int*)payload->Data; + const int payload_count = (int)payload->DataSize / (int)sizeof(int); + if (payload_count == 1) + ImGui::Text("Object %05d: %s", payload_items[0], ExampleNames[payload_items[0] % IM_ARRAYSIZE(ExampleNames)]); + else + ImGui::Text("Dragging %d objects", payload_count); + + ImGui::EndDragDropSource(); + } + + if (widget_type == WidgetType_TreeNode && item_is_open) + ImGui::TreePop(); + + // Right-click: context menu + if (ImGui::BeginPopupContextItem()) + { + ImGui::BeginDisabled(!use_deletion || selection.Size == 0); + sprintf(label, "Delete %d item(s)###DeleteSelected", selection.Size); + if (ImGui::Selectable(label)) + request_deletion_from_menu = true; + ImGui::EndDisabled(); + ImGui::Selectable("Close"); + ImGui::EndPopup(); + } + + // Demo content within a table + if (show_in_table) + { + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(-FLT_MIN); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); + ImGui::InputText("###NoLabel", (char*)(void*)item_category, strlen(item_category), ImGuiInputTextFlags_ReadOnly); + ImGui::PopStyleVar(); + } + + ImGui::PopID(); + } + if (!use_clipper) + break; + } + + if (show_in_table) + { + ImGui::EndTable(); + if (widget_type == WidgetType_TreeNode) + ImGui::PopStyleVar(); + } + + // Apply multi-select requests + ms_io = ImGui::EndMultiSelect(); + selection.ApplyRequests(ms_io); + if (want_delete) + selection.ApplyDeletionPostLoop(ms_io, items, item_curr_idx_to_focus); + + if (widget_type == WidgetType_TreeNode) + ImGui::PopStyleVar(); + } + ImGui::EndChild(); + ImGui::TreePop(); + } + ImGui::TreePop(); + } +} + +//----------------------------------------------------------------------------- +// [SECTION] ShowDemoWindowLayout() +//----------------------------------------------------------------------------- + static void ShowDemoWindowLayout() { IMGUI_DEMO_MARKER("Layout"); @@ -3147,7 +4211,7 @@ static void ShowDemoWindowLayout() ImGui::Text("Manual wrapping:"); ImGuiStyle& style = ImGui::GetStyle(); int buttons_count = 20; - float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x; + float window_visible_x2 = ImGui::GetCursorScreenPos().x + ImGui::GetContentRegionAvail().x; for (int n = 0; n < buttons_count; n++) { ImGui::PushID(n); @@ -3615,8 +4679,8 @@ static void ShowDemoWindowLayout() ImGui::TreePop(); } - IMGUI_DEMO_MARKER("Layout/Clipping"); - if (ImGui::TreeNode("Clipping")) + IMGUI_DEMO_MARKER("Layout/Text Clipping"); + if (ImGui::TreeNode("Text Clipping")) { static ImVec2 size(100.0f, 100.0f); static ImVec2 offset(30.0f, 30.0f); @@ -3712,6 +4776,10 @@ static void ShowDemoWindowLayout() } } +//----------------------------------------------------------------------------- +// [SECTION] ShowDemoWindowPopups() +//----------------------------------------------------------------------------- + static void ShowDemoWindowPopups() { IMGUI_DEMO_MARKER("Popups"); @@ -4172,6 +5240,10 @@ static void ShowTableColumnsStatusFlags(ImGuiTableColumnFlags flags) ImGui::CheckboxFlags("_IsHovered", &flags, ImGuiTableColumnFlags_IsHovered); } +//----------------------------------------------------------------------------- +// [SECTION] ShowDemoWindowTables() +//----------------------------------------------------------------------------- + static void ShowDemoWindowTables() { //ImGui::SetNextItemOpen(true, ImGuiCond_Once); @@ -4290,7 +5362,7 @@ static void ShowDemoWindowTables() PushStyleCompact(); ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg); ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags, ImGuiTableFlags_Borders); - ImGui::SameLine(); HelpMarker("ImGuiTableFlags_Borders\n = ImGuiTableFlags_BordersInnerV\n | ImGuiTableFlags_BordersOuterV\n | ImGuiTableFlags_BordersInnerV\n | ImGuiTableFlags_BordersOuterH"); + ImGui::SameLine(); HelpMarker("ImGuiTableFlags_Borders\n = ImGuiTableFlags_BordersInnerV\n | ImGuiTableFlags_BordersOuterV\n | ImGuiTableFlags_BordersInnerH\n | ImGuiTableFlags_BordersOuterH"); ImGui::Indent(); ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags, ImGuiTableFlags_BordersH); @@ -5944,7 +7016,6 @@ static void ShowDemoWindowTables() // Show data // FIXME-TABLE FIXME-NAV: How we can get decent up/down even though we have the buttons here? - ImGui::PushButtonRepeat(true); #if 1 // Demonstrate using clipper for large vertical lists ImGuiListClipper clipper; @@ -6029,7 +7100,6 @@ static void ShowDemoWindowTables() ImGui::PopID(); } } - ImGui::PopButtonRepeat(); // Store some info to display debug details below table_scroll_cur = ImVec2(ImGui::GetScrollX(), ImGui::GetScrollY()); @@ -6267,6 +7337,10 @@ static void ShowDemoWindowColumns() ImGui::TreePop(); } +//----------------------------------------------------------------------------- +// [SECTION] ShowDemoWindowInputs() +//----------------------------------------------------------------------------- + static void ShowDemoWindowInputs() { IMGUI_DEMO_MARKER("Inputs & Focus"); @@ -6492,10 +7566,10 @@ static void ShowDemoWindowInputs() ImGui::InputText("1", buf, IM_ARRAYSIZE(buf)); ImGui::InputText("2", buf, IM_ARRAYSIZE(buf)); ImGui::InputText("3", buf, IM_ARRAYSIZE(buf)); - ImGui::PushTabStop(false); + ImGui::PushItemFlag(ImGuiItemFlags_NoTabStop, true); ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf)); ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab."); - ImGui::PopTabStop(); + ImGui::PopItemFlag(); ImGui::InputText("5", buf, IM_ARRAYSIZE(buf)); ImGui::TreePop(); } @@ -6517,12 +7591,12 @@ static void ShowDemoWindowInputs() ImGui::InputText("2", buf, IM_ARRAYSIZE(buf)); if (ImGui::IsItemActive()) has_focus = 2; - ImGui::PushTabStop(false); + ImGui::PushItemFlag(ImGuiItemFlags_NoTabStop, true); if (focus_3) ImGui::SetKeyboardFocusHere(); ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf)); if (ImGui::IsItemActive()) has_focus = 3; ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab."); - ImGui::PopTabStop(); + ImGui::PopItemFlag(); if (has_focus) ImGui::Text("Item with focus: %d", has_focus); @@ -6587,6 +7661,17 @@ void ImGui::ShowAboutWindow(bool* p_open) } IMGUI_DEMO_MARKER("Tools/About Dear ImGui"); ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM); + + ImGui::TextLinkOpenURL("Homepage", "https://github.com/ocornut/imgui"); + ImGui::SameLine(); + ImGui::TextLinkOpenURL("FAQ", "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md"); + ImGui::SameLine(); + ImGui::TextLinkOpenURL("Wiki", "https://github.com/ocornut/imgui/wiki"); + ImGui::SameLine(); + ImGui::TextLinkOpenURL("Releases", "https://github.com/ocornut/imgui/releases"); + ImGui::SameLine(); + ImGui::TextLinkOpenURL("Funding", "https://github.com/ocornut/imgui/wiki/Funding"); + ImGui::Separator(); ImGui::Text("By Omar Cornut and all Dear ImGui contributors."); ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information."); @@ -6863,6 +7948,8 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f"); ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f"); ImGui::SliderFloat("TabBarBorderSize", &style.TabBarBorderSize, 0.0f, 2.0f, "%.0f"); + ImGui::SliderFloat("TabBarOverlineSize", &style.TabBarOverlineSize, 0.0f, 2.0f, "%.0f"); + ImGui::SameLine(); HelpMarker("Overline is only drawn over the selected tab when ImGuiTabBarFlags_DrawSelectedOverline is set."); ImGui::SeparatorText("Rounding"); ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f"); @@ -7846,57 +8933,130 @@ static void ShowExampleAppLayout(bool* p_open) //----------------------------------------------------------------------------- // [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor() //----------------------------------------------------------------------------- +// Some of the interactions are a bit lack-luster: +// - We would want pressing validating or leaving the filter to somehow restore focus. +// - We may want more advanced filtering (child nodes) and clipper support: both will need extra work. +// - We would want to customize some keyboard interactions to easily keyboard navigate between the tree and the properties. +//----------------------------------------------------------------------------- -static void ShowPlaceholderObject(const char* prefix, int uid) +struct ExampleAppPropertyEditor { - // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID. - ImGui::PushID(uid); + ImGuiTextFilter Filter; + ExampleTreeNode* VisibleNode = NULL; - // Text and Tree nodes are less high than framed widgets, using AlignTextToFramePadding() we add vertical spacing to make the tree lines equal high. - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::AlignTextToFramePadding(); - bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid); - ImGui::TableSetColumnIndex(1); - ImGui::Text("my sailor is rich"); - - if (node_open) + void Draw(ExampleTreeNode* root_node) { - static float placeholder_members[8] = { 0.0f, 0.0f, 1.0f, 3.1416f, 100.0f, 999.0f }; - for (int i = 0; i < 8; i++) + // Left side: draw tree + // - Currently using a table to benefit from RowBg feature + if (ImGui::BeginChild("##tree", ImVec2(300, 0), ImGuiChildFlags_ResizeX | ImGuiChildFlags_Border | ImGuiChildFlags_NavFlattened)) { - ImGui::PushID(i); // Use field index as identifier. - if (i < 2) - { - ShowPlaceholderObject("Child", 424242); - } - else - { - // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well) - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::AlignTextToFramePadding(); - ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet; - ImGui::TreeNodeEx("Field", flags, "Field_%d", i); + ImGui::SetNextItemWidth(-FLT_MIN); + ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip); + ImGui::PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true); + if (ImGui::InputTextWithHint("##Filter", "incl,-excl", Filter.InputBuf, IM_ARRAYSIZE(Filter.InputBuf), ImGuiInputTextFlags_EscapeClearsAll)) + Filter.Build(); + ImGui::PopItemFlag(); - ImGui::TableSetColumnIndex(1); - ImGui::SetNextItemWidth(-FLT_MIN); - if (i >= 5) - ImGui::InputFloat("##value", &placeholder_members[i], 1.0f); - else - ImGui::DragFloat("##value", &placeholder_members[i], 0.01f); - ImGui::NextColumn(); + if (ImGui::BeginTable("##bg", 1, ImGuiTableFlags_RowBg)) + { + for (ExampleTreeNode* node : root_node->Childs) + if (Filter.PassFilter(node->Name)) // Filter root node + DrawTreeNode(node); + ImGui::EndTable(); } - ImGui::PopID(); } - ImGui::TreePop(); - } - ImGui::PopID(); -} + ImGui::EndChild(); -// Demonstrate create a simple property editor. -// This demo is a bit lackluster nowadays, would be nice to improve. -static void ShowExampleAppPropertyEditor(bool* p_open) + // Right side: draw properties + ImGui::SameLine(); + + ImGui::BeginGroup(); // Lock X position + if (ExampleTreeNode* node = VisibleNode) + { + ImGui::Text("%s", node->Name); + ImGui::TextDisabled("UID: 0x%08X", node->UID); + ImGui::Separator(); + if (ImGui::BeginTable("##properties", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY)) + { + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 2.0f); // Default twice larger + if (node->HasData) + { + // In a typical application, the structure description would be derived from a data-driven system. + // - We try to mimic this with our ExampleMemberInfo structure and the ExampleTreeNodeMemberInfos[] array. + // - Limits and some details are hard-coded to simplify the demo. + for (const ExampleMemberInfo& field_desc : ExampleTreeNodeMemberInfos) + { + ImGui::TableNextRow(); + ImGui::PushID(field_desc.Name); + ImGui::TableNextColumn(); + ImGui::AlignTextToFramePadding(); + ImGui::TextUnformatted(field_desc.Name); + ImGui::TableNextColumn(); + void* field_ptr = (void*)(((unsigned char*)node) + field_desc.Offset); + switch (field_desc.DataType) + { + case ImGuiDataType_Bool: + { + IM_ASSERT(field_desc.DataCount == 1); + ImGui::Checkbox("##Editor", (bool*)field_ptr); + break; + } + case ImGuiDataType_S32: + { + int v_min = INT_MIN, v_max = INT_MAX; + ImGui::SetNextItemWidth(-FLT_MIN); + ImGui::DragScalarN("##Editor", field_desc.DataType, field_ptr, field_desc.DataCount, 1.0f, &v_min, &v_max); + break; + } + case ImGuiDataType_Float: + { + float v_min = 0.0f, v_max = 1.0f; + ImGui::SetNextItemWidth(-FLT_MIN); + ImGui::SliderScalarN("##Editor", field_desc.DataType, field_ptr, field_desc.DataCount, &v_min, &v_max); + break; + } + } + ImGui::PopID(); + } + } + ImGui::EndTable(); + } + } + ImGui::EndGroup(); + } + + void DrawTreeNode(ExampleTreeNode* node) + { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::PushID(node->UID); + ImGuiTreeNodeFlags tree_flags = ImGuiTreeNodeFlags_None; + tree_flags |= ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; // Standard opening mode as we are likely to want to add selection afterwards + tree_flags |= ImGuiTreeNodeFlags_NavLeftJumpsBackHere; // Left arrow support + if (node == VisibleNode) + tree_flags |= ImGuiTreeNodeFlags_Selected; + if (node->Childs.Size == 0) + tree_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet; + if (node->DataMyBool == false) + ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]); + bool node_open = ImGui::TreeNodeEx("", tree_flags, "%s", node->Name); + if (node->DataMyBool == false) + ImGui::PopStyleColor(); + if (ImGui::IsItemFocused()) + VisibleNode = node; + if (node_open) + { + for (ExampleTreeNode* child : node->Childs) + DrawTreeNode(child); + ImGui::TreePop(); + } + ImGui::PopID(); + } +}; + +// Demonstrate creating a simple property editor. +static void ShowExampleAppPropertyEditor(bool* p_open, ImGuiDemoWindowData* demo_data) { ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver); if (!ImGui::Begin("Example: Property editor", p_open)) @@ -7906,25 +9066,11 @@ static void ShowExampleAppPropertyEditor(bool* p_open) } IMGUI_DEMO_MARKER("Examples/Property Editor"); - HelpMarker( - "This example shows how you may implement a property editor using two columns.\n" - "All objects/fields data are dummies here.\n"); + static ExampleAppPropertyEditor property_editor; + if (demo_data->DemoTree == NULL) + demo_data->DemoTree = ExampleTree_CreateDemoTree(); + property_editor.Draw(demo_data->DemoTree); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); - if (ImGui::BeginTable("##split", 2, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY)) - { - ImGui::TableSetupScrollFreeze(0, 1); - ImGui::TableSetupColumn("Object"); - ImGui::TableSetupColumn("Contents"); - ImGui::TableHeadersRow(); - - // Iterate placeholder objects (all the same data) - for (int obj_i = 0; obj_i < 4; obj_i++) - ShowPlaceholderObject("Object", obj_i); - - ImGui::EndTable(); - } - ImGui::PopStyleVar(); ImGui::End(); } @@ -8538,7 +9684,10 @@ static void ShowExampleAppCustomRendering(bool* p_open) draw_list->Flags &= ~ImDrawListFlags_AntiAliasedFill; // Fill a strip of background - draw_list->AddRectFilled(ImVec2(ImGui::GetCursorScreenPos().x, ImGui::GetCursorScreenPos().y), ImVec2(ImGui::GetCursorScreenPos().x + ImGui::GetWindowContentRegionMax().x, ImGui::GetCursorScreenPos().y + 200.0f), ImGui::GetColorU32(background_color)); + { + ImVec2 p = ImGui::GetCursorScreenPos(); + draw_list->AddRectFilled(p, ImVec2(p.x + ImGui::GetContentRegionAvail().x, p.y + 200.0f), ImGui::GetColorU32(background_color)); + } // Rectangle { @@ -9232,6 +10381,404 @@ void ShowExampleAppDocuments(bool* p_open) ImGui::End(); } +//----------------------------------------------------------------------------- +// [SECTION] Example App: Assets Browser / ShowExampleAppAssetsBrowser() +//----------------------------------------------------------------------------- + +//#include "imgui_internal.h" // NavMoveRequestTryWrapping() + +struct ExampleAsset +{ + ImGuiID ID; + int Type; + + ExampleAsset(ImGuiID id, int type) { ID = id; Type = type; } + + static const ImGuiTableSortSpecs* s_current_sort_specs; + + static void SortWithSortSpecs(ImGuiTableSortSpecs* sort_specs, ExampleAsset* items, int items_count) + { + s_current_sort_specs = sort_specs; // Store in variable accessible by the sort function. + if (items_count > 1) + qsort(items, (size_t)items_count, sizeof(items[0]), ExampleAsset::CompareWithSortSpecs); + s_current_sort_specs = NULL; + } + + // Compare function to be used by qsort() + static int IMGUI_CDECL CompareWithSortSpecs(const void* lhs, const void* rhs) + { + const ExampleAsset* a = (const ExampleAsset*)lhs; + const ExampleAsset* b = (const ExampleAsset*)rhs; + for (int n = 0; n < s_current_sort_specs->SpecsCount; n++) + { + const ImGuiTableColumnSortSpecs* sort_spec = &s_current_sort_specs->Specs[n]; + int delta = 0; + if (sort_spec->ColumnIndex == 0) + delta = ((int)a->ID - (int)b->ID); + else if (sort_spec->ColumnIndex == 1) + delta = (a->Type - b->Type); + if (delta > 0) + return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? +1 : -1; + if (delta < 0) + return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? -1 : +1; + } + return ((int)a->ID - (int)b->ID); + } +}; +const ImGuiTableSortSpecs* ExampleAsset::s_current_sort_specs = NULL; + +struct ExampleAssetsBrowser +{ + // Options + bool ShowTypeOverlay = true; + bool AllowSorting = true; + bool AllowDragUnselected = false; + bool AllowBoxSelect = true; + float IconSize = 32.0f; + int IconSpacing = 10; + int IconHitSpacing = 4; // Increase hit-spacing if you want to make it possible to clear or box-select from gaps. Some spacing is required to able to amend with Shift+box-select. Value is small in Explorer. + bool StretchSpacing = true; + + // State + ImVector Items; // Our items + ExampleSelectionWithDeletion Selection; // Our selection (ImGuiSelectionBasicStorage + helper funcs to handle deletion) + ImGuiID NextItemId = 0; // Unique identifier when creating new items + bool RequestDelete = false; // Deferred deletion request + bool RequestSort = false; // Deferred sort request + float ZoomWheelAccum = 0.0f; // Mouse wheel accumulator to handle smooth wheels better + + // Calculated sizes for layout, output of UpdateLayoutSizes(). Could be locals but our code is simpler this way. + ImVec2 LayoutItemSize; + ImVec2 LayoutItemStep; // == LayoutItemSize + LayoutItemSpacing + float LayoutItemSpacing = 0.0f; + float LayoutSelectableSpacing = 0.0f; + float LayoutOuterPadding = 0.0f; + int LayoutColumnCount = 0; + int LayoutLineCount = 0; + + // Functions + ExampleAssetsBrowser() + { + AddItems(10000); + } + void AddItems(int count) + { + if (Items.Size == 0) + NextItemId = 0; + Items.reserve(Items.Size + count); + for (int n = 0; n < count; n++, NextItemId++) + Items.push_back(ExampleAsset(NextItemId, (NextItemId % 20) < 15 ? 0 : (NextItemId % 20) < 18 ? 1 : 2)); + RequestSort = true; + } + void ClearItems() + { + Items.clear(); + Selection.Clear(); + } + + // Logic would be written in the main code BeginChild() and outputing to local variables. + // We extracted it into a function so we can call it easily from multiple places. + void UpdateLayoutSizes(float avail_width) + { + // Layout: when not stretching: allow extending into right-most spacing. + LayoutItemSpacing = (float)IconSpacing; + if (StretchSpacing == false) + avail_width += floorf(LayoutItemSpacing * 0.5f); + + // Layout: calculate number of icon per line and number of lines + LayoutItemSize = ImVec2(floorf(IconSize), floorf(IconSize)); + LayoutColumnCount = IM_MAX((int)(avail_width / (LayoutItemSize.x + LayoutItemSpacing)), 1); + LayoutLineCount = (Items.Size + LayoutColumnCount - 1) / LayoutColumnCount; + + // Layout: when stretching: allocate remaining space to more spacing. Round before division, so item_spacing may be non-integer. + if (StretchSpacing && LayoutColumnCount > 1) + LayoutItemSpacing = floorf(avail_width - LayoutItemSize.x * LayoutColumnCount) / LayoutColumnCount; + + LayoutItemStep = ImVec2(LayoutItemSize.x + LayoutItemSpacing, LayoutItemSize.y + LayoutItemSpacing); + LayoutSelectableSpacing = IM_MAX(floorf(LayoutItemSpacing) - IconHitSpacing, 0.0f); + LayoutOuterPadding = floorf(LayoutItemSpacing * 0.5f); + } + + void Draw(const char* title, bool* p_open) + { + ImGui::SetNextWindowSize(ImVec2(IconSize * 25, IconSize * 15), ImGuiCond_FirstUseEver); + if (!ImGui::Begin(title, p_open, ImGuiWindowFlags_MenuBar)) + { + ImGui::End(); + return; + } + + // Menu bar + if (ImGui::BeginMenuBar()) + { + if (ImGui::BeginMenu("File")) + { + if (ImGui::MenuItem("Add 10000 items")) + AddItems(10000); + if (ImGui::MenuItem("Clear items")) + ClearItems(); + ImGui::Separator(); + if (ImGui::MenuItem("Close", NULL, false, p_open != NULL)) + *p_open = false; + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Edit")) + { + if (ImGui::MenuItem("Delete", "Del", false, Selection.Size > 0)) + RequestDelete = true; + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Options")) + { + ImGui::PushItemWidth(ImGui::GetFontSize() * 10); + + ImGui::SeparatorText("Contents"); + ImGui::Checkbox("Show Type Overlay", &ShowTypeOverlay); + ImGui::Checkbox("Allow Sorting", &AllowSorting); + + ImGui::SeparatorText("Selection Behavior"); + ImGui::Checkbox("Allow dragging unselected item", &AllowDragUnselected); + ImGui::Checkbox("Allow box-selection", &AllowBoxSelect); + + ImGui::SeparatorText("Layout"); + ImGui::SliderFloat("Icon Size", &IconSize, 16.0f, 128.0f, "%.0f"); + ImGui::SameLine(); HelpMarker("Use CTRL+Wheel to zoom"); + ImGui::SliderInt("Icon Spacing", &IconSpacing, 0, 32); + ImGui::SliderInt("Icon Hit Spacing", &IconHitSpacing, 0, 32); + ImGui::Checkbox("Stretch Spacing", &StretchSpacing); + ImGui::PopItemWidth(); + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); + } + + // Show a table with ONLY one header row to showcase the idea/possibility of using this to provide a sorting UI + if (AllowSorting) + { + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); + ImGuiTableFlags table_flags_for_sort_specs = ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Borders; + if (ImGui::BeginTable("for_sort_specs_only", 2, table_flags_for_sort_specs, ImVec2(0.0f, ImGui::GetFrameHeight()))) + { + ImGui::TableSetupColumn("Index"); + ImGui::TableSetupColumn("Type"); + ImGui::TableHeadersRow(); + if (ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs()) + if (sort_specs->SpecsDirty || RequestSort) + { + ExampleAsset::SortWithSortSpecs(sort_specs, Items.Data, Items.Size); + sort_specs->SpecsDirty = RequestSort = false; + } + ImGui::EndTable(); + } + ImGui::PopStyleVar(); + } + + ImGuiIO& io = ImGui::GetIO(); + ImGui::SetNextWindowContentSize(ImVec2(0.0f, LayoutOuterPadding + LayoutLineCount * (LayoutItemSize.x + LayoutItemSpacing))); + if (ImGui::BeginChild("Assets", ImVec2(0.0f, -ImGui::GetTextLineHeightWithSpacing()), ImGuiChildFlags_Border, ImGuiWindowFlags_NoMove)) + { + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + + const float avail_width = ImGui::GetContentRegionAvail().x; + UpdateLayoutSizes(avail_width); + + // Calculate and store start position. + ImVec2 start_pos = ImGui::GetCursorScreenPos(); + start_pos = ImVec2(start_pos.x + LayoutOuterPadding, start_pos.y + LayoutOuterPadding); + ImGui::SetCursorScreenPos(start_pos); + + // Multi-select + ImGuiMultiSelectFlags ms_flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_ClearOnClickVoid; + + // - Enable box-select (in 2D mode, so that changing box-select rectangle X1/X2 boundaries will affect clipped items) + if (AllowBoxSelect) + ms_flags |= ImGuiMultiSelectFlags_BoxSelect2d; + + // - This feature allows dragging an unselected item without selecting it (rarely used) + if (AllowDragUnselected) + ms_flags |= ImGuiMultiSelectFlags_SelectOnClickRelease; + + // - Enable keyboard wrapping on X axis + // (FIXME-MULTISELECT: We haven't designed/exposed a general nav wrapping api yet, so this flag is provided as a courtesy to avoid doing: + // ImGui::NavMoveRequestTryWrapping(ImGui::GetCurrentWindow(), ImGuiNavMoveFlags_WrapX); + // When we finish implementing a more general API for this, we will obsolete this flag in favor of the new system) + ms_flags |= ImGuiMultiSelectFlags_NavWrapX; + + ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(ms_flags, Selection.Size, Items.Size); + + // Use custom selection adapter: store ID in selection (recommended) + Selection.UserData = this; + Selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self_, int idx) { ExampleAssetsBrowser* self = (ExampleAssetsBrowser*)self_->UserData; return self->Items[idx].ID; }; + Selection.ApplyRequests(ms_io); + + const bool want_delete = (ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (Selection.Size > 0)) || RequestDelete; + const int item_curr_idx_to_focus = want_delete ? Selection.ApplyDeletionPreLoop(ms_io, Items.Size) : -1; + RequestDelete = false; + + // Push LayoutSelectableSpacing (which is LayoutItemSpacing minus hit-spacing, if we decide to have hit gaps between items) + // Altering style ItemSpacing may seem unnecessary as we position every items using SetCursorScreenPos()... + // But it is necessary for two reasons: + // - Selectables uses it by default to visually fill the space between two items. + // - The vertical spacing would be measured by Clipper to calculate line height if we didn't provide it explicitly (here we do). + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(LayoutSelectableSpacing, LayoutSelectableSpacing)); + + // Rendering parameters + const ImU32 icon_type_overlay_colors[3] = { 0, IM_COL32(200, 70, 70, 255), IM_COL32(70, 170, 70, 255) }; + const ImU32 icon_bg_color = ImGui::GetColorU32(ImGuiCol_MenuBarBg); + const ImVec2 icon_type_overlay_size = ImVec2(4.0f, 4.0f); + const bool display_label = (LayoutItemSize.x >= ImGui::CalcTextSize("999").x); + + const int column_count = LayoutColumnCount; + ImGuiListClipper clipper; + clipper.Begin(LayoutLineCount, LayoutItemStep.y); + if (item_curr_idx_to_focus != -1) + clipper.IncludeItemByIndex(item_curr_idx_to_focus / column_count); // Ensure focused item line is not clipped. + if (ms_io->RangeSrcItem != -1) + clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem / column_count); // Ensure RangeSrc item line is not clipped. + while (clipper.Step()) + { + for (int line_idx = clipper.DisplayStart; line_idx < clipper.DisplayEnd; line_idx++) + { + const int item_min_idx_for_current_line = line_idx * column_count; + const int item_max_idx_for_current_line = IM_MIN((line_idx + 1) * column_count, Items.Size); + for (int item_idx = item_min_idx_for_current_line; item_idx < item_max_idx_for_current_line; ++item_idx) + { + ExampleAsset* item_data = &Items[item_idx]; + ImGui::PushID((int)item_data->ID); + + // Position item + ImVec2 pos = ImVec2(start_pos.x + (item_idx % column_count) * LayoutItemStep.x, start_pos.y + line_idx * LayoutItemStep.y); + ImGui::SetCursorScreenPos(pos); + + ImGui::SetNextItemSelectionUserData(item_idx); + bool item_is_selected = Selection.Contains((ImGuiID)item_data->ID); + bool item_is_visible = ImGui::IsRectVisible(LayoutItemSize); + ImGui::Selectable("", item_is_selected, ImGuiSelectableFlags_None, LayoutItemSize); + + // Update our selection state immediately (without waiting for EndMultiSelect() requests) + // because we use this to alter the color of our text/icon. + if (ImGui::IsItemToggledSelection()) + item_is_selected = !item_is_selected; + + // Focus (for after deletion) + if (item_curr_idx_to_focus == item_idx) + ImGui::SetKeyboardFocusHere(-1); + + // Drag and drop + if (ImGui::BeginDragDropSource()) + { + // Create payload with full selection OR single unselected item. + // (the later is only possible when using ImGuiMultiSelectFlags_SelectOnClickRelease) + if (ImGui::GetDragDropPayload() == NULL) + { + ImVector payload_items; + void* it = NULL; + ImGuiID id = 0; + if (!item_is_selected) + payload_items.push_back(item_data->ID); + else + while (Selection.GetNextSelectedItem(&it, &id)) + payload_items.push_back(id); + ImGui::SetDragDropPayload("ASSETS_BROWSER_ITEMS", payload_items.Data, (size_t)payload_items.size_in_bytes()); + } + + // Display payload content in tooltip, by extracting it from the payload data + // (we could read from selection, but it is more correct and reusable to read from payload) + const ImGuiPayload* payload = ImGui::GetDragDropPayload(); + const int payload_count = (int)payload->DataSize / (int)sizeof(ImGuiID); + ImGui::Text("%d assets", payload_count); + + ImGui::EndDragDropSource(); + } + + // Render icon (a real app would likely display an image/thumbnail here) + // Because we use ImGuiMultiSelectFlags_BoxSelect2d, clipping vertical may occasionally be larger, so we coarse-clip our rendering as well. + if (item_is_visible) + { + ImVec2 box_min(pos.x - 1, pos.y - 1); + ImVec2 box_max(box_min.x + LayoutItemSize.x + 2, box_min.y + LayoutItemSize.y + 2); // Dubious + draw_list->AddRectFilled(box_min, box_max, icon_bg_color); // Background color + if (ShowTypeOverlay && item_data->Type != 0) + { + ImU32 type_col = icon_type_overlay_colors[item_data->Type % IM_ARRAYSIZE(icon_type_overlay_colors)]; + draw_list->AddRectFilled(ImVec2(box_max.x - 2 - icon_type_overlay_size.x, box_min.y + 2), ImVec2(box_max.x - 2, box_min.y + 2 + icon_type_overlay_size.y), type_col); + } + if (display_label) + { + ImU32 label_col = ImGui::GetColorU32(item_is_selected ? ImGuiCol_Text : ImGuiCol_TextDisabled); + char label[32]; + sprintf(label, "%d", item_data->ID); + draw_list->AddText(ImVec2(box_min.x, box_max.y - ImGui::GetFontSize()), label_col, label); + } + } + + ImGui::PopID(); + } + } + } + clipper.End(); + ImGui::PopStyleVar(); // ImGuiStyleVar_ItemSpacing + + // Context menu + if (ImGui::BeginPopupContextWindow()) + { + ImGui::Text("Selection: %d items", Selection.Size); + ImGui::Separator(); + if (ImGui::MenuItem("Delete", "Del", false, Selection.Size > 0)) + RequestDelete = true; + ImGui::EndPopup(); + } + + ms_io = ImGui::EndMultiSelect(); + Selection.ApplyRequests(ms_io); + if (want_delete) + Selection.ApplyDeletionPostLoop(ms_io, Items, item_curr_idx_to_focus); + + // Zooming with CTRL+Wheel + if (ImGui::IsWindowAppearing()) + ZoomWheelAccum = 0.0f; + if (ImGui::IsWindowHovered() && io.MouseWheel != 0.0f && ImGui::IsKeyDown(ImGuiMod_Ctrl) && ImGui::IsAnyItemActive() == false) + { + ZoomWheelAccum += io.MouseWheel; + if (fabsf(ZoomWheelAccum) >= 1.0f) + { + // Calculate hovered item index from mouse location + // FIXME: Locking aiming on 'hovered_item_idx' (with a cool-down timer) would ensure zoom keeps on it. + const float hovered_item_nx = (io.MousePos.x - start_pos.x + LayoutItemSpacing * 0.5f) / LayoutItemStep.x; + const float hovered_item_ny = (io.MousePos.y - start_pos.y + LayoutItemSpacing * 0.5f) / LayoutItemStep.y; + const int hovered_item_idx = ((int)hovered_item_ny * LayoutColumnCount) + (int)hovered_item_nx; + //ImGui::SetTooltip("%f,%f -> item %d", hovered_item_nx, hovered_item_ny, hovered_item_idx); // Move those 4 lines in block above for easy debugging + + // Zoom + IconSize *= powf(1.1f, (float)(int)ZoomWheelAccum); + IconSize = IM_CLAMP(IconSize, 16.0f, 128.0f); + ZoomWheelAccum -= (int)ZoomWheelAccum; + UpdateLayoutSizes(avail_width); + + // Manipulate scroll to that we will land at the same Y location of currently hovered item. + // - Calculate next frame position of item under mouse + // - Set new scroll position to be used in next ImGui::BeginChild() call. + float hovered_item_rel_pos_y = ((float)(hovered_item_idx / LayoutColumnCount) + fmodf(hovered_item_ny, 1.0f)) * LayoutItemStep.y; + hovered_item_rel_pos_y += ImGui::GetStyle().WindowPadding.y; + float mouse_local_y = io.MousePos.y - ImGui::GetWindowPos().y; + ImGui::SetScrollY(hovered_item_rel_pos_y - mouse_local_y); + } + } + } + ImGui::EndChild(); + + ImGui::Text("Selected: %d/%d items", Selection.Size, Items.Size); + ImGui::End(); + } +}; + +void ShowExampleAppAssetsBrowser(bool* p_open) +{ + IMGUI_DEMO_MARKER("Examples/Assets Browser"); + static ExampleAssetsBrowser assets_browser; + assets_browser.Draw("Example: Assets Browser", p_open); +} + // End of Demo code #else diff --git a/lib/third_party/imgui/imgui/source/imgui_draw.cpp b/lib/third_party/imgui/imgui/source/imgui_draw.cpp index c2a053fdc..2cfb118ff 100644 --- a/lib/third_party/imgui/imgui/source/imgui_draw.cpp +++ b/lib/third_party/imgui/imgui/source/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.9 +// dear imgui, v1.91.0 // (drawing and font code) /* @@ -231,6 +231,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst) colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f); // Prefer using Alpha=1.0 here colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f); + colors[ImGuiCol_TextLink] = colors[ImGuiCol_HeaderActive]; colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); @@ -296,6 +297,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst) colors[ImGuiCol_TableBorderLight] = ImVec4(0.26f, 0.26f, 0.28f, 1.00f); // Prefer using Alpha=1.0 here colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.07f); + colors[ImGuiCol_TextLink] = colors[ImGuiCol_HeaderActive]; colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; @@ -362,6 +364,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst) colors[ImGuiCol_TableBorderLight] = ImVec4(0.68f, 0.68f, 0.74f, 1.00f); // Prefer using Alpha=1.0 here colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_TableRowBgAlt] = ImVec4(0.30f, 0.30f, 0.30f, 0.09f); + colors[ImGuiCol_TextLink] = colors[ImGuiCol_HeaderActive]; colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; diff --git a/lib/third_party/imgui/imgui/source/imgui_tables.cpp b/lib/third_party/imgui/imgui/source/imgui_tables.cpp index dc69f9462..37dd70304 100644 --- a/lib/third_party/imgui/imgui/source/imgui_tables.cpp +++ b/lib/third_party/imgui/imgui/source/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.9 +// dear imgui, v1.91.0 // (tables and columns code) /* @@ -412,8 +412,8 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG SetNextWindowScroll(ImVec2(0.0f, 0.0f)); // Create scrolling region (without border and zero window padding) - ImGuiWindowFlags child_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None; - BeginChildEx(name, instance_id, outer_rect.GetSize(), false, child_flags); + ImGuiWindowFlags child_window_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None; + BeginChildEx(name, instance_id, outer_rect.GetSize(), ImGuiChildFlags_None, child_window_flags); table->InnerWindow = g.CurrentWindow; table->WorkRect = table->InnerWindow->WorkRect; table->OuterRect = table->InnerWindow->Rect(); @@ -1996,34 +1996,37 @@ void ImGui::TableEndRow(ImGuiTable* table) // We need to do that in TableEndRow() instead of TableBeginRow() so the list clipper can mark end of row and // get the new cursor position. if (unfreeze_rows_request) + { for (int column_n = 0; column_n < table->ColumnsCount; column_n++) table->Columns[column_n].NavLayerCurrent = ImGuiNavLayer_Main; - if (unfreeze_rows_actual) - { - IM_ASSERT(table->IsUnfrozenRows == false); const float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y); - table->IsUnfrozenRows = true; table_instance->LastFrozenHeight = y0 - table->OuterRect.Min.y; - // BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect - table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y); - table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y; - table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen; - IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.Max.y); - - float row_height = table->RowPosY2 - table->RowPosY1; - table->RowPosY2 = window->DC.CursorPos.y = table->WorkRect.Min.y + table->RowPosY2 - table->OuterRect.Min.y; - table->RowPosY1 = table->RowPosY2 - row_height; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) + if (unfreeze_rows_actual) { - ImGuiTableColumn* column = &table->Columns[column_n]; - column->DrawChannelCurrent = column->DrawChannelUnfrozen; - column->ClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y; - } + IM_ASSERT(table->IsUnfrozenRows == false); + table->IsUnfrozenRows = true; - // Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y - SetWindowClipRectBeforeSetChannel(window, table->Columns[0].ClipRect); - table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Columns[0].DrawChannelCurrent); + // BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect + table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y); + table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y; + table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen; + IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.Max.y); + + float row_height = table->RowPosY2 - table->RowPosY1; + table->RowPosY2 = window->DC.CursorPos.y = table->WorkRect.Min.y + table->RowPosY2 - table->OuterRect.Min.y; + table->RowPosY1 = table->RowPosY2 - row_height; + for (int column_n = 0; column_n < table->ColumnsCount; column_n++) + { + ImGuiTableColumn* column = &table->Columns[column_n]; + column->DrawChannelCurrent = column->DrawChannelUnfrozen; + column->ClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y; + } + + // Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y + SetWindowClipRectBeforeSetChannel(window, table->Columns[0].ClipRect); + table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Columns[0].DrawChannelCurrent); + } } if (!(table->RowFlags & ImGuiTableRowFlags_Headers)) @@ -3269,7 +3272,7 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label ButtonBehavior(row_r, row_id, NULL, NULL); KeepAliveID(row_id); - const float ascent_scaled = g.Font->Ascent * (g.FontSize / g.Font->FontSize); // FIXME: Standardize those scaling factors better + const float ascent_scaled = g.Font->Ascent * g.FontScale; // FIXME: Standardize those scaling factors better const float line_off_for_ascent_x = (ImMax((g.FontSize - ascent_scaled) * 0.5f, 0.0f) / -sin_a) * (flip_label ? -1.0f : 1.0f); const ImVec2 padding = g.Style.CellPadding; // We will always use swapped component const ImVec2 align = g.Style.TableAngledHeadersTextAlign; @@ -3471,7 +3474,7 @@ void ImGui::TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags Separator(); want_separator = true; - PushItemFlag(ImGuiItemFlags_SelectableDontClosePopup, true); + PushItemFlag(ImGuiItemFlags_AutoClosePopups, false); for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++) { ImGuiTableColumn* other_column = &table->Columns[other_column_n]; diff --git a/lib/third_party/imgui/imgui/source/imgui_widgets.cpp b/lib/third_party/imgui/imgui/source/imgui_widgets.cpp index 56829e7a6..27b198dfa 100644 --- a/lib/third_party/imgui/imgui/source/imgui_widgets.cpp +++ b/lib/third_party/imgui/imgui/source/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.9 +// dear imgui, v1.91.0 // (widgets code) /* @@ -19,7 +19,9 @@ Index of this file: // [SECTION] Widgets: TreeNode, CollapsingHeader, etc. // [SECTION] Widgets: Selectable // [SECTION] Widgets: Typing-Select support +// [SECTION] Widgets: Box-Select support // [SECTION] Widgets: Multi-Select support +// [SECTION] Widgets: Multi-Select helpers // [SECTION] Widgets: ListBox // [SECTION] Widgets: PlotLines, PlotHistogram // [SECTION] Widgets: Value helpers @@ -70,6 +72,7 @@ Index of this file: #pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok. #pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. #pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness +#pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used // we define snprintf/vsnprintf on Windows so they are available, but not always used. #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0 #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. #pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') @@ -422,6 +425,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args) // - RadioButton() // - ProgressBar() // - Bullet() +// - Hyperlink() //------------------------------------------------------------------------- // The ButtonBehavior() function is key to many interactions and used by many/most widgets. @@ -563,8 +567,14 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool SetActiveID(id, window); g.ActiveIdMouseButton = mouse_button_clicked; if (!(flags & ImGuiButtonFlags_NoNavFocus)) + { SetFocusID(id, window); - FocusWindow(window); + FocusWindow(window); + } + else + { + FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild); // Still need to focus and bring to front, but try to avoid losing NavId when navigating a child + } } if ((flags & ImGuiButtonFlags_PressedOnClick) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseClickedCount[mouse_button_clicked] == 2)) { @@ -573,10 +583,16 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool ClearActiveID(); else SetActiveID(id, window); // Hold on ID - if (!(flags & ImGuiButtonFlags_NoNavFocus)) - SetFocusID(id, window); g.ActiveIdMouseButton = mouse_button_clicked; - FocusWindow(window); + if (!(flags & ImGuiButtonFlags_NoNavFocus)) + { + SetFocusID(id, window); + FocusWindow(window); + } + else + { + FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild); // Still need to focus and bring to front, but try to avoid losing NavId when navigating a child + } } } if (flags & ImGuiButtonFlags_PressedOnRelease) @@ -834,17 +850,15 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos) return pressed; // Render - // FIXME: Clarify this mess - ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered); - ImVec2 center = bb.GetCenter(); + ImU32 bg_col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered); if (hovered) - window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col); - - float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f; + window->DrawList->AddRectFilled(bb.Min, bb.Max, bg_col); + RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact); ImU32 cross_col = GetColorU32(ImGuiCol_Text); - center -= ImVec2(0.5f, 0.5f); - window->DrawList->AddLine(center + ImVec2(+cross_extent, +cross_extent), center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f); - window->DrawList->AddLine(center + ImVec2(+cross_extent, -cross_extent), center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f); + ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f); + float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f; + window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, +cross_extent), cross_center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f); + window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, -cross_extent), cross_center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f); return pressed; } @@ -867,7 +881,8 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_no ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); ImU32 text_col = GetColorU32(ImGuiCol_Text); if (hovered || held) - window->DrawList->AddCircleFilled(bb.GetCenter() + ImVec2(0.0f, -0.5f), g.FontSize * 0.5f + 1.0f, bg_col); + window->DrawList->AddRectFilled(bb.Min, bb.Max, bg_col); + RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact); if (dock_node) RenderArrowDockMenu(window->DrawList, bb.Min, g.FontSize, text_col); @@ -1139,17 +1154,32 @@ bool ImGui::Checkbox(const char* label, bool* v) const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f)); ItemSize(total_bb, style.FramePadding.y); const bool is_visible = ItemAdd(total_bb, id); + const bool is_multi_select = (g.LastItemData.InFlags & ImGuiItemFlags_IsMultiSelect) != 0; if (!is_visible) - { - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); - return false; - } + if (!is_multi_select || !g.BoxSelectState.UnclipMode || !g.BoxSelectState.UnclipRect.Overlaps(total_bb)) // Extra layer of "no logic clip" for box-select support + { + IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); + return false; + } + + // Range-Selection/Multi-selection support (header) + bool checked = *v; + if (is_multi_select) + MultiSelectItemHeader(id, &checked, NULL); bool hovered, held; bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); - if (pressed) + + // Range-Selection/Multi-selection support (footer) + if (is_multi_select) + MultiSelectItemFooter(id, &checked, &pressed); + else if (pressed) + checked = !checked; + + if (*v != checked) { - *v = !(*v); + *v = checked; + pressed = true; // return value MarkItemEdited(id); } @@ -1376,6 +1406,76 @@ void ImGui::Bullet() SameLine(0, style.FramePadding.x * 2.0f); } +// This is provided as a convenience for being an often requested feature. +// FIXME-STYLE: we delayed adding as there is a larger plan to revamp the styling system. +// Because of this we currently don't provide many styling options for this widget +// (e.g. hovered/active colors are automatically inferred from a single color). +bool ImGui::TextLink(const char* label) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiID id = window->GetID(label); + const char* label_end = FindRenderedTextEnd(label); + + ImVec2 pos = window->DC.CursorPos; + ImVec2 size = CalcTextSize(label, label_end, true); + ImRect bb(pos, pos + size); + ItemSize(size, 0.0f); + if (!ItemAdd(bb, id)) + return false; + + bool hovered, held; + bool pressed = ButtonBehavior(bb, id, &hovered, &held); + RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_None); + + ImVec4 text_colf = g.Style.Colors[ImGuiCol_TextLink]; + ImVec4 line_colf = text_colf; + { + // FIXME-STYLE: Read comments above. This widget is NOT written in the same style as some earlier widgets, + // as we are currently experimenting/planning a different styling system. + float h, s, v; + ColorConvertRGBtoHSV(text_colf.x, text_colf.y, text_colf.z, h, s, v); + if (held || hovered) + { + v = ImSaturate(v + (held ? 0.4f : 0.3f)); + h = ImFmod(h + 0.02f, 1.0f); + } + ColorConvertHSVtoRGB(h, s, v, text_colf.x, text_colf.y, text_colf.z); + v = ImSaturate(v - 0.20f); + ColorConvertHSVtoRGB(h, s, v, line_colf.x, line_colf.y, line_colf.z); + } + + float line_y = bb.Max.y + ImFloor(g.Font->Descent * g.FontScale * 0.20f); + window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf)); // FIXME-TEXT: Underline mode. + + PushStyleColor(ImGuiCol_Text, GetColorU32(text_colf)); + RenderText(bb.Min, label, label_end); + PopStyleColor(); + + IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); + return pressed; +} + +void ImGui::TextLinkOpenURL(const char* label, const char* url) +{ + ImGuiContext& g = *GImGui; + if (url == NULL) + url = label; + if (TextLink(label)) + if (g.IO.PlatformOpenInShellFn != NULL) + g.IO.PlatformOpenInShellFn(&g, url); + SetItemTooltip("%s", url); // It is more reassuring for user to _always_ display URL when we same as label + if (BeginPopupContextItem()) + { + if (MenuItem(LocalizeGetMsg(ImGuiLocKey_CopyLink))) + SetClipboardText(url); + EndPopup(); + } +} + //------------------------------------------------------------------------- // [SECTION] Widgets: Low-level Layout helpers //------------------------------------------------------------------------- @@ -2066,6 +2166,7 @@ static const ImGuiDataTypeInfo GDataTypeInfo[] = #endif { sizeof(float), "float", "%.3f","%f" }, // ImGuiDataType_Float (float are promoted to double in va_arg) { sizeof(double), "double","%f", "%lf" }, // ImGuiDataType_Double + { sizeof(bool), "bool", "%d", "%d" }, // ImGuiDataType_Bool }; IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo) == ImGuiDataType_COUNT); @@ -3784,7 +3885,7 @@ namespace ImStb static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->CurLenW; } static ImWchar STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { IM_ASSERT(idx <= obj->CurLenW); return obj->TextW[idx]; } -static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx + char_idx]; if (c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance(c) * (g.FontSize / g.Font->FontSize); } +static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx + char_idx]; if (c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance(c) * g.FontScale; } static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x200000 ? 0 : key; } static ImWchar STB_TEXTEDIT_NEWLINE = '\n'; static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx) @@ -3802,7 +3903,7 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* ob static bool is_separator(unsigned int c) { - return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r' || c=='.' || c=='!'; + return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r' || c=='.' || c=='!' || c=='\\' || c=='/'; } static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx) @@ -4218,7 +4319,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding); PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize); PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); // Ensure no clip rect so mouse hover can reach FramePadding edges - bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), true, ImGuiWindowFlags_NoMove); + bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), ImGuiChildFlags_Border, ImGuiWindowFlags_NoMove); g.NavActivateId = backup_activate_id; PopStyleVar(3); PopStyleColor(); @@ -6131,7 +6232,8 @@ bool ImGui::TreeNode(const char* label) ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; - return TreeNodeBehavior(window->GetID(label), 0, label, NULL); + ImGuiID id = window->GetID(label); + return TreeNodeBehavior(id, ImGuiTreeNodeFlags_None, label, NULL); } bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) @@ -6149,8 +6251,8 @@ bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags) ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; - - return TreeNodeBehavior(window->GetID(label), flags, label, NULL); + ImGuiID id = window->GetID(label); + return TreeNodeBehavior(id, flags, label, NULL); } bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) @@ -6177,9 +6279,10 @@ bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char if (window->SkipItems) return false; + ImGuiID id = window->GetID(str_id); const char* label, *label_end; ImFormatStringToTempBufferV(&label, &label_end, fmt, args); - return TreeNodeBehavior(window->GetID(str_id), flags, label, label_end); + return TreeNodeBehavior(id, flags, label, label_end); } bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) @@ -6188,24 +6291,32 @@ bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char if (window->SkipItems) return false; + ImGuiID id = window->GetID(ptr_id); const char* label, *label_end; ImFormatStringToTempBufferV(&label, &label_end, fmt, args); - return TreeNodeBehavior(window->GetID(ptr_id), flags, label, label_end); + return TreeNodeBehavior(id, flags, label, label_end); } -void ImGui::TreeNodeSetOpen(ImGuiID id, bool open) +bool ImGui::TreeNodeGetOpen(ImGuiID storage_id) { ImGuiContext& g = *GImGui; ImGuiStorage* storage = g.CurrentWindow->DC.StateStorage; - storage->SetInt(id, open ? 1 : 0); + return storage->GetInt(storage_id, 0) != 0; } -bool ImGui::TreeNodeUpdateNextOpen(ImGuiID id, ImGuiTreeNodeFlags flags) +void ImGui::TreeNodeSetOpen(ImGuiID storage_id, bool open) +{ + ImGuiContext& g = *GImGui; + ImGuiStorage* storage = g.CurrentWindow->DC.StateStorage; + storage->SetInt(storage_id, open ? 1 : 0); +} + +bool ImGui::TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags) { if (flags & ImGuiTreeNodeFlags_Leaf) return true; - // We only write to the tree storage if the user clicks (or explicitly use the SetNextItemOpen function) + // We only write to the tree storage if the user clicks, or explicitly use the SetNextItemOpen function ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiStorage* storage = window->DC.StateStorage; @@ -6216,16 +6327,16 @@ bool ImGui::TreeNodeUpdateNextOpen(ImGuiID id, ImGuiTreeNodeFlags flags) if (g.NextItemData.OpenCond & ImGuiCond_Always) { is_open = g.NextItemData.OpenVal; - TreeNodeSetOpen(id, is_open); + TreeNodeSetOpen(storage_id, is_open); } else { // We treat ImGuiCond_Once and ImGuiCond_FirstUseEver the same because tree node state are not saved persistently. - const int stored_value = storage->GetInt(id, -1); + const int stored_value = storage->GetInt(storage_id, -1); if (stored_value == -1) { is_open = g.NextItemData.OpenVal; - TreeNodeSetOpen(id, is_open); + TreeNodeSetOpen(storage_id, is_open); } else { @@ -6235,7 +6346,7 @@ bool ImGui::TreeNodeUpdateNextOpen(ImGuiID id, ImGuiTreeNodeFlags flags) } else { - is_open = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0; + is_open = storage->GetInt(storage_id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0; } // When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior). @@ -6246,6 +6357,23 @@ bool ImGui::TreeNodeUpdateNextOpen(ImGuiID id, ImGuiTreeNodeFlags flags) return is_open; } +// Store ImGuiTreeNodeStackData for just submitted node. +// Currently only supports 32 level deep and we are fine with (1 << Depth) overflowing into a zero, easy to increase. +static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + g.TreeNodeStack.resize(g.TreeNodeStack.Size + 1); + ImGuiTreeNodeStackData* tree_node_data = &g.TreeNodeStack.back(); + tree_node_data->ID = g.LastItemData.ID; + tree_node_data->TreeFlags = flags; + tree_node_data->InFlags = g.LastItemData.InFlags; + tree_node_data->NavRect = g.LastItemData.NavRect; + window->DC.TreeHasStackDataDepthMask |= (1 << window->DC.TreeDepth); +} + +// When using public API, currently 'id == storage_id' is always true, but we separate the values to facilitate advanced user code doing storage queries outside of UI loop. bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end) { ImGuiWindow* window = GetCurrentWindow(); @@ -6275,10 +6403,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l frame_bb.Max.y = window->DC.CursorPos.y + frame_height; if (display_frame) { - // Framed header expand a little outside the default padding, to the edge of InnerClipRect - // (FIXME: May remove this at some point and make InnerClipRect align with WindowPadding.x instead of WindowPadding.x*0.5f) - frame_bb.Min.x -= IM_TRUNC(window->WindowPadding.x * 0.5f - 1.0f); - frame_bb.Max.x += IM_TRUNC(window->WindowPadding.x * 0.5f); + const float outer_extend = IM_TRUNC(window->WindowPadding.x * 0.5f); // Framed header expand a little outside of current limits + frame_bb.Min.x -= outer_extend; + frame_bb.Max.x += outer_extend; } ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y); @@ -6289,46 +6416,46 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if ((flags & (ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_SpanTextWidth | ImGuiTreeNodeFlags_SpanAllColumns)) == 0) interact_bb.Max.x = frame_bb.Min.x + text_width + (label_size.x > 0.0f ? style.ItemSpacing.x * 2.0f : 0.0f); - // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable.. - const float backup_clip_rect_min_x = window->ClipRect.Min.x; - const float backup_clip_rect_max_x = window->ClipRect.Max.x; + // Compute open and multi-select states before ItemAdd() as it clear NextItem data. + ImGuiID storage_id = (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasStorageID) ? g.NextItemData.StorageId : id; + bool is_open = TreeNodeUpdateNextOpen(storage_id, flags); + + bool is_visible; if (span_all_columns) { + // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable.. + const float backup_clip_rect_min_x = window->ClipRect.Min.x; + const float backup_clip_rect_max_x = window->ClipRect.Max.x; window->ClipRect.Min.x = window->ParentWorkRect.Min.x; window->ClipRect.Max.x = window->ParentWorkRect.Max.x; - } - - // Compute open and multi-select states before ItemAdd() as it clear NextItem data. - bool is_open = TreeNodeUpdateNextOpen(id, flags); - bool item_add = ItemAdd(interact_bb, id); - g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect; - g.LastItemData.DisplayRect = frame_bb; - - if (span_all_columns) - { + is_visible = ItemAdd(interact_bb, id); window->ClipRect.Min.x = backup_clip_rect_min_x; window->ClipRect.Max.x = backup_clip_rect_max_x; } + else + { + is_visible = ItemAdd(interact_bb, id); + } + g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect; + g.LastItemData.DisplayRect = frame_bb; // If a NavLeft request is happening and ImGuiTreeNodeFlags_NavLeftJumpsBackHere enabled: // Store data for the current depth to allow returning to this node from any child item. // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop(). // It will become tempting to enable ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default or move it to ImGuiStyle. - // Currently only supports 32 level deep and we are fine with (1 << Depth) overflowing into a zero, easy to increase. - if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) - if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) - { - g.NavTreeNodeStack.resize(g.NavTreeNodeStack.Size + 1); - ImGuiNavTreeNodeData* nav_tree_node_data = &g.NavTreeNodeStack.back(); - nav_tree_node_data->ID = id; - nav_tree_node_data->InFlags = g.LastItemData.InFlags; - nav_tree_node_data->NavRect = g.LastItemData.NavRect; - window->DC.TreeJumpToParentOnPopMask |= (1 << window->DC.TreeDepth); - } + bool store_tree_node_stack_data = false; + if (!(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) + { + if ((flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && is_open && !g.NavIdIsAlive) + if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) + store_tree_node_stack_data = true; + } const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0; - if (!item_add) + if (!is_visible) { + if (store_tree_node_stack_data && is_open) + TreeNodeStoreStackData(flags); // Call before TreePushOverrideID() if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) TreePushOverrideID(id); IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0)); @@ -6354,8 +6481,6 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l const float arrow_hit_x1 = (text_pos.x - text_offset_x) - style.TouchExtraPadding.x; const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + style.TouchExtraPadding.x; const bool is_mouse_x_over_arrow = (g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2); - if (window != g.HoveredWindow || !is_mouse_x_over_arrow) - button_flags |= ImGuiButtonFlags_NoKeyModifiers; // Open behaviors can be altered with the _OpenOnArrow and _OnOnDoubleClick flags. // Some alteration have subtle effects (e.g. toggle on MouseUp vs MouseDown events) due to requirements for multi-selection and drag and drop support. @@ -6376,6 +6501,24 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l bool selected = (flags & ImGuiTreeNodeFlags_Selected) != 0; const bool was_selected = selected; + // Multi-selection support (header) + const bool is_multi_select = (g.LastItemData.InFlags & ImGuiItemFlags_IsMultiSelect) != 0; + if (is_multi_select) + { + // Handle multi-select + alter button flags for it + MultiSelectItemHeader(id, &selected, &button_flags); + if (is_mouse_x_over_arrow) + button_flags = (button_flags | ImGuiButtonFlags_PressedOnClick) & ~ImGuiButtonFlags_PressedOnClickRelease; + + // We absolutely need to distinguish open vs select so comes by default + flags |= ImGuiTreeNodeFlags_OpenOnArrow; + } + else + { + if (window != g.HoveredWindow || !is_mouse_x_over_arrow) + button_flags |= ImGuiButtonFlags_NoKeyModifiers; + } + bool hovered, held; bool pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); bool toggled = false; @@ -6383,7 +6526,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l { if (pressed && g.DragDropHoldJustPressedId != id) { - if ((flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) == 0 || (g.NavActivateId == id)) + if ((flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) == 0 || (g.NavActivateId == id && !is_multi_select)) toggled = true; if (flags & ImGuiTreeNodeFlags_OpenOnArrow) toggled |= is_mouse_x_over_arrow && !g.NavDisableMouseHover; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job @@ -6413,64 +6556,78 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if (toggled) { is_open = !is_open; - window->DC.StateStorage->SetInt(id, is_open); + window->DC.StateStorage->SetInt(storage_id, is_open); g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledOpen; } } - // In this branch, TreeNodeBehavior() cannot toggle the selection so this will never trigger. - if (selected != was_selected) //-V547 + // Multi-selection support (footer) + if (is_multi_select) + { + bool pressed_copy = pressed && !toggled; + MultiSelectItemFooter(id, &selected, &pressed_copy); + if (pressed) + SetNavID(id, window->DC.NavLayerCurrent, g.CurrentFocusScopeId, interact_bb); + } + + if (selected != was_selected) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection; // Render - const ImU32 text_col = GetColorU32(ImGuiCol_Text); - ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_Compact; - if (display_frame) { - // Framed type - const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding); - RenderNavHighlight(frame_bb, id, nav_highlight_flags); - if (flags & ImGuiTreeNodeFlags_Bullet) - RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col); - else if (!is_leaf) - RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 1.0f); - else // Leaf without bullet, left-adjusted text - text_pos.x -= text_offset_x -padding.x; - if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton) - frame_bb.Max.x -= g.FontSize + style.FramePadding.x; - - if (g.LogEnabled) - LogSetNextTextDecoration("###", "###"); - } - else - { - // Unframed typed for tree nodes - if (hovered || selected) + const ImU32 text_col = GetColorU32(ImGuiCol_Text); + ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_Compact; + if (is_multi_select) + nav_highlight_flags |= ImGuiNavHighlightFlags_AlwaysDraw; // Always show the nav rectangle + if (display_frame) { + // Framed type const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false); + RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding); + RenderNavHighlight(frame_bb, id, nav_highlight_flags); + if (flags & ImGuiTreeNodeFlags_Bullet) + RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col); + else if (!is_leaf) + RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 1.0f); + else // Leaf without bullet, left-adjusted text + text_pos.x -= text_offset_x - padding.x; + if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton) + frame_bb.Max.x -= g.FontSize + style.FramePadding.x; + if (g.LogEnabled) + LogSetNextTextDecoration("###", "###"); } - RenderNavHighlight(frame_bb, id, nav_highlight_flags); - if (flags & ImGuiTreeNodeFlags_Bullet) - RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col); - else if (!is_leaf) - RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 0.70f); - if (g.LogEnabled) - LogSetNextTextDecoration(">", NULL); + else + { + // Unframed typed for tree nodes + if (hovered || selected) + { + const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); + RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false); + } + RenderNavHighlight(frame_bb, id, nav_highlight_flags); + if (flags & ImGuiTreeNodeFlags_Bullet) + RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col); + else if (!is_leaf) + RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 0.70f); + if (g.LogEnabled) + LogSetNextTextDecoration(">", NULL); + } + + if (span_all_columns) + TablePopBackgroundChannel(); + + // Label + if (display_frame) + RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); + else + RenderText(text_pos, label, label_end, false); } - if (span_all_columns) - TablePopBackgroundChannel(); - - // Label - if (display_frame) - RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); - else - RenderText(text_pos, label, label_end, false); - + if (store_tree_node_stack_data && is_open) + TreeNodeStoreStackData(flags); // Call before TreePushOverrideID() if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) - TreePushOverrideID(id); + TreePushOverrideID(id); // Could use TreePush(label) but this avoid computing twice + IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0)); return is_open; } @@ -6509,16 +6666,19 @@ void ImGui::TreePop() window->DC.TreeDepth--; ImU32 tree_depth_mask = (1 << window->DC.TreeDepth); - // Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsBackHere is enabled) - if (window->DC.TreeJumpToParentOnPopMask & tree_depth_mask) // Only set during request + if (window->DC.TreeHasStackDataDepthMask & tree_depth_mask) // Only set during request { - ImGuiNavTreeNodeData* nav_tree_node_data = &g.NavTreeNodeStack.back(); - IM_ASSERT(nav_tree_node_data->ID == window->IDStack.back()); - if (g.NavIdIsAlive && g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) - NavMoveRequestResolveWithPastTreeNode(&g.NavMoveResultLocal, nav_tree_node_data); - g.NavTreeNodeStack.pop_back(); + ImGuiTreeNodeStackData* data = &g.TreeNodeStack.back(); + IM_ASSERT(data->ID == window->IDStack.back()); + if (data->TreeFlags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) + { + // Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsBackHere is enabled) + if (g.NavIdIsAlive && g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) + NavMoveRequestResolveWithPastTreeNode(&g.NavMoveResultLocal, data); + } + g.TreeNodeStack.pop_back(); + window->DC.TreeHasStackDataDepthMask &= ~tree_depth_mask; } - window->DC.TreeJumpToParentOnPopMask &= tree_depth_mask - 1; IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much. PopID(); @@ -6542,6 +6702,16 @@ void ImGui::SetNextItemOpen(bool is_open, ImGuiCond cond) g.NextItemData.OpenCond = (ImU8)(cond ? cond : ImGuiCond_Always); } +// Set next TreeNode/CollapsingHeader storage id. +void ImGui::SetNextItemStorageID(ImGuiID storage_id) +{ + ImGuiContext& g = *GImGui; + if (g.CurrentWindow->SkipItems) + return; + g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasStorageID; + g.NextItemData.StorageId = storage_id; +} + // CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag). // This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode(). bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) @@ -6549,8 +6719,8 @@ bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; - - return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader, label); + ImGuiID id = window->GetID(label); + return TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader, label); } // p_visible == NULL : regular collapsing header @@ -6630,6 +6800,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl const ImVec2 text_max(min_x + size.x, pos.y + size.y); // Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable. + // FIXME: Not part of layout so not included in clipper calculation, but ItemSize currently doesn't allow offsetting CursorPos. ImRect bb(min_x, pos.y, text_max.x, text_max.y); if ((flags & ImGuiSelectableFlags_NoPadWithHalfSpacing) == 0) { @@ -6644,25 +6815,29 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl } //if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(0, 255, 0, 255)); } - // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable.. - const float backup_clip_rect_min_x = window->ClipRect.Min.x; - const float backup_clip_rect_max_x = window->ClipRect.Max.x; + const bool disabled_item = (flags & ImGuiSelectableFlags_Disabled) != 0; + const ImGuiItemFlags extra_item_flags = disabled_item ? (ImGuiItemFlags)ImGuiItemFlags_Disabled : ImGuiItemFlags_None; + bool is_visible; if (span_all_columns) { + // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable.. + const float backup_clip_rect_min_x = window->ClipRect.Min.x; + const float backup_clip_rect_max_x = window->ClipRect.Max.x; window->ClipRect.Min.x = window->ParentWorkRect.Min.x; window->ClipRect.Max.x = window->ParentWorkRect.Max.x; - } - - const bool disabled_item = (flags & ImGuiSelectableFlags_Disabled) != 0; - const bool item_add = ItemAdd(bb, id, NULL, disabled_item ? ImGuiItemFlags_Disabled : ImGuiItemFlags_None); - if (span_all_columns) - { + is_visible = ItemAdd(bb, id, NULL, extra_item_flags); window->ClipRect.Min.x = backup_clip_rect_min_x; window->ClipRect.Max.x = backup_clip_rect_max_x; } + else + { + is_visible = ItemAdd(bb, id, NULL, extra_item_flags); + } - if (!item_add) - return false; + const bool is_multi_select = (g.LastItemData.InFlags & ImGuiItemFlags_IsMultiSelect) != 0; + if (!is_visible) + if (!is_multi_select || !g.BoxSelectState.UnclipMode || !g.BoxSelectState.UnclipRect.Overlaps(bb)) // Extra layer of "no logic clip" for box-select support (would be more overhead to add to ItemAdd) + return false; const bool disabled_global = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0; if (disabled_item && !disabled_global) // Only testing this as an optimization @@ -6689,20 +6864,35 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (flags & ImGuiSelectableFlags_AllowDoubleClick) { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; } if ((flags & ImGuiSelectableFlags_AllowOverlap) || (g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap)) { button_flags |= ImGuiButtonFlags_AllowOverlap; } + // Multi-selection support (header) const bool was_selected = selected; + if (is_multi_select) + { + // Handle multi-select + alter button flags for it + MultiSelectItemHeader(id, &selected, &button_flags); + } + bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); - // Auto-select when moved into - // - This will be more fully fleshed in the range-select branch - // - This is not exposed as it won't nicely work with some user side handling of shift/control - // - We cannot do 'if (g.NavJustMovedToId != id) { selected = false; pressed = was_selected; }' for two reasons - // - (1) it would require focus scope to be set, need exposing PushFocusScope() or equivalent (e.g. BeginSelection() calling PushFocusScope()) - // - (2) usage will fail with clipped items - // The multi-select API aim to fix those issues, e.g. may be replaced with a BeginSelection() API. - if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == g.CurrentFocusScopeId) - if (g.NavJustMovedToId == id) - selected = pressed = true; + // Multi-selection support (footer) + if (is_multi_select) + { + MultiSelectItemFooter(id, &selected, &pressed); + } + else + { + // Auto-select when moved into + // - This will be more fully fleshed in the range-select branch + // - This is not exposed as it won't nicely work with some user side handling of shift/control + // - We cannot do 'if (g.NavJustMovedToId != id) { selected = false; pressed = was_selected; }' for two reasons + // - (1) it would require focus scope to be set, need exposing PushFocusScope() or equivalent (e.g. BeginSelection() calling PushFocusScope()) + // - (2) usage will fail with clipped items + // The multi-select API aim to fix those issues, e.g. may be replaced with a BeginSelection() API. + if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == g.CurrentFocusScopeId) + if (g.NavJustMovedToId == id) + selected = pressed = true; + } // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover))) @@ -6716,18 +6906,31 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (pressed) MarkItemEdited(id); - // In this branch, Selectable() cannot toggle the selection so this will never trigger. - if (selected != was_selected) //-V547 + if (selected != was_selected) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection; // Render - if (hovered || selected) + if (is_visible) { - const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - RenderFrame(bb.Min, bb.Max, col, false, 0.0f); + const bool highlighted = hovered || (flags & ImGuiSelectableFlags_Highlight); + if (highlighted || selected) + { + // FIXME-MULTISELECT: Styling: Color for 'selected' elements? ImGuiCol_HeaderSelected + ImU32 col; + if (selected && !highlighted) + col = GetColorU32(ImLerp(GetStyleColorVec4(ImGuiCol_Header), GetStyleColorVec4(ImGuiCol_HeaderHovered), 0.5f)); + else + col = GetColorU32((held && highlighted) ? ImGuiCol_HeaderActive : highlighted ? ImGuiCol_HeaderHovered : ImGuiCol_Header); + RenderFrame(bb.Min, bb.Max, col, false, 0.0f); + } + if (g.NavId == id) + { + ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_Compact | ImGuiNavHighlightFlags_NoRounding; + if (is_multi_select) + nav_highlight_flags |= ImGuiNavHighlightFlags_AlwaysDraw; // Always show the nav rectangle + RenderNavHighlight(bb, id, nav_highlight_flags); + } } - if (g.NavId == id) - RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact | ImGuiNavHighlightFlags_NoRounding); if (span_all_columns) { @@ -6737,15 +6940,19 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl PopColumnsBackground(); } - RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb); + if (is_visible) + RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb); // Automatically close popups - if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(g.LastItemData.InFlags & ImGuiItemFlags_SelectableDontClosePopup)) + if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_NoAutoClosePopups) && (g.LastItemData.InFlags & ImGuiItemFlags_AutoClosePopups)) CloseCurrentPopup(); if (disabled_item && !disabled_global) EndDisabled(); + // Selectable() always returns a pressed state! + // Users of BeginMultiSelect()/EndMultiSelect() scope: you may call ImGui::IsItemToggledSelection() to retrieve + // selection toggle, only useful if you need that state updated (e.g. for rendering purpose) before reaching EndMultiSelect(). IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); return pressed; //-V1020 } @@ -6881,7 +7088,7 @@ static int ImStrimatchlen(const char* s1, const char* s1_end, const char* s2) // When SingleCharMode is set: // - it is better to NOT display a tooltip of other on-screen display indicator. // - the index of the currently focused item is required. -// if your SetNextItemSelectionData() values are indices, you can obtain it from ImGuiMultiSelectIO::NavIdItem, otherwise from g.NavLastValidSelectionUserData. +// if your SetNextItemSelectionUserData() values are indices, you can obtain it from ImGuiMultiSelectIO::NavIdItem, otherwise from g.NavLastValidSelectionUserData. int ImGui::TypingSelectFindMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx) { if (req == NULL || req->SelectRequest == false) // Support NULL parameter so both calls can be done from same spot. @@ -6951,20 +7158,927 @@ void ImGui::DebugNodeTypingSelectState(ImGuiTypingSelectState* data) #endif } +//------------------------------------------------------------------------- +// [SECTION] Widgets: Box-Select support +// This has been extracted away from Multi-Select logic in the hope that it could eventually be used elsewhere, but hasn't been yet. +//------------------------------------------------------------------------- +// Extra logic in MultiSelectItemFooter() and ImGuiListClipper::Step() +//------------------------------------------------------------------------- +// - BoxSelectPreStartDrag() [Internal] +// - BoxSelectActivateDrag() [Internal] +// - BoxSelectDeactivateDrag() [Internal] +// - BoxSelectScrollWithMouseDrag() [Internal] +// - BeginBoxSelect() [Internal] +// - EndBoxSelect() [Internal] +//------------------------------------------------------------------------- + +// Call on the initial click. +static void BoxSelectPreStartDrag(ImGuiID id, ImGuiSelectionUserData clicked_item) +{ + ImGuiContext& g = *GImGui; + ImGuiBoxSelectState* bs = &g.BoxSelectState; + bs->ID = id; + bs->IsStarting = true; // Consider starting box-select. + bs->IsStartedFromVoid = (clicked_item == ImGuiSelectionUserData_Invalid); + bs->IsStartedSetNavIdOnce = bs->IsStartedFromVoid; + bs->KeyMods = g.IO.KeyMods; + bs->StartPosRel = bs->EndPosRel = ImGui::WindowPosAbsToRel(g.CurrentWindow, g.IO.MousePos); + bs->ScrollAccum = ImVec2(0.0f, 0.0f); +} + +static void BoxSelectActivateDrag(ImGuiBoxSelectState* bs, ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + IMGUI_DEBUG_LOG_SELECTION("[selection] BeginBoxSelect() 0X%08X: Activate\n", bs->ID); + bs->IsActive = true; + bs->Window = window; + bs->IsStarting = false; + ImGui::SetActiveID(bs->ID, window); + ImGui::SetActiveIdUsingAllKeyboardKeys(); + if (bs->IsStartedFromVoid && (bs->KeyMods & (ImGuiMod_Ctrl | ImGuiMod_Shift)) == 0) + bs->RequestClear = true; +} + +static void BoxSelectDeactivateDrag(ImGuiBoxSelectState* bs) +{ + ImGuiContext& g = *GImGui; + bs->IsActive = bs->IsStarting = false; + if (g.ActiveId == bs->ID) + { + IMGUI_DEBUG_LOG_SELECTION("[selection] BeginBoxSelect() 0X%08X: Deactivate\n", bs->ID); + ImGui::ClearActiveID(); + } + bs->ID = 0; +} + +static void BoxSelectScrollWithMouseDrag(ImGuiBoxSelectState* bs, ImGuiWindow* window, const ImRect& inner_r) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(bs->Window == window); + for (int n = 0; n < 2; n++) // each axis + { + const float mouse_pos = g.IO.MousePos[n]; + const float dist = (mouse_pos > inner_r.Max[n]) ? mouse_pos - inner_r.Max[n] : (mouse_pos < inner_r.Min[n]) ? mouse_pos - inner_r.Min[n] : 0.0f; + const float scroll_curr = window->Scroll[n]; + if (dist == 0.0f || (dist < 0.0f && scroll_curr < 0.0f) || (dist > 0.0f && scroll_curr >= window->ScrollMax[n])) + continue; + + const float speed_multiplier = ImLinearRemapClamp(g.FontSize, g.FontSize * 5.0f, 1.0f, 4.0f, ImAbs(dist)); // x1 to x4 depending on distance + const float scroll_step = g.FontSize * 35.0f * speed_multiplier * ImSign(dist) * g.IO.DeltaTime; + bs->ScrollAccum[n] += scroll_step; + + // Accumulate into a stored value so we can handle high-framerate + const float scroll_step_i = ImFloor(bs->ScrollAccum[n]); + if (scroll_step_i == 0.0f) + continue; + if (n == 0) + ImGui::SetScrollX(window, scroll_curr + scroll_step_i); + else + ImGui::SetScrollY(window, scroll_curr + scroll_step_i); + bs->ScrollAccum[n] -= scroll_step_i; + } +} + +bool ImGui::BeginBoxSelect(const ImRect& scope_rect, ImGuiWindow* window, ImGuiID box_select_id, ImGuiMultiSelectFlags ms_flags) +{ + ImGuiContext& g = *GImGui; + ImGuiBoxSelectState* bs = &g.BoxSelectState; + KeepAliveID(box_select_id); + if (bs->ID != box_select_id) + return false; + + // IsStarting is set by MultiSelectItemFooter() when considering a possible box-select. We validate it here and lock geometry. + bs->UnclipMode = false; + bs->RequestClear = false; + if (bs->IsStarting && IsMouseDragPastThreshold(0)) + BoxSelectActivateDrag(bs, window); + else if ((bs->IsStarting || bs->IsActive) && g.IO.MouseDown[0] == false) + BoxSelectDeactivateDrag(bs); + if (!bs->IsActive) + return false; + + // Current frame absolute prev/current rectangles are used to toggle selection. + // They are derived from positions relative to scrolling space. + ImVec2 start_pos_abs = WindowPosRelToAbs(window, bs->StartPosRel); + ImVec2 prev_end_pos_abs = WindowPosRelToAbs(window, bs->EndPosRel); // Clamped already + ImVec2 curr_end_pos_abs = g.IO.MousePos; + if (ms_flags & ImGuiMultiSelectFlags_ScopeWindow) // Box-select scrolling only happens with ScopeWindow + curr_end_pos_abs = ImClamp(curr_end_pos_abs, scope_rect.Min, scope_rect.Max); + bs->BoxSelectRectPrev.Min = ImMin(start_pos_abs, prev_end_pos_abs); + bs->BoxSelectRectPrev.Max = ImMax(start_pos_abs, prev_end_pos_abs); + bs->BoxSelectRectCurr.Min = ImMin(start_pos_abs, curr_end_pos_abs); + bs->BoxSelectRectCurr.Max = ImMax(start_pos_abs, curr_end_pos_abs); + + // Box-select 2D mode detects horizontal changes (vertical ones are already picked by Clipper) + // Storing an extra rect used by widgets supporting box-select. + if (ms_flags & ImGuiMultiSelectFlags_BoxSelect2d) + if (bs->BoxSelectRectPrev.Min.x != bs->BoxSelectRectCurr.Min.x || bs->BoxSelectRectPrev.Max.x != bs->BoxSelectRectCurr.Max.x) + { + bs->UnclipMode = true; + bs->UnclipRect = bs->BoxSelectRectPrev; // FIXME-OPT: UnclipRect x coordinates could be intersection of Prev and Curr rect on X axis. + bs->UnclipRect.Add(bs->BoxSelectRectCurr); + } + + //GetForegroundDrawList()->AddRect(bs->UnclipRect.Min, bs->UnclipRect.Max, IM_COL32(255,0,0,200), 0.0f, 0, 3.0f); + //GetForegroundDrawList()->AddRect(bs->BoxSelectRectPrev.Min, bs->BoxSelectRectPrev.Max, IM_COL32(255,0,0,200), 0.0f, 0, 3.0f); + //GetForegroundDrawList()->AddRect(bs->BoxSelectRectCurr.Min, bs->BoxSelectRectCurr.Max, IM_COL32(0,255,0,200), 0.0f, 0, 1.0f); + return true; +} + +void ImGui::EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + ImGuiBoxSelectState* bs = &g.BoxSelectState; + IM_ASSERT(bs->IsActive); + bs->UnclipMode = false; + + // Render selection rectangle + bs->EndPosRel = WindowPosAbsToRel(window, ImClamp(g.IO.MousePos, scope_rect.Min, scope_rect.Max)); // Clamp stored position according to current scrolling view + ImRect box_select_r = bs->BoxSelectRectCurr; + box_select_r.ClipWith(scope_rect); + window->DrawList->AddRectFilled(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_SeparatorHovered, 0.30f)); // FIXME-MULTISELECT: Styling + window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavHighlight)); // FIXME-MULTISELECT: Styling + + // Scroll + const bool enable_scroll = (ms_flags & ImGuiMultiSelectFlags_ScopeWindow) && (ms_flags & ImGuiMultiSelectFlags_BoxSelectNoScroll) == 0; + if (enable_scroll) + { + ImRect scroll_r = scope_rect; + scroll_r.Expand(-g.FontSize); + //GetForegroundDrawList()->AddRect(scroll_r.Min, scroll_r.Max, IM_COL32(0, 255, 0, 255)); + if (!scroll_r.Contains(g.IO.MousePos)) + BoxSelectScrollWithMouseDrag(bs, window, scroll_r); + } +} //------------------------------------------------------------------------- // [SECTION] Widgets: Multi-Select support //------------------------------------------------------------------------- +// - DebugLogMultiSelectRequests() [Internal] +// - CalcScopeRect() [Internal] +// - BeginMultiSelect() +// - EndMultiSelect() +// - SetNextItemSelectionUserData() +// - MultiSelectItemHeader() [Internal] +// - MultiSelectItemFooter() [Internal] +// - DebugNodeMultiSelectState() [Internal] +//------------------------------------------------------------------------- + +static void DebugLogMultiSelectRequests(const char* function, const ImGuiMultiSelectIO* io) +{ + ImGuiContext& g = *GImGui; + for (const ImGuiSelectionRequest& req : io->Requests) + { + if (req.Type == ImGuiSelectionRequestType_SetAll) IMGUI_DEBUG_LOG_SELECTION("[selection] %s: Request: SetAll %d (= %s)\n", function, req.Selected, req.Selected ? "SelectAll" : "Clear"); + if (req.Type == ImGuiSelectionRequestType_SetRange) IMGUI_DEBUG_LOG_SELECTION("[selection] %s: Request: SetRange %" IM_PRId64 "..%" IM_PRId64 " (0x%" IM_PRIX64 "..0x%" IM_PRIX64 ") = %d (dir %d)\n", function, req.RangeFirstItem, req.RangeLastItem, req.RangeFirstItem, req.RangeLastItem, req.Selected, req.RangeDirection); + } +} + +static ImRect CalcScopeRect(ImGuiMultiSelectTempData* ms, ImGuiWindow* window) +{ + if (ms->Flags & ImGuiMultiSelectFlags_ScopeRect) + { + // Warning: this depends on CursorMaxPos so it means to be called by EndMultiSelect() only + return ImRect(ms->ScopeRectMin, ImMax(window->DC.CursorMaxPos, ms->ScopeRectMin)); + } + else + { + // Add inner table decoration (#7821) // FIXME: Why not baking in InnerClipRect? + ImRect scope_rect = window->InnerClipRect; + scope_rect.Min = ImMin(scope_rect.Min + ImVec2(window->DecoInnerSizeX1, window->DecoInnerSizeY1), scope_rect.Max); + return scope_rect; + } +} + +// Return ImGuiMultiSelectIO structure. +// Lifetime: don't hold on ImGuiMultiSelectIO* pointers over multiple frames or past any subsequent call to BeginMultiSelect() or EndMultiSelect(). +// Passing 'selection_size' and 'items_count' parameters is currently optional. +// - 'selection_size' is useful to disable some shortcut routing: e.g. ImGuiMultiSelectFlags_ClearOnEscape won't claim Escape key when selection_size 0, +// allowing a first press to clear selection THEN the second press to leave child window and return to parent. +// - 'items_count' is stored in ImGuiMultiSelectIO which makes it a convenient way to pass the information to your ApplyRequest() handler (but you may pass it differently). +// - If they are costly for you to compute (e.g. external intrusive selection without maintaining size), you may avoid them and pass -1. +// - If you can easily tell if your selection is empty or not, you may pass 0/1, or you may enable ImGuiMultiSelectFlags_ClearOnEscape flag dynamically. +ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int selection_size, int items_count) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + if (++g.MultiSelectTempDataStacked > g.MultiSelectTempData.Size) + g.MultiSelectTempData.resize(g.MultiSelectTempDataStacked, ImGuiMultiSelectTempData()); + ImGuiMultiSelectTempData* ms = &g.MultiSelectTempData[g.MultiSelectTempDataStacked - 1]; + IM_STATIC_ASSERT(offsetof(ImGuiMultiSelectTempData, IO) == 0); // Clear() relies on that. + g.CurrentMultiSelect = ms; + if ((flags & (ImGuiMultiSelectFlags_ScopeWindow | ImGuiMultiSelectFlags_ScopeRect)) == 0) + flags |= ImGuiMultiSelectFlags_ScopeWindow; + if (flags & ImGuiMultiSelectFlags_SingleSelect) + flags &= ~(ImGuiMultiSelectFlags_BoxSelect2d | ImGuiMultiSelectFlags_BoxSelect1d); + if (flags & ImGuiMultiSelectFlags_BoxSelect2d) + flags &= ~ImGuiMultiSelectFlags_BoxSelect1d; + + // FIXME: BeginFocusScope() + const ImGuiID id = window->IDStack.back(); + ms->Clear(); + ms->FocusScopeId = id; + ms->Flags = flags; + ms->IsFocused = (ms->FocusScopeId == g.NavFocusScopeId); + ms->BackupCursorMaxPos = window->DC.CursorMaxPos; + ms->ScopeRectMin = window->DC.CursorMaxPos = window->DC.CursorPos; + PushFocusScope(ms->FocusScopeId); + if (flags & ImGuiMultiSelectFlags_ScopeWindow) // Mark parent child window as navigable into, with highlight. Assume user will always submit interactive items. + window->DC.NavLayersActiveMask |= 1 << ImGuiNavLayer_Main; + + // Use copy of keyboard mods at the time of the request, otherwise we would requires mods to be held for an extra frame. + ms->KeyMods = g.NavJustMovedToId ? (g.NavJustMovedToIsTabbing ? 0 : g.NavJustMovedToKeyMods) : g.IO.KeyMods; + if (flags & ImGuiMultiSelectFlags_NoRangeSelect) + ms->KeyMods &= ~ImGuiMod_Shift; + + // Bind storage + ImGuiMultiSelectState* storage = g.MultiSelectStorage.GetOrAddByKey(id); + storage->ID = id; + storage->LastFrameActive = g.FrameCount; + storage->LastSelectionSize = selection_size; + storage->Window = window; + ms->Storage = storage; + + // Output to user + ms->IO.Requests.resize(0); + ms->IO.RangeSrcItem = storage->RangeSrcItem; + ms->IO.NavIdItem = storage->NavIdItem; + ms->IO.NavIdSelected = (storage->NavIdSelected == 1) ? true : false; + ms->IO.ItemsCount = items_count; + + // Clear when using Navigation to move within the scope + // (we compare FocusScopeId so it possible to use multiple selections inside a same window) + bool request_clear = false; + bool request_select_all = false; + if (g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == ms->FocusScopeId && g.NavJustMovedToHasSelectionData) + { + if (ms->KeyMods & ImGuiMod_Shift) + ms->IsKeyboardSetRange = true; + if (ms->IsKeyboardSetRange) + IM_ASSERT(storage->RangeSrcItem != ImGuiSelectionUserData_Invalid); // Not ready -> could clear? + if ((ms->KeyMods & (ImGuiMod_Ctrl | ImGuiMod_Shift)) == 0 && (flags & (ImGuiMultiSelectFlags_NoAutoClear | ImGuiMultiSelectFlags_NoAutoSelect)) == 0) + request_clear = true; + } + else if (g.NavJustMovedFromFocusScopeId == ms->FocusScopeId) + { + // Also clear on leaving scope (may be optional?) + if ((ms->KeyMods & (ImGuiMod_Ctrl | ImGuiMod_Shift)) == 0 && (flags & (ImGuiMultiSelectFlags_NoAutoClear | ImGuiMultiSelectFlags_NoAutoSelect)) == 0) + request_clear = true; + } + + // Box-select handling: update active state. + ImGuiBoxSelectState* bs = &g.BoxSelectState; + if (flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d)) + { + ms->BoxSelectId = GetID("##BoxSelect"); + if (BeginBoxSelect(CalcScopeRect(ms, window), window, ms->BoxSelectId, flags)) + request_clear |= bs->RequestClear; + } + + if (ms->IsFocused) + { + // Shortcut: Clear selection (Escape) + // - Only claim shortcut if selection is not empty, allowing further presses on Escape to e.g. leave current child window. + // - Box select also handle Escape and needs to pass an id to bypass ActiveIdUsingAllKeyboardKeys lock. + if (flags & ImGuiMultiSelectFlags_ClearOnEscape) + { + if (selection_size != 0 || bs->IsActive) + if (Shortcut(ImGuiKey_Escape, ImGuiInputFlags_None, bs->IsActive ? bs->ID : 0)) + { + request_clear = true; + if (bs->IsActive) + BoxSelectDeactivateDrag(bs); + } + } + + // Shortcut: Select all (CTRL+A) + if (!(flags & ImGuiMultiSelectFlags_SingleSelect) && !(flags & ImGuiMultiSelectFlags_NoSelectAll)) + if (Shortcut(ImGuiMod_Ctrl | ImGuiKey_A)) + request_select_all = true; + } + + if (request_clear || request_select_all) + { + MultiSelectAddSetAll(ms, request_select_all); + if (!request_select_all) + storage->LastSelectionSize = 0; + } + ms->LoopRequestSetAll = request_select_all ? 1 : request_clear ? 0 : -1; + ms->LastSubmittedItem = ImGuiSelectionUserData_Invalid; + + if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection) + DebugLogMultiSelectRequests("BeginMultiSelect", &ms->IO); + + return &ms->IO; +} + +// Return updated ImGuiMultiSelectIO structure. +// Lifetime: don't hold on ImGuiMultiSelectIO* pointers over multiple frames or past any subsequent call to BeginMultiSelect() or EndMultiSelect(). +ImGuiMultiSelectIO* ImGui::EndMultiSelect() +{ + ImGuiContext& g = *GImGui; + ImGuiMultiSelectTempData* ms = g.CurrentMultiSelect; + ImGuiMultiSelectState* storage = ms->Storage; + ImGuiWindow* window = g.CurrentWindow; + IM_ASSERT(ms->FocusScopeId == g.CurrentFocusScopeId); + IM_ASSERT(g.CurrentMultiSelect != NULL && storage->Window == g.CurrentWindow); + IM_ASSERT(g.MultiSelectTempDataStacked > 0 && &g.MultiSelectTempData[g.MultiSelectTempDataStacked - 1] == g.CurrentMultiSelect); + + ImRect scope_rect = CalcScopeRect(ms, window); + if (ms->IsFocused) + { + // We currently don't allow user code to modify RangeSrcItem by writing to BeginIO's version, but that would be an easy change here. + if (ms->IO.RangeSrcReset || (ms->RangeSrcPassedBy == false && ms->IO.RangeSrcItem != ImGuiSelectionUserData_Invalid)) // Can't read storage->RangeSrcItem here -> we want the state at begining of the scope (see tests for easy failure) + { + IMGUI_DEBUG_LOG_SELECTION("[selection] EndMultiSelect: Reset RangeSrcItem.\n"); // Will set be to NavId. + storage->RangeSrcItem = ImGuiSelectionUserData_Invalid; + } + if (ms->NavIdPassedBy == false && storage->NavIdItem != ImGuiSelectionUserData_Invalid) + { + IMGUI_DEBUG_LOG_SELECTION("[selection] EndMultiSelect: Reset NavIdItem.\n"); + storage->NavIdItem = ImGuiSelectionUserData_Invalid; + storage->NavIdSelected = -1; + } + + if ((ms->Flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d)) && GetBoxSelectState(ms->BoxSelectId)) + EndBoxSelect(scope_rect, ms->Flags); + } + + if (ms->IsEndIO == false) + ms->IO.Requests.resize(0); + + // Clear selection when clicking void? + // We specifically test for IsMouseDragPastThreshold(0) == false to allow box-selection! + // The InnerRect test is necessary for non-child/decorated windows. + bool scope_hovered = IsWindowHovered() && window->InnerRect.Contains(g.IO.MousePos); + if (scope_hovered && (ms->Flags & ImGuiMultiSelectFlags_ScopeRect)) + scope_hovered &= scope_rect.Contains(g.IO.MousePos); + if (scope_hovered && g.HoveredId == 0 && g.ActiveId == 0) + { + if (ms->Flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d)) + { + if (!g.BoxSelectState.IsActive && !g.BoxSelectState.IsStarting && g.IO.MouseClickedCount[0] == 1) + { + BoxSelectPreStartDrag(ms->BoxSelectId, ImGuiSelectionUserData_Invalid); + FocusWindow(window, ImGuiFocusRequestFlags_UnlessBelowModal); + SetHoveredID(ms->BoxSelectId); + if (ms->Flags & ImGuiMultiSelectFlags_ScopeRect) + SetNavID(0, ImGuiNavLayer_Main, ms->FocusScopeId, ImRect(g.IO.MousePos, g.IO.MousePos)); // Automatically switch FocusScope for initial click from void to box-select. + } + } + + if (ms->Flags & ImGuiMultiSelectFlags_ClearOnClickVoid) + if (IsMouseReleased(0) && IsMouseDragPastThreshold(0) == false && g.IO.KeyMods == ImGuiMod_None) + MultiSelectAddSetAll(ms, false); + } + + // Courtesy nav wrapping helper flag + if (ms->Flags & ImGuiMultiSelectFlags_NavWrapX) + { + IM_ASSERT(ms->Flags & ImGuiMultiSelectFlags_ScopeWindow); // Only supported at window scope + ImGui::NavMoveRequestTryWrapping(ImGui::GetCurrentWindow(), ImGuiNavMoveFlags_WrapX); + } + + // Unwind + window->DC.CursorMaxPos = ImMax(ms->BackupCursorMaxPos, window->DC.CursorMaxPos); + PopFocusScope(); + + if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection) + DebugLogMultiSelectRequests("EndMultiSelect", &ms->IO); + + ms->FocusScopeId = 0; + ms->Flags = ImGuiMultiSelectFlags_None; + g.CurrentMultiSelect = (--g.MultiSelectTempDataStacked > 0) ? &g.MultiSelectTempData[g.MultiSelectTempDataStacked - 1] : NULL; + + return &ms->IO; +} void ImGui::SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data) { // Note that flags will be cleared by ItemAdd(), so it's only useful for Navigation code! // This designed so widgets can also cheaply set this before calling ItemAdd(), so we are not tied to MultiSelect api. ImGuiContext& g = *GImGui; - g.NextItemData.ItemFlags |= ImGuiItemFlags_HasSelectionUserData; g.NextItemData.SelectionUserData = selection_user_data; + g.NextItemData.FocusScopeId = g.CurrentFocusScopeId; + + if (ImGuiMultiSelectTempData* ms = g.CurrentMultiSelect) + { + // Auto updating RangeSrcPassedBy for cases were clipper is not used (done before ItemAdd() clipping) + g.NextItemData.ItemFlags |= ImGuiItemFlags_HasSelectionUserData | ImGuiItemFlags_IsMultiSelect; + if (ms->IO.RangeSrcItem == selection_user_data) + ms->RangeSrcPassedBy = true; + } + else + { + g.NextItemData.ItemFlags |= ImGuiItemFlags_HasSelectionUserData; + } } +// In charge of: +// - Applying SetAll for submitted items. +// - Applying SetRange for submitted items and record end points. +// - Altering button behavior flags to facilitate use with drag and drop. +void ImGui::MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags* p_button_flags) +{ + ImGuiContext& g = *GImGui; + ImGuiMultiSelectTempData* ms = g.CurrentMultiSelect; + + bool selected = *p_selected; + if (ms->IsFocused) + { + ImGuiMultiSelectState* storage = ms->Storage; + ImGuiSelectionUserData item_data = g.NextItemData.SelectionUserData; + IM_ASSERT(g.NextItemData.FocusScopeId == g.CurrentFocusScopeId && "Forgot to call SetNextItemSelectionUserData() prior to item, required in BeginMultiSelect()/EndMultiSelect() scope"); + + // Apply SetAll (Clear/SelectAll) requests requested by BeginMultiSelect(). + // This is only useful if the user hasn't processed them already, and this only works if the user isn't using the clipper. + // If you are using a clipper you need to process the SetAll request after calling BeginMultiSelect() + if (ms->LoopRequestSetAll != -1) + selected = (ms->LoopRequestSetAll == 1); + + // When using SHIFT+Nav: because it can incur scrolling we cannot afford a frame of lag with the selection highlight (otherwise scrolling would happen before selection) + // For this to work, we need someone to set 'RangeSrcPassedBy = true' at some point (either clipper either SetNextItemSelectionUserData() function) + if (ms->IsKeyboardSetRange) + { + IM_ASSERT(id != 0 && (ms->KeyMods & ImGuiMod_Shift) != 0); + const bool is_range_dst = (ms->RangeDstPassedBy == false) && g.NavJustMovedToId == id; // Assume that g.NavJustMovedToId is not clipped. + if (is_range_dst) + ms->RangeDstPassedBy = true; + if (is_range_dst && storage->RangeSrcItem == ImGuiSelectionUserData_Invalid) // If we don't have RangeSrc, assign RangeSrc = RangeDst + { + storage->RangeSrcItem = item_data; + storage->RangeSelected = selected ? 1 : 0; + } + const bool is_range_src = storage->RangeSrcItem == item_data; + if (is_range_src || is_range_dst || ms->RangeSrcPassedBy != ms->RangeDstPassedBy) + { + // Apply range-select value to visible items + IM_ASSERT(storage->RangeSrcItem != ImGuiSelectionUserData_Invalid && storage->RangeSelected != -1); + selected = (storage->RangeSelected != 0); + } + else if ((ms->KeyMods & ImGuiMod_Ctrl) == 0 && (ms->Flags & ImGuiMultiSelectFlags_NoAutoClear) == 0) + { + // Clear other items + selected = false; + } + } + *p_selected = selected; + } + + // Alter button behavior flags + // To handle drag and drop of multiple items we need to avoid clearing selection on click. + // Enabling this test makes actions using CTRL+SHIFT delay their effect on MouseUp which is annoying, but it allows drag and drop of multiple items. + if (p_button_flags != NULL) + { + ImGuiButtonFlags button_flags = *p_button_flags; + button_flags |= ImGuiButtonFlags_NoHoveredOnFocus; + if ((!selected || (g.ActiveId == id && g.ActiveIdHasBeenPressedBefore)) && !(ms->Flags & ImGuiMultiSelectFlags_SelectOnClickRelease)) + button_flags = (button_flags | ImGuiButtonFlags_PressedOnClick) & ~ImGuiButtonFlags_PressedOnClickRelease; + else + button_flags |= ImGuiButtonFlags_PressedOnClickRelease; + *p_button_flags = button_flags; + } +} + +// In charge of: +// - Auto-select on navigation. +// - Box-select toggle handling. +// - Right-click handling. +// - Altering selection based on Ctrl/Shift modifiers, both for keyboard and mouse. +// - Record current selection state for RangeSrc +// This is all rather complex, best to run and refer to "widgets_multiselect_xxx" tests in imgui_test_suite. +void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + bool selected = *p_selected; + bool pressed = *p_pressed; + ImGuiMultiSelectTempData* ms = g.CurrentMultiSelect; + ImGuiMultiSelectState* storage = ms->Storage; + if (pressed) + ms->IsFocused = true; + + bool hovered = false; + if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) + hovered = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup); + if (!ms->IsFocused && !hovered) + return; + + ImGuiSelectionUserData item_data = g.NextItemData.SelectionUserData; + + ImGuiMultiSelectFlags flags = ms->Flags; + const bool is_singleselect = (flags & ImGuiMultiSelectFlags_SingleSelect) != 0; + bool is_ctrl = (ms->KeyMods & ImGuiMod_Ctrl) != 0; + bool is_shift = (ms->KeyMods & ImGuiMod_Shift) != 0; + + bool apply_to_range_src = false; + + if (g.NavId == id && storage->RangeSrcItem == ImGuiSelectionUserData_Invalid) + apply_to_range_src = true; + if (ms->IsEndIO == false) + { + ms->IO.Requests.resize(0); + ms->IsEndIO = true; + } + + // Auto-select as you navigate a list + if (g.NavJustMovedToId == id) + { + if ((flags & ImGuiMultiSelectFlags_NoAutoSelect) == 0) + { + if (is_ctrl && is_shift) + pressed = true; + else if (!is_ctrl) + selected = pressed = true; + } + else + { + // With NoAutoSelect, using Shift+keyboard performs a write/copy + if (is_shift) + pressed = true; + else if (!is_ctrl) + apply_to_range_src = true; // Since if (pressed) {} main block is not running we update this + } + } + + if (apply_to_range_src) + { + storage->RangeSrcItem = item_data; + storage->RangeSelected = selected; // Will be updated at the end of this function anyway. + } + + // Box-select toggle handling + if (ms->BoxSelectId != 0) + if (ImGuiBoxSelectState* bs = GetBoxSelectState(ms->BoxSelectId)) + { + const bool rect_overlap_curr = bs->BoxSelectRectCurr.Overlaps(g.LastItemData.Rect); + const bool rect_overlap_prev = bs->BoxSelectRectPrev.Overlaps(g.LastItemData.Rect); + if ((rect_overlap_curr && !rect_overlap_prev && !selected) || (rect_overlap_prev && !rect_overlap_curr)) + { + if (storage->LastSelectionSize <= 0 && bs->IsStartedSetNavIdOnce) + { + pressed = true; // First item act as a pressed: code below will emit selection request and set NavId (whatever we emit here will be overridden anyway) + bs->IsStartedSetNavIdOnce = false; + } + else + { + selected = !selected; + MultiSelectAddSetRange(ms, selected, +1, item_data, item_data); + } + storage->LastSelectionSize = ImMax(storage->LastSelectionSize + 1, 1); + } + } + + // Right-click handling. + // FIXME-MULTISELECT: Currently filtered out by ImGuiMultiSelectFlags_NoAutoSelect but maybe should be moved to Selectable(). See https://github.com/ocornut/imgui/pull/5816 + if (hovered && IsMouseClicked(1) && (flags & ImGuiMultiSelectFlags_NoAutoSelect) == 0) + { + if (g.ActiveId != 0 && g.ActiveId != id) + ClearActiveID(); + SetFocusID(id, window); + if (!pressed && !selected) + { + pressed = true; + is_ctrl = is_shift = false; + } + } + + // Unlike Space, Enter doesn't alter selection (but can still return a press) unless current item is not selected. + // The later, "unless current item is not select", may become optional? It seems like a better default if Enter doesn't necessarily open something + // (unlike e.g. Windows explorer). For use case where Enter always open something, we might decide to make this optional? + const bool enter_pressed = pressed && (g.NavActivateId == id) && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput); + + // Alter selection + if (pressed && (!enter_pressed || !selected)) + { + // Box-select + ImGuiInputSource input_source = (g.NavJustMovedToId == id || g.NavActivateId == id) ? g.NavInputSource : ImGuiInputSource_Mouse; + if (flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d)) + if (selected == false && !g.BoxSelectState.IsActive && !g.BoxSelectState.IsStarting && input_source == ImGuiInputSource_Mouse && g.IO.MouseClickedCount[0] == 1) + BoxSelectPreStartDrag(ms->BoxSelectId, item_data); + + //---------------------------------------------------------------------------------------- + // ACTION | Begin | Pressed/Activated | End + //---------------------------------------------------------------------------------------- + // Keys Navigated: | Clear | Src=item, Sel=1 SetRange 1 + // Keys Navigated: Ctrl | n/a | n/a + // Keys Navigated: Shift | n/a | Dst=item, Sel=1, => Clear + SetRange 1 + // Keys Navigated: Ctrl+Shift | n/a | Dst=item, Sel=Src => Clear + SetRange Src-Dst + // Keys Activated: | n/a | Src=item, Sel=1 => Clear + SetRange 1 + // Keys Activated: Ctrl | n/a | Src=item, Sel=!Sel => SetSange 1 + // Keys Activated: Shift | n/a | Dst=item, Sel=1 => Clear + SetSange 1 + //---------------------------------------------------------------------------------------- + // Mouse Pressed: | n/a | Src=item, Sel=1, => Clear + SetRange 1 + // Mouse Pressed: Ctrl | n/a | Src=item, Sel=!Sel => SetRange 1 + // Mouse Pressed: Shift | n/a | Dst=item, Sel=1, => Clear + SetRange 1 + // Mouse Pressed: Ctrl+Shift | n/a | Dst=item, Sel=!Sel => SetRange Src-Dst + //---------------------------------------------------------------------------------------- + + if ((flags & ImGuiMultiSelectFlags_NoAutoClear) == 0) + { + bool request_clear = false; + if (is_singleselect) + request_clear = true; + else if ((input_source == ImGuiInputSource_Mouse || g.NavActivateId == id) && !is_ctrl) + request_clear = (flags & ImGuiMultiSelectFlags_NoAutoClearOnReselect) ? !selected : true; + else if ((input_source == ImGuiInputSource_Keyboard || input_source == ImGuiInputSource_Gamepad) && is_shift && !is_ctrl) + request_clear = true; // With is_shift==false the RequestClear was done in BeginIO, not necessary to do again. + if (request_clear) + MultiSelectAddSetAll(ms, false); + } + + int range_direction; + bool range_selected; + if (is_shift && !is_singleselect) + { + //IM_ASSERT(storage->HasRangeSrc && storage->HasRangeValue); + if (storage->RangeSrcItem == ImGuiSelectionUserData_Invalid) + storage->RangeSrcItem = item_data; + if ((flags & ImGuiMultiSelectFlags_NoAutoSelect) == 0) + { + // Shift+Arrow always select + // Ctrl+Shift+Arrow copy source selection state (already stored by BeginMultiSelect() in storage->RangeSelected) + range_selected = (is_ctrl && storage->RangeSelected != -1) ? (storage->RangeSelected != 0) : true; + } + else + { + // Shift+Arrow copy source selection state + // Shift+Click always copy from target selection state + if (ms->IsKeyboardSetRange) + range_selected = (storage->RangeSelected != -1) ? (storage->RangeSelected != 0) : true; + else + range_selected = !selected; + } + range_direction = ms->RangeSrcPassedBy ? +1 : -1; + } + else + { + // Ctrl inverts selection, otherwise always select + if ((flags & ImGuiMultiSelectFlags_NoAutoSelect) == 0) + selected = is_ctrl ? !selected : true; + else + selected = !selected; + storage->RangeSrcItem = item_data; + range_selected = selected; + range_direction = +1; + } + MultiSelectAddSetRange(ms, range_selected, range_direction, storage->RangeSrcItem, item_data); + } + + // Update/store the selection state of the Source item (used by CTRL+SHIFT, when Source is unselected we perform a range unselect) + if (storage->RangeSrcItem == item_data) + storage->RangeSelected = selected ? 1 : 0; + + // Update/store the selection state of focused item + if (g.NavId == id) + { + storage->NavIdItem = item_data; + storage->NavIdSelected = selected ? 1 : 0; + } + if (storage->NavIdItem == item_data) + ms->NavIdPassedBy = true; + ms->LastSubmittedItem = item_data; + + *p_selected = selected; + *p_pressed = pressed; +} + +void ImGui::MultiSelectAddSetAll(ImGuiMultiSelectTempData* ms, bool selected) +{ + ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetAll, selected, 0, ImGuiSelectionUserData_Invalid, ImGuiSelectionUserData_Invalid }; + ms->IO.Requests.resize(0); // Can always clear previous requests + ms->IO.Requests.push_back(req); // Add new request +} + +void ImGui::MultiSelectAddSetRange(ImGuiMultiSelectTempData* ms, bool selected, int range_dir, ImGuiSelectionUserData first_item, ImGuiSelectionUserData last_item) +{ + // Merge contiguous spans into same request (unless NoRangeSelect is set which guarantees single-item ranges) + if (ms->IO.Requests.Size > 0 && first_item == last_item && (ms->Flags & ImGuiMultiSelectFlags_NoRangeSelect) == 0) + { + ImGuiSelectionRequest* prev = &ms->IO.Requests.Data[ms->IO.Requests.Size - 1]; + if (prev->Type == ImGuiSelectionRequestType_SetRange && prev->RangeLastItem == ms->LastSubmittedItem && prev->Selected == selected) + { + prev->RangeLastItem = last_item; + return; + } + } + + ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetRange, selected, (ImS8)range_dir, (range_dir > 0) ? first_item : last_item, (range_dir > 0) ? last_item : first_item }; + ms->IO.Requests.push_back(req); // Add new request +} + +void ImGui::DebugNodeMultiSelectState(ImGuiMultiSelectState* storage) +{ +#ifndef IMGUI_DISABLE_DEBUG_TOOLS + const bool is_active = (storage->LastFrameActive >= GetFrameCount() - 2); // Note that fully clipped early out scrolling tables will appear as inactive here. + if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } + bool open = TreeNode((void*)(intptr_t)storage->ID, "MultiSelect 0x%08X in '%s'%s", storage->ID, storage->Window ? storage->Window->Name : "N/A", is_active ? "" : " *Inactive*"); + if (!is_active) { PopStyleColor(); } + if (!open) + return; + Text("RangeSrcItem = %" IM_PRId64 " (0x%" IM_PRIX64 "), RangeSelected = %d", storage->RangeSrcItem, storage->RangeSrcItem, storage->RangeSelected); + Text("NavIdItem = %" IM_PRId64 " (0x%" IM_PRIX64 "), NavIdSelected = %d", storage->NavIdItem, storage->NavIdItem, storage->NavIdSelected); + Text("LastSelectionSize = %d", storage->LastSelectionSize); // Provided by user + TreePop(); +#else + IM_UNUSED(storage); +#endif +} + +//------------------------------------------------------------------------- +// [SECTION] Widgets: Multi-Select helpers +//------------------------------------------------------------------------- +// - ImGuiSelectionBasicStorage +// - ImGuiSelectionExternalStorage +//------------------------------------------------------------------------- + +ImGuiSelectionBasicStorage::ImGuiSelectionBasicStorage() +{ + Size = 0; + PreserveOrder = false; + UserData = NULL; + AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage*, int idx) { return (ImGuiID)idx; }; + _SelectionOrder = 1; // Always >0 +} + +void ImGuiSelectionBasicStorage::Clear() +{ + Size = 0; + _SelectionOrder = 1; // Always >0 + _Storage.Data.resize(0); +} + +void ImGuiSelectionBasicStorage::Swap(ImGuiSelectionBasicStorage& r) +{ + ImSwap(Size, r.Size); + ImSwap(_SelectionOrder, r._SelectionOrder); + _Storage.Data.swap(r._Storage.Data); +} + +bool ImGuiSelectionBasicStorage::Contains(ImGuiID id) const +{ + return _Storage.GetInt(id, 0) != 0; +} + +static int IMGUI_CDECL PairComparerByValueInt(const void* lhs, const void* rhs) +{ + int lhs_v = ((const ImGuiStoragePair*)lhs)->val_i; + int rhs_v = ((const ImGuiStoragePair*)rhs)->val_i; + return (lhs_v > rhs_v ? +1 : lhs_v < rhs_v ? -1 : 0); +} + +// GetNextSelectedItem() is an abstraction allowing us to change our underlying actual storage system without impacting user. +// (e.g. store unselected vs compact down, compact down on demand, use raw ImVector instead of ImGuiStorage...) +bool ImGuiSelectionBasicStorage::GetNextSelectedItem(void** opaque_it, ImGuiID* out_id) +{ + ImGuiStoragePair* it = (ImGuiStoragePair*)*opaque_it; + ImGuiStoragePair* it_end = _Storage.Data.Data + _Storage.Data.Size; + if (PreserveOrder && it == NULL && it_end != NULL) + ImQsort(_Storage.Data.Data, (size_t)_Storage.Data.Size, sizeof(ImGuiStoragePair), PairComparerByValueInt); // ~ImGuiStorage::BuildSortByValueInt() + if (it == NULL) + it = _Storage.Data.Data; + IM_ASSERT(it >= _Storage.Data.Data && it <= it_end); + if (it != it_end) + while (it->val_i == 0 && it < it_end) + it++; + const bool has_more = (it != it_end); + *opaque_it = has_more ? (void**)(it + 1) : (void**)(it); + *out_id = has_more ? it->key : 0; + if (PreserveOrder && !has_more) + _Storage.BuildSortByKey(); + return has_more; +} + +void ImGuiSelectionBasicStorage::SetItemSelected(ImGuiID id, bool selected) +{ + int* p_int = _Storage.GetIntRef(id, 0); + if (selected && *p_int == 0) { *p_int = _SelectionOrder++; Size++; } + else if (!selected && *p_int != 0) { *p_int = 0; Size--; } +} + +// Optimized for batch edits (with same value of 'selected') +static void ImGuiSelectionBasicStorage_BatchSetItemSelected(ImGuiSelectionBasicStorage* selection, ImGuiID id, bool selected, int size_before_amends, int selection_order) +{ + ImGuiStorage* storage = &selection->_Storage; + ImGuiStoragePair* it = ImLowerBound(storage->Data.Data, storage->Data.Data + size_before_amends, id); + const bool is_contained = (it != storage->Data.Data + size_before_amends) && (it->key == id); + if (selected == (is_contained && it->val_i != 0)) + return; + if (selected && !is_contained) + storage->Data.push_back(ImGuiStoragePair(id, selection_order)); // Push unsorted at end of vector, will be sorted in SelectionMultiAmendsFinish() + else if (is_contained) + it->val_i = selected ? selection_order : 0; // Modify in-place. + selection->Size += selected ? +1 : -1; +} + +static void ImGuiSelectionBasicStorage_BatchFinish(ImGuiSelectionBasicStorage* selection, bool selected, int size_before_amends) +{ + ImGuiStorage* storage = &selection->_Storage; + if (selected && selection->Size != size_before_amends) + storage->BuildSortByKey(); // When done selecting: sort everything +} + +// Apply requests coming from BeginMultiSelect() and EndMultiSelect(). +// - Enable 'Demo->Tools->Debug Log->Selection' to see selection requests as they happen. +// - Honoring SetRange requests requires that you can iterate/interpolate between RangeFirstItem and RangeLastItem. +// - In this demo we often submit indices to SetNextItemSelectionUserData() + store the same indices in persistent selection. +// - Your code may do differently. If you store pointers or objects ID in ImGuiSelectionUserData you may need to perform +// a lookup in order to have some way to iterate/interpolate between two items. +// - A full-featured application is likely to allow search/filtering which is likely to lead to using indices +// and constructing a view index <> object id/ptr data structure anyway. +// WHEN YOUR APPLICATION SETTLES ON A CHOICE, YOU WILL PROBABLY PREFER TO GET RID OF THIS UNNECESSARY 'ImGuiSelectionBasicStorage' INDIRECTION LOGIC. +// Notice that with the simplest adapter (using indices everywhere), all functions return their parameters. +// The most simple implementation (using indices everywhere) would look like: +// for (ImGuiSelectionRequest& req : ms_io->Requests) +// { +// if (req.Type == ImGuiSelectionRequestType_SetAll) { Clear(); if (req.Selected) { for (int n = 0; n < items_count; n++) { SetItemSelected(n, true); } } +// if (req.Type == ImGuiSelectionRequestType_SetRange) { for (int n = (int)ms_io->RangeFirstItem; n <= (int)ms_io->RangeLastItem; n++) { SetItemSelected(n, ms_io->Selected); } } +// } +void ImGuiSelectionBasicStorage::ApplyRequests(ImGuiMultiSelectIO* ms_io) +{ + // For convenience we obtain ItemsCount as passed to BeginMultiSelect(), which is optional. + // It makes sense when using ImGuiSelectionBasicStorage to simply pass your items count to BeginMultiSelect(). + // Other scheme may handle SetAll differently. + IM_ASSERT(ms_io->ItemsCount != -1 && "Missing value for items_count in BeginMultiSelect() call!"); + IM_ASSERT(AdapterIndexToStorageId != NULL); + + // This is optimized/specialized to cope with very large selections (e.g. 100k+ items) + // - A simpler version could call SetItemSelected() directly instead of ImGuiSelectionBasicStorage_BatchSetItemSelected() + ImGuiSelectionBasicStorage_BatchFinish(). + // - Optimized select can append unsorted, then sort in a second pass. Optimized unselect can clear in-place then compact in a second pass. + // - A more optimal version wouldn't even use ImGuiStorage but directly a ImVector to reduce bandwidth, but this is a reasonable trade off to reuse code. + // - There are many ways this could be better optimized. The worse case scenario being: using BoxSelect2d in a grid, box-select scrolling down while wiggling + // left and right: it affects coarse clipping + can emit multiple SetRange with 1 item each.) + // FIXME-OPT: For each block of consecutive SetRange request: + // - add all requests to a sorted list, store ID, selected, offset in ImGuiStorage. + // - rewrite sorted storage a single time. + for (ImGuiSelectionRequest& req : ms_io->Requests) + { + if (req.Type == ImGuiSelectionRequestType_SetAll) + { + Clear(); + if (req.Selected) + { + _Storage.Data.reserve(ms_io->ItemsCount); + const int size_before_amends = _Storage.Data.Size; + for (int idx = 0; idx < ms_io->ItemsCount; idx++, _SelectionOrder++) + ImGuiSelectionBasicStorage_BatchSetItemSelected(this, GetStorageIdFromIndex(idx), req.Selected, size_before_amends, _SelectionOrder); + ImGuiSelectionBasicStorage_BatchFinish(this, req.Selected, size_before_amends); + } + } + else if (req.Type == ImGuiSelectionRequestType_SetRange) + { + const int selection_changes = (int)req.RangeLastItem - (int)req.RangeFirstItem + 1; + //ImGuiContext& g = *GImGui; IMGUI_DEBUG_LOG_SELECTION("Req %d/%d: set %d to %d\n", ms_io->Requests.index_from_ptr(&req), ms_io->Requests.Size, selection_changes, req.Selected); + if (selection_changes == 1 || (selection_changes < Size / 100)) + { + // Multiple sorted insertion + copy likely to be faster. + // Technically we could do a single copy with a little more work (sort sequential SetRange requests) + for (int idx = (int)req.RangeFirstItem; idx <= (int)req.RangeLastItem; idx++) + SetItemSelected(GetStorageIdFromIndex(idx), req.Selected); + } + else + { + // Append insertion + single sort likely be faster. + // Use req.RangeDirection to set order field so that shift+clicking from 1 to 5 is different than shift+clicking from 5 to 1 + const int size_before_amends = _Storage.Data.Size; + int selection_order = _SelectionOrder + ((req.RangeDirection < 0) ? selection_changes - 1 : 0); + for (int idx = (int)req.RangeFirstItem; idx <= (int)req.RangeLastItem; idx++, selection_order += req.RangeDirection) + ImGuiSelectionBasicStorage_BatchSetItemSelected(this, GetStorageIdFromIndex(idx), req.Selected, size_before_amends, selection_order); + if (req.Selected) + _SelectionOrder += selection_changes; + ImGuiSelectionBasicStorage_BatchFinish(this, req.Selected, size_before_amends); + } + } + } +} + +//------------------------------------------------------------------------- + +ImGuiSelectionExternalStorage::ImGuiSelectionExternalStorage() +{ + UserData = NULL; + AdapterSetItemSelected = NULL; +} + +// Apply requests coming from BeginMultiSelect() and EndMultiSelect(). +// We also pull 'ms_io->ItemsCount' as passed for BeginMultiSelect() for consistency with ImGuiSelectionBasicStorage +// This makes no assumption about underlying storage. +void ImGuiSelectionExternalStorage::ApplyRequests(ImGuiMultiSelectIO* ms_io) +{ + IM_ASSERT(AdapterSetItemSelected); + for (ImGuiSelectionRequest& req : ms_io->Requests) + { + if (req.Type == ImGuiSelectionRequestType_SetAll) + for (int idx = 0; idx < ms_io->ItemsCount; idx++) + AdapterSetItemSelected(this, idx, req.Selected); + if (req.Type == ImGuiSelectionRequestType_SetRange) + for (int idx = (int)req.RangeFirstItem; idx <= (int)req.RangeLastItem; idx++) + AdapterSetItemSelected(this, idx, req.Selected); + } +} //------------------------------------------------------------------------- // [SECTION] Widgets: ListBox @@ -7451,6 +8565,7 @@ bool ImGui::BeginViewportSideBar(const char* name, ImGuiViewport* viewport_p, Im } window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking; + // Create window SetNextWindowViewport(viewport->ID); // Enforce viewport so we don't create our own viewport when ImGuiConfigFlags_ViewportsNoMerge is set. PushStyleColor(ImGuiCol_WindowShadow, ImVec4(0, 0, 0, 0)); @@ -7575,7 +8690,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) bool pressed; // We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another. - const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups; + const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_NoAutoClosePopups; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { // Menu inside an horizontal menu bar @@ -8968,13 +10083,13 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImDrawList* display_draw_list = window->DrawList; const ImU32 tab_col = GetColorU32((held || hovered) ? ImGuiCol_TabHovered : tab_contents_visible ? (tab_bar_focused ? ImGuiCol_TabSelected : ImGuiCol_TabDimmedSelected) : (tab_bar_focused ? ImGuiCol_Tab : ImGuiCol_TabDimmed)); TabItemBackground(display_draw_list, bb, flags, tab_col); - if (tab_contents_visible && (tab_bar->Flags & ImGuiTabBarFlags_DrawSelectedOverline)) + if (tab_contents_visible && (tab_bar->Flags & ImGuiTabBarFlags_DrawSelectedOverline) && style.TabBarOverlineSize > 0.0f) { float x_offset = IM_TRUNC(0.4f * style.TabRounding); if (x_offset < 2.0f * g.CurrentDpiScale) x_offset = 0.0f; float y_offset = 1.0f * g.CurrentDpiScale; - display_draw_list->AddLine(bb.GetTL() + ImVec2(x_offset, y_offset), bb.GetTR() + ImVec2(-x_offset, y_offset), GetColorU32(tab_bar_focused ? ImGuiCol_TabSelectedOverline : ImGuiCol_TabDimmedSelectedOverline), 2.0f * g.CurrentDpiScale); + display_draw_list->AddLine(bb.GetTL() + ImVec2(x_offset, y_offset), bb.GetTR() + ImVec2(-x_offset, y_offset), GetColorU32(tab_bar_focused ? ImGuiCol_TabSelectedOverline : ImGuiCol_TabDimmedSelectedOverline), style.TabBarOverlineSize); } RenderNavHighlight(bb, id); diff --git a/plugins/builtin/include/content/views/view_pattern_editor.hpp b/plugins/builtin/include/content/views/view_pattern_editor.hpp index fbc6d9c11..751e259ba 100644 --- a/plugins/builtin/include/content/views/view_pattern_editor.hpp +++ b/plugins/builtin/include/content/views/view_pattern_editor.hpp @@ -100,7 +100,7 @@ namespace hex::plugin::builtin { displayValue = fileName; } - if (ImGui::Selectable(displayValue.c_str(), index == m_selectedPatternFile, ImGuiSelectableFlags_DontClosePopups)) + if (ImGui::Selectable(displayValue.c_str(), index == m_selectedPatternFile, ImGuiSelectableFlags_NoAutoClosePopups)) m_selectedPatternFile = index; if (ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayNormal)) { diff --git a/plugins/builtin/source/content/views/view_command_palette.cpp b/plugins/builtin/source/content/views/view_command_palette.cpp index 6c8d298af..f9b0bd4d2 100644 --- a/plugins/builtin/source/content/views/view_command_palette.cpp +++ b/plugins/builtin/source/content/views/view_command_palette.cpp @@ -105,11 +105,11 @@ namespace hex::plugin::builtin { // Draw the results if (ImGui::BeginChild("##results", ImGui::GetContentRegionAvail(), ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_AlwaysVerticalScrollbar)) { for (const auto &[displayResult, matchedCommand, callback] : m_lastResults) { - ImGui::PushTabStop(true); - ON_SCOPE_EXIT { ImGui::PopTabStop(); }; + ImGui::PushItemFlag(ImGuiItemFlags_NoTabStop, false); + ON_SCOPE_EXIT { ImGui::PopItemFlag(); }; // Allow executing a command by clicking on it or selecting it with the keyboard and pressing enter - if (ImGui::Selectable(displayResult.c_str(), false, ImGuiSelectableFlags_DontClosePopups)) { + if (ImGui::Selectable(displayResult.c_str(), false, ImGuiSelectableFlags_NoAutoClosePopups)) { callback(matchedCommand); break; } diff --git a/plugins/builtin/source/content/views/view_hex_editor.cpp b/plugins/builtin/source/content/views/view_hex_editor.cpp index cc6883780..95f88ae67 100644 --- a/plugins/builtin/source/content/views/view_hex_editor.cpp +++ b/plugins/builtin/source/content/views/view_hex_editor.cpp @@ -574,7 +574,7 @@ namespace hex::plugin::builtin { void ViewHexEditor::drawPopup() { bool open = true; - ImGui::SetNextWindowPos(ImGui::GetWindowPos() + ImGui::GetWindowContentRegionMin() - ImGui::GetStyle().WindowPadding, ImGuiCond_Once); + ImGui::SetNextWindowPos(ImGui::GetCurrentWindowRead()->ContentRegionRect.Min - ImGui::GetStyle().WindowPadding, ImGuiCond_Once); const auto configuredAlpha = ImGuiExt::GetCustomStyle().PopupWindowAlpha; bool alphaIsChanged = false; if (m_currPopup != nullptr && !m_currentPopupHover && m_currentPopupHasHovered && m_currentPopupDetached && configuredAlpha < 0.99F && configuredAlpha > 0.01F) { diff --git a/plugins/builtin/source/content/views/view_settings.cpp b/plugins/builtin/source/content/views/view_settings.cpp index a319964c7..6c5fb4eaf 100644 --- a/plugins/builtin/source/content/views/view_settings.cpp +++ b/plugins/builtin/source/content/views/view_settings.cpp @@ -66,7 +66,7 @@ namespace hex::plugin::builtin { if (category.subCategories.empty()) continue; - if (ImGui::Selectable(Lang(category.unlocalizedName), m_selectedCategory == &category, ImGuiSelectableFlags_DontClosePopups) || m_selectedCategory == nullptr) + if (ImGui::Selectable(Lang(category.unlocalizedName), m_selectedCategory == &category, ImGuiSelectableFlags_NoAutoClosePopups) || m_selectedCategory == nullptr) m_selectedCategory = &category; if (m_selectedCategory == &category) diff --git a/plugins/ui/include/popups/popup_file_chooser.hpp b/plugins/ui/include/popups/popup_file_chooser.hpp index d9701f252..2d4985c56 100644 --- a/plugins/ui/include/popups/popup_file_chooser.hpp +++ b/plugins/ui/include/popups/popup_file_chooser.hpp @@ -68,7 +68,7 @@ namespace hex::ui { ImGui::PushID(&*fileIt); bool selected = m_selectedFiles.contains(fileIt); - if (ImGui::Selectable(pathNameString.c_str(), selected, ImGuiSelectableFlags_DontClosePopups)) { + if (ImGui::Selectable(pathNameString.c_str(), selected, ImGuiSelectableFlags_NoAutoClosePopups)) { if (!m_multiple) { m_selectedFiles.clear(); m_selectedFiles.insert(fileIt);