From aaf157cfdd9aec8cdf1da4c4a61b055ee8cb586d Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 5 Dec 2023 17:04:19 +0100 Subject: [PATCH 001/237] Commented out ImGuiFreeType::BuildFontAtlas() obsoleted in 1.81. Commented out legacy ImGuiColumnsFlags_XXX symbols redirecting to ImGuiOldColumnsFlags_XXX, obsoleted in 1.80. Amend 9499afdf and 72de6f336 --- docs/CHANGELOG.txt | 5 +++++ imgui.cpp | 2 ++ imgui_internal.h | 16 ++++++++-------- misc/freetype/imgui_freetype.h | 3 +-- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ec709cf1ee76..691c7ebb866d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -42,6 +42,11 @@ HOW TO UPDATE? Breaking changes: +- imgui_freetype: commented out ImGuiFreeType::BuildFontAtlas() obsoleted in 1.81. + Prefer using #define IMGUI_ENABLE_FREETYPE or see commented code for manual calls. +- Internals, Columns: commented out legacy ImGuiColumnsFlags_XXX symbols redirecting + to ImGuiOldColumnsFlags_XXX, obsoleted from imgui_internal.h in 1.80. + Other changes: - Windows: BeginChild(): Fixed auto-resizing erroneously limiting size to host viewport diff --git a/imgui.cpp b/imgui.cpp index 09f154b69de7..d04ebeaa0d02 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -424,6 +424,8 @@ CODE When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2023/11/05 (1.90.1) - imgui_freetype: commented out ImGuiFreeType::BuildFontAtlas() obsoleted in 1.81. prefer using #define IMGUI_ENABLE_FREETYPE or see commented code for manual calls. + - 2023/11/05 (1.90.1) - internals,columns: commented out legacy ImGuiColumnsFlags_XXX symbols redirecting to ImGuiOldColumnsFlags_XXX, obsoleted from imgui_internal.h in 1.80. - 2023/11/09 (1.90.0) - removed IM_OFFSETOF() macro in favor of using offsetof() available in C++11. Kept redirection define (will obsolete). - 2023/11/07 (1.90.0) - removed BeginChildFrame()/EndChildFrame() in favor of using BeginChild() with the ImGuiChildFlags_FrameStyle flag. kept inline redirection function (will obsolete). those functions were merely PushStyle/PopStyle helpers, the removal isn't so much motivated by needing to add the feature in BeginChild(), but by the necessity to avoid BeginChildFrame() signature mismatching BeginChild() signature and features. diff --git a/imgui_internal.h b/imgui_internal.h index bb80eeabf6c2..6ed1c10093dd 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1600,7 +1600,7 @@ struct IMGUI_API ImGuiTypingSelectState // [SECTION] Columns support //----------------------------------------------------------------------------- -// Flags for internal's BeginColumns(). Prefix using BeginTable() nowadays! +// Flags for internal's BeginColumns(). This is an obsolete API. Prefer using BeginTable() nowadays! enum ImGuiOldColumnFlags_ { ImGuiOldColumnFlags_None = 0, @@ -1608,16 +1608,16 @@ enum ImGuiOldColumnFlags_ ImGuiOldColumnFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers ImGuiOldColumnFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns ImGuiOldColumnFlags_NoForceWithinWindow = 1 << 3, // Disable forcing columns to fit within window - ImGuiOldColumnFlags_GrowParentContentsSize = 1 << 4, // (WIP) Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove. + ImGuiOldColumnFlags_GrowParentContentsSize = 1 << 4, // Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove. // Obsolete names (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - ImGuiColumnsFlags_None = ImGuiOldColumnFlags_None, - ImGuiColumnsFlags_NoBorder = ImGuiOldColumnFlags_NoBorder, - ImGuiColumnsFlags_NoResize = ImGuiOldColumnFlags_NoResize, - ImGuiColumnsFlags_NoPreserveWidths = ImGuiOldColumnFlags_NoPreserveWidths, - ImGuiColumnsFlags_NoForceWithinWindow = ImGuiOldColumnFlags_NoForceWithinWindow, - ImGuiColumnsFlags_GrowParentContentsSize = ImGuiOldColumnFlags_GrowParentContentsSize, + //ImGuiColumnsFlags_None = ImGuiOldColumnFlags_None, + //ImGuiColumnsFlags_NoBorder = ImGuiOldColumnFlags_NoBorder, + //ImGuiColumnsFlags_NoResize = ImGuiOldColumnFlags_NoResize, + //ImGuiColumnsFlags_NoPreserveWidths = ImGuiOldColumnFlags_NoPreserveWidths, + //ImGuiColumnsFlags_NoForceWithinWindow = ImGuiOldColumnFlags_NoForceWithinWindow, + //ImGuiColumnsFlags_GrowParentContentsSize = ImGuiOldColumnFlags_GrowParentContentsSize, #endif }; diff --git a/misc/freetype/imgui_freetype.h b/misc/freetype/imgui_freetype.h index cc58ba6ab575..b4e1d4893303 100644 --- a/misc/freetype/imgui_freetype.h +++ b/misc/freetype/imgui_freetype.h @@ -43,9 +43,8 @@ namespace ImGuiFreeType IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = nullptr); // Obsolete names (will be removed soon) - // Prefer using '#define IMGUI_ENABLE_FREETYPE' #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); } + //static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); } // Prefer using '#define IMGUI_ENABLE_FREETYPE' #endif } From 0b77980cab290292116fd15a5891398c73acd76c Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 5 Dec 2023 18:04:33 +0100 Subject: [PATCH 002/237] Moved Tables API related declarations to their own section in imgui.h --- imgui.h | 341 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 172 insertions(+), 169 deletions(-) diff --git a/imgui.h b/imgui.h index b4a5a9249466..40882995d1a3 100644 --- a/imgui.h +++ b/imgui.h @@ -34,10 +34,11 @@ Index of this file: // [SECTION] Forward declarations and basic types // [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] ImGuiStyle // [SECTION] ImGuiIO -// [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiPayload, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs) +// [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiPayload) // [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor) // [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData) // [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont) @@ -759,12 +760,10 @@ namespace ImGui // TableNextColumn() will automatically wrap-around into the next row if needed. // - IMPORTANT: Comparatively to the old Columns() API, we need to call TableNextColumn() for the first column! // - Summary of possible call flow: - // -------------------------------------------------------------------------------------------------------- - // TableNextRow() -> TableSetColumnIndex(0) -> Text("Hello 0") -> TableSetColumnIndex(1) -> Text("Hello 1") // OK - // TableNextRow() -> TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK - // TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK: TableNextColumn() automatically gets to next row! - // TableNextRow() -> Text("Hello 0") // Not OK! Missing TableSetColumnIndex() or TableNextColumn()! Text will not appear! - // -------------------------------------------------------------------------------------------------------- + // - TableNextRow() -> TableSetColumnIndex(0) -> Text("Hello 0") -> TableSetColumnIndex(1) -> Text("Hello 1") // OK + // - TableNextRow() -> TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK + // - TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK: TableNextColumn() automatically gets to next row! + // - TableNextRow() -> Text("Hello 0") // Not OK! Missing TableSetColumnIndex() or TableNextColumn()! Text will not appear! // - 5. Call EndTable() IMGUI_API bool BeginTable(const char* str_id, int column, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0.0f, 0.0f), float inner_width = 0.0f); IMGUI_API void EndTable(); // only call EndTable() if BeginTable() returns true! @@ -1187,142 +1186,6 @@ enum ImGuiTabItemFlags_ ImGuiTabItemFlags_Trailing = 1 << 7, // Enforce the tab position to the right of the tab bar (before the scrolling buttons) }; -// Flags for ImGui::BeginTable() -// - Important! Sizing policies have complex and subtle side effects, much more so than you would expect. -// Read comments/demos carefully + experiment with live demos to get acquainted with them. -// - The DEFAULT sizing policies are: -// - Default to ImGuiTableFlags_SizingFixedFit if ScrollX is on, or if host window has ImGuiWindowFlags_AlwaysAutoResize. -// - Default to ImGuiTableFlags_SizingStretchSame if ScrollX is off. -// - When ScrollX is off: -// - Table defaults to ImGuiTableFlags_SizingStretchSame -> all Columns defaults to ImGuiTableColumnFlags_WidthStretch with same weight. -// - Columns sizing policy allowed: Stretch (default), Fixed/Auto. -// - Fixed Columns (if any) will generally obtain their requested width (unless the table cannot fit them all). -// - Stretch Columns will share the remaining width according to their respective weight. -// - Mixed Fixed/Stretch columns is possible but has various side-effects on resizing behaviors. -// The typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns. -// (this is because the visible order of columns have subtle but necessary effects on how they react to manual resizing). -// - When ScrollX is on: -// - Table defaults to ImGuiTableFlags_SizingFixedFit -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed -// - Columns sizing policy allowed: Fixed/Auto mostly. -// - Fixed Columns can be enlarged as needed. Table will show a horizontal scrollbar if needed. -// - When using auto-resizing (non-resizable) fixed columns, querying the content width to use item right-alignment e.g. SetNextItemWidth(-FLT_MIN) doesn't make sense, would create a feedback loop. -// - Using Stretch columns OFTEN DOES NOT MAKE SENSE if ScrollX is on, UNLESS you have specified a value for 'inner_width' in BeginTable(). -// If you specify a value for 'inner_width' then effectively the scrolling space is known and Stretch or mixed Fixed/Stretch columns become meaningful again. -// - Read on documentation at the top of imgui_tables.cpp for details. -enum ImGuiTableFlags_ -{ - // Features - ImGuiTableFlags_None = 0, - ImGuiTableFlags_Resizable = 1 << 0, // Enable resizing columns. - ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers) - ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu. - ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate. - ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width and sort settings in the .ini file. - ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow(). - // Decorations - ImGuiTableFlags_RowBg = 1 << 6, // Set each RowBg color with ImGuiCol_TableRowBg or ImGuiCol_TableRowBgAlt (equivalent of calling TableSetBgColor with ImGuiTableBgFlags_RowBg0 on each row manually) - ImGuiTableFlags_BordersInnerH = 1 << 7, // Draw horizontal borders between rows. - ImGuiTableFlags_BordersOuterH = 1 << 8, // Draw horizontal borders at the top and bottom. - ImGuiTableFlags_BordersInnerV = 1 << 9, // Draw vertical borders between columns. - ImGuiTableFlags_BordersOuterV = 1 << 10, // Draw vertical borders on the left and right sides. - ImGuiTableFlags_BordersH = ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_BordersOuterH, // Draw horizontal borders. - ImGuiTableFlags_BordersV = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersOuterV, // Draw vertical borders. - ImGuiTableFlags_BordersInner = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersInnerH, // Draw inner borders. - ImGuiTableFlags_BordersOuter = ImGuiTableFlags_BordersOuterV | ImGuiTableFlags_BordersOuterH, // Draw outer borders. - ImGuiTableFlags_Borders = ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter, // Draw all borders. - ImGuiTableFlags_NoBordersInBody = 1 << 11, // [ALPHA] Disable vertical borders in columns Body (borders will always appear in Headers). -> May move to style - ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // [ALPHA] Disable vertical borders in columns Body until hovered for resize (borders will always appear in Headers). -> May move to style - // Sizing Policy (read above for defaults) - ImGuiTableFlags_SizingFixedFit = 1 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching contents width. - ImGuiTableFlags_SizingFixedSame = 2 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching the maximum contents width of all columns. Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible. - ImGuiTableFlags_SizingStretchProp = 3 << 13, // Columns default to _WidthStretch with default weights proportional to each columns contents widths. - ImGuiTableFlags_SizingStretchSame = 4 << 13, // Columns default to _WidthStretch with default weights all equal, unless overridden by TableSetupColumn(). - // Sizing Extra Options - ImGuiTableFlags_NoHostExtendX = 1 << 16, // Make outer width auto-fit to columns, overriding outer_size.x value. Only available when ScrollX/ScrollY are disabled and Stretch columns are not used. - ImGuiTableFlags_NoHostExtendY = 1 << 17, // Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible. - ImGuiTableFlags_NoKeepColumnsVisible = 1 << 18, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. Not recommended if columns are resizable. - ImGuiTableFlags_PreciseWidths = 1 << 19, // Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth. - // Clipping - ImGuiTableFlags_NoClip = 1 << 20, // Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with TableSetupScrollFreeze(). - // Padding - ImGuiTableFlags_PadOuterX = 1 << 21, // Default if BordersOuterV is on. Enable outermost padding. Generally desirable if you have headers. - ImGuiTableFlags_NoPadOuterX = 1 << 22, // Default if BordersOuterV is off. Disable outermost padding. - ImGuiTableFlags_NoPadInnerX = 1 << 23, // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off). - // Scrolling - ImGuiTableFlags_ScrollX = 1 << 24, // Enable horizontal scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. Changes default sizing policy. Because this creates a child window, ScrollY is currently generally recommended when using ScrollX. - ImGuiTableFlags_ScrollY = 1 << 25, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. - // Sorting - ImGuiTableFlags_SortMulti = 1 << 26, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1). - ImGuiTableFlags_SortTristate = 1 << 27, // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0). - // Miscellaneous - ImGuiTableFlags_HighlightHoveredColumn = 1 << 28, // Highlight column headers when hovered (may evolve into a fuller highlight) - - // [Internal] Combinations and masks - ImGuiTableFlags_SizingMask_ = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_SizingFixedSame | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_SizingStretchSame, -}; - -// Flags for ImGui::TableSetupColumn() -enum ImGuiTableColumnFlags_ -{ - // Input configuration flags - ImGuiTableColumnFlags_None = 0, - ImGuiTableColumnFlags_Disabled = 1 << 0, // Overriding/master disable flag: hide column, won't show in context menu (unlike calling TableSetColumnEnabled() which manipulates the user accessible state) - ImGuiTableColumnFlags_DefaultHide = 1 << 1, // Default as a hidden/disabled column. - ImGuiTableColumnFlags_DefaultSort = 1 << 2, // Default as a sorting column. - ImGuiTableColumnFlags_WidthStretch = 1 << 3, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingStretchSame or _SizingStretchProp). - ImGuiTableColumnFlags_WidthFixed = 1 << 4, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingFixedFit and table is resizable). - ImGuiTableColumnFlags_NoResize = 1 << 5, // Disable manual resizing. - ImGuiTableColumnFlags_NoReorder = 1 << 6, // Disable manual reordering this column, this will also prevent other columns from crossing over this column. - ImGuiTableColumnFlags_NoHide = 1 << 7, // Disable ability to hide/disable this column. - ImGuiTableColumnFlags_NoClip = 1 << 8, // Disable clipping for this column (all NoClip columns will render in a same draw command). - ImGuiTableColumnFlags_NoSort = 1 << 9, // Disable ability to sort on this field (even if ImGuiTableFlags_Sortable is set on the table). - ImGuiTableColumnFlags_NoSortAscending = 1 << 10, // Disable ability to sort in the ascending direction. - ImGuiTableColumnFlags_NoSortDescending = 1 << 11, // Disable ability to sort in the descending direction. - ImGuiTableColumnFlags_NoHeaderLabel = 1 << 12, // TableHeadersRow() will not submit horizontal label for this column. Convenient for some small columns. Name will still appear in context menu or in angled headers. - ImGuiTableColumnFlags_NoHeaderWidth = 1 << 13, // Disable header text width contribution to automatic column width. - ImGuiTableColumnFlags_PreferSortAscending = 1 << 14, // Make the initial sort direction Ascending when first sorting on this column (default). - ImGuiTableColumnFlags_PreferSortDescending = 1 << 15, // Make the initial sort direction Descending when first sorting on this column. - ImGuiTableColumnFlags_IndentEnable = 1 << 16, // Use current Indent value when entering cell (default for column 0). - ImGuiTableColumnFlags_IndentDisable = 1 << 17, // Ignore current Indent value when entering cell (default for columns > 0). Indentation changes _within_ the cell will still be honored. - ImGuiTableColumnFlags_AngledHeader = 1 << 18, // TableHeadersRow() will submit an angled header row for this column. Note this will add an extra row. - - // Output status flags, read-only via TableGetColumnFlags() - ImGuiTableColumnFlags_IsEnabled = 1 << 24, // Status: is enabled == not hidden by user/api (referred to as "Hide" in _DefaultHide and _NoHide) flags. - ImGuiTableColumnFlags_IsVisible = 1 << 25, // Status: is visible == is enabled AND not clipped by scrolling. - ImGuiTableColumnFlags_IsSorted = 1 << 26, // Status: is currently part of the sort specs - ImGuiTableColumnFlags_IsHovered = 1 << 27, // Status: is hovered by mouse - - // [Internal] Combinations and masks - ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed, - ImGuiTableColumnFlags_IndentMask_ = ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_IndentDisable, - ImGuiTableColumnFlags_StatusMask_ = ImGuiTableColumnFlags_IsEnabled | ImGuiTableColumnFlags_IsVisible | ImGuiTableColumnFlags_IsSorted | ImGuiTableColumnFlags_IsHovered, - ImGuiTableColumnFlags_NoDirectResize_ = 1 << 30, // [Internal] Disable user resizing this column directly (it may however we resized indirectly from its left edge) -}; - -// Flags for ImGui::TableNextRow() -enum ImGuiTableRowFlags_ -{ - ImGuiTableRowFlags_None = 0, - ImGuiTableRowFlags_Headers = 1 << 0, // Identify header row (set default background color + width of its contents accounted differently for auto column width) -}; - -// Enum for ImGui::TableSetBgColor() -// Background colors are rendering in 3 layers: -// - Layer 0: draw with RowBg0 color if set, otherwise draw with ColumnBg0 if set. -// - Layer 1: draw with RowBg1 color if set, otherwise draw with ColumnBg1 if set. -// - Layer 2: draw with CellBg color if set. -// The purpose of the two row/columns layers is to let you decide if a background color change should override or blend with the existing color. -// When using ImGuiTableFlags_RowBg on the table, each row has the RowBg0 color automatically set for odd/even rows. -// If you set the color of RowBg0 target, your color will override the existing RowBg0 color. -// If you set the color of RowBg1 or ColumnBg1 target, your color will blend over the RowBg0 color. -enum ImGuiTableBgTarget_ -{ - ImGuiTableBgTarget_None = 0, - ImGuiTableBgTarget_RowBg0 = 1, // Set row background color 0 (generally used for background, automatically set when ImGuiTableFlags_RowBg is used) - ImGuiTableBgTarget_RowBg1 = 2, // Set row background color 1 (generally used for selection marking) - ImGuiTableBgTarget_CellBg = 3, // Set cell background color (top-most color) -}; - // Flags for ImGui::IsWindowFocused() enum ImGuiFocusedFlags_ { @@ -1822,7 +1685,7 @@ enum ImGuiMouseSource : int ImGuiMouseSource_COUNT }; -// Enumeration for ImGui::SetWindow***(), SetNextWindow***(), SetNextItem***() functions +// Enumeration for ImGui::SetNextWindow***(), SetWindow***(), SetNextItem***() functions // Represent a condition. // Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always. enum ImGuiCond_ @@ -1834,6 +1697,170 @@ enum ImGuiCond_ ImGuiCond_Appearing = 1 << 3, // Set the variable if the object/window is appearing after being hidden/inactive (or the first time) }; +//----------------------------------------------------------------------------- +// [SECTION] Tables API flags and structures (ImGuiTableFlags, ImGuiTableColumnFlags, ImGuiTableRowFlags, ImGuiTableBgTarget, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs) +//----------------------------------------------------------------------------- + +// Flags for ImGui::BeginTable() +// - Important! Sizing policies have complex and subtle side effects, much more so than you would expect. +// Read comments/demos carefully + experiment with live demos to get acquainted with them. +// - The DEFAULT sizing policies are: +// - Default to ImGuiTableFlags_SizingFixedFit if ScrollX is on, or if host window has ImGuiWindowFlags_AlwaysAutoResize. +// - Default to ImGuiTableFlags_SizingStretchSame if ScrollX is off. +// - When ScrollX is off: +// - Table defaults to ImGuiTableFlags_SizingStretchSame -> all Columns defaults to ImGuiTableColumnFlags_WidthStretch with same weight. +// - Columns sizing policy allowed: Stretch (default), Fixed/Auto. +// - Fixed Columns (if any) will generally obtain their requested width (unless the table cannot fit them all). +// - Stretch Columns will share the remaining width according to their respective weight. +// - Mixed Fixed/Stretch columns is possible but has various side-effects on resizing behaviors. +// The typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns. +// (this is because the visible order of columns have subtle but necessary effects on how they react to manual resizing). +// - When ScrollX is on: +// - Table defaults to ImGuiTableFlags_SizingFixedFit -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed +// - Columns sizing policy allowed: Fixed/Auto mostly. +// - Fixed Columns can be enlarged as needed. Table will show a horizontal scrollbar if needed. +// - When using auto-resizing (non-resizable) fixed columns, querying the content width to use item right-alignment e.g. SetNextItemWidth(-FLT_MIN) doesn't make sense, would create a feedback loop. +// - Using Stretch columns OFTEN DOES NOT MAKE SENSE if ScrollX is on, UNLESS you have specified a value for 'inner_width' in BeginTable(). +// If you specify a value for 'inner_width' then effectively the scrolling space is known and Stretch or mixed Fixed/Stretch columns become meaningful again. +// - Read on documentation at the top of imgui_tables.cpp for details. +enum ImGuiTableFlags_ +{ + // Features + ImGuiTableFlags_None = 0, + ImGuiTableFlags_Resizable = 1 << 0, // Enable resizing columns. + ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers) + ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu. + ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate. + ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width and sort settings in the .ini file. + ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow(). + // Decorations + ImGuiTableFlags_RowBg = 1 << 6, // Set each RowBg color with ImGuiCol_TableRowBg or ImGuiCol_TableRowBgAlt (equivalent of calling TableSetBgColor with ImGuiTableBgFlags_RowBg0 on each row manually) + ImGuiTableFlags_BordersInnerH = 1 << 7, // Draw horizontal borders between rows. + ImGuiTableFlags_BordersOuterH = 1 << 8, // Draw horizontal borders at the top and bottom. + ImGuiTableFlags_BordersInnerV = 1 << 9, // Draw vertical borders between columns. + ImGuiTableFlags_BordersOuterV = 1 << 10, // Draw vertical borders on the left and right sides. + ImGuiTableFlags_BordersH = ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_BordersOuterH, // Draw horizontal borders. + ImGuiTableFlags_BordersV = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersOuterV, // Draw vertical borders. + ImGuiTableFlags_BordersInner = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersInnerH, // Draw inner borders. + ImGuiTableFlags_BordersOuter = ImGuiTableFlags_BordersOuterV | ImGuiTableFlags_BordersOuterH, // Draw outer borders. + ImGuiTableFlags_Borders = ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter, // Draw all borders. + ImGuiTableFlags_NoBordersInBody = 1 << 11, // [ALPHA] Disable vertical borders in columns Body (borders will always appear in Headers). -> May move to style + ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // [ALPHA] Disable vertical borders in columns Body until hovered for resize (borders will always appear in Headers). -> May move to style + // Sizing Policy (read above for defaults) + ImGuiTableFlags_SizingFixedFit = 1 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching contents width. + ImGuiTableFlags_SizingFixedSame = 2 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching the maximum contents width of all columns. Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible. + ImGuiTableFlags_SizingStretchProp = 3 << 13, // Columns default to _WidthStretch with default weights proportional to each columns contents widths. + ImGuiTableFlags_SizingStretchSame = 4 << 13, // Columns default to _WidthStretch with default weights all equal, unless overridden by TableSetupColumn(). + // Sizing Extra Options + ImGuiTableFlags_NoHostExtendX = 1 << 16, // Make outer width auto-fit to columns, overriding outer_size.x value. Only available when ScrollX/ScrollY are disabled and Stretch columns are not used. + ImGuiTableFlags_NoHostExtendY = 1 << 17, // Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible. + ImGuiTableFlags_NoKeepColumnsVisible = 1 << 18, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. Not recommended if columns are resizable. + ImGuiTableFlags_PreciseWidths = 1 << 19, // Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth. + // Clipping + ImGuiTableFlags_NoClip = 1 << 20, // Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with TableSetupScrollFreeze(). + // Padding + ImGuiTableFlags_PadOuterX = 1 << 21, // Default if BordersOuterV is on. Enable outermost padding. Generally desirable if you have headers. + ImGuiTableFlags_NoPadOuterX = 1 << 22, // Default if BordersOuterV is off. Disable outermost padding. + ImGuiTableFlags_NoPadInnerX = 1 << 23, // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off). + // Scrolling + ImGuiTableFlags_ScrollX = 1 << 24, // Enable horizontal scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. Changes default sizing policy. Because this creates a child window, ScrollY is currently generally recommended when using ScrollX. + ImGuiTableFlags_ScrollY = 1 << 25, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. + // Sorting + ImGuiTableFlags_SortMulti = 1 << 26, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1). + ImGuiTableFlags_SortTristate = 1 << 27, // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0). + // Miscellaneous + ImGuiTableFlags_HighlightHoveredColumn = 1 << 28, // Highlight column headers when hovered (may evolve into a fuller highlight) + + // [Internal] Combinations and masks + ImGuiTableFlags_SizingMask_ = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_SizingFixedSame | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_SizingStretchSame, +}; + +// Flags for ImGui::TableSetupColumn() +enum ImGuiTableColumnFlags_ +{ + // Input configuration flags + ImGuiTableColumnFlags_None = 0, + ImGuiTableColumnFlags_Disabled = 1 << 0, // Overriding/master disable flag: hide column, won't show in context menu (unlike calling TableSetColumnEnabled() which manipulates the user accessible state) + ImGuiTableColumnFlags_DefaultHide = 1 << 1, // Default as a hidden/disabled column. + ImGuiTableColumnFlags_DefaultSort = 1 << 2, // Default as a sorting column. + ImGuiTableColumnFlags_WidthStretch = 1 << 3, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingStretchSame or _SizingStretchProp). + ImGuiTableColumnFlags_WidthFixed = 1 << 4, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingFixedFit and table is resizable). + ImGuiTableColumnFlags_NoResize = 1 << 5, // Disable manual resizing. + ImGuiTableColumnFlags_NoReorder = 1 << 6, // Disable manual reordering this column, this will also prevent other columns from crossing over this column. + ImGuiTableColumnFlags_NoHide = 1 << 7, // Disable ability to hide/disable this column. + ImGuiTableColumnFlags_NoClip = 1 << 8, // Disable clipping for this column (all NoClip columns will render in a same draw command). + ImGuiTableColumnFlags_NoSort = 1 << 9, // Disable ability to sort on this field (even if ImGuiTableFlags_Sortable is set on the table). + ImGuiTableColumnFlags_NoSortAscending = 1 << 10, // Disable ability to sort in the ascending direction. + ImGuiTableColumnFlags_NoSortDescending = 1 << 11, // Disable ability to sort in the descending direction. + ImGuiTableColumnFlags_NoHeaderLabel = 1 << 12, // TableHeadersRow() will not submit horizontal label for this column. Convenient for some small columns. Name will still appear in context menu or in angled headers. + ImGuiTableColumnFlags_NoHeaderWidth = 1 << 13, // Disable header text width contribution to automatic column width. + ImGuiTableColumnFlags_PreferSortAscending = 1 << 14, // Make the initial sort direction Ascending when first sorting on this column (default). + ImGuiTableColumnFlags_PreferSortDescending = 1 << 15, // Make the initial sort direction Descending when first sorting on this column. + ImGuiTableColumnFlags_IndentEnable = 1 << 16, // Use current Indent value when entering cell (default for column 0). + ImGuiTableColumnFlags_IndentDisable = 1 << 17, // Ignore current Indent value when entering cell (default for columns > 0). Indentation changes _within_ the cell will still be honored. + ImGuiTableColumnFlags_AngledHeader = 1 << 18, // TableHeadersRow() will submit an angled header row for this column. Note this will add an extra row. + + // Output status flags, read-only via TableGetColumnFlags() + ImGuiTableColumnFlags_IsEnabled = 1 << 24, // Status: is enabled == not hidden by user/api (referred to as "Hide" in _DefaultHide and _NoHide) flags. + ImGuiTableColumnFlags_IsVisible = 1 << 25, // Status: is visible == is enabled AND not clipped by scrolling. + ImGuiTableColumnFlags_IsSorted = 1 << 26, // Status: is currently part of the sort specs + ImGuiTableColumnFlags_IsHovered = 1 << 27, // Status: is hovered by mouse + + // [Internal] Combinations and masks + ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed, + ImGuiTableColumnFlags_IndentMask_ = ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_IndentDisable, + ImGuiTableColumnFlags_StatusMask_ = ImGuiTableColumnFlags_IsEnabled | ImGuiTableColumnFlags_IsVisible | ImGuiTableColumnFlags_IsSorted | ImGuiTableColumnFlags_IsHovered, + ImGuiTableColumnFlags_NoDirectResize_ = 1 << 30, // [Internal] Disable user resizing this column directly (it may however we resized indirectly from its left edge) +}; + +// Flags for ImGui::TableNextRow() +enum ImGuiTableRowFlags_ +{ + ImGuiTableRowFlags_None = 0, + ImGuiTableRowFlags_Headers = 1 << 0, // Identify header row (set default background color + width of its contents accounted differently for auto column width) +}; + +// Enum for ImGui::TableSetBgColor() +// Background colors are rendering in 3 layers: +// - Layer 0: draw with RowBg0 color if set, otherwise draw with ColumnBg0 if set. +// - Layer 1: draw with RowBg1 color if set, otherwise draw with ColumnBg1 if set. +// - Layer 2: draw with CellBg color if set. +// The purpose of the two row/columns layers is to let you decide if a background color change should override or blend with the existing color. +// When using ImGuiTableFlags_RowBg on the table, each row has the RowBg0 color automatically set for odd/even rows. +// If you set the color of RowBg0 target, your color will override the existing RowBg0 color. +// If you set the color of RowBg1 or ColumnBg1 target, your color will blend over the RowBg0 color. +enum ImGuiTableBgTarget_ +{ + ImGuiTableBgTarget_None = 0, + ImGuiTableBgTarget_RowBg0 = 1, // Set row background color 0 (generally used for background, automatically set when ImGuiTableFlags_RowBg is used) + ImGuiTableBgTarget_RowBg1 = 2, // Set row background color 1 (generally used for selection marking) + ImGuiTableBgTarget_CellBg = 3, // Set cell background color (top-most color) +}; + +// Sorting specifications for a table (often handling sort specs for a single column, occasionally more) +// Obtained by calling TableGetSortSpecs(). +// When 'SpecsDirty == true' you can sort your data. It will be true with sorting specs have changed since last call, or the first time. +// Make sure to set 'SpecsDirty = false' after sorting, else you may wastefully sort your data every frame! +struct ImGuiTableSortSpecs +{ + const ImGuiTableColumnSortSpecs* Specs; // Pointer to sort spec array. + int SpecsCount; // Sort spec count. Most often 1. May be > 1 when ImGuiTableFlags_SortMulti is enabled. May be == 0 when ImGuiTableFlags_SortTristate is enabled. + bool SpecsDirty; // Set to true when specs have changed since last time! Use this to sort again, then clear the flag. + + ImGuiTableSortSpecs() { memset(this, 0, sizeof(*this)); } +}; + +// Sorting specification for one column of a table (sizeof == 12 bytes) +struct ImGuiTableColumnSortSpecs +{ + ImGuiID ColumnUserID; // User id of the column (if specified by a TableSetupColumn() call) + ImS16 ColumnIndex; // Index of the column + ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here) + ImGuiSortDirection SortDirection : 8; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending + + ImGuiTableColumnSortSpecs() { memset(this, 0, sizeof(*this)); } +}; + //----------------------------------------------------------------------------- // [SECTION] Helpers: Memory allocations macros, ImVector<> //----------------------------------------------------------------------------- @@ -2207,7 +2234,7 @@ struct ImGuiIO }; //----------------------------------------------------------------------------- -// [SECTION] Misc data structures +// [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiPayload) //----------------------------------------------------------------------------- // Shared state of InputText(), passed as an argument to your callback when a ImGuiInputTextFlags_Callback* flag is used. @@ -2281,30 +2308,6 @@ struct ImGuiPayload bool IsDelivery() const { return Delivery; } }; -// Sorting specification for one column of a table (sizeof == 12 bytes) -struct ImGuiTableColumnSortSpecs -{ - ImGuiID ColumnUserID; // User id of the column (if specified by a TableSetupColumn() call) - ImS16 ColumnIndex; // Index of the column - ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here) - ImGuiSortDirection SortDirection : 8; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending - - ImGuiTableColumnSortSpecs() { memset(this, 0, sizeof(*this)); } -}; - -// Sorting specifications for a table (often handling sort specs for a single column, occasionally more) -// Obtained by calling TableGetSortSpecs(). -// When 'SpecsDirty == true' you can sort your data. It will be true with sorting specs have changed since last call, or the first time. -// Make sure to set 'SpecsDirty = false' after sorting, else you may wastefully sort your data every frame! -struct ImGuiTableSortSpecs -{ - const ImGuiTableColumnSortSpecs* Specs; // Pointer to sort spec array. - int SpecsCount; // Sort spec count. Most often 1. May be > 1 when ImGuiTableFlags_SortMulti is enabled. May be == 0 when ImGuiTableFlags_SortTristate is enabled. - bool SpecsDirty; // Set to true when specs have changed since last time! Use this to sort again, then clear the flag. - - ImGuiTableSortSpecs() { memset(this, 0, sizeof(*this)); } -}; - //----------------------------------------------------------------------------- // [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor) //----------------------------------------------------------------------------- From 9a2985611cca63ce6d4712eec08c06005dccba16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C4=B1lcan=20G=C3=BClkaya?= <48527900+benanil@users.noreply.github.com> Date: Wed, 6 Dec 2023 06:29:40 +0300 Subject: [PATCH 003/237] Backend: Android: Remove Redundant Check (#7093) --- backends/imgui_impl_android.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/imgui_impl_android.cpp b/backends/imgui_impl_android.cpp index 3954536066a3..7dd2afc2efce 100644 --- a/backends/imgui_impl_android.cpp +++ b/backends/imgui_impl_android.cpp @@ -183,7 +183,7 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(const AInputEvent* input_event) case AKEY_EVENT_ACTION_UP: { ImGuiKey key = ImGui_ImplAndroid_KeyCodeToImGuiKey(event_key_code); - if (key != ImGuiKey_None && (event_action == AKEY_EVENT_ACTION_DOWN || event_action == AKEY_EVENT_ACTION_UP)) + if (key != ImGuiKey_None) { io.AddKeyEvent(key, event_action == AKEY_EVENT_ACTION_DOWN); io.SetKeyEventNativeData(key, event_key_code, event_scan_code); From d72e1563d4274e0f1a21973cf2d98563d579d377 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 6 Dec 2023 14:58:38 +0100 Subject: [PATCH 004/237] Removed CalcListClipping() marked obsolete in 1.86. (#3841) + comments Amend 64daeddf --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 49 +--------------------------------------------- imgui.h | 27 ++++++++++++------------- 3 files changed, 16 insertions(+), 62 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 691c7ebb866d..772583e33061 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -44,6 +44,8 @@ Breaking changes: - imgui_freetype: commented out ImGuiFreeType::BuildFontAtlas() obsoleted in 1.81. Prefer using #define IMGUI_ENABLE_FREETYPE or see commented code for manual calls. +- Removed CalcListClipping() marked obsolete in 1.86. (#3841) + Prefer using ImGuiListClipper which can return non-contiguous ranges. - Internals, Columns: commented out legacy ImGuiColumnsFlags_XXX symbols redirecting to ImGuiOldColumnsFlags_XXX, obsoleted from imgui_internal.h in 1.80. diff --git a/imgui.cpp b/imgui.cpp index d04ebeaa0d02..90b96c165a5e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -424,6 +424,7 @@ CODE When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2023/11/06 (1.90.1) - removed CalcListClipping() marked obsolete in 1.86. Prefer using ImGuiListClipper which can return non-contiguous ranges. - 2023/11/05 (1.90.1) - imgui_freetype: commented out ImGuiFreeType::BuildFontAtlas() obsoleted in 1.81. prefer using #define IMGUI_ENABLE_FREETYPE or see commented code for manual calls. - 2023/11/05 (1.90.1) - internals,columns: commented out legacy ImGuiColumnsFlags_XXX symbols redirecting to ImGuiOldColumnsFlags_XXX, obsoleted from imgui_internal.h in 1.80. - 2023/11/09 (1.90.0) - removed IM_OFFSETOF() macro in favor of using offsetof() available in C++11. Kept redirection define (will obsolete). @@ -2726,54 +2727,6 @@ static bool GetSkipItemForListClipping() return (g.CurrentTable ? g.CurrentTable->HostSkipItems : g.CurrentWindow->SkipItems); } -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS -// Legacy helper to calculate coarse clipping of large list of evenly sized items. -// This legacy API is not ideal because it assumes we will return a single contiguous rectangle. -// Prefer using ImGuiListClipper which can returns non-contiguous ranges. -void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (g.LogEnabled) - { - // If logging is active, do not perform any clipping - *out_items_display_start = 0; - *out_items_display_end = items_count; - return; - } - if (GetSkipItemForListClipping()) - { - *out_items_display_start = *out_items_display_end = 0; - return; - } - - // We create the union of the ClipRect and the scoring rect which at worst should be 1 page away from ClipRect - // We don't include g.NavId's rectangle in there (unless g.NavJustMovedToId is set) because the rectangle enlargement can get costly. - ImRect rect = window->ClipRect; - if (g.NavMoveScoringItems) - rect.Add(g.NavScoringNoClipRect); - if (g.NavJustMovedToId && window->NavLastIds[0] == g.NavJustMovedToId) - rect.Add(WindowRectRelToAbs(window, window->NavRectRel[0])); // Could store and use NavJustMovedToRectRel - - const ImVec2 pos = window->DC.CursorPos; - int start = (int)((rect.Min.y - pos.y) / items_height); - int end = (int)((rect.Max.y - pos.y) / items_height); - - // When performing a navigation request, ensure we have one item extra in the direction we are moving to - // FIXME: Verify this works with tabbing - const bool is_nav_request = (g.NavMoveScoringItems && g.NavWindow && g.NavWindow->RootWindowForNav == window->RootWindowForNav); - if (is_nav_request && g.NavMoveClipDir == ImGuiDir_Up) - start--; - if (is_nav_request && g.NavMoveClipDir == ImGuiDir_Down) - end++; - - start = ImClamp(start, 0, items_count); - end = ImClamp(end + 1, start, items_count); - *out_items_display_start = start; - *out_items_display_end = end; -} -#endif - static void ImGuiListClipper_SortAndFuseRanges(ImVector& ranges, int offset = 0) { if (ranges.Size - offset <= 1) diff --git a/imgui.h b/imgui.h index 40882995d1a3..d5893cf5e907 100644 --- a/imgui.h +++ b/imgui.h @@ -183,7 +183,7 @@ typedef int ImGuiSortDirection; // -> enum ImGuiSortDirection_ // Enum: A typedef int ImGuiStyleVar; // -> enum ImGuiStyleVar_ // Enum: A variable identifier for styling typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A color target for TableSetBgColor() -// Flags (declared as int for compatibility with old C++, to allow using as flags without overhead, and to not pollute the top of this file) +// Flags (declared as int to allow using as flags without overhead, and to not pollute the top of this file) // - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists! // In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. @@ -200,7 +200,7 @@ typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: f typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: for IsWindowFocused() typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc. typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline() -typedef int ImGuiKeyChord; // -> ImGuiKey | ImGuiMod_XXX // Flags: for storage only for now: an ImGuiKey optionally OR-ed with one or more ImGuiMod_XXX values. +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 ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable() typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc. @@ -631,9 +631,9 @@ namespace ImGui IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); - IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call TreePush/TreePop yourself if desired. + IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushID(). Already called by TreeNode() when returning true, but you can call TreePush/TreePop yourself if desired. IMGUI_API void TreePush(const void* ptr_id); // " - IMGUI_API void TreePop(); // ~ Unindent()+PopId() + IMGUI_API void TreePop(); // ~ Unindent()+PopID() IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode 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. @@ -708,9 +708,7 @@ namespace ImGui // - You can bypass the hovering restriction by using ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered(). // - IMPORTANT: Popup identifiers are relative to the current ID stack, so OpenPopup and BeginPopup generally needs to be at the same level of the stack. // This is sometimes leading to confusing mistakes. May rework this in the future. - - // Popups: begin/end functions - // - BeginPopup(): query popup state, if open start appending into the window. Call EndPopup() afterwards. ImGuiWindowFlags are forwarded to the window. + // - BeginPopup(): query popup state, if open start appending into the window. Call EndPopup() afterwards if returned true. ImGuiWindowFlags are forwarded to the window. // - BeginPopupModal(): block every interaction behind the window, cannot be closed by user, add a dimming background, has a title bar. IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // return true if the modal is open, and you can start outputting to it. @@ -962,6 +960,7 @@ namespace ImGui IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings. // Debug Utilities + // - Your main debugging friend is the ShowMetricsWindow() function, which is also accessible from Demo->Tools->Metrics Debugger IMGUI_API void DebugTextEncoding(const char* text); IMGUI_API void DebugFlashStyleColor(ImGuiCol idx); 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. @@ -1095,7 +1094,7 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (bypass the indented area). ImGuiTreeNodeFlags_SpanAllColumns = 1 << 13, // Frame will span all columns of its container table (text will still fit in current column) ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 14, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) - //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 14, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible + //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 15, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog, #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS @@ -1485,15 +1484,15 @@ enum ImGuiCol_ ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive, - ImGuiCol_TitleBg, - ImGuiCol_TitleBgActive, - ImGuiCol_TitleBgCollapsed, + ImGuiCol_TitleBg, // Title bar + ImGuiCol_TitleBgActive, // Title bar when focused + ImGuiCol_TitleBgCollapsed, // Title bar when collapsed ImGuiCol_MenuBarBg, ImGuiCol_ScrollbarBg, ImGuiCol_ScrollbarGrab, ImGuiCol_ScrollbarGrabHovered, ImGuiCol_ScrollbarGrabActive, - ImGuiCol_CheckMark, + ImGuiCol_CheckMark, // Checkbox tick and RadioButton circle ImGuiCol_SliderGrab, ImGuiCol_SliderGrabActive, ImGuiCol_Button, @@ -3180,10 +3179,10 @@ namespace ImGui // 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. - // 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); // Calculate coarse clipping for large list of evenly sized items. Prefer using ImGuiListClipper. // Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE) + //-- 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) //static inline float GetWindowContentRegionWidth() { return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; } //-- OBSOLETED in 1.81 (from February 2021) From 58ca5f64246304e8bb8dea1527c6dfb283aa5e8e Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 6 Dec 2023 16:15:11 +0100 Subject: [PATCH 005/237] Shortcut(): clearer early out in SetShortcutRouting() -> CalcRoutingScore() path. --- imgui.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 90b96c165a5e..71c8569f14fe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8294,22 +8294,25 @@ static int CalcRoutingScore(ImGuiWindow* location, ImGuiID owner_id, ImGuiInputF if (owner_id != 0 && g.ActiveId == owner_id) return 1; + // Early out when not in focus stack + if (focused == NULL || focused->RootWindow != location->RootWindow) + return 255; + // Score based on distance to focused window (lower is better) // Assuming both windows are submitting a routing request, // - When Window....... is focused -> Window scores 3 (best), Window/ChildB scores 255 (no match) // - When Window/ChildB is focused -> Window scores 4, Window/ChildB scores 3 (best) // Assuming only WindowA is submitting a routing request, // - When Window/ChildB is focused -> Window scores 4 (best), Window/ChildB doesn't have a score. - if (focused != NULL && focused->RootWindow == location->RootWindow) - for (int next_score = 3; focused != NULL; next_score++) + for (int next_score = 3; focused != NULL; next_score++) + { + if (focused == location) { - if (focused == location) - { - IM_ASSERT(next_score < 255); - return next_score; - } - focused = (focused->RootWindow != focused) ? focused->ParentWindow : NULL; // FIXME: This could be later abstracted as a focus path + IM_ASSERT(next_score < 255); + return next_score; } + focused = (focused->RootWindow != focused) ? focused->ParentWindow : NULL; // FIXME: This could be later abstracted as a focus path + } return 255; } From 1fade351595af3553678c8b954bf279084964683 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 Dec 2023 14:01:53 +0100 Subject: [PATCH 006/237] DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: Fixed incorrect pushes into ItemWidth stack when number of components is 1. [#7095] --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 772583e33061..a94f8f69b4de 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -42,6 +42,8 @@ HOW TO UPDATE? Breaking changes: +- DragScalarN, SliderScalarN, InputScalarN: Fixed incorrect pushes into ItemWidth + stack when number of components is 1. [#7095] [@Nahor] - imgui_freetype: commented out ImGuiFreeType::BuildFontAtlas() obsoleted in 1.81. Prefer using #define IMGUI_ENABLE_FREETYPE or see commented code for manual calls. - Removed CalcListClipping() marked obsolete in 1.86. (#3841) diff --git a/imgui.cpp b/imgui.cpp index 71c8569f14fe..84bc9d376602 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9864,7 +9864,8 @@ void ImGui::PushMultiItemsWidths(int components, float w_full) const float w_item_one = ImMax(1.0f, IM_TRUNC((w_full - (style.ItemInnerSpacing.x) * (components - 1)) / (float)components)); const float w_item_last = ImMax(1.0f, IM_TRUNC(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components - 1))); window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); // Backup current width - window->DC.ItemWidthStack.push_back(w_item_last); + if (components > 1) + window->DC.ItemWidthStack.push_back(w_item_last); for (int i = 0; i < components - 2; i++) window->DC.ItemWidthStack.push_back(w_item_one); window->DC.ItemWidth = (components == 1) ? w_item_last : w_item_one; From c58d2c89c3f91bbd42b66d67f42f6f11363867d3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 Dec 2023 14:20:30 +0100 Subject: [PATCH 007/237] Tabs: Added ImGuiTabItemFlags_NoAssumedClosure to enable app to react on closure attempt. (#7084) --- docs/CHANGELOG.txt | 2 ++ imgui.h | 9 +++++---- imgui_widgets.cpp | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a94f8f69b4de..ff279d42f126 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -3465,6 +3465,8 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v Breaking Changes: +- Tabs: Added ImGuiTabItemFlags_NoAssumedClosure to enable app to react on closure attempt, without having to draw + an unsaved document marker (ImGuiTabItemFlags_UnsavedDocument sets _NoAssumedClosure automatically). (#7084) - DragInt(): The default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally any more. If you used DragInt() with custom format strings, make sure you change them to use %d or an integer-compatible format. To honor backward-compatibility, the DragInt() code will currently parse and modify format strings to replace %*f with %d, diff --git a/imgui.h b/imgui.h index d5893cf5e907..bf739e2be492 100644 --- a/imgui.h +++ b/imgui.h @@ -1162,7 +1162,7 @@ enum ImGuiTabBarFlags_ ImGuiTabBarFlags_Reorderable = 1 << 0, // Allow manually dragging tabs to re-order them + New tabs are appended at the end of list ImGuiTabBarFlags_AutoSelectNewTabs = 1 << 1, // Automatically select new tabs when they appear ImGuiTabBarFlags_TabListPopupButton = 1 << 2, // Disable buttons to open the tab list popup - ImGuiTabBarFlags_NoCloseWithMiddleMouseButton = 1 << 3, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false. + ImGuiTabBarFlags_NoCloseWithMiddleMouseButton = 1 << 3, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You may handle this behavior manually on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false. ImGuiTabBarFlags_NoTabListScrollingButtons = 1 << 4, // Disable scrolling buttons (apply when fitting policy is ImGuiTabBarFlags_FittingPolicyScroll) ImGuiTabBarFlags_NoTooltip = 1 << 5, // Disable tooltips when hovering a tab ImGuiTabBarFlags_FittingPolicyResizeDown = 1 << 6, // Resize tabs when they don't fit @@ -1175,14 +1175,15 @@ enum ImGuiTabBarFlags_ enum ImGuiTabItemFlags_ { ImGuiTabItemFlags_None = 0, - ImGuiTabItemFlags_UnsavedDocument = 1 << 0, // Display a dot next to the title + tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar. + ImGuiTabItemFlags_UnsavedDocument = 1 << 0, // Display a dot next to the title + set ImGuiTabItemFlags_NoAssumedClosure. ImGuiTabItemFlags_SetSelected = 1 << 1, // Trigger flag to programmatically make the tab selected when calling BeginTabItem() - ImGuiTabItemFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false. - ImGuiTabItemFlags_NoPushId = 1 << 3, // Don't call PushID(tab->ID)/PopID() on BeginTabItem()/EndTabItem() + ImGuiTabItemFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You may handle this behavior manually on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false. + ImGuiTabItemFlags_NoPushId = 1 << 3, // Don't call PushID()/PopID() on BeginTabItem()/EndTabItem() ImGuiTabItemFlags_NoTooltip = 1 << 4, // Disable tooltip for the given tab ImGuiTabItemFlags_NoReorder = 1 << 5, // Disable reordering this tab or having another tab cross over this tab ImGuiTabItemFlags_Leading = 1 << 6, // Enforce the tab position to the left of the tab bar (after the tab list popup button) ImGuiTabItemFlags_Trailing = 1 << 7, // Enforce the tab position to the right of the tab bar (before the scrolling buttons) + ImGuiTabItemFlags_NoAssumedClosure = 1 << 8, // Tab is selected when trying to close + closure is not immediately assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar. }; // Flags for ImGui::IsWindowFocused() diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ec20a28ce694..570e60fde2da 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -8257,7 +8257,7 @@ void ImGui::TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab) if (tab->Flags & ImGuiTabItemFlags_Button) return; // A button appended with TabItemButton(). - if (!(tab->Flags & ImGuiTabItemFlags_UnsavedDocument)) + if ((tab->Flags & (ImGuiTabItemFlags_UnsavedDocument | ImGuiTabItemFlags_NoAssumedClosure)) == 0) { // This will remove a frame of lag for selecting another tab on closure. // However we don't run it in the case where the 'Unsaved' flag is set, so user gets a chance to fully undo the closure From 5366bd09bfaec70f8dedaabff89dd925f544548a Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 Dec 2023 15:46:49 +0100 Subject: [PATCH 008/237] Scrolling: internal scrolling value is rounded instead of truncated. (#6677) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ff279d42f126..ffd6394d26a6 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,8 @@ Other changes: - Windows: BeginChild(): Fixed auto-resizing erroneously limiting size to host viewport minus padding. There are no limit to a child width/height. (#7063) [@Devyre] +- Scrolling: internal scrolling value is rounded instead of truncated, as a way to reduce + speed asymetry when (incorrectly) attempting to scroll by non-integer amount. (#6677) - Nav, IO: SetNextFrameWantCaptureKeyboard(false) calls are not overrided back to true when navigation is enabled. SetNextFrameWantCaptureKeyboard() is always higher priority. (#6997) - Drag and Drop: Fixed drop target highlight on items temporarily pushing a widened clip rect diff --git a/imgui.cpp b/imgui.cpp index 84bc9d376602..4bfe45c1f145 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10122,7 +10122,7 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window) } scroll[axis] = scroll_target - center_ratio * (window->SizeFull[axis] - decoration_size[axis]); } - scroll[axis] = IM_TRUNC(ImMax(scroll[axis], 0.0f)); + scroll[axis] = IM_ROUND(ImMax(scroll[axis], 0.0f)); if (!window->Collapsed && !window->SkipItems) scroll[axis] = ImMin(scroll[axis], window->ScrollMax[axis]); } From 9d8de45313c4b6032e09ff00878ec232d389fb8a Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 Dec 2023 16:07:37 +0100 Subject: [PATCH 009/237] Image(): comment and minor refactor to resurface the fact that a border size may be added. (#2118) Make more similar to ImageButton() --- imgui.h | 4 ++-- imgui_widgets.cpp | 21 ++++++++------------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/imgui.h b/imgui.h index bf739e2be492..0b7be292d6b1 100644 --- a/imgui.h +++ b/imgui.h @@ -532,8 +532,8 @@ namespace ImGui // Widgets: Images // - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples - // - Note that ImageButton() adds style.FramePadding*2.0f to provided size. This is in order to facilitate fitting an image in a button. - IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), const ImVec4& border_col = ImVec4(0, 0, 0, 0)); + // - Note that Image() may add +2.0f to provided size if a border is visible, ImageButton() adds style.FramePadding*2.0f to provided size. + IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), const ImVec4& border_col = ImVec4(0, 0, 0, 0)); IMGUI_API bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // Widgets: Combo Box (Dropdown) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 570e60fde2da..ba103b14fda1 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1007,28 +1007,23 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6 return held; } -void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) +void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; - ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); - if (border_col.w > 0.0f) - bb.Max += ImVec2(2, 2); + const float border_size = (border_col.w > 0.0f) ? 1.0f : 0.0f; + const ImVec2 padding(border_size, border_size); + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + image_size + padding * 2.0f); ItemSize(bb); if (!ItemAdd(bb, 0)) return; - if (border_col.w > 0.0f) - { - window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f); - window->DrawList->AddImage(user_texture_id, bb.Min + ImVec2(1, 1), bb.Max - ImVec2(1, 1), uv0, uv1, GetColorU32(tint_col)); - } - else - { - window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, GetColorU32(tint_col)); - } + // Render + if (border_size > 0.0f) + window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f, ImDrawFlags_None, border_size); + window->DrawList->AddImage(user_texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col)); } // ImageButton() is flawed as 'id' is always derived from 'texture_id' (see #2464 #1390) From 69f524ba959c694a304dd71765d84e1422ce1eb2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 8 Dec 2023 18:43:29 +0100 Subject: [PATCH 010/237] DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: Added when component <= 0. (#7095) --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index 4bfe45c1f145..10ccf02222db 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9860,6 +9860,7 @@ void ImGui::PushMultiItemsWidths(int components, float w_full) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; + IM_ASSERT(components > 0); const ImGuiStyle& style = g.Style; const float w_item_one = ImMax(1.0f, IM_TRUNC((w_full - (style.ItemInnerSpacing.x) * (components - 1)) / (float)components)); const float w_item_last = ImMax(1.0f, IM_TRUNC(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components - 1))); From 03298fe875c0855097af6f79be631952054f984d Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 10 Dec 2023 12:53:20 +0100 Subject: [PATCH 011/237] Windows: Fixed some auto-resizing path using style.WindowMinSize.x (instead of x/y). (#7106) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ffd6394d26a6..0249fbe3e1e0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,8 @@ Other changes: - Windows: BeginChild(): Fixed auto-resizing erroneously limiting size to host viewport minus padding. There are no limit to a child width/height. (#7063) [@Devyre] +- Windows: Fixed some auto-resizing path using style.WindowMinSize.x (instead of x/y) + for both axises since 1.90. (#7106) [@n0bodysec] - Scrolling: internal scrolling value is rounded instead of truncated, as a way to reduce speed asymetry when (incorrectly) attempting to scroll by non-integer amount. (#6677) - Nav, IO: SetNextFrameWantCaptureKeyboard(false) calls are not overrided back to true when diff --git a/imgui.cpp b/imgui.cpp index 10ccf02222db..2a3b25bc3bab 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5674,7 +5674,7 @@ static inline ImVec2 CalcWindowMinSize(ImGuiWindow* window) { ImGuiWindow* window_for_height = window; size_min.x = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ? g.Style.WindowMinSize.x : 4.0f; - size_min.y = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ? g.Style.WindowMinSize.x : 4.0f; + size_min.y = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ? g.Style.WindowMinSize.y : 4.0f; size_min.y = ImMax(size_min.y, window_for_height->TitleBarHeight() + window_for_height->MenuBarHeight() + ImMax(0.0f, g.Style.WindowRounding - 1.0f)); // Reduce artifacts with very small windows } return size_min; From 86512eac067afaeb39e2ade870ba08b6bd861274 Mon Sep 17 00:00:00 2001 From: Nahor Date: Mon, 11 Dec 2023 14:01:22 -0800 Subject: [PATCH 012/237] DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: improve multi-components width computation to better distribute the error. (#7120, #7121) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 16 +++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0249fbe3e1e0..76d7d1f2247c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,8 @@ Other changes: - Drag and Drop: Fixed drop target highlight on items temporarily pushing a widened clip rect (namely Selectables and Treenodes using SpanAllColumn flag) so the highlight properly covers all columns. (#7049, #4281, #3272) +- DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: improve multi-components + width computation to better distribute the error. (#7120, #7121) [@Nahor] - Menus: Tweaked hover slack logic, adding a timer to avoid situations where a slow vertical movements toward another parent BeginMenu() can keep the wrong child menu open. (#6671, #6926) - Debug Tools: Added DebugFlashStyleColor() to identify a style color. Added to Style Editor. diff --git a/imgui.cpp b/imgui.cpp index 2a3b25bc3bab..9db6c17e4c94 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9862,14 +9862,16 @@ void ImGui::PushMultiItemsWidths(int components, float w_full) ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(components > 0); const ImGuiStyle& style = g.Style; - const float w_item_one = ImMax(1.0f, IM_TRUNC((w_full - (style.ItemInnerSpacing.x) * (components - 1)) / (float)components)); - const float w_item_last = ImMax(1.0f, IM_TRUNC(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components - 1))); window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); // Backup current width - if (components > 1) - window->DC.ItemWidthStack.push_back(w_item_last); - for (int i = 0; i < components - 2; i++) - window->DC.ItemWidthStack.push_back(w_item_one); - window->DC.ItemWidth = (components == 1) ? w_item_last : w_item_one; + float w_items = w_full - style.ItemInnerSpacing.x * (components - 1); + float prev_split = w_items; + for (int i = components - 1; i > 0; i--) + { + float next_split = IM_TRUNC(w_items * i / components); + window->DC.ItemWidthStack.push_back(prev_split - next_split); + prev_split = next_split; + } + window->DC.ItemWidth = prev_split; g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth; } From 34646627aa3bdfabf80d35c4536001f080a17b5d Mon Sep 17 00:00:00 2001 From: Nahor Date: Tue, 12 Dec 2023 02:07:01 -0800 Subject: [PATCH 013/237] ColorEdit4: improve components width computation to better distribute the error (#7120) (#7123) --- imgui_widgets.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ba103b14fda1..69f387040977 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5189,10 +5189,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag if ((flags & (ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0) { // RGB/HSV 0..255 Sliders - const float w_item_one = ImMax(1.0f, IM_TRUNC((w_inputs - (style.ItemInnerSpacing.x) * (components - 1)) / (float)components)); - const float w_item_last = ImMax(1.0f, IM_TRUNC(w_inputs - (w_item_one + style.ItemInnerSpacing.x) * (components - 1))); + const float w_items = w_inputs - style.ItemInnerSpacing.x * (components - 1); - const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x); + const bool hide_prefix = (IM_TRUNC(w_items / components) <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x); static const char* ids[4] = { "##X", "##Y", "##Z", "##W" }; static const char* fmt_table_int[3][4] = { @@ -5208,11 +5207,14 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag }; const int fmt_idx = hide_prefix ? 0 : (flags & ImGuiColorEditFlags_DisplayHSV) ? 2 : 1; + float prev_split = 0.0f; for (int n = 0; n < components; n++) { if (n > 0) SameLine(0, style.ItemInnerSpacing.x); - SetNextItemWidth((n + 1 < components) ? w_item_one : w_item_last); + float next_split = IM_TRUNC(w_items * (n + 1) / components); + SetNextItemWidth(next_split - prev_split); + prev_split = next_split; // FIXME: When ImGuiColorEditFlags_HDR flag is passed HS values snap in weird ways when SV values go below 0. if (flags & ImGuiColorEditFlags_Float) From 07dbd46ddded40415ac88ea7e0f380a989d44e05 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 12 Dec 2023 18:18:52 +0100 Subject: [PATCH 014/237] Misc: Rework debug display of texture id in Metrics window to avoid compile-error when ImTextureID is defined to be larger than 64-bits. (#7090) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 76d7d1f2247c..9c86c9b50c13 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -71,6 +71,8 @@ Other changes: - Debug Tools: Added DebugFlashStyleColor() to identify a style color. Added to Style Editor. - Misc: Added IMGUI_USER_H_FILENAME to change the path included when using IMGUI_INCLUDE_IMGUI_USER_H. (#7039) [@bryceberger] +- Misc: Rework debug display of texture id in Metrics window to avoid compile-error when + ImTextureID is defined to be larger than 64-bits. (#7090) - Misc: Added extra courtesy ==/!= operators when IMGUI_DEFINE_MATH_OPERATORS is defined. - Misc: Fixed text functions fast-path for handling "%s" and "%.*s" to handle null pointers gracefully, like most printf implementations. (#7016, #3466, #6846) [@codefrog2002] diff --git a/imgui.cpp b/imgui.cpp index 9db6c17e4c94..1368b9a09ff6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -14472,6 +14472,14 @@ void ImGui::DebugNodeColumns(ImGuiOldColumns* columns) TreePop(); } +static void FormatTextureIDForDebugDisplay(char* buf, int buf_size, const ImTextureID& tex_id) +{ + if (sizeof(tex_id) >= sizeof(void*)) + ImFormatString(buf, buf_size, "0x%p", (void*)*(intptr_t*)(void*)&tex_id); + else + ImFormatString(buf, buf_size, "0x%04X", *(int*)(void*)&tex_id); +} + // [DEBUG] Display contents of ImDrawList void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, const ImDrawList* draw_list, const char* label) { @@ -14508,10 +14516,11 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, con continue; } + char texid_desc[20]; + FormatTextureIDForDebugDisplay(texid_desc, IM_ARRAYSIZE(texid_desc), pcmd->TextureId); char buf[300]; - ImFormatString(buf, IM_ARRAYSIZE(buf), "DrawCmd:%5d tris, Tex 0x%p, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", - pcmd->ElemCount / 3, (void*)(intptr_t)pcmd->TextureId, - pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); + ImFormatString(buf, IM_ARRAYSIZE(buf), "DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", + pcmd->ElemCount / 3, texid_desc, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); bool pcmd_node_open = TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf); if (IsItemHovered() && (cfg->ShowDrawCmdMesh || cfg->ShowDrawCmdBoundingBoxes) && fg_draw_list) DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, cfg->ShowDrawCmdMesh, cfg->ShowDrawCmdBoundingBoxes); From f6836ff37fd361010829621f610837686aa00944 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 12 Dec 2023 18:24:30 +0100 Subject: [PATCH 015/237] Misc: Rework debug display of texture id in Metrics window (amend) (#7090) Amend 96b5b17 --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 1368b9a09ff6..7d6627579ccd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -14472,7 +14472,7 @@ void ImGui::DebugNodeColumns(ImGuiOldColumns* columns) TreePop(); } -static void FormatTextureIDForDebugDisplay(char* buf, int buf_size, const ImTextureID& tex_id) +static void FormatTextureIDForDebugDisplay(char* buf, int buf_size, ImTextureID tex_id) { if (sizeof(tex_id) >= sizeof(void*)) ImFormatString(buf, buf_size, "0x%p", (void*)*(intptr_t*)(void*)&tex_id); From 4afffa36e99c2cb6f03786fdb869fd3f599552a2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 14 Dec 2023 16:31:08 +0100 Subject: [PATCH 016/237] InputTextMultiline: Fixed Tab character input not repeating (1.89.4 regression) --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9c86c9b50c13..44f9fc4ef7fa 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,7 @@ Other changes: - Drag and Drop: Fixed drop target highlight on items temporarily pushing a widened clip rect (namely Selectables and Treenodes using SpanAllColumn flag) so the highlight properly covers all columns. (#7049, #4281, #3272) +- InputTextMultiline: Fixed Tab character input not repeating (1.89.4 regression). - DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: improve multi-components width computation to better distribute the error. (#7120, #7121) [@Nahor] - Menus: Tweaked hover slack logic, adding a timer to avoid situations where a slow vertical diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 69f387040977..31654c98ea9a 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4403,7 +4403,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // We expect backends to emit a Tab key but some also emit a Tab character which we ignore (#2467, #1336) // (For Tab and Enter: Win32/SFML/Allegro are sending both keys and chars, GLFW and SDL are only sending keys. For Space they all send all threes) - if ((flags & ImGuiInputTextFlags_AllowTabInput) && Shortcut(ImGuiKey_Tab, id) && !is_readonly) + if ((flags & ImGuiInputTextFlags_AllowTabInput) && Shortcut(ImGuiKey_Tab, id, ImGuiInputFlags_Repeat) && !is_readonly) { unsigned int c = '\t'; // Insert TAB if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) From 54c1bdecebf3c9bb9259c07c5f5666bb4bd5c3ea Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 14 Dec 2023 16:45:23 +0100 Subject: [PATCH 017/237] Internals: removed unused ImGuiItemStatusFlags_FocusedByTabbing. (#4449) Amend 1a7526d --- imgui_internal.h | 5 ++--- imgui_widgets.cpp | 15 ++++++--------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 6ed1c10093dd..ee8098f75154 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -835,9 +835,8 @@ enum ImGuiItemStatusFlags_ ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag. ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. ImGuiItemStatusFlags_HoveredWindow = 1 << 7, // Override the HoveredWindow test to allow cross-window hover testing. - ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8, // Set when the Focusable item just got focused by Tabbing (FIXME: to be removed soon) - ImGuiItemStatusFlags_Visible = 1 << 9, // [WIP] Set when item is overlapping the current clipping rectangle (Used internally. Please don't use yet: API/system will change as we refactor Itemadd()). - ImGuiItemStatusFlags_HasClipRect = 1 << 10, // g.LastItemData.ClipRect is valid + ImGuiItemStatusFlags_Visible = 1 << 8, // [WIP] Set when item is overlapping the current clipping rectangle (Used internally. Please don't use yet: API/system will change as we refactor Itemadd()). + ImGuiItemStatusFlags_HasClipRect = 1 << 9, // g.LastItemData.ClipRect is valid // Additional status + semantic for ImGuiTestEngine #ifdef IMGUI_ENABLE_TEST_ENGINE diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 31654c98ea9a..7194ad3eb1e2 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2427,14 +2427,13 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, if (!temp_input_is_active) { // Tabbing or CTRL-clicking on Drag turns it into an InputText - const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; const bool clicked = hovered && IsMouseClicked(0, id); const bool double_clicked = (hovered && g.IO.MouseClickedCount[0] == 2 && TestKeyOwner(ImGuiKey_MouseLeft, id)); - const bool make_active = (input_requested_by_tabbing || clicked || double_clicked || g.NavActivateId == id); + const bool make_active = (clicked || double_clicked || g.NavActivateId == id); if (make_active && (clicked || double_clicked)) SetKeyOwner(ImGuiKey_MouseLeft, id); if (make_active && temp_input_allowed) - if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || double_clicked || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))) + if ((clicked && g.IO.KeyCtrl) || double_clicked || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))) temp_input_is_active = true; // (Optional) simple click (without moving) turns Drag into an InputText @@ -3019,13 +3018,12 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat if (!temp_input_is_active) { // Tabbing or CTRL-clicking on Slider turns it into an input box - const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; const bool clicked = hovered && IsMouseClicked(0, id); - const bool make_active = (input_requested_by_tabbing || clicked || g.NavActivateId == id); + const bool make_active = (clicked || g.NavActivateId == id); if (make_active && clicked) SetKeyOwner(ImGuiKey_MouseLeft, id); if (make_active && temp_input_allowed) - if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))) + if ((clicked && g.IO.KeyCtrl) || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))) temp_input_is_active = true; if (make_active && !temp_input_is_active) @@ -4178,7 +4176,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (is_resizable) IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag! - const bool input_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateId == id) && ((g.NavActivateFlags & ImGuiActivateFlags_PreferInput) || (g.NavInputSource == ImGuiInputSource_Keyboard))); const bool user_clicked = hovered && io.MouseClicked[0]; @@ -4190,7 +4187,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX; const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); // state != NULL means its our state. - const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav || input_requested_by_tabbing); + const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav); const bool init_state = (init_make_active || user_scroll_active); if ((init_state && g.ActiveId != id) || init_changed_specs) { @@ -4240,7 +4237,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ select_all = true; if (input_requested_by_nav && (!recycle_state || !(g.NavActivateFlags & ImGuiActivateFlags_TryToPreserveState))) select_all = true; - if (input_requested_by_tabbing || (user_clicked && io.KeyCtrl)) + if (user_clicked && io.KeyCtrl) select_all = true; } From 6cfe3ddf528a13728a75df7db4c856d5d8770e2e Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 14 Dec 2023 17:02:23 +0100 Subject: [PATCH 018/237] InputTextMultiline: Tabbing through a multi-line text editor using ImGuiInputTextFlags_AllowTabInput doesn't activate it. (#3092, #5759, #787) --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 2 +- imgui_demo.cpp | 1 + imgui_internal.h | 1 + imgui_widgets.cpp | 6 +++++- 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 44f9fc4ef7fa..f4543da00b94 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -65,6 +65,9 @@ Other changes: (namely Selectables and Treenodes using SpanAllColumn flag) so the highlight properly covers all columns. (#7049, #4281, #3272) - InputTextMultiline: Fixed Tab character input not repeating (1.89.4 regression). +- InputTextMultiline: Tabbing through a multi-line text editor which allows Tab character inputs + (using the ImGuiInputTextFlags_AllowTabInput flag) doesn't automatically activate it, in order + to allow passing through multiple widgets easily. (#3092, #5759, #787) - DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: improve multi-components width computation to better distribute the error. (#7120, #7121) [@Nahor] - Menus: Tweaked hover slack logic, adding a timer to avoid situations where a slow vertical diff --git a/imgui.cpp b/imgui.cpp index 7d6627579ccd..a7a9cf98a2bb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12034,7 +12034,7 @@ void ImGui::NavMoveRequestApplyResult() g.NavNextActivateId = result->ID; g.NavNextActivateFlags = ImGuiActivateFlags_None; if (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) - g.NavNextActivateFlags |= ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState; + g.NavNextActivateFlags |= ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState | ImGuiActivateFlags_FromTabbing; } // Enable nav highlight diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 86d5ad367aa1..763e0a9e9622 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1479,6 +1479,7 @@ static void ShowDemoWindowWidgets() HelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp because we don't want to include in here)"); ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly); ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput); + ImGui::SameLine(); HelpMarker("When _AllowTabInput is set, passing through the widget with Tabbing doesn't automatically activate it, in order to also cycling through subsequent widgets."); ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine); ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags); ImGui::TreePop(); diff --git a/imgui_internal.h b/imgui_internal.h index ee8098f75154..35c48616e91a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1488,6 +1488,7 @@ enum ImGuiActivateFlags_ ImGuiActivateFlags_PreferInput = 1 << 0, // Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default for Enter key. ImGuiActivateFlags_PreferTweak = 1 << 1, // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default for Space key and if keyboard is not used. ImGuiActivateFlags_TryToPreserveState = 1 << 2, // Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection) + ImGuiActivateFlags_FromTabbing = 1 << 3, // Activation requested by a tabbing request }; // Early work-in-progress API for ScrollToItem() diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 7194ad3eb1e2..5ad751d4609a 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4126,7 +4126,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ item_data_backup = g.LastItemData; window->DC.CursorPos = backup_pos; - // Prevent NavActivate reactivating in BeginChild(). + // Prevent NavActivation from Tabbing when our widget accepts Tab inputs: this allows cycling through widgets without stopping. + if (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_FromTabbing) && (flags & ImGuiInputTextFlags_AllowTabInput)) + g.NavActivateId = 0; + + // Prevent NavActivate reactivating in BeginChild() when we are already active. const ImGuiID backup_activate_id = g.NavActivateId; if (g.ActiveId == id) // Prevent reactivation g.NavActivateId = 0; From 0d582dabf34e9e31f072b1ee5c353c18351b4424 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 14 Dec 2023 17:24:13 +0100 Subject: [PATCH 019/237] Fixed warning (amend 54c1bde) --- imgui_widgets.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 5ad751d4609a..ac5455b05cfd 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4111,7 +4111,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ ImGuiWindow* draw_window = window; ImVec2 inner_size = frame_size; - ImGuiItemStatusFlags item_status_flags = 0; ImGuiLastItemData item_data_backup; if (is_multiline) { @@ -4122,7 +4121,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ EndGroup(); return false; } - item_status_flags = g.LastItemData.StatusFlags; item_data_backup = g.LastItemData; window->DC.CursorPos = backup_pos; @@ -4162,7 +4160,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (!(flags & ImGuiInputTextFlags_MergedItem)) if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable)) return false; - item_status_flags = g.LastItemData.StatusFlags; } const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags); if (hovered) From f59b54c6f436113991693e73831a8ed65183a13b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 18 Dec 2023 18:23:53 +0100 Subject: [PATCH 020/237] Nav: Activation can also be performed with Keypad Enter. (#5606) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f4543da00b94..731ec4d5b0f3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -61,6 +61,7 @@ Other changes: speed asymetry when (incorrectly) attempting to scroll by non-integer amount. (#6677) - Nav, IO: SetNextFrameWantCaptureKeyboard(false) calls are not overrided back to true when navigation is enabled. SetNextFrameWantCaptureKeyboard() is always higher priority. (#6997) +- Nav: Activation can also be performed with Keypad Enter. (#5606) - Drag and Drop: Fixed drop target highlight on items temporarily pushing a widened clip rect (namely Selectables and Treenodes using SpanAllColumn flag) so the highlight properly covers all columns. (#7049, #4281, #3272) diff --git a/imgui.cpp b/imgui.cpp index a7a9cf98a2bb..57498b8b1337 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11652,8 +11652,8 @@ static void ImGui::NavUpdate() { const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate)); const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, false)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, false))); - const bool input_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Enter)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput)); - const bool input_pressed = input_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Enter, false)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, false))); + const bool input_down = (nav_keyboard_active && (IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_KeyPadEnter))) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput)); + const bool input_pressed = input_down && ((nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, false) || IsKeyPressed(ImGuiKey_KeyPadEnter, false))) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, false))); if (g.ActiveId == 0 && activate_pressed) { g.NavActivateId = g.NavId; From e265610a0c4143b9abc64c50a3950ddcd0243622 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 18 Dec 2023 18:36:01 +0100 Subject: [PATCH 021/237] Fixes for MSVC code analyzer. --- imgui.cpp | 2 +- imgui_demo.cpp | 2 +- imgui_widgets.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 57498b8b1337..f6d3ccf2a8f6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -14280,7 +14280,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } }; #else - struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key < 512 && GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array + struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key >= 0 && key < 512 && GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array //Text("Legacy raw:"); for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key++) { if (io.KeysDown[key]) { SameLine(); Text("\"%s\" %d", GetKeyName(key), key); } } #endif Text("Keys down:"); for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !IsKeyDown(key)) continue; SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); SameLine(); Text("(%.02f)", GetKeyData(key)->DownDuration); } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 763e0a9e9622..94972dd1ae35 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6098,7 +6098,7 @@ static void ShowDemoWindowInputs() struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } }; ImGuiKey start_key = ImGuiKey_NamedKey_BEGIN; #else - struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array + struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key >= 0 && key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array ImGuiKey start_key = (ImGuiKey)0; #endif ImGui::Text("Keys down:"); for (ImGuiKey key = start_key; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyDown(key)) continue; ImGui::SameLine(); ImGui::Text((key < ImGuiKey_NamedKey_BEGIN) ? "\"%s\"" : "\"%s\" %d", ImGui::GetKeyName(key), key); } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ac5455b05cfd..8d486d48b7d5 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3925,8 +3925,8 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im if (c < 0x20) { bool pass = false; - pass |= (c == '\n' && (flags & ImGuiInputTextFlags_Multiline)); // Note that an Enter KEY will emit \r and be ignored (we poll for KEY in InputText() code) - pass |= (c == '\t' && (flags & ImGuiInputTextFlags_AllowTabInput)); + pass |= (c == '\n') && (flags & ImGuiInputTextFlags_Multiline) != 0; // Note that an Enter KEY will emit \r and be ignored (we poll for KEY in InputText() code) + pass |= (c == '\t') && (flags & ImGuiInputTextFlags_AllowTabInput) != 0; if (!pass) return false; apply_named_filters = false; // Override named filters below so newline and tabs can still be inserted. From 089ed3032359f7c83c0c608d500c518b359bf25f Mon Sep 17 00:00:00 2001 From: Kevin Coghlan Date: Mon, 18 Dec 2023 23:30:49 +0000 Subject: [PATCH 022/237] Replace usages of ImGuiKey_KeyPadEnter with ImGuiKey_KeypadEnter. (#7143) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f6d3ccf2a8f6..51751da46a0e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11652,8 +11652,8 @@ static void ImGui::NavUpdate() { const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate)); const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, false)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, false))); - const bool input_down = (nav_keyboard_active && (IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_KeyPadEnter))) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput)); - const bool input_pressed = input_down && ((nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, false) || IsKeyPressed(ImGuiKey_KeyPadEnter, false))) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, false))); + const bool input_down = (nav_keyboard_active && (IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_KeypadEnter))) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput)); + const bool input_pressed = input_down && ((nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, false) || IsKeyPressed(ImGuiKey_KeypadEnter, false))) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, false))); if (g.ActiveId == 0 && activate_pressed) { g.NavActivateId = g.NavId; From 8764a1b7c4f8428e55da52d61f7a6d772bf01008 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Dec 2023 10:51:11 +0100 Subject: [PATCH 023/237] Backends: Vulkan: free FontCommandBuffer explicitely (not actually required in normal code path, unless ImGui_ImplVulkan_DestroyDeviceObjects is declared directly). (#7104) --- backends/imgui_impl_vulkan.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index d58a28cbbcfb..0f36ba8ff731 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -1021,6 +1021,7 @@ void ImGui_ImplVulkan_DestroyDeviceObjects() ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator); ImGui_ImplVulkan_DestroyFontsTexture(); + if (bd->FontCommandBuffer) { vkFreeCommandBuffers(v->Device, bd->FontCommandPool, 1, &bd->FontCommandBuffer); bd->FontCommandBuffer = VK_NULL_HANDLE; } if (bd->FontCommandPool) { vkDestroyCommandPool(v->Device, bd->FontCommandPool, v->Allocator); bd->FontCommandPool = VK_NULL_HANDLE; } if (bd->ShaderModuleVert) { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; } if (bd->ShaderModuleFrag) { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; } From 55073aa7a39c6d9485fa0c1dec854ec654e618d6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Dec 2023 11:22:43 +0100 Subject: [PATCH 024/237] Examples; SDL: added missing return values checks from SDL_CreateWindow() calls. (#7147) --- examples/example_sdl2_directx11/main.cpp | 6 ++++++ examples/example_sdl2_opengl2/main.cpp | 6 ++++++ examples/example_sdl2_opengl3/main.cpp | 6 ++++++ examples/example_sdl2_sdlrenderer2/main.cpp | 5 +++++ examples/example_sdl2_vulkan/main.cpp | 5 +++++ 5 files changed, 28 insertions(+) diff --git a/examples/example_sdl2_directx11/main.cpp b/examples/example_sdl2_directx11/main.cpp index 7c16605910d6..3275bafde502 100644 --- a/examples/example_sdl2_directx11/main.cpp +++ b/examples/example_sdl2_directx11/main.cpp @@ -47,6 +47,12 @@ int main(int, char**) // Setup window SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+DirectX11 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); + if (window == nullptr) + { + printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); + return -1; + } + SDL_SysWMinfo wmInfo; SDL_VERSION(&wmInfo.version); SDL_GetWindowWMInfo(window, &wmInfo); diff --git a/examples/example_sdl2_opengl2/main.cpp b/examples/example_sdl2_opengl2/main.cpp index e1451a61946a..efb28edbc417 100644 --- a/examples/example_sdl2_opengl2/main.cpp +++ b/examples/example_sdl2_opengl2/main.cpp @@ -41,6 +41,12 @@ int main(int, char**) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); + if (window == nullptr) + { + printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); + return -1; + } + SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GL_MakeCurrent(window, gl_context); SDL_GL_SetSwapInterval(1); // Enable vsync diff --git a/examples/example_sdl2_opengl3/main.cpp b/examples/example_sdl2_opengl3/main.cpp index 344f7452d520..d748c1360bb2 100644 --- a/examples/example_sdl2_opengl3/main.cpp +++ b/examples/example_sdl2_opengl3/main.cpp @@ -68,6 +68,12 @@ int main(int, char**) SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); + if (window == nullptr) + { + printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); + return -1; + } + SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GL_MakeCurrent(window, gl_context); SDL_GL_SetSwapInterval(1); // Enable vsync diff --git a/examples/example_sdl2_sdlrenderer2/main.cpp b/examples/example_sdl2_sdlrenderer2/main.cpp index bc7603eeb22f..bfba8fa6ac20 100644 --- a/examples/example_sdl2_sdlrenderer2/main.cpp +++ b/examples/example_sdl2_sdlrenderer2/main.cpp @@ -38,6 +38,11 @@ int main(int, char**) // Create window with SDL_Renderer graphics context SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+SDL_Renderer example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); + if (window == nullptr) + { + printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); + return -1; + } SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); if (renderer == nullptr) { diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index 3163446f3a8b..bbd9eec4284d 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -385,6 +385,11 @@ int main(int, char**) // Create window with Vulkan graphics context SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); + if (window == nullptr) + { + printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); + return -1; + } ImVector extensions; uint32_t extensions_count = 0; From 70f2aaff430b21fef083cc75b52d47debf2b7b41 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 14 Dec 2023 17:24:47 +0100 Subject: [PATCH 025/237] Nav: tabbing happen within FocusScope. ImGuiWindowFlags_NavFlattened make window inherit focus scope from parent. --- imgui.cpp | 9 +++++++-- imgui.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 51751da46a0e..5af35dfb6b30 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6420,7 +6420,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Add to focus scope stack // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow() - PushFocusScope(window->ID); + if ((flags & ImGuiWindowFlags_NavFlattened) == 0) + PushFocusScope(window->ID); window->NavRootFocusScopeId = g.CurrentFocusScopeId; g.CurrentWindow = NULL; @@ -7061,7 +7062,8 @@ void ImGui::End() if (window->DC.CurrentColumns) EndColumns(); PopClipRect(); // Inner window clip rectangle - PopFocusScope(); + if ((window->Flags & ImGuiWindowFlags_NavFlattened) == 0) + PopFocusScope(); // Stop logging if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging @@ -9679,6 +9681,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu // If we crash on a NULL g.NavWindow we need to fix the bug elsewhere. if (!(g.LastItemData.InFlags & ImGuiItemFlags_NoNav)) { + // FIMXE-NAV: investigate changing the window tests into a simple 'if (g.NavFocusScopeId == g.CurrentFocusScopeId)' test. window->DC.NavLayersActiveMaskNext |= (1 << window->DC.NavLayerCurrent); if (g.NavId == id || g.NavAnyRequest) if (g.NavWindow->RootWindowForNav == window->RootWindowForNav) @@ -11310,6 +11313,8 @@ void ImGui::NavProcessItemForTabbingRequest(ImGuiID id, ImGuiItemFlags item_flag if ((move_flags & ImGuiNavMoveFlags_FocusApi) == 0) if (g.NavLayer != g.CurrentWindow->DC.NavLayerCurrent) return; + if (g.NavFocusScopeId != g.CurrentFocusScopeId) + return; // - Can always land on an item when using API call. // - Tabbing with _NavEnableKeyboard (space/enter/arrows): goes through every item. diff --git a/imgui.h b/imgui.h index 0b7be292d6b1..dc3b50f3dab3 100644 --- a/imgui.h +++ b/imgui.h @@ -1009,7 +1009,7 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, // [Internal] - ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] On child window: allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows. + ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] On child window: share focus scope, allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows. ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip() ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup() From b4c5a83cfe6c204bbff1f8cdabf3abbfea9130e5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Dec 2023 13:52:40 +0100 Subject: [PATCH 026/237] Commented out obsolete ImGuiKey_KeyPadEnter redirection to ImGuiKey_KeypadEnter. (#2625, #7143) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 1 + imgui.h | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 731ec4d5b0f3..504a544273e4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,6 +50,7 @@ Breaking changes: Prefer using ImGuiListClipper which can return non-contiguous ranges. - Internals, Columns: commented out legacy ImGuiColumnsFlags_XXX symbols redirecting to ImGuiOldColumnsFlags_XXX, obsoleted from imgui_internal.h in 1.80. +- Commented out obsolete ImGuiKey_KeyPadEnter redirection to ImGuiKey_KeypadEnter. (#2625, #7143) Other changes: diff --git a/imgui.cpp b/imgui.cpp index 5af35dfb6b30..a455b28f0444 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -424,6 +424,7 @@ CODE When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2023/12/19 (1.90.1) - commented out obsolete ImGuiKey_KeyPadEnter redirection to ImGuiKey_KeypadEnter. - 2023/11/06 (1.90.1) - removed CalcListClipping() marked obsolete in 1.86. Prefer using ImGuiListClipper which can return non-contiguous ranges. - 2023/11/05 (1.90.1) - imgui_freetype: commented out ImGuiFreeType::BuildFontAtlas() obsoleted in 1.81. prefer using #define IMGUI_ENABLE_FREETYPE or see commented code for manual calls. - 2023/11/05 (1.90.1) - internals,columns: commented out legacy ImGuiColumnsFlags_XXX symbols redirecting to ImGuiOldColumnsFlags_XXX, obsoleted from imgui_internal.h in 1.80. diff --git a/imgui.h b/imgui.h index dc3b50f3dab3..44fab7dc0cc8 100644 --- a/imgui.h +++ b/imgui.h @@ -1430,7 +1430,7 @@ enum ImGuiKey : int #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS ImGuiKey_ModCtrl = ImGuiMod_Ctrl, ImGuiKey_ModShift = ImGuiMod_Shift, ImGuiKey_ModAlt = ImGuiMod_Alt, ImGuiKey_ModSuper = ImGuiMod_Super, // Renamed in 1.89 - ImGuiKey_KeyPadEnter = ImGuiKey_KeypadEnter, // Renamed in 1.87 + //ImGuiKey_KeyPadEnter = ImGuiKey_KeypadEnter, // Renamed in 1.87 #endif }; @@ -2148,7 +2148,7 @@ struct ImGuiIO IMGUI_API void ClearEventsQueue(); // Clear all incoming events. IMGUI_API void ClearInputKeys(); // Clear current keyboard/mouse/gamepad state + current frame text input buffer. Equivalent to releasing all keys/buttons. #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - IMGUI_API void ClearInputCharacters(); // [Obsolete] Clear the current frame text input buffer. Now included within ClearInputKeys(). + IMGUI_API void ClearInputCharacters(); // [Obsoleted in 1.89.8] Clear the current frame text input buffer. Now included within ClearInputKeys(). #endif //------------------------------------------------------------------ From 22a7d241ff3bf03f031b07d0422ad66e455efe70 Mon Sep 17 00:00:00 2001 From: Pello Rao Date: Tue, 19 Dec 2023 15:52:44 +0100 Subject: [PATCH 027/237] Backends: GLFW, Emscripten: fixes for canvas resizing. (#6751) --- backends/imgui_impl_glfw.cpp | 47 +++++++++++++++++++ backends/imgui_impl_glfw.h | 5 ++ examples/example_emscripten_wgpu/main.cpp | 3 ++ .../example_glfw_opengl3/Makefile.emscripten | 2 +- examples/example_glfw_opengl3/main.cpp | 7 +++ 5 files changed, 63 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index b3b91dc4a44a..1d981d9dab71 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2023-12-18: Emscripten: Change the size of the GLFW window according to the size of the canvas // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys. // 2023-07-18: Inputs: Revert ignoring mouse data on GLFW_CURSOR_DISABLED as it can be used differently. User may set ImGuiConfigFLags_NoMouse if desired. (#5625, #6609) // 2023-06-12: Accept glfwGetTime() not returning a monotonically increasing value. This seems to happens on some Windows setup when peripherals disconnect, and is likely to also happen on browser + Emscripten. (#6491) @@ -126,6 +127,9 @@ struct ImGui_ImplGlfw_Data ImVec2 LastValidMousePos; bool InstalledCallbacks; bool CallbacksChainForAllWindows; +#ifdef __EMSCRIPTEN__ + const char* CanvasSelector; +#endif // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. GLFWwindowfocusfun PrevUserCallbackWindowFocus; @@ -807,6 +811,49 @@ void ImGui_ImplGlfw_NewFrame() ImGui_ImplGlfw_UpdateGamepads(); } +#ifdef __EMSCRIPTEN__ +static EM_BOOL ImGui_ImplGlfw_OnCanvasSizeChange(int event_type, const EmscriptenUiEvent* event, void* user_data) +{ + ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data *) user_data; + + double canvas_width, canvas_height; + emscripten_get_element_css_size(bd->CanvasSelector, &canvas_width, &canvas_height); + + glfwSetWindowSize(bd->Window, (int)canvas_width, (int)canvas_height); + + return true; +} + +static EM_BOOL ImGui_ImplGlfw_OnFullscreenChange(int event_type, const EmscriptenFullscreenChangeEvent* event, void* user_data) +{ + ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data *) user_data; + + double canvas_width, canvas_height; + emscripten_get_element_css_size(bd->CanvasSelector, &canvas_width, &canvas_height); + + glfwSetWindowSize(bd->Window, (int)canvas_width, (int)canvas_height); + + return true; +} + +/** + * @param canvas_selector A CSS selector, the event listener is applied to the first element that matches the query. + */ +void ImGui_ImplGlfw_SetEmscriptenCanvasSelector(const char *canvas_selector) +{ + IM_ASSERT(canvas_selector != nullptr); + ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); + IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplGlfw_InitForXXX()?"); + bd->CanvasSelector = canvas_selector; + + emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, bd, false, ImGui_ImplGlfw_OnCanvasSizeChange); + emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, bd, false, ImGui_ImplGlfw_OnFullscreenChange); + + // Change the size of the GLFW window according to the size of the canvas + ImGui_ImplGlfw_OnCanvasSizeChange(EMSCRIPTEN_EVENT_RESIZE, {}, bd); +} +#endif + //----------------------------------------------------------------------------- #if defined(__clang__) diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index b9a9a40a7729..e008e5dea911 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -30,6 +30,11 @@ IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool ins IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown(); IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); +// Emscripten related initialization phase methods +#ifdef __EMSCRIPTEN__ +IMGUI_IMPL_API void ImGui_ImplGlfw_SetEmscriptenCanvasSelector(const char* canvas_selector); +#endif + // GLFW callbacks install // - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any. // - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks. diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index a2126bcd1519..b04db9e79272 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -26,6 +26,8 @@ static WGPUSwapChain wgpu_swap_chain = nullptr; static int wgpu_swap_chain_width = 0; static int wgpu_swap_chain_height = 0; +const char* canvas_selector = "#canvas"; + // Forward declarations static void MainLoopStep(void* window); static bool InitWGPU(); @@ -76,6 +78,7 @@ int main(int, char**) // Setup Platform/Renderer backends ImGui_ImplGlfw_InitForOther(window, true); + ImGui_ImplGlfw_SetEmscriptenCanvasSelector(canvas_selector); ImGui_ImplWGPU_Init(wgpu_device, 3, wgpu_preferred_fmt, WGPUTextureFormat_Undefined); // Load Fonts diff --git a/examples/example_glfw_opengl3/Makefile.emscripten b/examples/example_glfw_opengl3/Makefile.emscripten index 8ea4eacfc4c1..bd972abffc85 100644 --- a/examples/example_glfw_opengl3/Makefile.emscripten +++ b/examples/example_glfw_opengl3/Makefile.emscripten @@ -59,7 +59,7 @@ endif CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends #CPPFLAGS += -g CPPFLAGS += -Wall -Wformat -Os $(EMS) -# LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html +LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html LDFLAGS += $(EMS) ##--------------------------------------------------------------------- diff --git a/examples/example_glfw_opengl3/main.cpp b/examples/example_glfw_opengl3/main.cpp index 212c7fb1a4c4..f36eaf1fd835 100644 --- a/examples/example_glfw_opengl3/main.cpp +++ b/examples/example_glfw_opengl3/main.cpp @@ -26,9 +26,13 @@ // This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details. #ifdef __EMSCRIPTEN__ +#include +#include #include "../libs/emscripten/emscripten_mainloop_stub.h" #endif +const char* canvas_selector = "#canvas"; + static void glfw_error_callback(int error, const char* description) { fprintf(stderr, "GLFW Error %d: %s\n", error, description); @@ -84,6 +88,9 @@ int main(int, char**) // Setup Platform/Renderer backends ImGui_ImplGlfw_InitForOpenGL(window, true); +#ifdef __EMSCRIPTEN__ + ImGui_ImplGlfw_SetEmscriptenCanvasSelector(canvas_selector); +#endif ImGui_ImplOpenGL3_Init(glsl_version); // Load Fonts From 3cb805489b69680af5ad1ac5bc219ea69f12bbd2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Dec 2023 15:57:00 +0100 Subject: [PATCH 028/237] Backends: GLFW, Emscripten: fixes for canvas resizing, amends. (#6751) Amend 22a7d24 --- backends/imgui_impl_glfw.cpp | 25 ++++++++--------------- backends/imgui_impl_glfw.h | 2 +- docs/CHANGELOG.txt | 4 ++++ examples/example_emscripten_wgpu/main.cpp | 4 +--- examples/example_glfw_opengl3/main.cpp | 6 +----- 5 files changed, 16 insertions(+), 25 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 1d981d9dab71..60723d2700ef 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -20,7 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2023-12-18: Emscripten: Change the size of the GLFW window according to the size of the canvas +// 2023-12-19: Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to register canvas selector and auto-resize GLFW window. // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys. // 2023-07-18: Inputs: Revert ignoring mouse data on GLFW_CURSOR_DISABLED as it can be used differently. User may set ImGuiConfigFLags_NoMouse if desired. (#5625, #6609) // 2023-06-12: Accept glfwGetTime() not returning a monotonically increasing value. This seems to happens on some Windows setup when peripherals disconnect, and is likely to also happen on browser + Emscripten. (#6491) @@ -814,40 +814,33 @@ void ImGui_ImplGlfw_NewFrame() #ifdef __EMSCRIPTEN__ static EM_BOOL ImGui_ImplGlfw_OnCanvasSizeChange(int event_type, const EmscriptenUiEvent* event, void* user_data) { - ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data *) user_data; - + ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data; double canvas_width, canvas_height; emscripten_get_element_css_size(bd->CanvasSelector, &canvas_width, &canvas_height); - glfwSetWindowSize(bd->Window, (int)canvas_width, (int)canvas_height); - return true; } -static EM_BOOL ImGui_ImplGlfw_OnFullscreenChange(int event_type, const EmscriptenFullscreenChangeEvent* event, void* user_data) +static EM_BOOL ImGui_ImplEmscripten_FullscreenChangeCallback(int event_type, const EmscriptenFullscreenChangeEvent* event, void* user_data) { - ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data *) user_data; - + ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data; double canvas_width, canvas_height; emscripten_get_element_css_size(bd->CanvasSelector, &canvas_width, &canvas_height); - glfwSetWindowSize(bd->Window, (int)canvas_width, (int)canvas_height); - return true; } -/** - * @param canvas_selector A CSS selector, the event listener is applied to the first element that matches the query. - */ -void ImGui_ImplGlfw_SetEmscriptenCanvasSelector(const char *canvas_selector) +// 'canvas_selector' is a CSS selector. The event listener is applied to the first element that matches the query. +// STRING MUST PERSIST FOR THE APPLICATION DURATION. PLEASE USE A STRING LITERAL OR ENSURE POINTER WILL STAY VALID. +void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector) { IM_ASSERT(canvas_selector != nullptr); ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplGlfw_InitForXXX()?"); - bd->CanvasSelector = canvas_selector; + bd->CanvasSelector = canvas_selector; emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, bd, false, ImGui_ImplGlfw_OnCanvasSizeChange); - emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, bd, false, ImGui_ImplGlfw_OnFullscreenChange); + emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, bd, false, ImGui_ImplEmscripten_FullscreenChangeCallback); // Change the size of the GLFW window according to the size of the canvas ImGui_ImplGlfw_OnCanvasSizeChange(EMSCRIPTEN_EVENT_RESIZE, {}, bd); diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index e008e5dea911..6a9acd05b27d 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -32,7 +32,7 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); // Emscripten related initialization phase methods #ifdef __EMSCRIPTEN__ -IMGUI_IMPL_API void ImGui_ImplGlfw_SetEmscriptenCanvasSelector(const char* canvas_selector); +IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector); #endif // GLFW callbacks install diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 504a544273e4..07115664d59b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -84,8 +84,12 @@ Other changes: like most printf implementations. (#7016, #3466, #6846) [@codefrog2002] - Misc: Renamed some defines in imstb_textedit.h to avoid conflicts when using unity/jumbo builds on a codebase where another copy of the library is used. +- Backends: GLFW, Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to + register canvas selector and auto-resize GLFW window. (#6751) [@Traveller23, @ypujante] - Backends: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075) [@FoonTheRaccoon] +- Examples: GLFW+Emscripten: Fixed examples not consistently resizing according to host canvas. + (#6751) [@Traveller23, @ypujante] ----------------------------------------------------------------------- diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index b04db9e79272..590453c15fcb 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -26,8 +26,6 @@ static WGPUSwapChain wgpu_swap_chain = nullptr; static int wgpu_swap_chain_width = 0; static int wgpu_swap_chain_height = 0; -const char* canvas_selector = "#canvas"; - // Forward declarations static void MainLoopStep(void* window); static bool InitWGPU(); @@ -78,7 +76,7 @@ int main(int, char**) // Setup Platform/Renderer backends ImGui_ImplGlfw_InitForOther(window, true); - ImGui_ImplGlfw_SetEmscriptenCanvasSelector(canvas_selector); + ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback("#canvas"); ImGui_ImplWGPU_Init(wgpu_device, 3, wgpu_preferred_fmt, WGPUTextureFormat_Undefined); // Load Fonts diff --git a/examples/example_glfw_opengl3/main.cpp b/examples/example_glfw_opengl3/main.cpp index f36eaf1fd835..4438fa5bb6c7 100644 --- a/examples/example_glfw_opengl3/main.cpp +++ b/examples/example_glfw_opengl3/main.cpp @@ -26,13 +26,9 @@ // This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details. #ifdef __EMSCRIPTEN__ -#include -#include #include "../libs/emscripten/emscripten_mainloop_stub.h" #endif -const char* canvas_selector = "#canvas"; - static void glfw_error_callback(int error, const char* description) { fprintf(stderr, "GLFW Error %d: %s\n", error, description); @@ -89,7 +85,7 @@ int main(int, char**) // Setup Platform/Renderer backends ImGui_ImplGlfw_InitForOpenGL(window, true); #ifdef __EMSCRIPTEN__ - ImGui_ImplGlfw_SetEmscriptenCanvasSelector(canvas_selector); + ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback("#canvas"); #endif ImGui_ImplOpenGL3_Init(glsl_version); From 33d426842dffe0e281518e693f0ed3eca33f917d Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Dec 2023 18:25:02 +0100 Subject: [PATCH 029/237] Backends: Vulkan: ImGui_ImplVulkan_CreateFontsTexture() calls vkQueueWaitIdle() instead of vkDeviceWaitIdle(). (#7148, #6943, #6715, #6327, #3743, #4618) --- backends/imgui_impl_vulkan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 0f36ba8ff731..94e9a0f7cb62 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -784,7 +784,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture() err = vkQueueSubmit(v->Queue, 1, &end_info, VK_NULL_HANDLE); check_vk_result(err); - err = vkDeviceWaitIdle(v->Device); + err = vkQueueWaitIdle(v->Queue); check_vk_result(err); vkDestroyBuffer(v->Device, upload_buffer, v->Allocator); From 0000739c086682e08f9260bda12b7d7961716122 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Dec 2023 20:32:09 +0100 Subject: [PATCH 030/237] Internals: Fixed function name typo. --- imgui.cpp | 6 +++--- imgui_internal.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a455b28f0444..af1f23814628 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7633,7 +7633,7 @@ void ImGui::SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const I window->HitTestHoleOffset = ImVec2ih(pos - window->Pos); } -void ImGui::SetWindowHiddendAndSkipItemsForCurrentFrame(ImGuiWindow* window) +void ImGui::SetWindowHiddenAndSkipItemsForCurrentFrame(ImGuiWindow* window) { window->Hidden = window->SkipItems = true; window->HiddenFramesCanSkipItems = 1; @@ -10377,7 +10377,7 @@ bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags ext if (window->Active) { // Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one. - SetWindowHiddendAndSkipItemsForCurrentFrame(window); + SetWindowHiddenAndSkipItemsForCurrentFrame(window); ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount); } ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize; @@ -12548,7 +12548,7 @@ bool ImGui::BeginTooltipHidden() { ImGuiContext& g = *GImGui; bool ret = Begin("##Tooltip_Hidden", NULL, ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize); - SetWindowHiddendAndSkipItemsForCurrentFrame(g.CurrentWindow); + SetWindowHiddenAndSkipItemsForCurrentFrame(g.CurrentWindow); return ret; } diff --git a/imgui_internal.h b/imgui_internal.h index 35c48616e91a..d796c4b7fcb2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2909,7 +2909,7 @@ namespace ImGui IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0); IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0); IMGUI_API void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size); - IMGUI_API void SetWindowHiddendAndSkipItemsForCurrentFrame(ImGuiWindow* window); + IMGUI_API void SetWindowHiddenAndSkipItemsForCurrentFrame(ImGuiWindow* window); 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); } From 0bd6489721328ba28b2bb19088f988ca54a881da Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Dec 2023 20:50:17 +0100 Subject: [PATCH 031/237] DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: fixed multi-components width in tight space (#7120, #7121) + extra tweak color ColorEdit4() label. Amend 86512ea, 3464662 --- imgui.cpp | 4 ++-- imgui_widgets.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index af1f23814628..d89e7e26cd86 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9872,10 +9872,10 @@ void ImGui::PushMultiItemsWidths(int components, float w_full) for (int i = components - 1; i > 0; i--) { float next_split = IM_TRUNC(w_items * i / components); - window->DC.ItemWidthStack.push_back(prev_split - next_split); + window->DC.ItemWidthStack.push_back(ImMax(prev_split - next_split, 1.0f)); prev_split = next_split; } - window->DC.ItemWidth = prev_split; + window->DC.ItemWidth = ImMax(prev_split, 1.0f); g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth; } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 8d486d48b7d5..abf1f0c18fb9 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5128,8 +5128,6 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag const ImGuiStyle& style = g.Style; const float square_sz = GetFrameHeight(); const float w_full = CalcItemWidth(); - const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); - const float w_inputs = w_full - w_button; const char* label_display_end = FindRenderedTextEnd(label); g.NextItemData.ClearFlags(); @@ -5164,6 +5162,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag const bool alpha = (flags & ImGuiColorEditFlags_NoAlpha) == 0; const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0; const int components = alpha ? 4 : 3; + const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); + const float w_inputs = ImMax(w_full - w_button, 1.0f * components); // Convert to the formats we need float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f }; @@ -5211,7 +5211,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag if (n > 0) SameLine(0, style.ItemInnerSpacing.x); float next_split = IM_TRUNC(w_items * (n + 1) / components); - SetNextItemWidth(next_split - prev_split); + SetNextItemWidth(ImMax(next_split - prev_split, 1.0f)); prev_split = next_split; // FIXME: When ImGuiColorEditFlags_HDR flag is passed HS values snap in weird ways when SV values go below 0. From 036a6c875ec590bc01a4809756b20bcc96181f74 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 20 Dec 2023 11:06:22 +0100 Subject: [PATCH 032/237] ColorEdit4: Further tweaks for very small sizes. (#7120, #7121) --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 07115664d59b..97ead430acf6 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -72,6 +72,7 @@ Other changes: to allow passing through multiple widgets easily. (#3092, #5759, #787) - DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: improve multi-components width computation to better distribute the error. (#7120, #7121) [@Nahor] +- ColorEdit4: Layout tweaks for very small sizes. (#7120, #7121) - Menus: Tweaked hover slack logic, adding a timer to avoid situations where a slow vertical movements toward another parent BeginMenu() can keep the wrong child menu open. (#6671, #6926) - Debug Tools: Added DebugFlashStyleColor() to identify a style color. Added to Style Editor. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index abf1f0c18fb9..99d0c6c25868 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5127,8 +5127,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const float square_sz = GetFrameHeight(); - const float w_full = CalcItemWidth(); const char* label_display_end = FindRenderedTextEnd(label); + float w_full = CalcItemWidth(); g.NextItemData.ClearFlags(); BeginGroup(); @@ -5163,7 +5163,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0; const int components = alpha ? 4 : 3; const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); - const float w_inputs = ImMax(w_full - w_button, 1.0f * components); + const float w_inputs = ImMax(w_full - w_button, 1.0f); + w_full = w_inputs + w_button; // Convert to the formats we need float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f }; From 1e1013085b227aed162858d956a881c3637dd980 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 20 Dec 2023 15:46:26 +0100 Subject: [PATCH 033/237] Debug Tools: Debug Log: Hide its own clipper log to reduce noise in the output. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 97ead430acf6..8a17ad099370 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -76,6 +76,7 @@ Other changes: - Menus: Tweaked hover slack logic, adding a timer to avoid situations where a slow vertical movements toward another parent BeginMenu() can keep the wrong child menu open. (#6671, #6926) - Debug Tools: Added DebugFlashStyleColor() to identify a style color. Added to Style Editor. +- Debug Tools: Debug Log: Hide its own clipper log to reduce noise in the output. - Misc: Added IMGUI_USER_H_FILENAME to change the path included when using IMGUI_INCLUDE_IMGUI_USER_H. (#7039) [@bryceberger] - Misc: Rework debug display of texture id in Metrics window to avoid compile-error when diff --git a/imgui.cpp b/imgui.cpp index d89e7e26cd86..b2c13fc58584 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4787,7 +4787,7 @@ void ImGui::NewFrame() g.DebugLocateId = 0; if (g.DebugLogClipperAutoDisableFrames > 0 && --g.DebugLogClipperAutoDisableFrames == 0) { - DebugLog("(Auto-disabled ImGuiDebugLogFlags_EventClipper to avoid spamming)\n"); + DebugLog("(Debug Log: Auto-disabled ImGuiDebugLogFlags_EventClipper after 2 frames)\n"); g.DebugLogFlags &= ~ImGuiDebugLogFlags_EventClipper; } @@ -14939,6 +14939,9 @@ void ImGui::ShowDebugLogWindow(bool* p_open) SetClipboardText(g.DebugLogBuf.c_str()); BeginChild("##log", ImVec2(0.0f, 0.0f), ImGuiChildFlags_Border, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar); + const ImGuiDebugLogFlags backup_log_flags = g.DebugLogFlags; + g.DebugLogFlags &= ~ImGuiDebugLogFlags_EventClipper; + ImGuiListClipper clipper; clipper.Begin(g.DebugLogIndex.size()); while (clipper.Step()) @@ -14946,10 +14949,10 @@ void ImGui::ShowDebugLogWindow(bool* p_open) { const char* line_begin = g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no); const char* line_end = g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no); - TextUnformatted(line_begin, line_end); + TextUnformatted(line_begin, line_end); // Display line ImRect text_rect = g.LastItemData.Rect; if (IsItemHovered()) - for (const char* p = line_begin; p <= line_end - 10; p++) + for (const char* p = line_begin; p <= line_end - 10; p++) // Search for 0x???????? identifiers { ImGuiID id = 0; if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1) @@ -14962,6 +14965,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open) p += 10; } } + g.DebugLogFlags = backup_log_flags; if (GetScrollY() >= GetScrollMaxY()) SetScrollHereY(1.0f); EndChild(); From 8340a30d277db0831676eb1e1be7deed2d3ce294 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 20 Dec 2023 16:06:59 +0100 Subject: [PATCH 034/237] Debug: move debug assertion in post-clip code to reduce overhead. (#4796 and more). Amend c80179921 --- imgui.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b2c13fc58584..dee32844fc48 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9613,6 +9613,7 @@ void ImGuiStackSizes::CompareWithContextState(ImGuiContext* ctx) // Advance cursor given item size for layout. // Register minimum needed size so it can extend the bounding box used for auto-fit calculation. // See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different. +// THIS IS IN THE PERFORMANCE CRITICAL PATH. void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) { ImGuiContext& g = *GImGui; @@ -9652,6 +9653,7 @@ void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) // Declare item bounding box for clipping and interaction. // Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface // declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction. +// THIS IS IN THE PERFORMANCE CRITICAL PATH (UNTIL THE CLIPPING TEST AND EARLY-RETURN) bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags) { ImGuiContext& g = *GImGui; @@ -9666,11 +9668,11 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu g.LastItemData.StatusFlags = ImGuiItemStatusFlags_None; // Note: we don't copy 'g.NextItemData.SelectionUserData' to an hypothetical g.LastItemData.SelectionUserData: since the former is not cleared. - // Directional navigation processing if (id != 0) { KeepAliveID(id); + // Directional navigation processing // Runs prior to clipping early-out // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests @@ -9689,12 +9691,9 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) NavProcessItem(); } - - // [DEBUG] People keep stumbling on this problem and using "" as identifier in the root of a window instead of "##something". - // Empty identifier are valid and useful in a small amount of cases, but 99.9% of the time you want to use "##something". - // READ THE FAQ: https://dearimgui.com/faq - IM_ASSERT(id != window->ID && "Cannot have an empty ID at the root of a window. If you need an empty label, use ## and read the FAQ about how the ID Stack works!"); } + + // Lightweight clear of SetNextItemXXX data. g.NextItemData.Flags = ImGuiNextItemDataFlags_None; g.NextItemData.ItemFlags = ImGuiItemFlags_None; @@ -9704,7 +9703,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu #endif // Clipping test - // (FIXME: This is a modified copy of IsClippedEx() so we can reuse the is_rect_visible value) + // (this is a modified copy of IsClippedEx() so we can reuse the is_rect_visible value) //const bool is_clipped = IsClippedEx(bb, id); //if (is_clipped) // return false; @@ -9716,12 +9715,20 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu // [DEBUG] #ifndef IMGUI_DISABLE_DEBUG_TOOLS - if (id != 0 && id == g.DebugLocateId) - DebugLocateItemResolveWithLastItem(); -#endif + if (id != 0) + { + if (id == g.DebugLocateId) + DebugLocateItemResolveWithLastItem(); + + // [DEBUG] People keep stumbling on this problem and using "" as identifier in the root of a window instead of "##something". + // Empty identifier are valid and useful in a small amount of cases, but 99.9% of the time you want to use "##something". + // READ THE FAQ: https://dearimgui.com/faq + IM_ASSERT(id != window->ID && "Cannot have an empty ID at the root of a window. If you need an empty label, use ## and read the FAQ about how the ID Stack works!"); + } //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] //if ((g.LastItemData.InFlags & ImGuiItemFlags_NoNav) == 0) // window->DrawList->AddRect(g.LastItemData.NavRect.Min, g.LastItemData.NavRect.Max, IM_COL32(255,255,0,255)); // [DEBUG] +#endif // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) if (is_rect_visible) From f039e69b9cb3434eb1bdfc764cb2b37afe50d275 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 21 Dec 2023 14:08:27 +0100 Subject: [PATCH 035/237] Settings: Fixed an issue marking settings as dirty when merely clicking on a border or resize grip without moving it. --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8a17ad099370..0293c721207a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -75,6 +75,8 @@ Other changes: - ColorEdit4: Layout tweaks for very small sizes. (#7120, #7121) - Menus: Tweaked hover slack logic, adding a timer to avoid situations where a slow vertical movements toward another parent BeginMenu() can keep the wrong child menu open. (#6671, #6926) +- Settings: Fixed an issue marking settings as dirty when merely clicking on a border or resize + grip without moving it. - Debug Tools: Added DebugFlashStyleColor() to identify a style color. Added to Style Editor. - Debug Tools: Debug Log: Hide its own clipper log to reduce noise in the output. - Misc: Added IMGUI_USER_H_FILENAME to change the path included when using diff --git a/imgui.cpp b/imgui.cpp index dee32844fc48..e94ea98f37ab 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6050,15 +6050,17 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si } // Apply back modified position/size to window - if (size_target.x != FLT_MAX) + const ImVec2 curr_pos = window->Pos; + const ImVec2 curr_size = window->SizeFull; + if (size_target.x != FLT_MAX && (window->Size.x != size_target.x || window->SizeFull.x != size_target.x)) window->Size.x = window->SizeFull.x = size_target.x; - if (size_target.y != FLT_MAX) + if (size_target.y != FLT_MAX && (window->Size.y != size_target.y || window->SizeFull.y != size_target.y)) window->Size.y = window->SizeFull.y = size_target.y; - if (pos_target.x != FLT_MAX) + if (pos_target.x != FLT_MAX && window->Pos.x != ImTrunc(pos_target.x)) window->Pos.x = ImTrunc(pos_target.x); - if (pos_target.y != FLT_MAX) + if (pos_target.y != FLT_MAX && window->Pos.y != ImTrunc(pos_target.y)) window->Pos.y = ImTrunc(pos_target.y); - if (size_target.x != FLT_MAX || size_target.y != FLT_MAX || pos_target.x != FLT_MAX || pos_target.y != FLT_MAX) + if (curr_pos.x != window->Pos.x || curr_pos.y != window->Pos.y || curr_size.x != window->SizeFull.x || curr_size.y != window->SizeFull.y) MarkIniSettingsDirty(window); // Recalculate next expected border expected coordinates From 20e1caec858caa8123a6d52d410fa3f2578d3054 Mon Sep 17 00:00:00 2001 From: Kai Wang Date: Wed, 20 Dec 2023 17:34:37 +0800 Subject: [PATCH 036/237] Backends: DX12: Changed swapchain scaling mode to `DXGI_SCALING_NONE`. (#7152, #7153) --- backends/imgui_impl_dx12.cpp | 2 +- docs/CHANGELOG.txt | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 428e47ee096f..cfec286b1aa7 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -899,7 +899,7 @@ static void ImGui_ImplDX12_CreateWindow(ImGuiViewport* viewport) sd1.SampleDesc.Quality = 0; sd1.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; sd1.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; - sd1.Scaling = DXGI_SCALING_STRETCH; + sd1.Scaling = DXGI_SCALING_NONE; sd1.Stereo = FALSE; IDXGIFactory4* dxgi_factory = nullptr; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1e520da5abad..6cf2c5d6b501 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -93,6 +93,11 @@ Other changes: - Examples: GLFW+Emscripten: Fixed examples not consistently resizing according to host canvas. (#6751) [@Traveller23, @ypujante] +Docking+Viewports Branch: + +- Backends: DX12: Changed swapchain scaling mode to DXGI_SCALING_NONE to reduce artifacts as + queued frames aren't synchronized with platform window resizes. (#7152, #7153) [@SuperWangKai] + ----------------------------------------------------------------------- VERSION 1.90.0 (Released 2023-11-15) From 4a2426449a4c65028c65c68ed9426495dec251e4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 22 Dec 2023 19:51:49 +0100 Subject: [PATCH 037/237] Drags, Sliders, Inputs: removed all attempts to filter non-numerical characters during text editing. (#6810, #7096) --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 16 +--------------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0293c721207a..5c31ad05573e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -70,6 +70,8 @@ Other changes: - InputTextMultiline: Tabbing through a multi-line text editor which allows Tab character inputs (using the ImGuiInputTextFlags_AllowTabInput flag) doesn't automatically activate it, in order to allow passing through multiple widgets easily. (#3092, #5759, #787) +- Drags, Sliders, Inputs: removed all attempts to filter non-numerical characters during text + editing. Invalid inputs not applied to value, visibly reverted after validation. (#6810, #7096) - DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: improve multi-components width computation to better distribute the error. (#7120, #7121) [@Nahor] - ColorEdit4: Layout tweaks for very small sizes. (#7120, #7121) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 99d0c6c25868..2ded6913a6ae 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3395,14 +3395,6 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* return value_changed; } -static inline ImGuiInputTextFlags InputScalar_DefaultCharsFilter(ImGuiDataType data_type, const char* format) -{ - if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) - return ImGuiInputTextFlags_CharsScientific; - const char format_last_char = format[0] ? format[strlen(format) - 1] : 0; - return (format_last_char == 'x' || format_last_char == 'X') ? ImGuiInputTextFlags_CharsHexadecimal : ImGuiInputTextFlags_CharsDecimal; -} - // Note that Drag/Slider functions are only forwarding the min/max values clamping values if the ImGuiSliderFlags_AlwaysClamp flag is set! // This is intended: this way we allow CTRL+Click manual input to set a value out of bounds, for maximum flexibility. // However this may not be ideal for all uses, as some user code may break on out of bound values. @@ -3420,7 +3412,6 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG ImStrTrimBlanks(data_buf); ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; - flags |= InputScalar_DefaultCharsFilter(data_type, format); bool value_changed = false; if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags)) @@ -3464,9 +3455,6 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data char buf[64]; DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format); - // Testing ActiveId as a minor optimization as filtering is not needed until active - if (g.ActiveId == 0 && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0) - flags |= InputScalar_DefaultCharsFilter(data_type, format); flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string. bool value_changed = false; @@ -3561,7 +3549,6 @@ bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* p_dat bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags flags) { - flags |= ImGuiInputTextFlags_CharsScientific; return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step > 0.0f ? &step : NULL), (void*)(step_fast > 0.0f ? &step_fast : NULL), format, flags); } @@ -3604,7 +3591,6 @@ bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags) bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags flags) { - flags |= ImGuiInputTextFlags_CharsScientific; return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step > 0.0 ? &step : NULL), (void*)(step_fast > 0.0 ? &step_fast : NULL), format, flags); } @@ -5238,7 +5224,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag else ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255)); SetNextItemWidth(w_inputs); - if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase)) + if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsUppercase)) { value_changed = true; char* p = buf; From 240ab5890b2e8da294937a1710b021ac3f271472 Mon Sep 17 00:00:00 2001 From: kida22 <40718043+kimidaisuki22@users.noreply.github.com> Date: Thu, 28 Dec 2023 04:17:28 +0000 Subject: [PATCH 038/237] Backends: GLFW, Input: Use Unicode version of WndProc for get correct input for text in utf-8 code page. (#7174) Similar to #6785, #6782, #5725, #5961 for for GLFW backend. --- backends/imgui_impl_glfw.cpp | 8 ++++---- docs/CHANGELOG.txt | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 60723d2700ef..b49c99bb8839 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -493,7 +493,7 @@ static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wPara ImGui::GetIO().AddMouseSourceEvent(GetMouseSourceFromMessageExtraInfo()); break; } - return ::CallWindowProc(bd->GlfwWndProc, hWnd, msg, wParam, lParam); + return ::CallWindowProcW(bd->GlfwWndProc, hWnd, msg, wParam, lParam); } #endif @@ -617,9 +617,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw // Windows: register a WndProc hook so we can intercept some messages. #ifdef _WIN32 - bd->GlfwWndProc = (WNDPROC)::GetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC); + bd->GlfwWndProc = (WNDPROC)::GetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC); IM_ASSERT(bd->GlfwWndProc != nullptr); - ::SetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc); + ::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc); #endif bd->ClientApi = client_api; @@ -659,7 +659,7 @@ void ImGui_ImplGlfw_Shutdown() // Windows: register a WndProc hook so we can intercept some messages. #ifdef _WIN32 ImGuiViewport* main_viewport = ImGui::GetMainViewport(); - ::SetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)bd->GlfwWndProc); + ::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)bd->GlfwWndProc); bd->GlfwWndProc = nullptr; #endif diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5c31ad05573e..65b1e926433c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -92,6 +92,8 @@ Other changes: on a codebase where another copy of the library is used. - Backends: GLFW, Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to register canvas selector and auto-resize GLFW window. (#6751) [@Traveller23, @ypujante] +- Backends: GLFW: Fixed Windows specific hooks to use Unicode version of WndProc even when + compiling in MBCS mode. (#7174) [@kimidaisuki22] - Backends: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075) [@FoonTheRaccoon] - Examples: GLFW+Emscripten: Fixed examples not consistently resizing according to host canvas. From 2523c197bc0c91d5aeb16131b0b0fd300a11bb06 Mon Sep 17 00:00:00 2001 From: David Maas Date: Sat, 30 Dec 2023 17:45:25 -0600 Subject: [PATCH 039/237] Fixed title bar background alpha being used to render viewport-owned windows. (#7184, #7181) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6cf2c5d6b501..8fcd87f4d7f2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -97,6 +97,7 @@ Docking+Viewports Branch: - Backends: DX12: Changed swapchain scaling mode to DXGI_SCALING_NONE to reduce artifacts as queued frames aren't synchronized with platform window resizes. (#7152, #7153) [@SuperWangKai] +- Windows: Fixed ImGuiCol_TitleBg/Active alpha being used for viewport-owned windows. (#7181) [@PathogenDavid] ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 268cee61393e..b3a6dcb0afc3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6492,6 +6492,8 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive) { ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg); + if (window->ViewportOwned) + title_bar_col |= IM_COL32_A_MASK; // No alpha window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawFlags_RoundCornersTop); } From 718fa0eec6dd6e6fbe6c139cebc2f1e23cd4861b Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 2 Jan 2024 22:03:36 +0100 Subject: [PATCH 040/237] Happy new year! --- LICENSE.txt | 2 +- imgui.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index fb715bdc84a1..3282f5b5b105 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2023 Omar Cornut +Copyright (c) 2014-2024 Omar Cornut Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/imgui.cpp b/imgui.cpp index e94ea98f37ab..77661fa960f8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -21,7 +21,7 @@ // please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above. // Everything else should be asked in 'Issues'! We are building a database of cross-linked knowledge there. -// Copyright (c) 2014-2023 Omar Cornut +// Copyright (c) 2014-2024 Omar Cornut // Developed by Omar Cornut and every direct or indirect contributors to the GitHub. // See LICENSE.txt for copyright and licensing details (standard MIT License). // This library is free but needs your support to sustain development and maintenance. From e8dd47effa52a8d830cfe7d539fd764428b7e154 Mon Sep 17 00:00:00 2001 From: Axel Paris Date: Wed, 3 Jan 2024 11:25:19 +0100 Subject: [PATCH 041/237] Backends: WebGPU: Fixing an issue when opening a popup in the wgpu backend (#7191) Amend 2b0bd40b9 --- backends/imgui_impl_wgpu.cpp | 10 +++++++++- docs/CHANGELOG.txt | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index e60ddcdda199..638e9fd2455c 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -329,7 +329,9 @@ static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPas void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder) { // Avoid rendering when minimized - if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) + int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); + int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); + if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdListsCount == 0) return; // FIXME: Assuming that this only gets called once per frame! @@ -448,6 +450,12 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder // Project scissor/clipping rectangles into framebuffer space ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); + + // Clamp to viewport as wgpuRenderPassEncoderSetScissorRect() won't accept values that are off bounds + if (clip_min.x < 0.0f) { clip_min.x = 0.0f; } + if (clip_min.y < 0.0f) { clip_min.y = 0.0f; } + if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; } + if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; } if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) continue; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 65b1e926433c..d699d614630b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -96,6 +96,8 @@ Other changes: compiling in MBCS mode. (#7174) [@kimidaisuki22] - Backends: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075) [@FoonTheRaccoon] +- Backends: WebGPU: Fixed wgpuRenderPassEncoderSetScissorRect() crash when rendering modal + window's dimming layer, which has an unclipped value in ImDrawCmd::ClipRect. (#7191) [@aparis69] - Examples: GLFW+Emscripten: Fixed examples not consistently resizing according to host canvas. (#6751) [@Traveller23, @ypujante] From 4778560e668b8ad1dae177a7819ed66675630c63 Mon Sep 17 00:00:00 2001 From: Tristan Gouge Date: Tue, 2 Jan 2024 17:06:21 +0100 Subject: [PATCH 042/237] Backends: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous validation layer. (#7189, #4238) --- backends/imgui_impl_vulkan.cpp | 13 +++++++++---- backends/imgui_impl_vulkan.h | 1 + docs/CHANGELOG.txt | 2 ++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 94e9a0f7cb62..7a9205a7436b 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -33,6 +33,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-01-03: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous "best practice" validation layer. (#7189, #4238) // 2023-11-29: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075) // 2023-11-10: *BREAKING CHANGE*: Removed parameter from ImGui_ImplVulkan_CreateFontsTexture(): backend now creates its own command-buffer to upload fonts. // *BREAKING CHANGE*: Removed ImGui_ImplVulkan_DestroyFontUploadObjects() which is now unecessary as we create and destroy those objects in the backend. @@ -79,6 +80,9 @@ #ifndef IMGUI_DISABLE #include "imgui_impl_vulkan.h" #include +#ifndef IM_MAX +#define IM_MAX(A, B) (((A) >= (B)) ? (A) : (B)) +#endif // Visual Studio warnings #ifdef _MSC_VER @@ -400,16 +404,17 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory VkMemoryRequirements req; vkGetBufferMemoryRequirements(v->Device, buffer, &req); bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment; + VkDeviceSize size = IM_MAX(v->MinAllocationSize, req.size); VkMemoryAllocateInfo alloc_info = {}; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.allocationSize = req.size; + alloc_info.allocationSize = size; alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &buffer_memory); check_vk_result(err); err = vkBindBufferMemory(v->Device, buffer, buffer_memory, 0); check_vk_result(err); - p_buffer_size = req.size; + p_buffer_size = size; } static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height) @@ -669,7 +674,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture() vkGetImageMemoryRequirements(v->Device, bd->FontImage, &req); VkMemoryAllocateInfo alloc_info = {}; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.allocationSize = req.size; + alloc_info.allocationSize = IM_MAX(v->MinAllocationSize, req.size); alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits); err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd->FontMemory); check_vk_result(err); @@ -710,7 +715,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture() bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment; VkMemoryAllocateInfo alloc_info = {}; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.allocationSize = req.size; + alloc_info.allocationSize = IM_MAX(v->MinAllocationSize, req.size); alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &upload_buffer_memory); check_vk_result(err); diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index c53ba68810a4..490fbb040dfc 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -71,6 +71,7 @@ struct ImGui_ImplVulkan_InitInfo // Allocation, Debugging const VkAllocationCallbacks* Allocator; void (*CheckVkResultFn)(VkResult err); + VkDeviceSize MinAllocationSize; // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory. }; // Called by user code diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d699d614630b..16afae940b35 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -96,6 +96,8 @@ Other changes: compiling in MBCS mode. (#7174) [@kimidaisuki22] - Backends: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075) [@FoonTheRaccoon] +- Backends: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous + "best practice" validation layer. (#7189, #4238) [@philae-ael] - Backends: WebGPU: Fixed wgpuRenderPassEncoderSetScissorRect() crash when rendering modal window's dimming layer, which has an unclipped value in ImDrawCmd::ClipRect. (#7191) [@aparis69] - Examples: GLFW+Emscripten: Fixed examples not consistently resizing according to host canvas. From 0ea99132c8daf253332df38951ba21a0a8746c4c Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Jan 2024 14:11:40 +0100 Subject: [PATCH 043/237] Backends: Vulkan: Stop creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them. --- backends/imgui_impl_vulkan.cpp | 9 +++++---- docs/CHANGELOG.txt | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 7a9205a7436b..59706741b75a 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -34,6 +34,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2024-01-03: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous "best practice" validation layer. (#7189, #4238) +// 2024-01-03: Vulkan: Stoped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them. // 2023-11-29: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075) // 2023-11-10: *BREAKING CHANGE*: Removed parameter from ImGui_ImplVulkan_CreateFontsTexture(): backend now creates its own command-buffer to upload fonts. // *BREAKING CHANGE*: Removed ImGui_ImplVulkan_DestroyFontUploadObjects() which is now unecessary as we create and destroy those objects in the backend. @@ -501,9 +502,9 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm // Upload vertex/index data into a single contiguous GPU buffer ImDrawVert* vtx_dst = nullptr; ImDrawIdx* idx_dst = nullptr; - VkResult err = vkMapMemory(v->Device, rb->VertexBufferMemory, 0, rb->VertexBufferSize, 0, (void**)(&vtx_dst)); + VkResult err = vkMapMemory(v->Device, rb->VertexBufferMemory, 0, rb->VertexBufferSize, 0, (void**)&vtx_dst); check_vk_result(err); - err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, rb->IndexBufferSize, 0, (void**)(&idx_dst)); + err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, rb->IndexBufferSize, 0, (void**)&idx_dst); check_vk_result(err); for (int n = 0; n < draw_data->CmdListsCount; n++) { @@ -622,7 +623,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture() { VkCommandPoolCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + info.flags = 0; info.queueFamilyIndex = v->QueueFamily; vkCreateCommandPool(v->Device, &info, v->Allocator, &bd->FontCommandPool); } @@ -1288,7 +1289,7 @@ void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_devi { VkCommandPoolCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + info.flags = 0; info.queueFamilyIndex = queue_family; err = vkCreateCommandPool(device, &info, allocator, &fd->CommandPool); check_vk_result(err); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 16afae940b35..6af62ec1c7e5 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -98,6 +98,8 @@ Other changes: vkDestroyCommandPool(). (#7075) [@FoonTheRaccoon] - Backends: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous "best practice" validation layer. (#7189, #4238) [@philae-ael] +- Backends: Vulkan: Stopped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT + as we don't reset them. - Backends: WebGPU: Fixed wgpuRenderPassEncoderSetScissorRect() crash when rendering modal window's dimming layer, which has an unclipped value in ImDrawCmd::ClipRect. (#7191) [@aparis69] - Examples: GLFW+Emscripten: Fixed examples not consistently resizing according to host canvas. From 33d18c580bd24109fe2d31cc57e31704df749001 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Jan 2024 14:56:21 +0100 Subject: [PATCH 044/237] Misc: During shutdown, check that io.BackendPlatformUserData and io.BackendRendererUserData are NULL. (#7175) --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6af62ec1c7e5..291030a9abcc 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -72,6 +72,7 @@ Other changes: to allow passing through multiple widgets easily. (#3092, #5759, #787) - Drags, Sliders, Inputs: removed all attempts to filter non-numerical characters during text editing. Invalid inputs not applied to value, visibly reverted after validation. (#6810, #7096) +- Drags, Sliders, Inputs: removal of filter means that "nan" and "inf" values may be input. (#7096) - DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: improve multi-components width computation to better distribute the error. (#7120, #7121) [@Nahor] - ColorEdit4: Layout tweaks for very small sizes. (#7120, #7121) @@ -90,6 +91,8 @@ Other changes: like most printf implementations. (#7016, #3466, #6846) [@codefrog2002] - Misc: Renamed some defines in imstb_textedit.h to avoid conflicts when using unity/jumbo builds on a codebase where another copy of the library is used. +- Misc: During shutdown, check that io.BackendPlatformUserData and io.BackendRendererUserData are NULL + in order to catch cases where backend was not shut down. (#7175) - Backends: GLFW, Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to register canvas selector and auto-resize GLFW window. (#6751) [@Traveller23, @ypujante] - Backends: GLFW: Fixed Windows specific hooks to use Unicode version of WndProc even when diff --git a/imgui.cpp b/imgui.cpp index 77661fa960f8..f5dc8f02f50f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3604,8 +3604,11 @@ void ImGui::Initialize() // This function is merely here to free heap allocations. void ImGui::Shutdown() { - // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame) ImGuiContext& g = *GImGui; + IM_ASSERT_USER_ERROR(g.IO.BackendPlatformUserData == NULL, "Forgot to shutdown Platform backend?"); + IM_ASSERT_USER_ERROR(g.IO.BackendRendererUserData == NULL, "Forgot to shutdown Renderer backend?"); + + // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame) if (g.IO.Fonts && g.FontAtlasOwnedByContext) { g.IO.Fonts->Locked = false; From 6f10cef2a1fc15c45ed61a8a427ccd7f45fb8bf0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Jan 2024 16:17:39 +0100 Subject: [PATCH 045/237] Backends: Vulkan: moved structure declarations. This is mostly to facilitate maintainance of #6616. --- backends/imgui_impl_vulkan.cpp | 114 +++++++++++++++++---------------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 59706741b75a..47e6fd824707 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -90,61 +90,9 @@ #pragma warning (disable: 4127) // condition expression is constant #endif -// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplVulkan_RenderDrawData() -// [Please zero-clear before use!] -struct ImGui_ImplVulkanH_FrameRenderBuffers -{ - VkDeviceMemory VertexBufferMemory; - VkDeviceMemory IndexBufferMemory; - VkDeviceSize VertexBufferSize; - VkDeviceSize IndexBufferSize; - VkBuffer VertexBuffer; - VkBuffer IndexBuffer; -}; - -// Each viewport will hold 1 ImGui_ImplVulkanH_WindowRenderBuffers -// [Please zero-clear before use!] -struct ImGui_ImplVulkanH_WindowRenderBuffers -{ - uint32_t Index; - uint32_t Count; - ImGui_ImplVulkanH_FrameRenderBuffers* FrameRenderBuffers; -}; - -// Vulkan data -struct ImGui_ImplVulkan_Data -{ - ImGui_ImplVulkan_InitInfo VulkanInitInfo; - VkRenderPass RenderPass; - VkDeviceSize BufferMemoryAlignment; - VkPipelineCreateFlags PipelineCreateFlags; - VkDescriptorSetLayout DescriptorSetLayout; - VkPipelineLayout PipelineLayout; - VkPipeline Pipeline; - uint32_t Subpass; - VkShaderModule ShaderModuleVert; - VkShaderModule ShaderModuleFrag; - - // Font data - VkSampler FontSampler; - VkDeviceMemory FontMemory; - VkImage FontImage; - VkImageView FontView; - VkDescriptorSet FontDescriptorSet; - VkCommandPool FontCommandPool; - VkCommandBuffer FontCommandBuffer; - - // Render buffers for main window - ImGui_ImplVulkanH_WindowRenderBuffers MainWindowRenderBuffers; - - ImGui_ImplVulkan_Data() - { - memset((void*)this, 0, sizeof(*this)); - BufferMemoryAlignment = 256; - } -}; - // Forward Declarations +struct ImGui_ImplVulkanH_FrameRenderBuffers; +struct ImGui_ImplVulkanH_WindowRenderBuffers; bool ImGui_ImplVulkan_CreateDeviceObjects(); void ImGui_ImplVulkan_DestroyDeviceObjects(); void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator); @@ -240,11 +188,65 @@ static PFN_vkCmdBeginRenderingKHR ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR; static PFN_vkCmdEndRenderingKHR ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR; #endif +// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplVulkan_RenderDrawData() +// [Please zero-clear before use!] +struct ImGui_ImplVulkanH_FrameRenderBuffers +{ + VkDeviceMemory VertexBufferMemory; + VkDeviceMemory IndexBufferMemory; + VkDeviceSize VertexBufferSize; + VkDeviceSize IndexBufferSize; + VkBuffer VertexBuffer; + VkBuffer IndexBuffer; +}; + +// Each viewport will hold 1 ImGui_ImplVulkanH_WindowRenderBuffers +// [Please zero-clear before use!] +struct ImGui_ImplVulkanH_WindowRenderBuffers +{ + uint32_t Index; + uint32_t Count; + ImGui_ImplVulkanH_FrameRenderBuffers* FrameRenderBuffers; +}; + +// Vulkan data +struct ImGui_ImplVulkan_Data +{ + ImGui_ImplVulkan_InitInfo VulkanInitInfo; + VkRenderPass RenderPass; + VkDeviceSize BufferMemoryAlignment; + VkPipelineCreateFlags PipelineCreateFlags; + VkDescriptorSetLayout DescriptorSetLayout; + VkPipelineLayout PipelineLayout; + VkPipeline Pipeline; + uint32_t Subpass; + VkShaderModule ShaderModuleVert; + VkShaderModule ShaderModuleFrag; + + // Font data + VkSampler FontSampler; + VkDeviceMemory FontMemory; + VkImage FontImage; + VkImageView FontView; + VkDescriptorSet FontDescriptorSet; + VkCommandPool FontCommandPool; + VkCommandBuffer FontCommandBuffer; + + // Render buffers for main window + ImGui_ImplVulkanH_WindowRenderBuffers MainWindowRenderBuffers; + + ImGui_ImplVulkan_Data() + { + memset((void*)this, 0, sizeof(*this)); + BufferMemoryAlignment = 256; + } +}; + //----------------------------------------------------------------------------- // SHADERS //----------------------------------------------------------------------------- -// glsl_shader.vert, compiled with: +// backends/vulkan/glsl_shader.vert, compiled with: // # glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert /* #version 450 core @@ -308,7 +310,7 @@ static uint32_t __glsl_shader_vert_spv[] = 0x0000002d,0x0000002c,0x000100fd,0x00010038 }; -// glsl_shader.frag, compiled with: +// backends/vulkan/glsl_shader.frag, compiled with: // # glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag /* #version 450 core From 4758f746761383d3c954532d71c713b483e0571d Mon Sep 17 00:00:00 2001 From: Pascal Thomet Date: Wed, 3 Jan 2024 22:54:36 +0100 Subject: [PATCH 046/237] imgui_freetype: fix nullptr to ImTextureID cast (#7192) --- misc/freetype/imgui_freetype.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index dcef17ff2a37..a78bd5e31a9a 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -437,7 +437,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u ImFontAtlasBuildInit(atlas); // Clear atlas - atlas->TexID = (ImTextureID)nullptr; + atlas->TexID = 0; atlas->TexWidth = atlas->TexHeight = 0; atlas->TexUvScale = ImVec2(0.0f, 0.0f); atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f); From 7938550d528132b4f4e6df8a5e7df25c949a38a6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 4 Jan 2024 11:50:38 +0100 Subject: [PATCH 047/237] Comments and some extra line-wrapping in demo (#3193) --- imgui.h | 1 + imgui_demo.cpp | 151 +++++++++++++++++++++++++++++++--------------- imgui_widgets.cpp | 2 + 3 files changed, 105 insertions(+), 49 deletions(-) diff --git a/imgui.h b/imgui.h index 44fab7dc0cc8..3a83a6331ea3 100644 --- a/imgui.h +++ b/imgui.h @@ -532,6 +532,7 @@ namespace ImGui // Widgets: Images // - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples + // - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above. // - Note that Image() may add +2.0f to provided size if a border is visible, ImageButton() adds style.FramePadding*2.0f to provided size. IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), const ImVec4& border_col = ImVec4(0, 0, 0, 0)); IMGUI_API bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 94972dd1ae35..a21843848b0d 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -54,7 +54,7 @@ // Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp. // Navigating this file: -// - In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. +// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. /* @@ -171,7 +171,8 @@ Index of this file: #define IM_MAX(A, B) (((A) >= (B)) ? (A) : (B)) #define IM_CLAMP(V, MN, MX) ((V) < (MN) ? (MN) : (V) > (MX) ? (MX) : (V)) -// Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall +// Enforce cdecl calling convention for functions called by the standard library, +// in case compilation settings changed the default to e.g. __vectorcall #ifndef IMGUI_CDECL #ifdef _MSC_VER #define IMGUI_CDECL __cdecl @@ -759,7 +760,8 @@ static void ShowDemoWindowWidgets() static int item_current = 0; ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items)); ImGui::SameLine(); HelpMarker( - "Using the simplified one-liner Combo API here.\nRefer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API."); + "Using the simplified one-liner Combo API here.\n" + "Refer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API."); } { @@ -770,7 +772,8 @@ static void ShowDemoWindowWidgets() static int item_current = 1; ImGui::ListBox("listbox", &item_current, items, IM_ARRAYSIZE(items), 4); ImGui::SameLine(); HelpMarker( - "Using the simplified one-liner ListBox API here.\nRefer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API."); + "Using the simplified one-liner ListBox API here.\n" + "Refer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API."); } ImGui::TreePop(); @@ -1088,7 +1091,7 @@ static void ShowDemoWindowWidgets() "CJK text will only appear if the font was loaded with the appropriate CJK character ranges. " "Call io.Fonts->AddFontFromFileTTF() manually to load extra character ranges. " "Read docs/FONTS.md for details."); - ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); // Normally we would use u8"blah blah" with the proper characters directly in the string. + ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)"); static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"; //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis @@ -1132,7 +1135,7 @@ static void ShowDemoWindowWidgets() ImVec2 pos = ImGui::GetCursorScreenPos(); ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right - ImVec4 tint_col = use_text_color_for_tint ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint + ImVec4 tint_col = use_text_color_for_tint ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint ImVec4 border_col = ImGui::GetStyleColorVec4(ImGuiCol_Border); ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col); if (ImGui::BeginItemTooltip()) @@ -1191,9 +1194,9 @@ static void ShowDemoWindowWidgets() ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", &flags, ImGuiComboFlags_PopupAlignLeft); ImGui::SameLine(); HelpMarker("Only makes a difference if the popup is larger than the combo"); if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", &flags, ImGuiComboFlags_NoArrowButton)) - flags &= ~ImGuiComboFlags_NoPreview; // Clear the other flag, as we cannot combine both + flags &= ~ImGuiComboFlags_NoPreview; // Clear incompatible flags if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", &flags, ImGuiComboFlags_NoPreview)) - flags &= ~(ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_WidthFitPreview); // Clear the other flag, as we cannot combine both + flags &= ~(ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_WidthFitPreview); // Clear incompatible flags if (ImGui::CheckboxFlags("ImGuiComboFlags_WidthFitPreview", &flags, ImGuiComboFlags_WidthFitPreview)) flags &= ~ImGuiComboFlags_NoPreview; @@ -1210,7 +1213,10 @@ static void ShowDemoWindowWidgets() // 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. - const char* combo_preview_value = items[item_current_idx]; // Pass in the preview value visible before opening the combo (it could be anything) + + // 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]; + if (ImGui::BeginCombo("combo 1", combo_preview_value, flags)) { for (int n = 0; n < IM_ARRAYSIZE(items); n++) @@ -1250,8 +1256,10 @@ static void ShowDemoWindowWidgets() IMGUI_DEMO_MARKER("Widgets/List Boxes"); if (ImGui::TreeNode("List boxes")) { - // BeginListBox() is essentially a thin wrapper to using BeginChild()/EndChild() with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label. - // You may be tempted to simply use BeginChild() directly, however note that BeginChild() requires EndChild() to always be called (inconsistent with BeginListBox()/EndListBox()). + // BeginListBox() is essentially a thin wrapper to using BeginChild()/EndChild() + // using the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label. + // You may be tempted to simply use BeginChild() directly. However note that BeginChild() requires EndChild() + // to always be called (inconsistent with BeginListBox()/EndListBox()). // Using the generic BeginListBox() API, you have full control over how to display the combo contents. // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively @@ -1570,16 +1578,21 @@ static void ShowDemoWindowWidgets() }; static char buf1[64]; ImGui::InputText("Completion", buf1, 64, ImGuiInputTextFlags_CallbackCompletion, Funcs::MyCallback); - ImGui::SameLine(); HelpMarker("Here we append \"..\" each time Tab is pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback."); + ImGui::SameLine(); HelpMarker( + "Here we append \"..\" each time Tab is pressed. " + "See 'Examples>Console' for a more meaningful demonstration of using this callback."); static char buf2[64]; ImGui::InputText("History", buf2, 64, ImGuiInputTextFlags_CallbackHistory, Funcs::MyCallback); - ImGui::SameLine(); HelpMarker("Here we replace and select text each time Up/Down are pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback."); + ImGui::SameLine(); HelpMarker( + "Here we replace and select text each time Up/Down are pressed. " + "See 'Examples>Console' for a more meaningful demonstration of using this callback."); static char buf3[64]; static int edit_count = 0; ImGui::InputText("Edit", buf3, 64, ImGuiInputTextFlags_CallbackEdit, Funcs::MyCallback, (void*)&edit_count); - ImGui::SameLine(); HelpMarker("Here we toggle the casing of the first character on every edit + count edits."); + ImGui::SameLine(); HelpMarker( + "Here we toggle the casing of the first character on every edit + count edits."); ImGui::SameLine(); ImGui::Text("(%d)", edit_count); ImGui::TreePop(); @@ -1754,8 +1767,9 @@ static void ShowDemoWindowWidgets() ImGui::EndPopup(); } - // Demo Trailing Tabs: click the "+" button to add a new tab (in your app you may want to use a font icon instead of the "+") - // Note that we submit it before the regular tabs, but because of the ImGuiTabItemFlags_Trailing flag it will always appear at the end. + // Demo Trailing Tabs: click the "+" button to add a new tab. + // (In your app you may want to use a font icon instead of the "+") + // We submit it before the regular tabs, but thanks to the ImGuiTabItemFlags_Trailing flag it will always appear at the end. if (show_trailing_button) if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip)) active_tabs.push_back(next_tab_id++); // Add new tab @@ -2039,7 +2053,8 @@ static void ShowDemoWindowWidgets() if (ImGui::Button("Default: Float + HDR + Hue Wheel")) ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel); - // Always both a small version of both types of pickers (to make it more visible in the demo to people who are skimming quickly through it) + // Always display a small version of both types of pickers + // (that's in order to make it more visible in the demo to people who are skimming quickly through it) ImGui::Text("Both types:"); float w = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.y) * 0.40f; ImGui::SetNextItemWidth(w); @@ -3381,7 +3396,9 @@ static void ShowDemoWindowLayout() IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal contents size demo window"); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 0)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 0)); - HelpMarker("Test of different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\nUse 'Metrics->Tools->Show windows rectangles' to visualize rectangles."); + HelpMarker( + "Test how different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\n" + "Use 'Metrics->Tools->Show windows rectangles' to visualize rectangles."); ImGui::Checkbox("H-scrollbar", &show_h_scrollbar); ImGui::Checkbox("Button", &show_button); // Will grow contents size (unless explicitly overwritten) ImGui::Checkbox("Tree nodes", &show_tree_nodes); // Will grow contents size and display highlight over full width @@ -3537,7 +3554,8 @@ static void ShowDemoWindowLayout() HelpMarker( "Hit-testing is by default performed in item submission order, which generally is perceived as 'back-to-front'.\n\n" - "By using SetNextItemAllowOverlap() you can notify that an item may be overlapped by another. Doing so alters the hovering logic: items using AllowOverlap mode requires an extra frame to accept hovered state."); + "By using SetNextItemAllowOverlap() you can notify that an item may be overlapped by another. " + "Doing so alters the hovering logic: items using AllowOverlap mode requires an extra frame to accept hovered state."); ImGui::Checkbox("Enable AllowOverlap", &enable_allow_overlap); ImVec2 button1_pos = ImGui::GetCursorScreenPos(); @@ -3924,7 +3942,8 @@ struct MyItem } // qsort() is instable so always return a way to differenciate items. - // Your own compare function may want to avoid fallback on implicit sort specs e.g. a Name compare if it wasn't already part of the sort specs. + // Your own compare function may want to avoid fallback on implicit sort specs. + // e.g. a Name compare if it wasn't already part of the sort specs. return (a->ID - b->ID); } }; @@ -4107,8 +4126,9 @@ static void ShowDemoWindowTables() // as TableNextColumn() will automatically wrap around and create new rows as needed. // This is generally more convenient when your cells all contains the same type of data. HelpMarker( - "Only using TableNextColumn(), which tends to be convenient for tables where every cell contains the same type of contents.\n" - "This is also more similar to the old NextColumn() function of the Columns API, and provided to facilitate the Columns->Tables API transition."); + "Only using TableNextColumn(), which tends to be convenient for tables where every cell contains " + "the same type of contents.\n This is also more similar to the old NextColumn() function of the " + "Columns API, and provided to facilitate the Columns->Tables API transition."); if (ImGui::BeginTable("table3", 3)) { for (int item = 0; item < 14; item++) @@ -4164,8 +4184,8 @@ static void ShowDemoWindowTables() if (ImGui::BeginTable("table1", 3, flags)) { - // Display headers so we can inspect their interaction with borders. - // (Headers are not the main purpose of this section of the demo, so we are not elaborating on them too much. See other sections for details) + // Display headers so we can inspect their interaction with borders + // (Headers are not the main purpose of this section of the demo, so we are not elaborating on them now. See other sections for details) if (display_headers) { ImGui::TableSetupColumn("One"); @@ -4204,7 +4224,9 @@ static void ShowDemoWindowTables() PushStyleCompact(); ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable); ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV); - ImGui::SameLine(); HelpMarker("Using the _Resizable flag automatically enables the _BordersInnerV flag as well, this is why the resize borders are still showing when unchecking this."); + ImGui::SameLine(); HelpMarker( + "Using the _Resizable flag automatically enables the _BordersInnerV flag as well, " + "this is why the resize borders are still showing when unchecking this."); PopStyleCompact(); if (ImGui::BeginTable("table1", 3, flags)) @@ -4345,7 +4367,8 @@ static void ShowDemoWindowTables() ImGui::EndTable(); } - // Use outer_size.x == 0.0f instead of default to make the table as tight as possible (only valid when no scrolling and no stretch column) + // Use outer_size.x == 0.0f instead of default to make the table as tight as possible + // (only valid when no scrolling and no stretch column) if (ImGui::BeginTable("table2", 3, flags | ImGuiTableFlags_SizingFixedFit, ImVec2(0.0f, 0.0f))) { ImGui::TableSetupColumn("One"); @@ -4378,7 +4401,8 @@ static void ShowDemoWindowTables() "e.g.:\n" "- BorderOuterV\n" "- any form of row selection\n" - "Because of this, activating BorderOuterV sets the default to PadOuterX. Using PadOuterX or NoPadOuterX you can override the default.\n\n" + "Because of this, activating BorderOuterV sets the default to PadOuterX. " + "Using PadOuterX or NoPadOuterX you can override the default.\n\n" "Actual padding values are using style.CellPadding.\n\n" "In this demo we don't show horizontal borders to emphasize how they don't affect default horizontal padding."); @@ -4494,7 +4518,8 @@ static void ShowDemoWindowTables() EditTableSizingFlags(&sizing_policy_flags[table_n]); // To make it easier to understand the different sizing policy, - // For each policy: we display one table where the columns have equal contents width, and one where the columns have different contents width. + // For each policy: we display one table where the columns have equal contents width, + // and one where the columns have different contents width. if (ImGui::BeginTable("table1", 3, sizing_policy_flags[table_n] | flags1)) { for (int row = 0; row < 3; row++) @@ -4523,7 +4548,9 @@ static void ShowDemoWindowTables() ImGui::Spacing(); ImGui::TextUnformatted("Advanced"); ImGui::SameLine(); - HelpMarker("This section allows you to interact and see the effect of various sizing policies depending on whether Scroll is enabled and the contents of your columns."); + HelpMarker( + "This section allows you to interact and see the effect of various sizing policies " + "depending on whether Scroll is enabled and the contents of your columns."); enum ContentsType { CT_ShowWidth, CT_ShortText, CT_LongText, CT_Button, CT_FillButton, CT_InputText }; static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable; @@ -4538,7 +4565,9 @@ static void ShowDemoWindowTables() if (contents_type == CT_FillButton) { ImGui::SameLine(); - HelpMarker("Be mindful that using right-alignment (e.g. size.x = -FLT_MIN) creates a feedback loop where contents width can feed into auto-column width can feed into contents width."); + HelpMarker( + "Be mindful that using right-alignment (e.g. size.x = -FLT_MIN) creates a feedback loop " + "where contents width can feed into auto-column width can feed into contents width."); } ImGui::DragInt("Columns", &column_count, 0.1f, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp); ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable); @@ -4584,7 +4613,9 @@ static void ShowDemoWindowTables() IMGUI_DEMO_MARKER("Tables/Vertical scrolling, with clipping"); if (ImGui::TreeNode("Vertical scrolling, with clipping")) { - HelpMarker("Here we activate ScrollY, which will create a child window container to allow hosting scrollable contents.\n\nWe also demonstrate using ImGuiListClipper to virtualize the submission of many items."); + HelpMarker( + "Here we activate ScrollY, which will create a child window container to allow hosting scrollable contents.\n\n" + "We also demonstrate using ImGuiListClipper to virtualize the submission of many items."); static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable; PushStyleCompact(); @@ -4630,8 +4661,9 @@ static void ShowDemoWindowTables() HelpMarker( "When ScrollX is enabled, the default sizing policy becomes ImGuiTableFlags_SizingFixedFit, " "as automatically stretching columns doesn't make much sense with horizontal scrolling.\n\n" - "Also note that as of the current version, you will almost always want to enable ScrollY along with ScrollX," - "because the container window won't automatically extend vertically to fix contents (this may be improved in future versions)."); + "Also note that as of the current version, you will almost always want to enable ScrollY along with ScrollX, " + "because the container window won't automatically extend vertically to fix contents " + "(this may be improved in future versions)."); static ImGuiTableFlags flags = ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable; static int freeze_cols = 1; static int freeze_rows = 1; @@ -4688,7 +4720,8 @@ static void ShowDemoWindowTables() HelpMarker( "Showcase using Stretch columns + ScrollX together: " "this is rather unusual and only makes sense when specifying an 'inner_width' for the table!\n" - "Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns + ScrollX together doesn't make sense."); + "Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns " + "along with ScrollX doesn't make sense."); static ImGuiTableFlags flags2 = ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg | ImGuiTableFlags_ContextMenuInBody; static float inner_width = 1000.0f; PushStyleCompact(); @@ -4746,8 +4779,9 @@ static void ShowDemoWindowTables() } // Create the real table we care about for the example! - // We use a scrolling table to be able to showcase the difference between the _IsEnabled and _IsVisible flags above, otherwise in - // a non-scrolling table columns are always visible (unless using ImGuiTableFlags_NoKeepColumnsVisible + resizing the parent window down) + // We use a scrolling table to be able to showcase the difference between the _IsEnabled and _IsVisible flags above, + // otherwise in a non-scrolling table columns are always visible (unless using ImGuiTableFlags_NoKeepColumnsVisible + // + resizing the parent window down). const ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV @@ -4769,7 +4803,8 @@ static void ShowDemoWindowTables() float indent_step = (float)((int)TEXT_BASE_WIDTH / 2); for (int row = 0; row < 8; row++) { - ImGui::Indent(indent_step); // Add some indentation to demonstrate usage of per-column IndentEnable/IndentDisable flags. + // Add some indentation to demonstrate usage of per-column IndentEnable/IndentDisable flags. + ImGui::Indent(indent_step); ImGui::TableNextRow(); for (int column = 0; column < column_count; column++) { @@ -4818,7 +4853,9 @@ static void ShowDemoWindowTables() ImGui::EndTable(); } - HelpMarker("Using TableSetupColumn() to setup explicit width.\n\nUnless _NoKeepColumnsVisible is set, fixed columns with set width may still be shrunk down if there's not enough space in the host."); + HelpMarker( + "Using TableSetupColumn() to setup explicit width.\n\nUnless _NoKeepColumnsVisible is set, " + "fixed columns with set width may still be shrunk down if there's not enough space in the host."); static ImGuiTableFlags flags2 = ImGuiTableFlags_None; PushStyleCompact(); @@ -4828,7 +4865,8 @@ static void ShowDemoWindowTables() PopStyleCompact(); if (ImGui::BeginTable("table2", 4, flags2)) { - // We could also set ImGuiTableFlags_SizingFixedFit on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed. + // We could also set ImGuiTableFlags_SizingFixedFit on the table and then all columns + // will default to ImGuiTableColumnFlags_WidthFixed. ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 100.0f); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 30.0f); @@ -4900,7 +4938,10 @@ static void ShowDemoWindowTables() IMGUI_DEMO_MARKER("Tables/Row height"); if (ImGui::TreeNode("Row height")) { - HelpMarker("You can pass a 'min_row_height' to TableNextRow().\n\nRows are padded with 'style.CellPadding.y' on top and bottom, so effectively the minimum row height will always be >= 'style.CellPadding.y * 2.0f'.\n\nWe cannot honor a _maximum_ row height as that would require a unique clipping rectangle per row."); + HelpMarker( + "You can pass a 'min_row_height' to TableNextRow().\n\nRows are padded with 'style.CellPadding.y' on top and bottom, " + "so effectively the minimum row height will always be >= 'style.CellPadding.y * 2.0f'.\n\n" + "We cannot honor a _maximum_ row height as that would require a unique clipping rectangle per row."); if (ImGui::BeginTable("table_row_height", 1, ImGuiTableFlags_Borders)) { for (int row = 0; row < 8; row++) @@ -4913,7 +4954,10 @@ static void ShowDemoWindowTables() ImGui::EndTable(); } - HelpMarker("Showcase using SameLine(0,0) to share Current Line Height between cells.\n\nPlease note that Tables Row Height is not the same thing as Current Line Height, as a table cell may contains multiple lines."); + HelpMarker( + "Showcase using SameLine(0,0) to share Current Line Height between cells.\n\n" + "Please note that Tables Row Height is not the same thing as Current Line Height, " + "as a table cell may contains multiple lines."); if (ImGui::BeginTable("table_share_lineheight", 2, ImGuiTableFlags_Borders)) { ImGui::TableNextRow(); @@ -5163,7 +5207,8 @@ static void ShowDemoWindowTables() { HelpMarker( "Showcase using PushItemWidth() and how it is preserved on a per-column basis.\n\n" - "Note that on auto-resizing non-resizable fixed columns, querying the content width for e.g. right-alignment doesn't make sense."); + "Note that on auto-resizing non-resizable fixed columns, querying the content width for " + "e.g. right-alignment doesn't make sense."); if (ImGui::BeginTable("table_item_width", 3, ImGuiTableFlags_Borders)) { ImGui::TableSetupColumn("small"); @@ -5302,13 +5347,16 @@ static void ShowDemoWindowTables() ImGui::TreePop(); } - // Demonstrate creating custom context menus inside columns, while playing it nice with context menus provided by TableHeadersRow()/TableHeader() + // Demonstrate creating custom context menus inside columns, + // while playing it nice with context menus provided by TableHeadersRow()/TableHeader() if (open_action != -1) ImGui::SetNextItemOpen(open_action != 0); IMGUI_DEMO_MARKER("Tables/Context menus"); if (ImGui::TreeNode("Context menus")) { - HelpMarker("By default, right-clicking over a TableHeadersRow()/TableHeader() line will open the default context-menu.\nUsing ImGuiTableFlags_ContextMenuInBody we also allow right-clicking over columns body."); + HelpMarker( + "By default, right-clicking over a TableHeadersRow()/TableHeader() line will open the default context-menu.\n" + "Using ImGuiTableFlags_ContextMenuInBody we also allow right-clicking over columns body."); static ImGuiTableFlags flags1 = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ContextMenuInBody; PushStyleCompact(); @@ -5345,7 +5393,9 @@ static void ShowDemoWindowTables() // [2.1] Right-click on the TableHeadersRow() line to open the default table context menu. // [2.2] Right-click on the ".." to open a custom popup // [2.3] Right-click in columns to open another custom popup - HelpMarker("Demonstrate mixing table context menu (over header), item context button (over button) and custom per-colum context menu (over column body)."); + HelpMarker( + "Demonstrate mixing table context menu (over header), item context button (over button) " + "and custom per-colunm context menu (over column body)."); ImGuiTableFlags flags2 = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders; if (ImGui::BeginTable("table_context_menu_2", COLUMNS_COUNT, flags2)) { @@ -5804,7 +5854,7 @@ static void ShowDemoWindowTables() // Here we demonstrate marking our data set as needing to be sorted again if we modified a quantity, // and we are currently sorting on the column showing the Quantity. // To avoid triggering a sort while holding the button, we only trigger it when the button has been released. - // You will probably need a more advanced system in your code if you want to automatically sort when a specific entry changes. + // You will probably need some extra logic if you want to automatically sort when a specific entry changes. if (ImGui::TableSetColumnIndex(2)) { if (ImGui::SmallButton("Chop")) { item->Quantity += 1; } @@ -6092,8 +6142,10 @@ static void ShowDemoWindowInputs() for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDown(i)) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); } ImGui::Text("Mouse wheel: %.1f", io.MouseWheel); - // We iterate both legacy native range and named ImGuiKey ranges, which is a little odd but this allows displaying the data for old/new backends. - // User code should never have to go through such hoops! You can generally iterate between ImGuiKey_NamedKey_BEGIN and ImGuiKey_NamedKey_END. + // We iterate both legacy native range and named ImGuiKey ranges. This is a little unusual/odd but this allows + // displaying the data for old/new backends. + // User code should never have to go through such hoops! + // You can generally iterate between ImGuiKey_NamedKey_BEGIN and ImGuiKey_NamedKey_END. #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } }; ImGuiKey start_key = ImGuiKey_NamedKey_BEGIN; @@ -6132,7 +6184,8 @@ static void ShowDemoWindowInputs() { HelpMarker( "Hovering the colored canvas will override io.WantCaptureXXX fields.\n" - "Notice how normally (when set to none), the value of io.WantCaptureKeyboard would be false when hovering and true when clicking."); + "Notice how normally (when set to none), the value of io.WantCaptureKeyboard would be false when hovering " + "and true when clicking."); static int capture_override_mouse = -1; static int capture_override_keyboard = -1; const char* capture_override_desc[] = { "None", "Set to false", "Set to true" }; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 2ded6913a6ae..12abfeab1193 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1007,6 +1007,8 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6 return held; } +// - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples +// - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above. void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) { ImGuiWindow* window = GetCurrentWindow(); From 26eef4df871819e21a0d5132aca321cac693fa05 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 4 Jan 2024 15:15:48 +0100 Subject: [PATCH 048/237] Update issue_template.md --- .github/issue_template.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/issue_template.md b/.github/issue_template.md index 0172e093e331..b6b248ce75e8 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,16 +1,14 @@ -(Click "Preview" above ^ to turn URL into clickable links) +(Click ^^^ "Preview" ^^^ above to turn URL into clickable links) -1. FOR FIRST-TIME USERS PROBLEMS COMPILING/LINKING/RUNNING or LOADING FONTS, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions). EVERYTHING ELSE CAN BE POSTED HERE! - -2. PLEASE CAREFULLY READ: [FAQ](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md) - -3. PLEASE CAREFULLY READ: [Contributing Guidelines](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md) +FOR FIRST-TIME USERS PROBLEMS COMPILING/LINKING/RUNNING or LOADING FONTS, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions). For anything else: we are happy to use 'Issues' for many type of open-ended questions. We are encouraging 'Issues' becoming a large, centralized and cross-referenced database of Dear ImGui contents. +1. PLEASE CAREFULLY READ: [FAQ](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md) +2. PLEASE CAREFULLY READ: [Contributing Guidelines -> General Advices](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#getting-started--general-advice) +3. PLEASE CAREFULLY READ: [Contributing Guidelines -> How to open an Issue](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#how-to-open-an-issue) 4. PLEASE MAKE SURE that you have: read the FAQ; explored the contents of `ShowDemoWindow()` including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the links above. - 5. Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users. -6. Delete points 1-6 and PLEASE FILL THE TEMPLATE BELOW before submitting your issue. +Delete points 1-5 above and PLEASE FILL THE TEMPLATE BELOW before submitting your issue. Thank you! @@ -37,7 +35,7 @@ XXX _(please provide as much context as possible)_ XXX _(you can drag files here)_ -**Standalone, minimal, complete and verifiable example:** _(see https://github.com/ocornut/imgui/issues/2261)_ +**Standalone, minimal, complete and verifiable example:** _(see https://stackoverflow.com/help/minimal-reproducible-example)_ ``` // Here's some code anyone can copy and paste to reproduce your issue ImGui::Begin("Example Bug"); From c528b688cf4a7a9a9aa74d0e31a3a4d372c9bc6c Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 4 Jan 2024 16:38:58 +0100 Subject: [PATCH 049/237] Reworked issue template. (#5927, #5915) --- .github/ISSUE_TEMPLATE/config.yml | 1 + .github/ISSUE_TEMPLATE/issue_template.yml | 104 ++++++++++++++++++++++ .github/issue_template.md | 44 --------- 3 files changed, 105 insertions(+), 44 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/issue_template.yml delete mode 100644 .github/issue_template.md diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000000..3ba13e0cec6c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/issue_template.yml b/.github/ISSUE_TEMPLATE/issue_template.yml new file mode 100644 index 000000000000..6574855870f4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue_template.yml @@ -0,0 +1,104 @@ +name: "Ask a question, report a bug, request a feature, etc." +description: "Ask any question, discuss best practices, report a bug, request a feature." +body: + - type: markdown + attributes: + value: | + FOR FIRST-TIME USERS ISSUES COMPILING/LINKING/RUNNING or LOADING FONTS, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions) + For anything else: we are happy to use 'GitHub Issues' for many types of open-ended questions. We are encouraging 'Issues' becoming a large, centralized and cross-referenced database of Dear ImGui contents. + + Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users. + - type: markdown + attributes: + value: | + **Prerequisites:** + - I have read [Frequently Asked Questions](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md). + - I have read [Contributing Guidelines -> General Advices](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#getting-started--general-advice). + - I have read [Contributing Guidelines -> How to open an Issue](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#how-to-open-an-issue). + - I have searched [Github Issues and PR](https://github.com/ocornut/imgui/issues?q=) for discussion of similar topics. + - type: input + id: specs_version + attributes: + label: "Version/Branch of Dear ImGui:" + description: "(please specify if you have made substantial modifications to your copy)" + value: "Version 1.XX, Branch: XXX (master/docking/etc.)" + placeholder: "Version 1.XX, Branch: XXX (master/docking/etc.)" + validations: + required: true + - type: input + id: specs_backend_platform + attributes: + label: "Platform back-end:" + description: (or specify if using a custom engine/back-end) + value: "imgui_impl_XXX.cpp" + placeholder: "imgui_impl_XXX.cpp or n/a" + validations: + required: true + - type: input + id: specs_backend_rendering + attributes: + label: "Rendering back-end:" + description: (or specify if using a custom engine/back-end) + value: "imgui_impl_XXX.cpp" + placeholder: "imgui_impl_XXX.cpp or n/a" + validations: + required: true + - type: input + id: specs_compiler + attributes: + label: "Compiler:" + placeholder: "e.g. MSVC 2022, GCC, Clang 12.0 etc." + validations: + required: true + - type: input + id: specs_os + attributes: + label: "Operating System:" + placeholder: "e.g. Windows 11, macOS, Android, GNU/Linux etc." + validations: + required: true + - type: textarea + id: specs_full + attributes: + label: "Full config/build information:" + placeholder: | + "If you can run, you may go to 'Demo->Tools->About Dear ImGui->Config/Build Info' to obtain detailed information that you can paste here." + validations: + required: false + - type: textarea + id: issue_description + attributes: + label: "Details:" + description: "Try to be explicit with your goals, your expectations and what you have tried. Be mindful of [The XY Problem](https://xyproblem.info). What you have in mind or in your code is not obvious to other people. People frequently discuss problems and suggest incorrect solutions without first clarifying their goals. When requesting a new feature, please describe the usage context (how you intend to use it, why you need it, etc.). If you tried something and it failed, show us what you tried. If you are reporting a bug, explain what's the bug, how does it occur, etc. If you are reporting a crash, please include a debugger callstack." + value: | + **My Issue/Question:** + + XXX _(please provide as much context as possible)_ + validations: + required: true + - type: textarea + id: screenshots + attributes: + label: "Screenshots/Video:" + description: "Attach screenshots or gif/videos to clarify the context. They often convey useful information that is omitted by the description." + placeholder: "(You can drag files here)" + validations: + required: false + - type: textarea + id: repro_code + attributes: + label: "Minimal, Complete and Verifiable Example code:" + description: "Provide an [MCVE](https://stackoverflow.com/help/mcve) to demonstrate your problem. An ideal submission includes a small piece of code that anyone can paste into one of the examples applications (examples/*/main.cpp) or the demo (imgui_demo.cpp) to understand and reproduce it. Narrowing your problem to its shortest and purest form is the easiest way to understand it, explain it and fix it. Please test your shortened code to ensure it exhibits the problem. Often while creating the MCVE you will solve the problem! Many questions that are missing a standalone verifiable example are missing the actual cause of their issue in the description, which ends up wasting everyone's time." + value: | + ```cpp + // Here's some code anyone can copy and paste to reproduce your issue + ImGui::Begin("Example Bug"); + MoreCodeToExplainMyIssue(); + ImGui::End(); + ``` + validations: + required: false + - type: markdown + attributes: + value: | + Thank you for taking the time to read prerequisites, filling this template and double-checking your message and your code! diff --git a/.github/issue_template.md b/.github/issue_template.md deleted file mode 100644 index b6b248ce75e8..000000000000 --- a/.github/issue_template.md +++ /dev/null @@ -1,44 +0,0 @@ -(Click ^^^ "Preview" ^^^ above to turn URL into clickable links) - -FOR FIRST-TIME USERS PROBLEMS COMPILING/LINKING/RUNNING or LOADING FONTS, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions). For anything else: we are happy to use 'Issues' for many type of open-ended questions. We are encouraging 'Issues' becoming a large, centralized and cross-referenced database of Dear ImGui contents. - -1. PLEASE CAREFULLY READ: [FAQ](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md) -2. PLEASE CAREFULLY READ: [Contributing Guidelines -> General Advices](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#getting-started--general-advice) -3. PLEASE CAREFULLY READ: [Contributing Guidelines -> How to open an Issue](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#how-to-open-an-issue) -4. PLEASE MAKE SURE that you have: read the FAQ; explored the contents of `ShowDemoWindow()` including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the links above. -5. Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users. - -Delete points 1-5 above and PLEASE FILL THE TEMPLATE BELOW before submitting your issue. - -Thank you! - ----- - -_(you may also go to Demo>About Window, and click "Config/Build Information" to obtain a bunch of detailed information that you can paste here)_ - -**Version/Branch of Dear ImGui:** - -Version: XXX -Branch: XXX _(master/viewport/docking/etc.)_ - -**Back-end/Renderer/Compiler/OS** - -Back-ends: imgui_impl_XXX.cpp + imgui_impl_XXX.cpp _(or specify if using a custom engine/back-end)_ -Compiler: XXX _(if the question is related to building or platform specific features)_ -Operating System: XXX - -**My Issue/Question:** - -XXX _(please provide as much context as possible)_ - -**Screenshots/Video** - -XXX _(you can drag files here)_ - -**Standalone, minimal, complete and verifiable example:** _(see https://stackoverflow.com/help/minimal-reproducible-example)_ -``` -// Here's some code anyone can copy and paste to reproduce your issue -ImGui::Begin("Example Bug"); -MoreCodeToExplainMyIssue(); -ImGui::End(); -``` From 0461ade24baf1728360cad1af266be0be20ec480 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 4 Jan 2024 16:51:10 +0100 Subject: [PATCH 050/237] Reworked issue template (amends) (#5927, #5915) --- .github/ISSUE_TEMPLATE/issue_template.yml | 4 +++- docs/CHANGELOG.txt | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/issue_template.yml b/.github/ISSUE_TEMPLATE/issue_template.yml index 6574855870f4..36ee1ee20a99 100644 --- a/.github/ISSUE_TEMPLATE/issue_template.yml +++ b/.github/ISSUE_TEMPLATE/issue_template.yml @@ -16,6 +16,8 @@ body: - I have read [Contributing Guidelines -> General Advices](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#getting-started--general-advice). - I have read [Contributing Guidelines -> How to open an Issue](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#how-to-open-an-issue). - I have searched [Github Issues and PR](https://github.com/ocornut/imgui/issues?q=) for discussion of similar topics. + + ---- - type: input id: specs_version attributes: @@ -62,7 +64,7 @@ body: attributes: label: "Full config/build information:" placeholder: | - "If you can run, you may go to 'Demo->Tools->About Dear ImGui->Config/Build Info' to obtain detailed information that you can paste here." + (If you can run, you may go to 'Demo->Tools->About Dear ImGui->Config/Build Info' to obtain detailed information that you can paste here) validations: required: false - type: textarea diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 291030a9abcc..12e437ac97a3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -93,6 +93,7 @@ Other changes: on a codebase where another copy of the library is used. - Misc: During shutdown, check that io.BackendPlatformUserData and io.BackendRendererUserData are NULL in order to catch cases where backend was not shut down. (#7175) +- Misc: Reworked Issue Template to with a shinier and better form. (#5927) [@Panquesito7, @PathogenDavid, @ocornut] - Backends: GLFW, Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to register canvas selector and auto-resize GLFW window. (#6751) [@Traveller23, @ypujante] - Backends: GLFW: Fixed Windows specific hooks to use Unicode version of WndProc even when From a1b06823fe2d964a62fda99385499b218cf5cea5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 4 Jan 2024 17:23:30 +0100 Subject: [PATCH 051/237] Windows: BeginChild(): Resize borders rendered even when ImGuiWindowFlags_NoBackground is specified. (#1710, #7194) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 36 ++++++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 12e437ac97a3..2369ea326d92 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,6 +56,8 @@ Other changes: - Windows: BeginChild(): Fixed auto-resizing erroneously limiting size to host viewport minus padding. There are no limit to a child width/height. (#7063) [@Devyre] +- Windows: BeginChild(): Resize borders rendered even when ImGuiWindowFlags_NoBackground + is specified. (#1710, #7194) - Windows: Fixed some auto-resizing path using style.WindowMinSize.x (instead of x/y) for both axises since 1.90. (#7106) [@n0bodysec] - Scrolling: internal scrolling value is rounded instead of truncated, as a way to reduce diff --git a/imgui.cpp b/imgui.cpp index f5dc8f02f50f..11cdce207c9c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6082,28 +6082,40 @@ static inline void ClampWindowPos(ImGuiWindow* window, const ImRect& visibility_ window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max); } +static void RenderWindowOuterSingleBorder(ImGuiWindow* window, int border_n, ImU32 border_col, float border_size) +{ + const ImGuiResizeBorderDef& def = resize_border_def[border_n]; + const float rounding = window->WindowRounding; + const ImRect border_r = GetResizeBorderRect(window, border_n, rounding, 0.0f); + window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI * 0.25f, def.OuterAngle); + window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN2) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle, def.OuterAngle + IM_PI * 0.25f); + window->DrawList->PathStroke(border_col, ImDrawFlags_None, border_size); +} + static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window) { ImGuiContext& g = *GImGui; - float rounding = window->WindowRounding; - float border_size = window->WindowBorderSize; - if (border_size > 0.0f && !(window->Flags & ImGuiWindowFlags_NoBackground)) - window->DrawList->AddRect(window->Pos, window->Pos + window->Size, GetColorU32(ImGuiCol_Border), rounding, 0, border_size); - + const float border_size = window->WindowBorderSize; + const ImU32 border_col = GetColorU32(ImGuiCol_Border); + if (border_size > 0.0f && (window->Flags & ImGuiWindowFlags_NoBackground) == 0) + window->DrawList->AddRect(window->Pos, window->Pos + window->Size, border_col, window->WindowRounding, 0, window->WindowBorderSize); + else if (border_size > 0.0f) + { + if (window->ChildFlags & ImGuiChildFlags_ResizeX) // Similar code as 'resize_border_mask' computation in UpdateWindowManualResize() but we specifically only always draw explicit child resize border. + RenderWindowOuterSingleBorder(window, 1, border_col, border_size); + if (window->ChildFlags & ImGuiChildFlags_ResizeY) + RenderWindowOuterSingleBorder(window, 3, border_col, border_size); + } if (window->ResizeBorderHovered != -1 || window->ResizeBorderHeld != -1) { const int border_n = (window->ResizeBorderHeld != -1) ? window->ResizeBorderHeld : window->ResizeBorderHovered; - const ImGuiResizeBorderDef& def = resize_border_def[border_n]; - const ImRect border_r = GetResizeBorderRect(window, border_n, rounding, 0.0f); - const ImU32 border_col = GetColorU32((window->ResizeBorderHeld != -1) ? ImGuiCol_SeparatorActive : ImGuiCol_SeparatorHovered); - window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI * 0.25f, def.OuterAngle); - window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN2) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle, def.OuterAngle + IM_PI * 0.25f); - window->DrawList->PathStroke(border_col, 0, ImMax(2.0f, border_size)); // Thicker than usual + const ImU32 border_col_resizing = GetColorU32((window->ResizeBorderHeld != -1) ? ImGuiCol_SeparatorActive : ImGuiCol_SeparatorHovered); + RenderWindowOuterSingleBorder(window, border_n, border_col_resizing, ImMax(2.0f, window->WindowBorderSize)); // Thicker than usual } if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) { float y = window->Pos.y + window->TitleBarHeight() - 1; - window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), GetColorU32(ImGuiCol_Border), g.Style.FrameBorderSize); + window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), border_col, g.Style.FrameBorderSize); } } From c6716f5e9f7863ae6a5f65114de58fd940a0f39a Mon Sep 17 00:00:00 2001 From: uusdnfdsfhnttyh <142380608+uusdnfdsfhnttyh@users.noreply.github.com> Date: Fri, 5 Jan 2024 03:11:08 -0600 Subject: [PATCH 052/237] Fixed typo (#7197) --- docs/FAQ.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index 012d2ce43ff9..c86cc1368bbe 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -426,7 +426,7 @@ Finally, you may call `ImGui::ShowMetricsWindow()` to explore/visualize/understa ### Q: How can I use maths operators with ImVec2? -We do not export maths operators by default in imgui.h in order to not conflict with the use of your own maths types and maths operators. As a convenience, you may use `#defne IMGUI_DEFINE_MATH_OPERATORS` + `#include "imgui.h"` to access our basic maths operators. +We do not export maths operators by default in imgui.h in order to not conflict with the use of your own maths types and maths operators. As a convenience, you may use `#define IMGUI_DEFINE_MATH_OPERATORS` + `#include "imgui.h"` to access our basic maths operators. ##### [Return to Index](#index) From edeb8ee3ab9abc3870ce122a9c7d7399d6a63d68 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 5 Jan 2024 11:42:22 +0100 Subject: [PATCH 053/237] More compact issue_template.yml --- .github/ISSUE_TEMPLATE/issue_template.yml | 32 ++++++----------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/issue_template.yml b/.github/ISSUE_TEMPLATE/issue_template.yml index 36ee1ee20a99..792d8f63ed49 100644 --- a/.github/ISSUE_TEMPLATE/issue_template.yml +++ b/.github/ISSUE_TEMPLATE/issue_template.yml @@ -28,35 +28,19 @@ body: validations: required: true - type: input - id: specs_backend_platform + id: specs_backend attributes: - label: "Platform back-end:" - description: (or specify if using a custom engine/back-end) - value: "imgui_impl_XXX.cpp" - placeholder: "imgui_impl_XXX.cpp or n/a" + label: "Back-ends:" + description: (or specify when using custom engine/back-ends) + value: "imgui_impl_XXX.cpp + imgui_impl_XXX.cpp" + placeholder: "imgui_impl_XXX.cpp + imgui_impl_XXX.cpp or n/a" validations: required: true - type: input - id: specs_backend_rendering + id: specs_compiler_os attributes: - label: "Rendering back-end:" - description: (or specify if using a custom engine/back-end) - value: "imgui_impl_XXX.cpp" - placeholder: "imgui_impl_XXX.cpp or n/a" - validations: - required: true - - type: input - id: specs_compiler - attributes: - label: "Compiler:" - placeholder: "e.g. MSVC 2022, GCC, Clang 12.0 etc." - validations: - required: true - - type: input - id: specs_os - attributes: - label: "Operating System:" - placeholder: "e.g. Windows 11, macOS, Android, GNU/Linux etc." + label: "Compiler, OS:" + placeholder: "e.g. Windows 11 + MSVC 2022, macOS + Clang 12, Linux + GCC etc." validations: required: true - type: textarea From 278cf1a7bc38d8fc4a371ffc21191e154a05b118 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 5 Jan 2024 16:45:22 +0100 Subject: [PATCH 054/237] Readme: updated binaries. (#7193) + removed two now unnecessary casts. --- docs/README.md | 2 +- imgui.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index cf8921c86e92..5c88b0eed4b6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -110,7 +110,7 @@ Reading the changelogs is a good way to keep up to date with the things Dear ImG Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing a variety of features and examples. The code is always available for reference in `imgui_demo.cpp`. [Here's how the demo looks](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/v167-misc.png). You should be able to build the examples from sources. If you don't, let us know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here: -- [imgui-demo-binaries-20230704.zip](https://www.dearimgui.com/binaries/imgui-demo-binaries-20230704.zip) (Windows, 1.89.7, built 2023/07/04, master) or [older binaries](https://www.dearimgui.com/binaries). +- [imgui-demo-binaries-20240105.zip](https://www.dearimgui.com/binaries/imgui-demo-binaries-20240105.zip) (Windows, 1.90.1 WIP, built 2024/01/05, master) or [older binaries](https://www.dearimgui.com/binaries). The demo applications are not DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at a different scale and scale your style with `style.ScaleAllSizes()` (see [FAQ](https://www.dearimgui.com/faq)). diff --git a/imgui.cpp b/imgui.cpp index 11cdce207c9c..81be26d9c297 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9298,7 +9298,7 @@ bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiIn ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); if (key == ImGuiKey_None) key = ConvertSingleModFlagToKey(&g, mods); - if (!IsKeyPressed(key, owner_id, (flags & (ImGuiInputFlags_Repeat | (ImGuiInputFlags)ImGuiInputFlags_RepeatRateMask_)))) + if (!IsKeyPressed(key, owner_id, (flags & (ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_)))) return false; return true; } @@ -11847,7 +11847,7 @@ void ImGui::NavUpdateCreateMoveRequest() g.NavMoveScrollFlags = ImGuiScrollFlags_None; if (window && !g.NavWindowingTarget && !(window->Flags & ImGuiWindowFlags_NoNavInputs)) { - const ImGuiInputFlags repeat_mode = ImGuiInputFlags_Repeat | (ImGuiInputFlags)ImGuiInputFlags_RepeatRateNavMove; + const ImGuiInputFlags repeat_mode = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateNavMove; if (!IsActiveIdUsingNavDir(ImGuiDir_Left) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadLeft, ImGuiKeyOwner_None, repeat_mode)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_LeftArrow, ImGuiKeyOwner_None, repeat_mode)))) { g.NavMoveDir = ImGuiDir_Left; } if (!IsActiveIdUsingNavDir(ImGuiDir_Right) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadRight, ImGuiKeyOwner_None, repeat_mode)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_RightArrow, ImGuiKeyOwner_None, repeat_mode)))) { g.NavMoveDir = ImGuiDir_Right; } if (!IsActiveIdUsingNavDir(ImGuiDir_Up) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadUp, ImGuiKeyOwner_None, repeat_mode)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_UpArrow, ImGuiKeyOwner_None, repeat_mode)))) { g.NavMoveDir = ImGuiDir_Up; } From 27e83c29537b74b226b313c7b1ec061fc8a652e5 Mon Sep 17 00:00:00 2001 From: Tom Seddon Date: Mon, 8 Jan 2024 10:37:38 +0000 Subject: [PATCH 055/237] Add comment about how ImGuiKey values are named after US keyboard keys. (#7205) General text input is already covered by AddInputCharacter. For scancode-based key up/down info, simplest to admit that the up/down state indexes are kind of arbitrary and may not actually map perfectly to the labels on the keys. --- imgui.h | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.h b/imgui.h index 3a83a6331ea3..3909dfa1d918 100644 --- a/imgui.h +++ b/imgui.h @@ -1306,6 +1306,7 @@ enum ImGuiSortDirection_ // Since >= 1.89 we increased typing (went from int to enum), some legacy code may need a cast to ImGuiKey. // Read details about the 1.87 and 1.89 transition : https://github.com/ocornut/imgui/issues/4921 // Note that "Keys" related to physical keys and are not the same concept as input "Characters", the later are submitted via io.AddInputCharacter(). +// The keyboard key enum values are named after the keys on a standard US keyboard, and on other keyboard types the keys reported may not match the keycaps. enum ImGuiKey : int { // Keyboard From 7f9533b8400120faa23e2cca7eec53e97e4143a9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 5 Jan 2024 17:23:42 +0100 Subject: [PATCH 056/237] ColorPicker: Fixed saturation/value cursor radius not scaling properly. + Misc docs/comments. --- docs/CHANGELOG.txt | 7 ++++--- imgui.cpp | 6 ++++-- imgui_widgets.cpp | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2369ea326d92..7b1d5fdda5df 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -42,8 +42,6 @@ HOW TO UPDATE? Breaking changes: -- DragScalarN, SliderScalarN, InputScalarN: Fixed incorrect pushes into ItemWidth - stack when number of components is 1. [#7095] [@Nahor] - imgui_freetype: commented out ImGuiFreeType::BuildFontAtlas() obsoleted in 1.81. Prefer using #define IMGUI_ENABLE_FREETYPE or see commented code for manual calls. - Removed CalcListClipping() marked obsolete in 1.86. (#3841) @@ -72,12 +70,15 @@ Other changes: - InputTextMultiline: Tabbing through a multi-line text editor which allows Tab character inputs (using the ImGuiInputTextFlags_AllowTabInput flag) doesn't automatically activate it, in order to allow passing through multiple widgets easily. (#3092, #5759, #787) +- DragScalarN, SliderScalarN, InputScalarN: Fixed incorrect pushes into ItemWidth + stack when number of components is 1. [#7095] [@Nahor] - Drags, Sliders, Inputs: removed all attempts to filter non-numerical characters during text editing. Invalid inputs not applied to value, visibly reverted after validation. (#6810, #7096) - Drags, Sliders, Inputs: removal of filter means that "nan" and "inf" values may be input. (#7096) - DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: improve multi-components width computation to better distribute the error. (#7120, #7121) [@Nahor] -- ColorEdit4: Layout tweaks for very small sizes. (#7120, #7121) +- ColorEdit: Layout tweaks for very small sizes. (#7120, #7121) +- ColorPicker: Fixed saturation/value cursor radius not scaling properly. - Menus: Tweaked hover slack logic, adding a timer to avoid situations where a slow vertical movements toward another parent BeginMenu() can keep the wrong child menu open. (#6671, #6926) - Settings: Fixed an issue marking settings as dirty when merely clicking on a border or resize diff --git a/imgui.cpp b/imgui.cpp index 81be26d9c297..2e9c7f41a8a2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8721,7 +8721,9 @@ static void ImGui::UpdateKeyboardInputs() GetKeyData(ImGuiMod_Super)->Down = io.KeySuper; } } +#endif + // Import legacy ImGuiNavInput_ io inputs and convert to gamepad keys #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; if (io.BackendUsingLegacyNavInputArray && nav_gamepad_active) @@ -8744,7 +8746,6 @@ static void ImGui::UpdateKeyboardInputs() MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickDown, ImGuiNavInput_LStickDown); #undef NAV_MAP_KEY } -#endif #endif // Update aliases @@ -8753,7 +8754,7 @@ static void ImGui::UpdateKeyboardInputs() UpdateAliasKey(ImGuiKey_MouseWheelX, io.MouseWheelH != 0.0f, io.MouseWheelH); UpdateAliasKey(ImGuiKey_MouseWheelY, io.MouseWheel != 0.0f, io.MouseWheel); - // Synchronize io.KeyMods and io.KeyXXX values. + // Synchronize io.KeyMods and io.KeyCtrl/io.KeyShift/etc. values. // - New backends (1.87+): send io.AddKeyEvent(ImGuiMod_XXX) -> -> (here) deriving io.KeyMods + io.KeyXXX from key array. // - Legacy backends: set io.KeyXXX bools -> (above) set key array from io.KeyXXX -> (here) deriving io.KeyMods + io.KeyXXX from key array. // So with legacy backends the 4 values will do a unnecessary back-and-forth but it makes the code simpler and future facing. @@ -8790,6 +8791,7 @@ static void ImGui::UpdateKeyboardInputs() owner_data->LockThisFrame = owner_data->LockUntilRelease = owner_data->LockUntilRelease && key_data->Down; // Clear LockUntilRelease when key is not Down anymore } + // Update key routing (for e.g. shortcuts) UpdateKeyRoutingTable(&g.KeysRoutingTable); } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 12abfeab1193..3bd656e079de 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5714,7 +5714,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl } // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range) - float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f; + float sv_cursor_rad = value_changed_sv ? wheel_thickness * 0.55f : wheel_thickness * 0.40f; int sv_cursor_segments = draw_list->_CalcCircleAutoSegmentCount(sv_cursor_rad); // Lock segment count so the +1 one matches others. draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, sv_cursor_segments); draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad + 1, col_midgrey, sv_cursor_segments); From f1ae47c4b9eea0fefe96af00585ebdf6dac0ec16 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 9 Jan 2024 12:05:41 +0100 Subject: [PATCH 057/237] Docs: update links to Proggy Fonts. (#7211) --- docs/FONTS.md | 2 +- docs/README.md | 2 +- imgui_draw.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/FONTS.md b/docs/FONTS.md index 8988fb1122e7..cbf13e13d4b9 100644 --- a/docs/FONTS.md +++ b/docs/FONTS.md @@ -482,7 +482,7 @@ Some fonts files are available in the `misc/fonts/` folder: #### MONOSPACE FONTS Pixel Perfect: -- Proggy Fonts, by Tristan Grimmer http://www.proggyfonts.net or http://upperbounds.net +- Proggy Fonts, by Tristan Grimmer http://www.proggyfonts.net or http://upperboundsinteractive.com/fonts.php - Sweet16, Sweet16 Mono, by Martin Sedlak (Latin + Supplemental + Extended A) https://github.com/kmar/Sweet16Font (also include an .inl file to use directly in dear imgui.) Regular: diff --git a/docs/README.md b/docs/README.md index 5c88b0eed4b6..27467920db34 100644 --- a/docs/README.md +++ b/docs/README.md @@ -207,7 +207,7 @@ Sponsoring, maintenance/support contracts and other B2B transactions are hosted Omar: "I first discovered the IMGUI paradigm at [Q-Games](https://www.q-games.com) where Atman Binstock had dropped his own simple implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating and improving it." -Embeds [ProggyClean.ttf](http://upperbounds.net) font by Tristan Grimmer (MIT license). +Embeds [ProggyClean.ttf](https://www.proggyfonts.net) font by Tristan Grimmer (MIT license).
Embeds [stb_textedit.h, stb_truetype.h, stb_rect_pack.h](https://github.com/nothings/stb/) by Sean Barrett (public domain). Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. Also thank you to everyone posting feedback, questions and patches on GitHub. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index f85ea58601fb..0bec639808d4 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -4205,8 +4205,8 @@ static unsigned int stb_decompress(unsigned char *output, const unsigned char *i //----------------------------------------------------------------------------- // ProggyClean.ttf // Copyright (c) 2004, 2005 Tristan Grimmer -// MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip) -// Download and more information at http://upperbounds.net +// MIT license (see License.txt in http://www.proggyfonts.net/index.php?menu=download) +// Download and more information at http://www.proggyfonts.net or http://upperboundsinteractive.com/fonts.php //----------------------------------------------------------------------------- // File: 'ProggyClean.ttf' (41208 bytes) // Exported using misc/fonts/binary_to_compressed_c.cpp (with compression + base85 string encoding). From 58261dbe9a33dd2b41115881b7ab1021f635e66a Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 8 Jan 2024 18:49:19 +0100 Subject: [PATCH 058/237] Internals: alter ImGuiInputFlags values to leave room + indent. --- imgui.cpp | 4 ++-- imgui_internal.h | 29 +++++++++++++++-------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2e9c7f41a8a2..e7f7841ced91 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8427,7 +8427,7 @@ bool ImGui::IsKeyPressed(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags) IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsKeyPressed) == 0); // Passing flags not supported by this function! bool pressed = (t == 0.0f); - if (!pressed && ((flags & ImGuiInputFlags_Repeat) != 0)) + if (!pressed && (flags & ImGuiInputFlags_Repeat) != 0) { float repeat_delay, repeat_rate; GetTypematicRepeatRate(flags, &repeat_delay, &repeat_rate); @@ -9300,7 +9300,7 @@ bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiIn ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); if (key == ImGuiKey_None) key = ConvertSingleModFlagToKey(&g, mods); - if (!IsKeyPressed(key, owner_id, (flags & (ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_)))) + if (!IsKeyPressed(key, owner_id, (flags & ImGuiInputFlags_RepeatMask_))) return false; return true; } diff --git a/imgui_internal.h b/imgui_internal.h index d796c4b7fcb2..d481ec59f0f3 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1404,23 +1404,22 @@ struct ImGuiKeyOwnerData // Don't mistake with ImGuiInputTextFlags! (for ImGui::InputText() function) enum ImGuiInputFlags_ { - // Flags for IsKeyPressed(), IsMouseClicked(), Shortcut() + // Flags for IsKeyPressed(), IsKeyChordPressed(), IsMouseClicked(), Shortcut() ImGuiInputFlags_None = 0, ImGuiInputFlags_Repeat = 1 << 0, // Return true on successive repeats. Default for legacy IsKeyPressed(). NOT Default for legacy IsMouseClicked(). MUST BE == 1. ImGuiInputFlags_RepeatRateDefault = 1 << 1, // Repeat rate: Regular (default) ImGuiInputFlags_RepeatRateNavMove = 1 << 2, // Repeat rate: Fast ImGuiInputFlags_RepeatRateNavTweak = 1 << 3, // Repeat rate: Faster - ImGuiInputFlags_RepeatRateMask_ = ImGuiInputFlags_RepeatRateDefault | ImGuiInputFlags_RepeatRateNavMove | ImGuiInputFlags_RepeatRateNavTweak, // Flags for SetItemKeyOwner() - ImGuiInputFlags_CondHovered = 1 << 4, // Only set if item is hovered (default to both) - ImGuiInputFlags_CondActive = 1 << 5, // Only set if item is active (default to both) + ImGuiInputFlags_CondHovered = 1 << 8, // Only set if item is hovered (default to both) + ImGuiInputFlags_CondActive = 1 << 9, // Only set if item is active (default to both) ImGuiInputFlags_CondDefault_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, ImGuiInputFlags_CondMask_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, // Flags for SetKeyOwner(), SetItemKeyOwner() - ImGuiInputFlags_LockThisFrame = 1 << 6, // Access to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared at end of frame. This is useful to make input-owner-aware code steal keys from non-input-owner-aware code. - ImGuiInputFlags_LockUntilRelease = 1 << 7, // Access to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared when the key is released or at end of each frame if key is released. This is useful to make input-owner-aware code steal keys from non-input-owner-aware code. + ImGuiInputFlags_LockThisFrame = 1 << 10, // Access to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared at end of frame. This is useful to make input-owner-aware code steal keys from non-input-owner-aware code. + ImGuiInputFlags_LockUntilRelease = 1 << 11, // Access to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared when the key is released or at end of each frame if key is released. This is useful to make input-owner-aware code steal keys from non-input-owner-aware code. // Routing policies for Shortcut() + low-level SetShortcutRouting() // - The general idea is that several callers register interest in a shortcut, and only one owner gets it. @@ -1432,18 +1431,20 @@ enum ImGuiInputFlags_ // - Using ImGuiInputFlags_RouteAlways is roughly equivalent to doing e.g. IsKeyPressed(key) + testing mods. // - Priorities: GlobalHigh > Focused (when owner is active item) > Global > Focused (when focused window) > GlobalLow. // - Can select only 1 policy among all available. - ImGuiInputFlags_RouteFocused = 1 << 8, // (Default) Register focused route: Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window. - ImGuiInputFlags_RouteGlobalLow = 1 << 9, // Register route globally (lowest priority: unless a focused window or active item registered the route) -> recommended Global priority. - ImGuiInputFlags_RouteGlobal = 1 << 10, // Register route globally (medium priority: unless an active item registered the route, e.g. CTRL+A registered by InputText). - ImGuiInputFlags_RouteGlobalHigh = 1 << 11, // Register route globally (highest priority: unlikely you need to use that: will interfere with every active items) + ImGuiInputFlags_RouteFocused = 1 << 12, // (Default) Register focused route: Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window. + ImGuiInputFlags_RouteGlobalLow = 1 << 13, // Register route globally (lowest priority: unless a focused window or active item registered the route) -> recommended Global priority. + ImGuiInputFlags_RouteGlobal = 1 << 14, // Register route globally (medium priority: unless an active item registered the route, e.g. CTRL+A registered by InputText). + ImGuiInputFlags_RouteGlobalHigh = 1 << 15, // Register route globally (highest priority: unlikely you need to use that: will interfere with every active items) ImGuiInputFlags_RouteMask_ = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteGlobalLow | ImGuiInputFlags_RouteGlobalHigh, // _Always not part of this! - ImGuiInputFlags_RouteAlways = 1 << 12, // Do not register route, poll keys directly. - ImGuiInputFlags_RouteUnlessBgFocused= 1 << 13, // Global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. + ImGuiInputFlags_RouteAlways = 1 << 16, // Do not register route, poll keys directly. + ImGuiInputFlags_RouteUnlessBgFocused= 1 << 17, // Global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. ImGuiInputFlags_RouteExtraMask_ = ImGuiInputFlags_RouteAlways | ImGuiInputFlags_RouteUnlessBgFocused, // [Internal] Mask of which function support which flags - ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_, - ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RouteMask_ | ImGuiInputFlags_RouteExtraMask_, + ImGuiInputFlags_RepeatRateMask_ = ImGuiInputFlags_RepeatRateDefault | ImGuiInputFlags_RepeatRateNavMove | ImGuiInputFlags_RepeatRateNavTweak, + ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_, + ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_, + ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteMask_ | ImGuiInputFlags_RouteExtraMask_, ImGuiInputFlags_SupportedBySetKeyOwner = ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease, ImGuiInputFlags_SupportedBySetItemKeyOwner = ImGuiInputFlags_SupportedBySetKeyOwner | ImGuiInputFlags_CondMask_, }; From 8323a06e6dc583f85354483c7d870fa5e83fb35e Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 9 Jan 2024 12:09:42 +0100 Subject: [PATCH 059/237] Inputs: passing ImGuiInputFlags_RepeatXXX options automatically adds ImGuiInputFlags_Repeat. Will make extra sense with next commit where we add ImGuiInputFlags_RepeatUntil options. --- imgui.cpp | 4 +++- imgui_internal.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index e7f7841ced91..ec195d7360f8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8425,6 +8425,8 @@ bool ImGui::IsKeyPressed(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags) if (t < 0.0f) return false; IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsKeyPressed) == 0); // Passing flags not supported by this function! + if (flags & ImGuiInputFlags_RepeatRateMask_) // Setting any _RepeatXXX option enables _Repeat + flags |= ImGuiInputFlags_Repeat; bool pressed = (t == 0.0f); if (!pressed && (flags & ImGuiInputFlags_Repeat) != 0) @@ -8483,7 +8485,7 @@ bool ImGui::IsMouseClicked(ImGuiMouseButton button, ImGuiID owner_id, ImGuiInput const float t = g.IO.MouseDownDuration[button]; if (t < 0.0f) return false; - IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsKeyPressed) == 0); // Passing flags not supported by this function! + IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsMouseClicked) == 0); // Passing flags not supported by this function! // FIXME: Could support RepeatRate and RepeatUntil flags here. const bool repeat = (flags & ImGuiInputFlags_Repeat) != 0; const bool pressed = (t == 0.0f) || (repeat && t > g.IO.KeyRepeatDelay && CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0); diff --git a/imgui_internal.h b/imgui_internal.h index d481ec59f0f3..9f8e7ac2e7d4 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1444,6 +1444,7 @@ enum ImGuiInputFlags_ ImGuiInputFlags_RepeatRateMask_ = ImGuiInputFlags_RepeatRateDefault | ImGuiInputFlags_RepeatRateNavMove | ImGuiInputFlags_RepeatRateNavTweak, ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_, ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_, + ImGuiInputFlags_SupportedByIsMouseClicked = ImGuiInputFlags_Repeat, ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteMask_ | ImGuiInputFlags_RouteExtraMask_, ImGuiInputFlags_SupportedBySetKeyOwner = ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease, ImGuiInputFlags_SupportedBySetItemKeyOwner = ImGuiInputFlags_SupportedBySetKeyOwner | ImGuiInputFlags_CondMask_, From fc2e532f9981410c1f30fbb57161bd4baafa7b2d Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 9 Jan 2024 15:54:00 +0100 Subject: [PATCH 060/237] Shortcut: do not return true on mods changes. Internals: added ImGuiInputFlags_RepeatUntilKeyModsChange, ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone, ImGuiInputFlags_RepeatUntilOtherKeyPress. (#456, #2637) Took a while to come to this design, but it is flexible and lightweight and allow all decision to be taken a polling location. All three policies are useful. --- imgui.cpp | 33 ++++++++++++++++++++++++++++++++- imgui.h | 2 +- imgui_internal.h | 15 ++++++++++++++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ec195d7360f8..ab99c4697281 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8425,7 +8425,7 @@ bool ImGui::IsKeyPressed(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags) if (t < 0.0f) return false; IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsKeyPressed) == 0); // Passing flags not supported by this function! - if (flags & ImGuiInputFlags_RepeatRateMask_) // Setting any _RepeatXXX option enables _Repeat + if (flags & (ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_)) // Setting any _RepeatXXX option enables _Repeat flags |= ImGuiInputFlags_Repeat; bool pressed = (t == 0.0f); @@ -8434,6 +8434,19 @@ bool ImGui::IsKeyPressed(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags) float repeat_delay, repeat_rate; GetTypematicRepeatRate(flags, &repeat_delay, &repeat_rate); pressed = (t > repeat_delay) && GetKeyPressedAmount(key, repeat_delay, repeat_rate) > 0; + if (pressed && (flags & ImGuiInputFlags_RepeatUntilMask_)) + { + // Slightly bias 'key_pressed_time' as DownDuration is an accumulation of DeltaTime which we compare to an absolute time value. + // Ideally we'd replace DownDuration with KeyPressedTime but it would break user's code. + ImGuiContext& g = *GImGui; + double key_pressed_time = g.Time - t + 0.00001f; + if ((flags & ImGuiInputFlags_RepeatUntilKeyModsChange) && (g.LastKeyModsChangeTime > key_pressed_time)) + pressed = false; + if ((flags & ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone) && (g.LastKeyModsChangeFromNoneTime > key_pressed_time)) + pressed = false; + if ((flags & ImGuiInputFlags_RepeatUntilOtherKeyPress) && (g.LastKeyboardKeyPressTime > key_pressed_time)) + pressed = false; + } } if (!pressed) return false; @@ -8760,11 +8773,16 @@ static void ImGui::UpdateKeyboardInputs() // - New backends (1.87+): send io.AddKeyEvent(ImGuiMod_XXX) -> -> (here) deriving io.KeyMods + io.KeyXXX from key array. // - Legacy backends: set io.KeyXXX bools -> (above) set key array from io.KeyXXX -> (here) deriving io.KeyMods + io.KeyXXX from key array. // So with legacy backends the 4 values will do a unnecessary back-and-forth but it makes the code simpler and future facing. + const ImGuiKeyChord prev_key_mods = io.KeyMods; io.KeyMods = GetMergedModsFromKeys(); io.KeyCtrl = (io.KeyMods & ImGuiMod_Ctrl) != 0; io.KeyShift = (io.KeyMods & ImGuiMod_Shift) != 0; io.KeyAlt = (io.KeyMods & ImGuiMod_Alt) != 0; io.KeySuper = (io.KeyMods & ImGuiMod_Super) != 0; + if (prev_key_mods != io.KeyMods) + g.LastKeyModsChangeTime = g.Time; + if (prev_key_mods != io.KeyMods && prev_key_mods == 0) + g.LastKeyModsChangeFromNoneTime = g.Time; // Clear gamepad data if disabled if ((io.BackendFlags & ImGuiBackendFlags_HasGamepad) == 0) @@ -8780,6 +8798,14 @@ static void ImGui::UpdateKeyboardInputs() ImGuiKeyData* key_data = &io.KeysData[i]; key_data->DownDurationPrev = key_data->DownDuration; key_data->DownDuration = key_data->Down ? (key_data->DownDuration < 0.0f ? 0.0f : key_data->DownDuration + io.DeltaTime) : -1.0f; + if (key_data->DownDuration == 0.0f) + { + ImGuiKey key = (ImGuiKey)(ImGuiKey_NamedKey_BEGIN + i); + if (IsKeyboardKey(key)) + g.LastKeyboardKeyPressTime = g.Time; + else if (key == ImGuiKey_ReservedForModCtrl || key == ImGuiKey_ReservedForModShift || key == ImGuiKey_ReservedForModAlt || key == ImGuiKey_ReservedForModSuper) + g.LastKeyboardKeyPressTime = g.Time; + } } // Update keys/input owner (named keys only): one entry per key @@ -9315,6 +9341,11 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags if (!SetShortcutRouting(key_chord, owner_id, flags)) return false; + // Default repeat behavior for Shortcut() + // So e.g. pressing Ctrl+W and releasing Ctrl while holding W will not trigger the W shortcut. + if ((flags & ImGuiInputFlags_RepeatUntilMask_) == 0) + flags |= ImGuiInputFlags_RepeatUntilKeyModsChange; + if (!IsKeyChordPressed(key_chord, owner_id, flags)) return false; IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByShortcut) == 0); // Passing flags not supported by this function! diff --git a/imgui.h b/imgui.h index 3909dfa1d918..6ccae9456c70 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.1 WIP" -#define IMGUI_VERSION_NUM 19002 +#define IMGUI_VERSION_NUM 19003 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 9f8e7ac2e7d4..62abb5368362 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1411,6 +1411,13 @@ enum ImGuiInputFlags_ ImGuiInputFlags_RepeatRateNavMove = 1 << 2, // Repeat rate: Fast ImGuiInputFlags_RepeatRateNavTweak = 1 << 3, // Repeat rate: Faster + // Specify when repeating key pressed can be interrupted. + // In theory ImGuiInputFlags_RepeatUntilOtherKeyPress may be a desirable default, but it would break too many behavior so everything is opt-in. + ImGuiInputFlags_RepeatUntilRelease = 1 << 4, // Stop repeating when released (default for all functions except Shortcut). This only exists to allow overriding Shortcut() default behavior. + ImGuiInputFlags_RepeatUntilKeyModsChange = 1 << 5, // Stop repeating when released OR if keyboard mods are changed (default for Shortcut) + ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone = 1 << 6, // Stop repeating when released OR if keyboard mods are leaving the None state. Allows going from Mod+Key to Key by releasing Mod. + ImGuiInputFlags_RepeatUntilOtherKeyPress = 1 << 7, // Stop repeating when released OR if any other keyboard key is pressed during the repeat + // Flags for SetItemKeyOwner() ImGuiInputFlags_CondHovered = 1 << 8, // Only set if item is hovered (default to both) ImGuiInputFlags_CondActive = 1 << 9, // Only set if item is active (default to both) @@ -1442,7 +1449,8 @@ enum ImGuiInputFlags_ // [Internal] Mask of which function support which flags ImGuiInputFlags_RepeatRateMask_ = ImGuiInputFlags_RepeatRateDefault | ImGuiInputFlags_RepeatRateNavMove | ImGuiInputFlags_RepeatRateNavTweak, - ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_, + ImGuiInputFlags_RepeatUntilMask_ = ImGuiInputFlags_RepeatUntilRelease | ImGuiInputFlags_RepeatUntilKeyModsChange | ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone | ImGuiInputFlags_RepeatUntilOtherKeyPress, + ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_, ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_, ImGuiInputFlags_SupportedByIsMouseClicked = ImGuiInputFlags_Repeat, ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteMask_ | ImGuiInputFlags_RouteExtraMask_, @@ -1941,6 +1949,9 @@ struct ImGuiContext // - The idea is that instead of "eating" a given key, we can link to an owner. // - Input query can then read input by specifying ImGuiKeyOwner_Any (== 0), ImGuiKeyOwner_None (== -1) or a custom ID. // - Routing is requested ahead of time for a given chord (Key + Mods) and granted in NewFrame(). + double LastKeyModsChangeTime; // Record the last time key mods changed (affect repeat delay when using shortcut logic) + double LastKeyModsChangeFromNoneTime; // Record the last time key mods changed away from being 0 (affect repeat delay when using shortcut logic) + double LastKeyboardKeyPressTime; // Record the last time a keyboard key (ignore mouse/gamepad ones) was pressed. 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) @@ -2227,6 +2238,8 @@ struct ImGuiContext LastActiveId = 0; LastActiveIdTimer = 0.0f; + LastKeyboardKeyPressTime = LastKeyModsChangeTime = LastKeyModsChangeFromNoneTime = -1.0; + ActiveIdUsingNavDirMask = 0x00; ActiveIdUsingAllKeyboardKeys = false; #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO From af00b182e3e7e5c2a10bf1534dcde7c6441e9200 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 9 Jan 2024 16:04:48 +0100 Subject: [PATCH 061/237] Examples: SDL3: Minor fixes following changes to API (SDL_WindowFlags -> Uint32). "The SDL_WindowFlags enum should be replaced with Uint32" --- examples/example_sdl3_opengl3/main.cpp | 2 +- examples/example_sdl3_sdlrenderer3/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/example_sdl3_opengl3/main.cpp b/examples/example_sdl3_opengl3/main.cpp index 1f6c6d1d0ddd..da12589f8b5f 100644 --- a/examples/example_sdl3_opengl3/main.cpp +++ b/examples/example_sdl3_opengl3/main.cpp @@ -64,7 +64,7 @@ int main(int, char**) SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN); + Uint32 window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN; SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+OpenGL3 example", 1280, 720, window_flags); if (window == nullptr) { diff --git a/examples/example_sdl3_sdlrenderer3/main.cpp b/examples/example_sdl3_sdlrenderer3/main.cpp index 7ee8bbff39ec..9740054e5173 100644 --- a/examples/example_sdl3_sdlrenderer3/main.cpp +++ b/examples/example_sdl3_sdlrenderer3/main.cpp @@ -35,7 +35,7 @@ int main(int, char**) SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1"); // Create window with SDL_Renderer graphics context - SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN); + Uint32 window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN; SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+SDL_Renderer example", 1280, 720, window_flags); if (window == nullptr) { From a683033e49592dfe04fc037a41f8bc8f0bf8a953 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 9 Jan 2024 21:13:30 +0100 Subject: [PATCH 062/237] Backends: OSX: Fixed monitor and window position by correctly transforming Y origin on multi-monitor setups. (#7028, #7101, #6009, #6432) --- backends/imgui_impl_osx.h | 3 ++- backends/imgui_impl_osx.mm | 28 +++++++++++++++++++--------- docs/CHANGELOG.txt | 4 +++- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/backends/imgui_impl_osx.h b/backends/imgui_impl_osx.h index 360317fc838d..f2c704fd84a6 100644 --- a/backends/imgui_impl_osx.h +++ b/backends/imgui_impl_osx.h @@ -10,7 +10,8 @@ // [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend). // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: IME support. -// [X] Platform: Multi-viewport / platform windows. +// [x] Platform: Multi-viewport / platform windows. +// - [ ] Window size not correctly reported when enabling io.ConfigViewportsNoDecoration // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 56de6c169a97..134141371f6b 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -10,7 +10,8 @@ // [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend). // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: IME support. -// [X] Platform: Multi-viewport / platform windows. +// [x] Platform: Multi-viewport / platform windows. +// - [ ] Window size not correctly reported when enabling io.ConfigViewportsNoDecoration // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. @@ -862,9 +863,11 @@ - (BOOL)canBecomeKeyWindow @end -static void ConvertNSRect(NSScreen* screen, NSRect* r) +static void ConvertNSRect(NSRect* r) { - r->origin.y = screen.frame.size.height - r->origin.y - r->size.height; + NSRect firstScreenFrame = NSScreen.screens[0].frame; + IM_ASSERT(firstScreenFrame.origin.x == 0 && firstScreenFrame.origin.y == 0); + r->origin.y = firstScreenFrame.size.height - r->origin.y - r->size.height; } static void ImGui_ImplOSX_CreateWindow(ImGuiViewport* viewport) @@ -875,7 +878,7 @@ static void ImGui_ImplOSX_CreateWindow(ImGuiViewport* viewport) NSScreen* screen = bd->Window.screen; NSRect rect = NSMakeRect(viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y); - ConvertNSRect(screen, &rect); + ConvertNSRect(&rect); NSWindowStyleMask styleMask = 0; if (viewport->Flags & ImGuiViewportFlags_NoDecoration) @@ -945,11 +948,13 @@ static ImVec2 ImGui_ImplOSX_GetWindowPos(ImGuiViewport* viewport) IM_ASSERT(data->Window != 0); NSWindow* window = data->Window; - NSScreen* screen = window.screen; - NSSize size = screen.frame.size; NSRect frame = window.frame; - NSRect rect = window.contentLayoutRect; - return ImVec2(frame.origin.x, size.height - frame.origin.y - rect.size.height); + NSRect contentRect = window.contentLayoutRect; + if (window.styleMask & NSWindowStyleMaskFullSizeContentView) // No title bar windows should be considered. + contentRect = frame; + + NSRect firstScreenFrame = NSScreen.screens[0].frame; + return ImVec2(frame.origin.x, firstScreenFrame.size.height - frame.origin.y - contentRect.size.height); } static void ImGui_ImplOSX_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos) @@ -961,7 +966,7 @@ static void ImGui_ImplOSX_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos) NSSize size = window.frame.size; NSRect r = NSMakeRect(pos.x, pos.y, size.width, size.height); - ConvertNSRect(window.screen, &r); + ConvertNSRect(&r); [window setFrameOrigin:r.origin]; } @@ -1042,10 +1047,15 @@ static void ImGui_ImplOSX_UpdateMonitors() ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); platform_io.Monitors.resize(0); + NSRect firstScreenFrame = NSScreen.screens[0].frame; + IM_ASSERT(firstScreenFrame.origin.x == 0 && firstScreenFrame.origin.y == 0); + for (NSScreen* screen in NSScreen.screens) { NSRect frame = screen.frame; NSRect visibleFrame = screen.visibleFrame; + ConvertNSRect(&frame); + ConvertNSRect(&visibleFrame); ImGuiPlatformMonitor imgui_monitor; imgui_monitor.MainPos = ImVec2(frame.origin.x, frame.origin.y); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 74160e8a0902..4d5d26d5eca2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -110,9 +110,11 @@ Other changes: Docking+Viewports Branch: +- Windows: Fixed ImGuiCol_TitleBg/Active alpha being used for viewport-owned windows. (#7181) [@PathogenDavid] - Backends: DX12: Changed swapchain scaling mode to DXGI_SCALING_NONE to reduce artifacts as queued frames aren't synchronized with platform window resizes. (#7152, #7153) [@SuperWangKai] -- Windows: Fixed ImGuiCol_TitleBg/Active alpha being used for viewport-owned windows. (#7181) [@PathogenDavid] +- Backends: OSX: Fixed monitor and window position by correctly transforming Y origin on multi-viewports + multi-monitor setups. (#7028, #7101, #6009, #6432) [@dmirty-kuzmenko, @734vin] ----------------------------------------------------------------------- From 8deb1007cdf4437b63b896615a71422c208327fd Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 9 Jan 2024 22:13:34 +0100 Subject: [PATCH 063/237] Backends: OSX: Fixed IME position in multi-monitor/multi-viewports setups. (#7028) --- backends/imgui_impl_osx.mm | 24 ++++++++++++++++++++---- docs/CHANGELOG.txt | 1 + 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 134141371f6b..f5f554b27851 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -141,12 +141,28 @@ - (void)setImePosX:(float)posX imePosY:(float)posY - (void)updateImePosWithView:(NSView *)view { - NSWindow *window = view.window; + NSWindow* window = view.window; if (!window) return; - NSRect contentRect = [window contentRectForFrameRect:window.frame]; - NSRect rect = NSMakeRect(_posX, contentRect.size.height - _posY, 0, 0); - _imeRect = [window convertRectToScreen:rect]; + + ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + NSRect frame = window.frame; + NSRect contentRect = window.contentLayoutRect; + if (window.styleMask & NSWindowStyleMaskFullSizeContentView) // No title bar windows should be considered. + contentRect = frame; + + NSRect firstScreenFrame = NSScreen.screens[0].frame; + _imeRect = NSMakeRect(_posX, _posY, 0, 0); + _imeRect.origin.y = firstScreenFrame.size.height - _imeRect.size.height - _imeRect.origin.y; // Opposite of ConvertNSRect() + } + else + { + NSRect contentRect = [window contentRectForFrameRect:window.frame]; + NSRect rect = NSMakeRect(_posX, contentRect.size.height - _posY, 0, 0); + _imeRect = [window convertRectToScreen:rect]; + } } - (void)viewDidMoveToWindow diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4d5d26d5eca2..9f109eb8f520 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -115,6 +115,7 @@ Docking+Viewports Branch: queued frames aren't synchronized with platform window resizes. (#7152, #7153) [@SuperWangKai] - Backends: OSX: Fixed monitor and window position by correctly transforming Y origin on multi-viewports multi-monitor setups. (#7028, #7101, #6009, #6432) [@dmirty-kuzmenko, @734vin] +- Backends: OSX: Fixed IME position in multi-monitor multi-viewports setups. (#7028) [@734vin] ----------------------------------------------------------------------- From 69bf3291dff4baf9b01dea3fd75cb8337f9d3e26 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 9 Jan 2024 23:04:57 +0100 Subject: [PATCH 064/237] Internals, Inputs: Fix for ImGuiInputFlags_RepeatUntilXXX logic when #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO is not set. Amend 8323a06. Eager to get rid of legacy IMGUI_DISABLE_OBSOLETE_KEYIO stuff: technically it's been two years, may give it another one. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index ab99c4697281..c8bd417a2fb9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8800,7 +8800,7 @@ static void ImGui::UpdateKeyboardInputs() key_data->DownDuration = key_data->Down ? (key_data->DownDuration < 0.0f ? 0.0f : key_data->DownDuration + io.DeltaTime) : -1.0f; if (key_data->DownDuration == 0.0f) { - ImGuiKey key = (ImGuiKey)(ImGuiKey_NamedKey_BEGIN + i); + ImGuiKey key = (ImGuiKey)(ImGuiKey_KeysData_OFFSET + i); if (IsKeyboardKey(key)) g.LastKeyboardKeyPressTime = g.Time; else if (key == ImGuiKey_ReservedForModCtrl || key == ImGuiKey_ReservedForModShift || key == ImGuiKey_ReservedForModAlt || key == ImGuiKey_ReservedForModSuper) From cf020235658f86cfbc8ae4596a5b2c946f5c846e Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 9 Jan 2024 23:04:57 +0100 Subject: [PATCH 065/237] Internals, Inputs: Fix for ImGuiInputFlags_RepeatUntilXXX logic when #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO is not set. Amend 8323a06. Eager to get rid of legacy IMGUI_DISABLE_OBSOLETE_KEYIO stuff: technically it's been two years, may give it another one. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index a7af1060d7d0..0edf67a46622 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9405,7 +9405,7 @@ static void ImGui::UpdateKeyboardInputs() key_data->DownDuration = key_data->Down ? (key_data->DownDuration < 0.0f ? 0.0f : key_data->DownDuration + io.DeltaTime) : -1.0f; if (key_data->DownDuration == 0.0f) { - ImGuiKey key = (ImGuiKey)(ImGuiKey_NamedKey_BEGIN + i); + ImGuiKey key = (ImGuiKey)(ImGuiKey_KeysData_OFFSET + i); if (IsKeyboardKey(key)) g.LastKeyboardKeyPressTime = g.Time; else if (key == ImGuiKey_ReservedForModCtrl || key == ImGuiKey_ReservedForModShift || key == ImGuiKey_ReservedForModAlt || key == ImGuiKey_ReservedForModSuper) From a3eea8a75a073694df72a31530632804df0001ec Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 9 Jan 2024 23:26:05 +0100 Subject: [PATCH 066/237] Backends: OpenGL3: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" and variants, fixing regression on distros missing a symlink. (#6983) Amend 0f50b52da --- backends/imgui_impl_opengl3.cpp | 3 ++- backends/imgui_impl_opengl3_loader.h | 4 ++++ docs/CHANGELOG.txt | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 08cc84a13587..a36a7ac278b0 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -22,7 +22,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2023-11-08: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" instead of "libGL.so.1", accomodating for NetBSD systems having only "libGL.so.3" available. (#6983) +// 2024-01-09: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" and variants, fixing regression on distros missing a symlink. +// 2023-11-08: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" instead of "libGL.so.1", accommodating for NetBSD systems having only "libGL.so.3" available. (#6983) // 2023-10-05: OpenGL: Rename symbols in our internal loader so that LTO compilation with another copy of gl3w is possible. (#6875, #6668, #4445) // 2023-06-20: OpenGL: Fixed erroneous use glGetIntegerv(GL_CONTEXT_PROFILE_MASK) on contexts lower than 3.2. (#6539, #6333) // 2023-05-09: OpenGL: Support for glBindSampler() backup/restore on ES3. (#6375) diff --git a/backends/imgui_impl_opengl3_loader.h b/backends/imgui_impl_opengl3_loader.h index 15ba44f5c677..85c58c4e27c6 100644 --- a/backends/imgui_impl_opengl3_loader.h +++ b/backends/imgui_impl_opengl3_loader.h @@ -668,6 +668,10 @@ static int open_libgl(void) { // While most systems use libGL.so.1, NetBSD seems to use that libGL.so.3. See https://github.com/ocornut/imgui/issues/6983 libgl = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL); + if (!libgl) + libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL); + if (!libgl) + libgl = dlopen("libGL.so.3", RTLD_LAZY | RTLD_LOCAL); if (!libgl) return GL3W_ERROR_LIBRARY_OPEN; *(void **)(&glx_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB"); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7b1d5fdda5df..55f1fbff8a5a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -101,6 +101,8 @@ Other changes: register canvas selector and auto-resize GLFW window. (#6751) [@Traveller23, @ypujante] - Backends: GLFW: Fixed Windows specific hooks to use Unicode version of WndProc even when compiling in MBCS mode. (#7174) [@kimidaisuki22] +- Backends: OpenGL3: Update GL3W based imgui_impl_opengl3_loader.h to load libGL.so variants in + case of missing symlink. Fix 1.90 regression for some distros. (#6983) - Backends: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075) [@FoonTheRaccoon] - Backends: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous From a5dec42866c6e8f92f64c7d48850ad36181de037 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 10 Jan 2024 12:56:16 +0100 Subject: [PATCH 067/237] Debug Tools: Debug Log: Clicking any filter with SHIFT held enables it for 2 frames only. (#5855) --- docs/CHANGELOG.txt | 4 +++- imgui.cpp | 44 ++++++++++++++++++++++++++++++++++---------- imgui_demo.cpp | 2 ++ imgui_internal.h | 29 ++++++++++++++++------------- 4 files changed, 55 insertions(+), 24 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 55f1fbff8a5a..244e29429c83 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -84,7 +84,9 @@ Other changes: - Settings: Fixed an issue marking settings as dirty when merely clicking on a border or resize grip without moving it. - Debug Tools: Added DebugFlashStyleColor() to identify a style color. Added to Style Editor. -- Debug Tools: Debug Log: Hide its own clipper log to reduce noise in the output. +- Debug Tools: Debug Log: Hide its own clipper log to reduce noise in the output. (#5855) +- Debug Tools: Debug Log: Clicking any filter with SHIFT held enables it for 2 frames only, + making it easier when dealing with spammy logs. (#5855) - Misc: Added IMGUI_USER_H_FILENAME to change the path included when using IMGUI_INCLUDE_IMGUI_USER_H. (#7039) [@bryceberger] - Misc: Rework debug display of texture id in Metrics window to avoid compile-error when diff --git a/imgui.cpp b/imgui.cpp index c8bd417a2fb9..ea6037c9f5a7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4788,10 +4788,11 @@ void ImGui::NewFrame() UpdateDebugToolFlashStyleColor(); if (g.DebugLocateFrames > 0 && --g.DebugLocateFrames == 0) g.DebugLocateId = 0; - if (g.DebugLogClipperAutoDisableFrames > 0 && --g.DebugLogClipperAutoDisableFrames == 0) + if (g.DebugLogAutoDisableFrames > 0 && --g.DebugLogAutoDisableFrames == 0) { - DebugLog("(Debug Log: Auto-disabled ImGuiDebugLogFlags_EventClipper after 2 frames)\n"); - g.DebugLogFlags &= ~ImGuiDebugLogFlags_EventClipper; + DebugLog("(Debug Log: Auto-disabled some ImGuiDebugLogFlags after 2 frames)\n"); + g.DebugLogFlags &= ~g.DebugLogAutoDisableFlags; + g.DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None; } // Create implicit/fallback window - which we will only render it if the user has added something to it. @@ -14968,6 +14969,29 @@ void ImGui::DebugLogV(const char* fmt, va_list args) #endif } +// FIXME-LAYOUT: To be done automatically via layout mode once we rework ItemSize/ItemAdd into ItemLayout. +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))) + ImGui::SameLine(); +} + +static void ShowDebugLogFlag(const char* name, ImGuiDebugLogFlags flags) +{ + ImGuiContext& g = *GImGui; + ImVec2 size(ImGui::GetFrameHeight() + g.Style.ItemInnerSpacing.x + ImGui::CalcTextSize(name).x, ImGui::GetFrameHeight()); + SameLineOrWrap(size); // FIXME-LAYOUT: To be done automatically once we rework ItemSize/ItemAdd into ItemLayout. + if (ImGui::CheckboxFlags(name, &g.DebugLogFlags, flags) && g.IO.KeyShift && (g.DebugLogFlags & flags) != 0) + { + g.DebugLogAutoDisableFrames = 2; + g.DebugLogAutoDisableFlags |= flags; + } + ImGui::SetItemTooltip("Hold SHIFT when clicking to enable for 2 frames only (useful for spammy log entries)"); +} + void ImGui::ShowDebugLogWindow(bool* p_open) { ImGuiContext& g = *GImGui; @@ -14980,13 +15004,13 @@ void ImGui::ShowDebugLogWindow(bool* p_open) } CheckboxFlags("All", &g.DebugLogFlags, ImGuiDebugLogFlags_EventMask_); - SameLine(); CheckboxFlags("ActiveId", &g.DebugLogFlags, ImGuiDebugLogFlags_EventActiveId); - SameLine(); CheckboxFlags("Focus", &g.DebugLogFlags, ImGuiDebugLogFlags_EventFocus); - SameLine(); CheckboxFlags("Popup", &g.DebugLogFlags, ImGuiDebugLogFlags_EventPopup); - SameLine(); CheckboxFlags("Nav", &g.DebugLogFlags, ImGuiDebugLogFlags_EventNav); - SameLine(); if (CheckboxFlags("Clipper", &g.DebugLogFlags, ImGuiDebugLogFlags_EventClipper)) { g.DebugLogClipperAutoDisableFrames = 2; } if (IsItemHovered()) SetTooltip("Clipper log auto-disabled after 2 frames"); - //SameLine(); CheckboxFlags("Selection", &g.DebugLogFlags, ImGuiDebugLogFlags_EventSelection); - SameLine(); CheckboxFlags("IO", &g.DebugLogFlags, ImGuiDebugLogFlags_EventIO); + ShowDebugLogFlag("ActiveId", ImGuiDebugLogFlags_EventActiveId); + ShowDebugLogFlag("Clipper", ImGuiDebugLogFlags_EventClipper); + ShowDebugLogFlag("Focus", ImGuiDebugLogFlags_EventFocus); + ShowDebugLogFlag("IO", ImGuiDebugLogFlags_EventIO); + ShowDebugLogFlag("Nav", ImGuiDebugLogFlags_EventNav); + ShowDebugLogFlag("Popup", ImGuiDebugLogFlags_EventPopup); + //ShowDebugLogFlag("Selection", ImGuiDebugLogFlags_EventSelection); if (SmallButton("Clear")) { diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a21843848b0d..90c7018b0257 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6685,10 +6685,12 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) if (!filter.PassFilter(name)) continue; ImGui::PushID(i); +#ifndef IMGUI_DISABLE_DEBUG_TOOLS if (ImGui::Button("?")) ImGui::DebugFlashStyleColor((ImGuiCol)i); ImGui::SetItemTooltip("Flash given color to identify places where it is used."); ImGui::SameLine(); +#endif ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags); if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0) { diff --git a/imgui_internal.h b/imgui_internal.h index 62abb5368362..c2e67dc34014 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1780,17 +1780,18 @@ struct ImGuiLocEntry enum ImGuiDebugLogFlags_ { // Event types - ImGuiDebugLogFlags_None = 0, - ImGuiDebugLogFlags_EventActiveId = 1 << 0, - ImGuiDebugLogFlags_EventFocus = 1 << 1, - ImGuiDebugLogFlags_EventPopup = 1 << 2, - ImGuiDebugLogFlags_EventNav = 1 << 3, - ImGuiDebugLogFlags_EventClipper = 1 << 4, - ImGuiDebugLogFlags_EventSelection = 1 << 5, - ImGuiDebugLogFlags_EventIO = 1 << 6, - ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO, - ImGuiDebugLogFlags_OutputToTTY = 1 << 10, // Also send output to TTY - ImGuiDebugLogFlags_OutputToTestEngine = 1 << 11, // Also send output to Test Engine + ImGuiDebugLogFlags_None = 0, + ImGuiDebugLogFlags_EventActiveId = 1 << 0, + ImGuiDebugLogFlags_EventFocus = 1 << 1, + ImGuiDebugLogFlags_EventPopup = 1 << 2, + ImGuiDebugLogFlags_EventNav = 1 << 3, + ImGuiDebugLogFlags_EventClipper = 1 << 4, + ImGuiDebugLogFlags_EventSelection = 1 << 5, + ImGuiDebugLogFlags_EventIO = 1 << 6, + + ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO, + ImGuiDebugLogFlags_OutputToTTY = 1 << 20, // Also send output to TTY + ImGuiDebugLogFlags_OutputToTestEngine = 1 << 21, // Also send output to Test Engine }; struct ImGuiDebugAllocEntry @@ -2161,7 +2162,8 @@ struct ImGuiContext ImGuiDebugLogFlags DebugLogFlags; ImGuiTextBuffer DebugLogBuf; ImGuiTextIndex DebugLogIndex; - ImU8 DebugLogClipperAutoDisableFrames; + ImGuiDebugLogFlags DebugLogAutoDisableFlags; + ImU8 DebugLogAutoDisableFrames; ImU8 DebugLocateFrames; // For DebugLocateItemOnHover(). This is used together with DebugLocateId which is in a hot/cached spot above. ImS8 DebugBeginReturnValueCullDepth; // Cycle between 0..9 then wrap around. bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker()) @@ -2347,7 +2349,8 @@ struct ImGuiContext DebugLogFlags = ImGuiDebugLogFlags_OutputToTTY; DebugLocateId = 0; - DebugLogClipperAutoDisableFrames = 0; + DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None; + DebugLogAutoDisableFrames = 0; DebugLocateFrames = 0; DebugBeginReturnValueCullDepth = -1; DebugItemPickerActive = false; From 788bb58b6bb12f3bc329ce54aa0f88eb35a3990f Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 10 Jan 2024 13:19:17 +0100 Subject: [PATCH 068/237] Metrics: Tweak, reorganize tools menu. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 54 ++++++++++++++++++++++++++++++---------------- imgui_internal.h | 17 ++++++++------- imgui_widgets.cpp | 2 +- 4 files changed, 47 insertions(+), 27 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 244e29429c83..82facd29deb2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -87,6 +87,7 @@ Other changes: - Debug Tools: Debug Log: Hide its own clipper log to reduce noise in the output. (#5855) - Debug Tools: Debug Log: Clicking any filter with SHIFT held enables it for 2 frames only, making it easier when dealing with spammy logs. (#5855) +- Debug Tools: Metrics: Reorganize Tools menu. - Misc: Added IMGUI_USER_H_FILENAME to change the path included when using IMGUI_INCLUDE_IMGUI_USER_H. (#7039) [@bryceberger] - Misc: Rework debug display of texture id in Metrics window to avoid compile-error when diff --git a/imgui.cpp b/imgui.cpp index ea6037c9f5a7..e8b21b35ae6d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8149,7 +8149,7 @@ const char* ImGui::GetKeyName(ImGuiKey key) } // ImGuiMod_Shortcut is translated to either Ctrl or Super. -void ImGui::GetKeyChordName(ImGuiKeyChord key_chord, char* out_buf, int out_buf_size) +const char* ImGui::GetKeyChordName(ImGuiKeyChord key_chord, char* out_buf, int out_buf_size) { ImGuiContext& g = *GImGui; if (key_chord & ImGuiMod_Shortcut) @@ -8160,6 +8160,7 @@ void ImGui::GetKeyChordName(ImGuiKeyChord key_chord, char* out_buf, int out_buf_ (key_chord & ImGuiMod_Alt) ? "Alt+" : "", (key_chord & ImGuiMod_Super) ? (g.IO.ConfigMacOSXBehaviors ? "Cmd+" : "Super+") : "", GetKeyName((ImGuiKey)(key_chord & ~ImGuiMod_Mask_))); + return out_buf; } // t0 = previous time (e.g.: g.Time - g.IO.DeltaTime) @@ -8234,11 +8235,15 @@ static void ImGui::UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt) rt->EntriesNext.push_back(*routing_entry); // Write alive ones into new buffer // Apply routing to owner if there's no owner already (RoutingCurr == None at this point) + // This is the result of previous frame's SetShortcutRouting() call. if (routing_entry->Mods == g.IO.KeyMods) { ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key); if (owner_data->OwnerCurr == ImGuiKeyOwner_None) + { owner_data->OwnerCurr = routing_entry->RoutingCurr; + //IMGUI_DEBUG_LOG("SetKeyOwner(%s, owner_id=0x%08X) via Routing\n", GetKeyName(key), routing_entry->RoutingCurr); + } } } @@ -8363,6 +8368,7 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI if (flags & ImGuiInputFlags_RouteUnlessBgFocused) if (g.NavWindow == NULL) return false; + // Note how ImGuiInputFlags_RouteAlways won't set routing and thus won't set owner. May want to rework this? if (flags & ImGuiInputFlags_RouteAlways) return true; @@ -9264,10 +9270,11 @@ bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id) // - SetKeyOwner(..., Any or None, Lock) : set lock void ImGui::SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags) { + ImGuiContext& g = *GImGui; IM_ASSERT(IsNamedKeyOrModKey(key) && (owner_id != ImGuiKeyOwner_Any || (flags & (ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease)))); // Can only use _Any with _LockXXX flags (to eat a key away without an ID to retrieve it) IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetKeyOwner) == 0); // Passing flags not supported by this function! + //IMGUI_DEBUG_LOG("SetKeyOwner(%s, owner_id=0x%08X, flags=%08X)\n", GetKeyName(key), owner_id, flags); - ImGuiContext& g = *GImGui; ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key); owner_data->OwnerCurr = owner_data->OwnerNext = owner_id; @@ -9336,6 +9343,9 @@ bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiIn bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags) { + //ImGuiContext& g = *GImGui; + //IMGUI_DEBUG_LOG("Shortcut(%s, owner_id=0x%08X, flags=%X)\n", GetKeyChordName(key_chord, g.TempBuffer.Data, g.TempBuffer.Size), owner_id, flags); + // When using (owner_id == 0/Any): SetShortcutRouting() will use CurrentFocusScopeId and filter with this, so IsKeyPressed() is fine with he 0/Any. if ((flags & ImGuiInputFlags_RouteMask_) == 0) flags |= ImGuiInputFlags_RouteFocused; @@ -12371,6 +12381,7 @@ static void ImGui::NavUpdateWindowing() } // Start CTRL+Tab or Square+L/R window selection + // (g.ConfigNavWindowingKeyNext/g.ConfigNavWindowingKeyPrev defaults are ImGuiMod_Ctrl|ImGuiKey_Tab and ImGuiMod_Ctrl|ImGuiMod_Shift|ImGuiKey_Tab) const ImGuiID owner_id = ImHashStr("###NavUpdateWindowing"); const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0; @@ -14061,18 +14072,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) // Tools if (TreeNode("Tools")) { - bool show_encoding_viewer = TreeNode("UTF-8 Encoding viewer"); - SameLine(); - MetricsHelpMarker("You can also call ImGui::DebugTextEncoding() from your code with a given string to test that your UTF-8 encoding settings are correct."); - if (show_encoding_viewer) - { - static char buf[100] = ""; - SetNextItemWidth(-FLT_MIN); - InputText("##Text", buf, IM_ARRAYSIZE(buf)); - if (buf[0] != 0) - DebugTextEncoding(buf); - TreePop(); - } + SeparatorText("Debug breaks"); // The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted. if (Checkbox("Show Item Picker", &g.DebugItemPickerActive) && g.DebugItemPickerActive) @@ -14080,6 +14080,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) SameLine(); MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash."); + SeparatorText("Visualize"); + Checkbox("Show Debug Log", &cfg->ShowDebugLog); SameLine(); MetricsHelpMarker("You can also call ImGui::ShowDebugLogWindow() from your code."); @@ -14151,10 +14153,24 @@ void ImGui::ShowMetricsWindow(bool* p_open) } Checkbox("Show groups rectangles", &g.DebugShowGroupRects); // Storing in context as this is used by group code and prefers to be in hot-data + SeparatorText("Validate"); + Checkbox("Debug Begin/BeginChild return value", &io.ConfigDebugBeginReturnValueLoop); SameLine(); MetricsHelpMarker("Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running."); + Checkbox("UTF-8 Encoding viewer", &cfg->ShowTextEncodingViewer); + SameLine(); + MetricsHelpMarker("You can also call ImGui::DebugTextEncoding() from your code with a given string to test that your UTF-8 encoding settings are correct."); + if (cfg->ShowTextEncodingViewer) + { + static char buf[64] = ""; + SetNextItemWidth(-FLT_MIN); + InputText("##Text", buf, IM_ARRAYSIZE(buf)); + if (buf[0] != 0) + DebugTextEncoding(buf); + } + TreePop(); } @@ -14389,7 +14405,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) Text("KEY OWNERS"); { Indent(); - if (BeginChild("##owners", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 6), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_NoSavedSettings)) + if (BeginChild("##owners", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_NoSavedSettings)) for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key); @@ -14403,9 +14419,11 @@ void ImGui::ShowMetricsWindow(bool* p_open) Unindent(); } Text("SHORTCUT ROUTING"); + SameLine(); + MetricsHelpMarker("Declared shortcut routes automatically set key owner when mods matches."); { Indent(); - if (BeginChild("##routes", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 6), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_NoSavedSettings)) + if (BeginChild("##routes", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_NoSavedSettings)) for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { ImGuiKeyRoutingTable* rt = &g.KeysRoutingTable; @@ -14413,8 +14431,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) { char key_chord_name[64]; ImGuiKeyRoutingData* routing_data = &rt->Entries[idx]; - GetKeyChordName(key | routing_data->Mods, key_chord_name, IM_ARRAYSIZE(key_chord_name)); - Text("%s: 0x%08X", key_chord_name, routing_data->RoutingCurr); + ImGuiKeyChord key_chord = key | routing_data->Mods; + Text("%s: 0x%08X", GetKeyChordName(key_chord, key_chord_name, IM_ARRAYSIZE(key_chord_name)), routing_data->RoutingCurr); DebugLocateItemOnHover(routing_data->RoutingCurr); idx = routing_data->NextEntryIndex; } diff --git a/imgui_internal.h b/imgui_internal.h index c2e67dc34014..af6792a8318e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -227,13 +227,13 @@ namespace ImStb #else #define IMGUI_DEBUG_LOG(...) ((void)0) #endif -#define IMGUI_DEBUG_LOG_ACTIVEID(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventActiveId) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) -#define IMGUI_DEBUG_LOG_FOCUS(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) -#define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) -#define IMGUI_DEBUG_LOG_NAV(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventNav) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) -#define IMGUI_DEBUG_LOG_SELECTION(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) -#define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) -#define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) +#define IMGUI_DEBUG_LOG_ACTIVEID(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventActiveId) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) +#define IMGUI_DEBUG_LOG_FOCUS(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) +#define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) +#define IMGUI_DEBUG_LOG_NAV(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventNav) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) +#define IMGUI_DEBUG_LOG_SELECTION(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) +#define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) +#define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) // Static Asserts #define IM_STATIC_ASSERT(_COND) static_assert(_COND, "") @@ -1820,6 +1820,7 @@ struct ImGuiMetricsConfig bool ShowTablesRects = false; bool ShowDrawCmdMesh = true; bool ShowDrawCmdBoundingBoxes = true; + bool ShowTextEncodingViewer = false; bool ShowAtlasTintedWithTextColor = false; int ShowWindowsRectsType = -1; int ShowTablesRectsType = -1; @@ -3116,7 +3117,7 @@ namespace ImGui IMGUI_API ImGuiKeyData* GetKeyData(ImGuiContext* ctx, ImGuiKey key); inline ImGuiKeyData* GetKeyData(ImGuiKey key) { ImGuiContext& g = *GImGui; return GetKeyData(&g, key); } - IMGUI_API void GetKeyChordName(ImGuiKeyChord key_chord, char* out_buf, int out_buf_size); + IMGUI_API const char* GetKeyChordName(ImGuiKeyChord key_chord, char* out_buf, int out_buf_size); inline ImGuiKey MouseButtonToKey(ImGuiMouseButton button) { IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT); return (ImGuiKey)(ImGuiKey_MouseLeft + button); } IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f); IMGUI_API ImVec2 GetKeyMagnitude2d(ImGuiKey key_left, ImGuiKey key_right, ImGuiKey key_up, ImGuiKey key_down); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3bd656e079de..d33699e2a577 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5030,7 +5030,7 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state) Text("CurLenW: %d, CurLenA: %d, Cursor: %d, Selection: %d..%d", state->CurLenW, state->CurLenA, stb_state->cursor, stb_state->select_start, stb_state->select_end); Text("has_preferred_x: %d (%.2f)", stb_state->has_preferred_x, stb_state->preferred_x); Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point); - if (BeginChild("undopoints", ImVec2(0.0f, GetTextLineHeight() * 15), ImGuiChildFlags_Border)) // Visualize undo state + if (BeginChild("undopoints", ImVec2(0.0f, GetTextLineHeight() * 10), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeY)) // Visualize undo state { PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); for (int n = 0; n < IMSTB_TEXTEDIT_UNDOSTATECOUNT; n++) From fdf8d02be1ddc6588fa5e403b4fa66dd2565791a Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 10 Jan 2024 15:35:35 +0100 Subject: [PATCH 069/237] Debug Tools: Added io.ConfigDebugIsDebuggerPresent and Debug Break buttons. (#2673) --- docs/CHANGELOG.txt | 8 +++- imgui.cpp | 106 ++++++++++++++++++++++++++++++++++++++++++--- imgui.h | 20 ++++++--- imgui_demo.cpp | 4 +- imgui_internal.h | 15 +++++++ imgui_tables.cpp | 14 +++++- 6 files changed, 152 insertions(+), 15 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 82facd29deb2..5d079bf51774 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -83,11 +83,17 @@ Other changes: movements toward another parent BeginMenu() can keep the wrong child menu open. (#6671, #6926) - Settings: Fixed an issue marking settings as dirty when merely clicking on a border or resize grip without moving it. +- Debug Tools: Added io.ConfigDebugIsDebuggerPresent option. When enabled, this adds buttons + in various locations of Metrics/Debugger to manually break in debugger in selected places: + - Request a debug break in a Begin() call. + - Request a debug break in a ItemAdd() call via debug log and hovering 0xXXXXXX identifiers. + - Request a debug break in a BeginTable() call. + - Request a debug break in a SetShortcutRouting()/Shortcut() call. [Internal] +- Debug Tools: Metrics: Reorganize Tools menu. - Debug Tools: Added DebugFlashStyleColor() to identify a style color. Added to Style Editor. - Debug Tools: Debug Log: Hide its own clipper log to reduce noise in the output. (#5855) - Debug Tools: Debug Log: Clicking any filter with SHIFT held enables it for 2 frames only, making it easier when dealing with spammy logs. (#5855) -- Debug Tools: Metrics: Reorganize Tools menu. - Misc: Added IMGUI_USER_H_FILENAME to change the path included when using IMGUI_INCLUDE_IMGUI_USER_H. (#7039) [@bryceberger] - Misc: Rework debug display of texture id in Metrics window to avoid compile-error when diff --git a/imgui.cpp b/imgui.cpp index e8b21b35ae6d..ebd4cb3514a1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4787,7 +4787,10 @@ void ImGui::NewFrame() UpdateDebugToolStackQueries(); UpdateDebugToolFlashStyleColor(); if (g.DebugLocateFrames > 0 && --g.DebugLocateFrames == 0) + { g.DebugLocateId = 0; + g.DebugBreakInLocateId = false; + } if (g.DebugLogAutoDisableFrames > 0 && --g.DebugLogAutoDisableFrames == 0) { DebugLog("(Debug Log: Auto-disabled some ImGuiDebugLogFlags after 2 frames)\n"); @@ -6372,6 +6375,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (window_just_created) window = CreateNewWindow(name, flags); + // [DEBUG] Debug break requested by user + if (g.DebugBreakInWindow == window->ID) + IM_DEBUG_BREAK(); + // Automatically disable manual moving/resizing when NoInputs is set if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs) flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; @@ -8365,6 +8372,10 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI else IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteMask_)); // Check that only 1 routing flag is used + // [DEBUG] Debug break requested by user + if (g.DebugBreakInShortcutRouting == key_chord) + IM_DEBUG_BREAK(); + if (flags & ImGuiInputFlags_RouteUnlessBgFocused) if (g.NavWindow == NULL) return false; @@ -14013,6 +14024,9 @@ void ImGui::ShowMetricsWindow(bool* p_open) return; } + // [DEBUG] Clear debug breaks hooks after exactly one cycle. + DebugBreakClearData(); + // Basic info Text("Dear ImGui %s", GetVersion()); Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); @@ -14072,13 +14086,14 @@ void ImGui::ShowMetricsWindow(bool* p_open) // Tools if (TreeNode("Tools")) { - SeparatorText("Debug breaks"); - + // Debug Break features // The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted. - if (Checkbox("Show Item Picker", &g.DebugItemPickerActive) && g.DebugItemPickerActive) - DebugStartItemPicker(); + SeparatorTextEx(0, "Debug breaks", NULL, CalcTextSize("(?)").x + g.Style.SeparatorTextPadding.x); SameLine(); MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash."); + if (Checkbox("Show Item Picker", &g.DebugItemPickerActive) && g.DebugItemPickerActive) + DebugStartItemPicker(); + Checkbox("Show \"Debug Break\" buttons in other sections", &g.IO.ConfigDebugIsDebuggerPresent); SeparatorText("Visualize"); @@ -14166,7 +14181,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) { static char buf[64] = ""; SetNextItemWidth(-FLT_MIN); - InputText("##Text", buf, IM_ARRAYSIZE(buf)); + InputText("##DebugTextEncodingBuf", buf, IM_ARRAYSIZE(buf)); if (buf[0] != 0) DebugTextEncoding(buf); } @@ -14434,6 +14449,12 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGuiKeyChord key_chord = key | routing_data->Mods; Text("%s: 0x%08X", GetKeyChordName(key_chord, key_chord_name, IM_ARRAYSIZE(key_chord_name)), routing_data->RoutingCurr); DebugLocateItemOnHover(routing_data->RoutingCurr); + if (g.IO.ConfigDebugIsDebuggerPresent) + { + SameLine(); + if (DebugBreakButton("**DebugBreak**", "in SetShortcutRouting() for this KeyChord")) + g.DebugBreakInShortcutRouting = key_chord; + } idx = routing_data->NextEntryIndex; } } @@ -14545,6 +14566,64 @@ void ImGui::ShowMetricsWindow(bool* p_open) End(); } +void ImGui::DebugBreakClearData() +{ + // Those fields are scattered in their respective subsystem to stay in hot-data locations + ImGuiContext& g = *GImGui; + g.DebugBreakInWindow = 0; + g.DebugBreakInTable = 0; + g.DebugBreakInShortcutRouting = ImGuiKey_None; +} + +void ImGui::DebugBreakButtonTooltip(bool keyboard_only, const char* description_of_location) +{ + if (!BeginItemTooltip()) + return; + Text("To call IM_DEBUG_BREAK() %s:", description_of_location); + Separator(); + TextUnformatted(keyboard_only ? "- Press 'Pause/Break' on keyboard." : "- Press 'Pause/Break' on keyboard.\n- or Click (may alter focus/active id).\n- or navigate using keyboard and press space."); + Separator(); + TextUnformatted("Choose one way that doesn't interfere with what you are trying to debug!\nYou need a debugger attached or this will crash!"); + EndTooltip(); +} + +// Special button that doesn't take focus, doesn't take input owner, and can be activated without a click etc. +// In order to reduce interferences with the contents we are trying to debug into. +bool ImGui::DebugBreakButton(const char* label, const char* description_of_location) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiID id = window->GetID(label); + const ImVec2 label_size = CalcTextSize(label, NULL, true); + ImVec2 pos = window->DC.CursorPos + ImVec2(0.0f, window->DC.CurrLineTextBaseOffset); + ImVec2 size = ImVec2(label_size.x + g.Style.FramePadding.x * 2.0f, label_size.y); + + const ImRect bb(pos, pos + size); + ItemSize(size, 0.0f); + if (!ItemAdd(bb, id)) + return false; + + // WE DO NOT USE ButtonEx() or ButtonBehavior() in order to reduce our side-effects. + bool hovered = ItemHoverable(bb, id, g.CurrentItemFlags); + bool pressed = hovered && (IsKeyChordPressed(g.DebugBreakKeyChord) || IsMouseClicked(0) || g.NavActivateId == id); + DebugBreakButtonTooltip(false, description_of_location); + + ImVec4 col4f = GetStyleColorVec4(hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); + ImVec4 hsv; + ColorConvertRGBtoHSV(col4f.x, col4f.y, col4f.z, hsv.x, hsv.y, hsv.z); + ColorConvertHSVtoRGB(hsv.x + 0.20f, hsv.y, hsv.z, col4f.x, col4f.y, col4f.z); + + RenderNavHighlight(bb, id); + RenderFrame(bb.Min, bb.Max, GetColorU32(col4f), true, g.Style.FrameRounding); + RenderTextClipped(bb.Min, bb.Max, label, NULL, &label_size, g.Style.ButtonTextAlign, &bb); + + IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); + return pressed; +} + // [DEBUG] Display contents of Columns void ImGui::DebugNodeColumns(ImGuiOldColumns* columns) { @@ -14883,6 +14962,9 @@ void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label) if (window->MemoryCompacted) TextDisabled("Note: some memory buffers have been compacted/freed."); + if (g.IO.ConfigDebugIsDebuggerPresent && DebugBreakButton("**DebugBreak**", "in Begin()")) + g.DebugBreakInWindow = window->ID; + ImGuiWindowFlags flags = window->Flags; DebugNodeDrawList(window, window->Viewport, window->DrawList, "DrawList"); BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), ContentSize (%.1f,%.1f) Ideal (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->ContentSize.x, window->ContentSize.y, window->ContentSizeIdeal.x, window->ContentSizeIdeal.y); @@ -15117,6 +15199,7 @@ void ImGui::DebugLocateItem(ImGuiID target_id) ImGuiContext& g = *GImGui; g.DebugLocateId = target_id; g.DebugLocateFrames = 2; + g.DebugBreakInLocateId = false; } void ImGui::DebugLocateItemOnHover(ImGuiID target_id) @@ -15126,11 +15209,24 @@ void ImGui::DebugLocateItemOnHover(ImGuiID target_id) ImGuiContext& g = *GImGui; DebugLocateItem(target_id); GetForegroundDrawList(g.CurrentWindow)->AddRect(g.LastItemData.Rect.Min - ImVec2(3.0f, 3.0f), g.LastItemData.Rect.Max + ImVec2(3.0f, 3.0f), DEBUG_LOCATE_ITEM_COLOR); + + // Can't easily use a context menu here because it will mess with focus, active id etc. + if (g.IO.ConfigDebugIsDebuggerPresent && g.MouseStationaryTimer > 1.0f) + { + DebugBreakButtonTooltip(false, "in ItemAdd()"); + if (IsKeyChordPressed(g.DebugBreakKeyChord)) + g.DebugBreakInLocateId = true; + } } void ImGui::DebugLocateItemResolveWithLastItem() { ImGuiContext& g = *GImGui; + + // [DEBUG] Debug break requested by user + if (g.DebugBreakInLocateId) + IM_DEBUG_BREAK(); + ImGuiLastItemData item_data = g.LastItemData; g.DebugLocateId = 0; ImDrawList* draw_list = GetForegroundDrawList(g.CurrentWindow); diff --git a/imgui.h b/imgui.h index 6ccae9456c70..1c5f7262ac72 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.1 WIP" -#define IMGUI_VERSION_NUM 19003 +#define IMGUI_VERSION_NUM 19004 #define IMGUI_HAS_TABLE /* @@ -2089,16 +2089,22 @@ struct ImGuiIO // Debug options //------------------------------------------------------------------ + // Option to enable various debug tools showing buttons that will call the IM_DEBUG_BREAK() macro. + // - The Item Picker tool will be available regardless of this being enabled, in order to maximize its discoverability. + // - Requires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application. + // e.g. io.ConfigDebugIsDebuggerPresent = ::IsDebuggerPresent() on Win32, or refer to ImOsIsDebuggerPresent() imgui_test_engine/imgui_te_utils.cpp for a Unix compatible version). + bool ConfigDebugIsDebuggerPresent; // = false // Enable various tools calling IM_DEBUG_BREAK(). + // Tools to test correct Begin/End and BeginChild/EndChild behaviors. - // Presently Begin()/End() and BeginChild()/EndChild() needs to ALWAYS be called in tandem, regardless of return value of BeginXXX() - // This is inconsistent with other BeginXXX functions and create confusion for many users. - // We expect to update the API eventually. In the meanwhile we provide tools to facilitate checking user-code behavior. + // - Presently Begin()/End() and BeginChild()/EndChild() needs to ALWAYS be called in tandem, regardless of return value of BeginXXX() + // - This is inconsistent with other BeginXXX functions and create confusion for many users. + // - We expect to update the API eventually. In the meanwhile we provide tools to facilitate checking user-code behavior. bool ConfigDebugBeginReturnValueOnce;// = false // First-time calls to Begin()/BeginChild() will return false. NEEDS TO BE SET AT APPLICATION BOOT TIME if you don't want to miss windows. bool ConfigDebugBeginReturnValueLoop;// = false // Some calls to Begin()/BeginChild() will return false. Will cycle through window depths then repeat. Suggested use: add "io.ConfigDebugBeginReturnValue = io.KeyShift" in your main loop then occasionally press SHIFT. Windows should be flickering while running. - // Option to deactivate io.AddFocusEvent(false) handling. May facilitate interactions with a debugger when focus loss leads to clearing inputs data. - // Backends may have other side-effects on focus loss, so this will reduce side-effects but not necessary remove all of them. - // Consider using e.g. Win32's IsDebuggerPresent() as an additional filter (or see ImOsIsDebuggerPresent() in imgui_test_engine/imgui_te_utils.cpp for a Unix compatible version). + // Option to deactivate io.AddFocusEvent(false) handling. + // - May facilitate interactions with a debugger when focus loss leads to clearing inputs data. + // - Backends may have other side-effects on focus loss, so this will reduce side-effects but not necessary remove all of them. bool ConfigDebugIgnoreFocusLoss; // = false // Ignore io.AddFocusEvent(false), consequently not calling io.ClearInputKeys() in input processing. // Options to audit .ini data diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 90c7018b0257..b3a987116ab6 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -478,10 +478,12 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Text("Also see Style->Rendering for rendering options."); ImGui::SeparatorText("Debug"); + ImGui::Checkbox("io.ConfigDebugIsDebuggerPresent", &io.ConfigDebugIsDebuggerPresent); + ImGui::SameLine(); HelpMarker("Enable various tools calling IM_DEBUG_BREAK().\n\nRequires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application."); ImGui::BeginDisabled(); ImGui::Checkbox("io.ConfigDebugBeginReturnValueOnce", &io.ConfigDebugBeginReturnValueOnce); // . ImGui::EndDisabled(); - ImGui::SameLine(); HelpMarker("First calls to Begin()/BeginChild() will return false.\n\nTHIS OPTION IS DISABLED because it needs to be set at application boot-time to make sense. Showing the disabled option is a way to make this feature easier to discover"); + ImGui::SameLine(); HelpMarker("First calls to Begin()/BeginChild() will return false.\n\nTHIS OPTION IS DISABLED because it needs to be set at application boot-time to make sense. Showing the disabled option is a way to make this feature easier to discover."); ImGui::Checkbox("io.ConfigDebugBeginReturnValueLoop", &io.ConfigDebugBeginReturnValueLoop); ImGui::SameLine(); HelpMarker("Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running."); ImGui::Checkbox("io.ConfigDebugIgnoreFocusLoss", &io.ConfigDebugIgnoreFocusLoss); diff --git a/imgui_internal.h b/imgui_internal.h index af6792a8318e..6e78cd007a5c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1907,6 +1907,7 @@ struct ImGuiContext ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow* int WindowsActiveCount; // Number of unique windows submitted by frame ImVec2 WindowsHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, WINDOWS_HOVER_PADDING) + ImGuiID DebugBreakInWindow; // Set to break in Begin() call. ImGuiWindow* CurrentWindow; // Window being drawn into ImGuiWindow* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs. ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set. @@ -1958,6 +1959,7 @@ struct ImGuiContext 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) + 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 @@ -2074,6 +2076,7 @@ struct ImGuiContext // Tables ImGuiTable* CurrentTable; + ImGuiID DebugBreakInTable; // Set to break in BeginTable() call. int TablesTempDataStacked; // Temporary table data size (because we leave previous instances undestructed, we generally don't use TablesTempData.Size) ImVector TablesTempData; // Temporary table data (buffers reused/shared across instances, support nesting) ImPool Tables; // Persistent table data @@ -2166,6 +2169,8 @@ struct ImGuiContext ImGuiDebugLogFlags DebugLogAutoDisableFlags; ImU8 DebugLogAutoDisableFrames; ImU8 DebugLocateFrames; // For DebugLocateItemOnHover(). This is used together with DebugLocateId which is in a hot/cached spot above. + bool DebugBreakInLocateId; // Debug break in ItemAdd() call for g.DebugLocateId. + ImGuiKeyChord DebugBreakKeyChord; // = ImGuiKey_Pause ImS8 DebugBeginReturnValueCullDepth; // Cycle between 0..9 then wrap around. bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker()) ImU8 DebugItemPickerMouseButton; @@ -2360,6 +2365,13 @@ struct ImGuiContext DebugFlashStyleColorTime = 0.0f; DebugFlashStyleColorIdx = ImGuiCol_COUNT; + // Same as DebugBreakClearData(). Those fields are scattered in their respective subsystem to stay in hot-data locations + DebugBreakInWindow = 0; + DebugBreakInTable = 0; + DebugBreakInLocateId = false; + DebugBreakKeyChord = ImGuiKey_Pause; + DebugBreakInShortcutRouting = ImGuiKey_None; + memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0; FramerateSecPerFrameAccum = 0.0f; @@ -3406,6 +3418,9 @@ namespace ImGui IMGUI_API void DebugLocateItem(ImGuiID target_id); // Call sparingly: only 1 at the same time! IMGUI_API void DebugLocateItemOnHover(ImGuiID target_id); // Only call on reaction to a mouse Hover: because only 1 at the same time! IMGUI_API void DebugLocateItemResolveWithLastItem(); + IMGUI_API void DebugBreakClearData(); + IMGUI_API bool DebugBreakButton(const char* label, const char* description_of_location); + IMGUI_API void DebugBreakButtonTooltip(bool keyboard_only, const char* description_of_location); inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); IMGUI_API void DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 13e0211cd042..13333901c634 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -329,6 +329,10 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG return false; } + // [DEBUG] Debug break requested by user + if (g.DebugBreakInTable == id) + IM_DEBUG_BREAK(); + // Acquire storage for the table ImGuiTable* table = g.Tables.GetOrAddByKey(id); const ImGuiTableFlags table_last_flags = table->Flags; @@ -3802,7 +3806,8 @@ static const char* DebugNodeTableGetSizingPolicyDesc(ImGuiTableFlags sizing_poli void ImGui::DebugNodeTable(ImGuiTable* table) { - const bool is_active = (table->LastFrameActive >= GetFrameCount() - 2); // Note that fully clipped early out scrolling tables will appear as inactive here. + ImGuiContext& g = *GImGui; + const bool is_active = (table->LastFrameActive >= g.FrameCount - 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(table, "Table 0x%08X (%d columns, in '%s')%s", table->ID, table->ColumnsCount, table->OuterWindow->Name, is_active ? "" : " *Inactive*"); if (!is_active) { PopStyleColor(); } @@ -3814,6 +3819,13 @@ void ImGui::DebugNodeTable(ImGuiTable* table) return; if (table->InstanceCurrent > 0) Text("** %d instances of same table! Some data below will refer to last instance.", table->InstanceCurrent + 1); + if (g.IO.ConfigDebugIsDebuggerPresent) + { + if (DebugBreakButton("**DebugBreak**", "in BeginTable()")) + g.DebugBreakInTable = table->ID; + SameLine(); + } + bool clear_settings = SmallButton("Clear settings"); BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags)); BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : ""); From 6470e2279e37754071d2066f2825abae9eaadbd2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 10 Jan 2024 17:35:41 +0100 Subject: [PATCH 070/237] Debug Tools: DebugRenderKeyboardPreview() scales better. --- imgui.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ebd4cb3514a1..fba92a784d28 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -13863,14 +13863,15 @@ static void RenderViewportsThumbnails() // Draw an arbitrary US keyboard layout to visualize translated keys void ImGui::DebugRenderKeyboardPreview(ImDrawList* draw_list) { - const ImVec2 key_size = ImVec2(35.0f, 35.0f); - const float key_rounding = 3.0f; - const ImVec2 key_face_size = ImVec2(25.0f, 25.0f); - const ImVec2 key_face_pos = ImVec2(5.0f, 3.0f); - const float key_face_rounding = 2.0f; - const ImVec2 key_label_pos = ImVec2(7.0f, 4.0f); + const float scale = ImGui::GetFontSize() / 13.0f; + const ImVec2 key_size = ImVec2(35.0f, 35.0f) * scale; + const float key_rounding = 3.0f * scale; + const ImVec2 key_face_size = ImVec2(25.0f, 25.0f) * scale; + const ImVec2 key_face_pos = ImVec2(5.0f, 3.0f) * scale; + const float key_face_rounding = 2.0f * scale; + const ImVec2 key_label_pos = ImVec2(7.0f, 4.0f) * scale; const ImVec2 key_step = ImVec2(key_size.x - 1.0f, key_size.y - 1.0f); - const float key_row_offset = 9.0f; + const float key_row_offset = 9.0f * scale; ImVec2 board_min = GetCursorScreenPos(); ImVec2 board_max = ImVec2(board_min.x + 3 * key_step.x + 2 * key_row_offset + 10.0f, board_min.y + 3 * key_step.y + 10.0f); From d6cb3c923d28dcebb2d8d9605ccc7229ccef19eb Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 9 Jan 2024 23:16:34 +0100 Subject: [PATCH 071/237] Version 1.90.1 --- docs/CHANGELOG.txt | 131 +++++++++++++++++++++++++-------------------- imgui.cpp | 2 +- imgui.h | 7 +-- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 83 insertions(+), 67 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5d079bf51774..dcf120325a3b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -37,9 +37,11 @@ HOW TO UPDATE? ----------------------------------------------------------------------- - VERSION 1.90.1 WIP (In Progress) + VERSION 1.90.1 (Released 2024-01-10) ----------------------------------------------------------------------- +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90.1 + Breaking changes: - imgui_freetype: commented out ImGuiFreeType::BuildFontAtlas() obsoleted in 1.81. @@ -52,48 +54,56 @@ Breaking changes: Other changes: -- Windows: BeginChild(): Fixed auto-resizing erroneously limiting size to host viewport - minus padding. There are no limit to a child width/height. (#7063) [@Devyre] -- Windows: BeginChild(): Resize borders rendered even when ImGuiWindowFlags_NoBackground - is specified. (#1710, #7194) -- Windows: Fixed some auto-resizing path using style.WindowMinSize.x (instead of x/y) - for both axises since 1.90. (#7106) [@n0bodysec] -- Scrolling: internal scrolling value is rounded instead of truncated, as a way to reduce - speed asymetry when (incorrectly) attempting to scroll by non-integer amount. (#6677) -- Nav, IO: SetNextFrameWantCaptureKeyboard(false) calls are not overrided back to true when - navigation is enabled. SetNextFrameWantCaptureKeyboard() is always higher priority. (#6997) -- Nav: Activation can also be performed with Keypad Enter. (#5606) -- Drag and Drop: Fixed drop target highlight on items temporarily pushing a widened clip rect - (namely Selectables and Treenodes using SpanAllColumn flag) so the highlight properly covers - all columns. (#7049, #4281, #3272) -- InputTextMultiline: Fixed Tab character input not repeating (1.89.4 regression). -- InputTextMultiline: Tabbing through a multi-line text editor which allows Tab character inputs - (using the ImGuiInputTextFlags_AllowTabInput flag) doesn't automatically activate it, in order - to allow passing through multiple widgets easily. (#3092, #5759, #787) -- DragScalarN, SliderScalarN, InputScalarN: Fixed incorrect pushes into ItemWidth - stack when number of components is 1. [#7095] [@Nahor] -- Drags, Sliders, Inputs: removed all attempts to filter non-numerical characters during text - editing. Invalid inputs not applied to value, visibly reverted after validation. (#6810, #7096) -- Drags, Sliders, Inputs: removal of filter means that "nan" and "inf" values may be input. (#7096) -- DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: improve multi-components - width computation to better distribute the error. (#7120, #7121) [@Nahor] -- ColorEdit: Layout tweaks for very small sizes. (#7120, #7121) -- ColorPicker: Fixed saturation/value cursor radius not scaling properly. -- Menus: Tweaked hover slack logic, adding a timer to avoid situations where a slow vertical - movements toward another parent BeginMenu() can keep the wrong child menu open. (#6671, #6926) +- Windows: + - BeginChild(): Fixed auto-resizing erroneously limiting size to host viewport + minus padding. There are no limit to a child width/height. (#7063) [@Devyre] + - BeginChild(): Resize borders rendered even when ImGuiWindowFlags_NoBackground + is specified. (#1710, #7194) + - Fixed some auto-resizing path using style.WindowMinSize.x (instead of x/y) + for both axises since 1.90. (#7106) [@n0bodysec] + - Scrolling: internal scrolling value is rounded instead of truncated, as a way to reduce + speed asymmetry when (incorrectly) attempting to scroll by non-integer amount. (#6677) +- Navigation (Keyboard/gamepad): + - Nav, IO: SetNextFrameWantCaptureKeyboard(false) calls are not overridden back to true when + navigation is enabled. SetNextFrameWantCaptureKeyboard() is always higher priority. (#6997) + - Nav: Activation can also be performed with Keypad Enter. (#5606) +- Drag and Drop: + - Fixed drop target highlight on items temporarily pushing a widened clip rect + (namely Selectables and Treenodes using SpanAllColumn flag) so the highlight properly covers + all columns. (#7049, #4281, #3272) +- InputText: + - InputTextMultiline: Fixed Tab character input not repeating (1.89.4 regression). + - InputTextMultiline: Tabbing through a multi-line text editor which allows Tab character inputs + (using the ImGuiInputTextFlags_AllowTabInput flag) doesn't automatically activate it, in order + to allow passing through multiple widgets easily. (#3092, #5759, #787) +- Drags, Sliders, Inputs: + - DragScalarN, SliderScalarN, InputScalarN: Fixed incorrect pushes into ItemWidth + stack when number of components is 1. [#7095] [@Nahor] + - Drags, Sliders, Inputs: removed all attempts to filter non-numerical characters during text + editing. Invalid inputs not applied to value, visibly reverted after validation. (#6810, #7096) + - Drags, Sliders, Inputs: removal of filter means that "nan" and "inf" values may be input. (#7096) + - DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: improve multi-components + width computation to better distribute the error. (#7120, #7121) [@Nahor] +- Menus: + - Tweaked hover slack logic, adding an extra timeout to avoid situations where a slow vertical + movements toward another parent BeginMenu() can keep the wrong child menu open. (#6671, #6926) +- Color Editors: + - ColorEdit: Layout tweaks for very small sizes. (#7120, #7121) + - ColorPicker: Fixed saturation/value cursor radius not scaling properly. +- Debug Tools: + - Added io.ConfigDebugIsDebuggerPresent option. When enabled, this adds buttons in various + locations of Metrics/Debugger to manually request a debugger break: + - Request a debug break in a Begin() call. + - Request a debug break in a ItemAdd() call via debug log and hovering 0xXXXXXX identifiers. + - Request a debug break in a BeginTable() call. + - Request a debug break in a SetShortcutRouting()/Shortcut() call. [Internal] + - Metrics: Reorganize Tools menu. + - Added DebugFlashStyleColor() to identify a style color. Added to Style Editor. + - Debug Log: Hide its own clipper log to reduce noise in the output. (#5855) + - Debug Log: Clicking any filter with SHIFT held enables it for 2 frames only, + making it easier when dealing with spammy logs. (#5855) - Settings: Fixed an issue marking settings as dirty when merely clicking on a border or resize grip without moving it. -- Debug Tools: Added io.ConfigDebugIsDebuggerPresent option. When enabled, this adds buttons - in various locations of Metrics/Debugger to manually break in debugger in selected places: - - Request a debug break in a Begin() call. - - Request a debug break in a ItemAdd() call via debug log and hovering 0xXXXXXX identifiers. - - Request a debug break in a BeginTable() call. - - Request a debug break in a SetShortcutRouting()/Shortcut() call. [Internal] -- Debug Tools: Metrics: Reorganize Tools menu. -- Debug Tools: Added DebugFlashStyleColor() to identify a style color. Added to Style Editor. -- Debug Tools: Debug Log: Hide its own clipper log to reduce noise in the output. (#5855) -- Debug Tools: Debug Log: Clicking any filter with SHIFT held enables it for 2 frames only, - making it easier when dealing with spammy logs. (#5855) - Misc: Added IMGUI_USER_H_FILENAME to change the path included when using IMGUI_INCLUDE_IMGUI_USER_H. (#7039) [@bryceberger] - Misc: Rework debug display of texture id in Metrics window to avoid compile-error when @@ -105,29 +115,34 @@ Other changes: on a codebase where another copy of the library is used. - Misc: During shutdown, check that io.BackendPlatformUserData and io.BackendRendererUserData are NULL in order to catch cases where backend was not shut down. (#7175) -- Misc: Reworked Issue Template to with a shinier and better form. (#5927) [@Panquesito7, @PathogenDavid, @ocornut] -- Backends: GLFW, Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to - register canvas selector and auto-resize GLFW window. (#6751) [@Traveller23, @ypujante] -- Backends: GLFW: Fixed Windows specific hooks to use Unicode version of WndProc even when - compiling in MBCS mode. (#7174) [@kimidaisuki22] -- Backends: OpenGL3: Update GL3W based imgui_impl_opengl3_loader.h to load libGL.so variants in - case of missing symlink. Fix 1.90 regression for some distros. (#6983) -- Backends: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs - vkDestroyCommandPool(). (#7075) [@FoonTheRaccoon] -- Backends: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous - "best practice" validation layer. (#7189, #4238) [@philae-ael] -- Backends: Vulkan: Stopped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT - as we don't reset them. -- Backends: WebGPU: Fixed wgpuRenderPassEncoderSetScissorRect() crash when rendering modal - window's dimming layer, which has an unclipped value in ImDrawCmd::ClipRect. (#7191) [@aparis69] -- Examples: GLFW+Emscripten: Fixed examples not consistently resizing according to host canvas. - (#6751) [@Traveller23, @ypujante] +- Misc: Reworked Issue Template to a shinier and better form. (#5927) [@Panquesito7, @PathogenDavid, @ocornut] +- Backends: + - GLFW, Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to + register canvas selector and auto-resize GLFW window. (#6751) [@Traveller23, @ypujante] + - GLFW: Fixed Windows specific hooks to use Unicode version of WndProc even when + compiling in MBCS mode. (#7174) [@kimidaisuki22] + - OpenGL3: Update GL3W based imgui_impl_opengl3_loader.h to load libGL.so variants in + case of missing symlink. Fix 1.90 regression for some distros. (#6983) + - Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs + vkDestroyCommandPool(). (#7075) [@FoonTheRaccoon] + - Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous + "best practice" validation layer. (#7189, #4238) [@philae-ael] + - Vulkan: Stopped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT + as we don't reset them. + - WebGPU: Fixed wgpuRenderPassEncoderSetScissorRect() crash when rendering modal window's + dimming layer, which has an unclipped value in ImDrawCmd::ClipRect. (#7191) [@aparis69] +- Examples: + - Examples: GLFW+Emscripten: Fixed examples not consistently resizing according to host canvas. + (#6751) [@Traveller23, @ypujante] + - Examples: SDL3: Minor fixes following recent SDL3 in-progress development. ----------------------------------------------------------------------- VERSION 1.90.0 (Released 2023-11-15) ----------------------------------------------------------------------- +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90 + Breaking changes: - BeginChild(): Upgraded 'bool border = false' parameter to 'ImGuiChildFlags flags = 0'. diff --git a/imgui.cpp b/imgui.cpp index fba92a784d28..e406a9f16be1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.1 WIP +// dear imgui, v1.90.1 // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 1c5f7262ac72..0ec197760e55 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.1 WIP +// dear imgui, v1.90.1 // (headers) // Help: @@ -23,8 +23,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.1 WIP" -#define IMGUI_VERSION_NUM 19004 +#define IMGUI_VERSION "1.90.1" +#define IMGUI_VERSION_NUM 19010 #define IMGUI_HAS_TABLE /* @@ -256,6 +256,7 @@ typedef void (*ImGuiMemFreeFunc)(void* ptr, void* user_data); // ImVec2: 2D vector used to store positions, sizes etc. [Compile-time configurable type] // This is a frequently used type in the API. Consider using IM_VEC2_CLASS_EXTRA to create implicit cast from/to our preferred type. +// Add '#define IMGUI_DEFINE_MATH_OPERATORS' in your imconfig.h file to benefit from courtesy maths operators for those types. IM_MSVC_RUNTIME_CHECKS_OFF struct ImVec2 { diff --git a/imgui_demo.cpp b/imgui_demo.cpp index b3a987116ab6..4a116922e92c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.1 WIP +// dear imgui, v1.90.1 // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 0bec639808d4..40a840c46519 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.1 WIP +// dear imgui, v1.90.1 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 6e78cd007a5c..1a55e171a423 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.1 WIP +// dear imgui, v1.90.1 // (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. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 13333901c634..eab542d8c3e9 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.1 WIP +// dear imgui, v1.90.1 // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d33699e2a577..e3f420a24e1e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.1 WIP +// dear imgui, v1.90.1 // (widgets code) /* From db049db860886906c4cbe16b22c4d72748c7a32f Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 11 Jan 2024 13:14:21 +0100 Subject: [PATCH 072/237] Docs: tweak, fixed misplaced changelog entry. (#7084) --- docs/CHANGELOG.txt | 5 +++-- docs/README.md | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index dcf120325a3b..6088d006c4f8 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -90,6 +90,9 @@ Other changes: - Color Editors: - ColorEdit: Layout tweaks for very small sizes. (#7120, #7121) - ColorPicker: Fixed saturation/value cursor radius not scaling properly. +- Tabs: Added ImGuiTabItemFlags_NoAssumedClosure to enable app to react on closure attempt, + without having to draw an unsaved document marker (ImGuiTabItemFlags_UnsavedDocument sets + _NoAssumedClosure automatically). (#7084) - Debug Tools: - Added io.ConfigDebugIsDebuggerPresent option. When enabled, this adds buttons in various locations of Metrics/Debugger to manually request a debugger break: @@ -3530,8 +3533,6 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v Breaking Changes: -- Tabs: Added ImGuiTabItemFlags_NoAssumedClosure to enable app to react on closure attempt, without having to draw - an unsaved document marker (ImGuiTabItemFlags_UnsavedDocument sets _NoAssumedClosure automatically). (#7084) - DragInt(): The default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally any more. If you used DragInt() with custom format strings, make sure you change them to use %d or an integer-compatible format. To honor backward-compatibility, the DragInt() code will currently parse and modify format strings to replace %*f with %d, diff --git a/docs/README.md b/docs/README.md index 27467920db34..ef4fb9753a4e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,7 +16,7 @@ Businesses: support continued development and maintenance via invoiced sponsorin | [The Pitch](#the-pitch) - [Usage](#usage) - [How it works](#how-it-works) - [Releases & Changelogs](#releases--changelogs) - [Demo](#demo) - [Integration](#integration) | :----------------------------------------------------------: | | [Gallery](#gallery) - [Support, FAQ](#support-frequently-asked-questions-faq) - [How to help](#how-to-help) - [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) - [Credits](#credits) - [License](#license) | -| [Wiki](https://github.com/ocornut/imgui/wiki) - [Languages & frameworks backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [User quotes](https://github.com/ocornut/imgui/wiki/Quotes) | +| [Wiki](https://github.com/ocornut/imgui/wiki) - [Extensions](https://github.com/ocornut/imgui/wiki/Useful-Extensions) - [Languages bindings & frameworks backends](https://github.com/ocornut/imgui/wiki/Bindings) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [User quotes](https://github.com/ocornut/imgui/wiki/Quotes) | ### The Pitch @@ -39,7 +39,7 @@ Dear ImGui is particularly suited to integration in game engines (for tooling), ### Usage -**The core of Dear ImGui is self-contained within a few platform-agnostic files** which you can easily compile in your application/engine. They are all the files in the root folder of the repository (imgui*.cpp, imgui*.h). **No specific build process is required**. You can add the .cpp files into your existing project. +**The core of Dear ImGui is self-contained within a few platform-agnostic files** which you can easily compile in your application/engine. They are all the files in the root folder of the repository (imgui*.cpp, imgui*.h). **No specific build process is required**. You can add the .cpp files into your existing project. **Backends for a variety of graphics API and rendering platforms** are provided in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder, along with example applications in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui. From 29809d72202865f4518db421ba96f19c46b46ab6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 11 Jan 2024 14:37:13 +0100 Subject: [PATCH 073/237] Version 1.90.2 WIP --- docs/CHANGELOG.txt | 8 ++++++++ imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6088d006c4f8..5f214721a9f5 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,14 @@ HOW TO UPDATE? and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users. - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.90.2 WIP (In Progress) +----------------------------------------------------------------------- + +Breaking changes: + +Other changes: + ----------------------------------------------------------------------- VERSION 1.90.1 (Released 2024-01-10) diff --git a/imgui.cpp b/imgui.cpp index e406a9f16be1..a8078f1fc53f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.1 +// dear imgui, v1.90.2 WIP // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 0ec197760e55..1ee1ac53f97b 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.1 +// dear imgui, v1.90.2 WIP // (headers) // Help: @@ -23,8 +23,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.1" -#define IMGUI_VERSION_NUM 19010 +#define IMGUI_VERSION "1.90.2 WIP" +#define IMGUI_VERSION_NUM 19011 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 4a116922e92c..53462be788c4 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.1 +// dear imgui, v1.90.2 WIP // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 40a840c46519..9008eb748248 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.1 +// dear imgui, v1.90.2 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 1a55e171a423..6f9171255bb1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.1 +// dear imgui, v1.90.2 WIP // (internal structures/api) // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index eab542d8c3e9..272842e09eeb 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.1 +// dear imgui, v1.90.2 WIP // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e3f420a24e1e..6b16f55b9143 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.1 +// dear imgui, v1.90.2 WIP // (widgets code) /* From 82df7c8bf41b3582996c86251c0dbdc27f651ed0 Mon Sep 17 00:00:00 2001 From: Tristan Gouge Date: Thu, 11 Jan 2024 14:42:48 +0100 Subject: [PATCH 074/237] Backends: Vulkan: Fixed handling of ImGui_ImplVulkan_InitInfo::MinAllocationSize field. (#7189, #4238) --- backends/imgui_impl_vulkan.cpp | 8 ++++---- docs/CHANGELOG.txt | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 47e6fd824707..0648a55cd843 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -33,6 +33,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-01-11: Vulkan: Fixed MinAllocationSize handing. (#7189) // 2024-01-03: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous "best practice" validation layer. (#7189, #4238) // 2024-01-03: Vulkan: Stoped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them. // 2023-11-29: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075) @@ -395,7 +396,7 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory if (buffer_memory != VK_NULL_HANDLE) vkFreeMemory(v->Device, buffer_memory, v->Allocator); - VkDeviceSize vertex_buffer_size_aligned = ((new_size - 1) / bd->BufferMemoryAlignment + 1) * bd->BufferMemoryAlignment; + VkDeviceSize vertex_buffer_size_aligned = ((IM_MAX(v->MinAllocationSize, new_size) - 1) / bd->BufferMemoryAlignment + 1) * bd->BufferMemoryAlignment; VkBufferCreateInfo buffer_info = {}; buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; buffer_info.size = vertex_buffer_size_aligned; @@ -407,17 +408,16 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory VkMemoryRequirements req; vkGetBufferMemoryRequirements(v->Device, buffer, &req); bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment; - VkDeviceSize size = IM_MAX(v->MinAllocationSize, req.size); VkMemoryAllocateInfo alloc_info = {}; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.allocationSize = size; + alloc_info.allocationSize = req.size; alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &buffer_memory); check_vk_result(err); err = vkBindBufferMemory(v->Device, buffer, buffer_memory, 0); check_vk_result(err); - p_buffer_size = size; + p_buffer_size = vertex_buffer_size_aligned; } static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5f214721a9f5..5722c776ea71 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,8 @@ Breaking changes: Other changes: +- Backends: Vulkan: Fixed handling of ImGui_ImplVulkan_InitInfo::MinAllocationSize field. (#7189, #4238) + ----------------------------------------------------------------------- VERSION 1.90.1 (Released 2024-01-10) From 70bb6d1e7906ac98eef5be5cf7c8b32f240c2968 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 11 Jan 2024 14:57:38 +0100 Subject: [PATCH 075/237] Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957) --- backends/imgui_impl_vulkan.cpp | 24 +++++++++++++++--------- docs/CHANGELOG.txt | 1 + 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 0648a55cd843..6fb7f16f6584 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -33,7 +33,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2024-01-11: Vulkan: Fixed MinAllocationSize handing. (#7189) +// 2024-01-11: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size (#3957). Fixed MinAllocationSize handing (#7189). // 2024-01-03: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous "best practice" validation layer. (#7189, #4238) // 2024-01-03: Vulkan: Stoped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them. // 2023-11-29: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075) @@ -386,7 +386,13 @@ static void check_vk_result(VkResult err) v->CheckVkResultFn(err); } -static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& p_buffer_size, size_t new_size, VkBufferUsageFlagBits usage) +// Same as IM_MEMALIGN(). 'alignment' must be a power of two. +static inline VkDeviceSize AlignBufferSize(VkDeviceSize size, VkDeviceSize alignment) +{ + return (size + alignment - 1) & ~(alignment - 1); +} + +static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& buffer_size, size_t new_size, VkBufferUsageFlagBits usage) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; @@ -396,10 +402,10 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory if (buffer_memory != VK_NULL_HANDLE) vkFreeMemory(v->Device, buffer_memory, v->Allocator); - VkDeviceSize vertex_buffer_size_aligned = ((IM_MAX(v->MinAllocationSize, new_size) - 1) / bd->BufferMemoryAlignment + 1) * bd->BufferMemoryAlignment; + VkDeviceSize buffer_size_aligned = AlignBufferSize(IM_MAX(v->MinAllocationSize, new_size), bd->BufferMemoryAlignment); VkBufferCreateInfo buffer_info = {}; buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_info.size = vertex_buffer_size_aligned; + buffer_info.size = buffer_size_aligned; buffer_info.usage = usage; buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &buffer); @@ -417,7 +423,7 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory err = vkBindBufferMemory(v->Device, buffer, buffer_memory, 0); check_vk_result(err); - p_buffer_size = vertex_buffer_size_aligned; + buffer_size = buffer_size_aligned; } static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height) @@ -494,8 +500,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm if (draw_data->TotalVtxCount > 0) { // Create or resize the vertex/index buffers - size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); - size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); + size_t vertex_size = AlignBufferSize(draw_data->TotalVtxCount * sizeof(ImDrawVert), bd->BufferMemoryAlignment); + size_t index_size = AlignBufferSize(draw_data->TotalIdxCount * sizeof(ImDrawIdx), bd->BufferMemoryAlignment); if (rb->VertexBuffer == VK_NULL_HANDLE || rb->VertexBufferSize < vertex_size) CreateOrResizeBuffer(rb->VertexBuffer, rb->VertexBufferMemory, rb->VertexBufferSize, vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); if (rb->IndexBuffer == VK_NULL_HANDLE || rb->IndexBufferSize < index_size) @@ -504,9 +510,9 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm // Upload vertex/index data into a single contiguous GPU buffer ImDrawVert* vtx_dst = nullptr; ImDrawIdx* idx_dst = nullptr; - VkResult err = vkMapMemory(v->Device, rb->VertexBufferMemory, 0, rb->VertexBufferSize, 0, (void**)&vtx_dst); + VkResult err = vkMapMemory(v->Device, rb->VertexBufferMemory, 0, vertex_size, 0, (void**)&vtx_dst); check_vk_result(err); - err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, rb->IndexBufferSize, 0, (void**)&idx_dst); + err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, index_size, 0, (void**)&idx_dst); check_vk_result(err); for (int n = 0; n < draw_data->CmdListsCount; n++) { diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5722c776ea71..90e00d95a040 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,7 @@ Breaking changes: Other changes: +- Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957) - Backends: Vulkan: Fixed handling of ImGui_ImplVulkan_InitInfo::MinAllocationSize field. (#7189, #4238) From 32a3c61d0001d75cdcf033015a1e27f1ea12c848 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 11 Jan 2024 19:48:31 +0100 Subject: [PATCH 076/237] Internals: Shortcut() follow docking chain (until we formalize a more general focus scope stack). (#456) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f4a1d852e945..49edd5b00b57 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8931,7 +8931,7 @@ static int CalcRoutingScore(ImGuiWindow* location, ImGuiID owner_id, ImGuiInputF return 1; // Early out when not in focus stack - if (focused == NULL || focused->RootWindow != location->RootWindow) + if (focused == NULL || focused->RootWindowDockTree != location->RootWindowDockTree) return 255; // Score based on distance to focused window (lower is better) @@ -8947,7 +8947,7 @@ static int CalcRoutingScore(ImGuiWindow* location, ImGuiID owner_id, ImGuiInputF IM_ASSERT(next_score < 255); return next_score; } - focused = (focused->RootWindow != focused) ? focused->ParentWindow : NULL; // FIXME: This could be later abstracted as a focus path + focused = (focused->RootWindowDockTree != focused) ? focused->ParentWindow : NULL; // FIXME: This could be later abstracted as a focus path } return 255; } From 6228c2e1ec7ef21ca1809579c055ed34540dedb0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 11 Jan 2024 20:22:37 +0100 Subject: [PATCH 077/237] Backends: Vulkan: moved ImGui_ImplVulkanH_DestroyFrameRenderBuffers/ImGui_ImplVulkanH_DestroyWindowRenderBuffers as they are always used in a state where backend data is available. --- backends/imgui_impl_vulkan.cpp | 70 +++++++++++++++++----------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 6fb7f16f6584..73213c986e56 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -92,14 +92,14 @@ #endif // Forward Declarations -struct ImGui_ImplVulkanH_FrameRenderBuffers; -struct ImGui_ImplVulkanH_WindowRenderBuffers; +struct ImGui_ImplVulkan_FrameRenderBuffers; +struct ImGui_ImplVulkan_WindowRenderBuffers; bool ImGui_ImplVulkan_CreateDeviceObjects(); void ImGui_ImplVulkan_DestroyDeviceObjects(); +void ImGui_ImplVulkan_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkan_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator); +void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkan_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator); void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator); void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator); -void ImGui_ImplVulkanH_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkanH_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator); -void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkanH_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator); void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count); void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator); @@ -191,7 +191,7 @@ static PFN_vkCmdEndRenderingKHR ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR; // Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplVulkan_RenderDrawData() // [Please zero-clear before use!] -struct ImGui_ImplVulkanH_FrameRenderBuffers +struct ImGui_ImplVulkan_FrameRenderBuffers { VkDeviceMemory VertexBufferMemory; VkDeviceMemory IndexBufferMemory; @@ -203,11 +203,11 @@ struct ImGui_ImplVulkanH_FrameRenderBuffers // Each viewport will hold 1 ImGui_ImplVulkanH_WindowRenderBuffers // [Please zero-clear before use!] -struct ImGui_ImplVulkanH_WindowRenderBuffers +struct ImGui_ImplVulkan_WindowRenderBuffers { uint32_t Index; uint32_t Count; - ImGui_ImplVulkanH_FrameRenderBuffers* FrameRenderBuffers; + ImGui_ImplVulkan_FrameRenderBuffers* FrameRenderBuffers; }; // Vulkan data @@ -234,7 +234,7 @@ struct ImGui_ImplVulkan_Data VkCommandBuffer FontCommandBuffer; // Render buffers for main window - ImGui_ImplVulkanH_WindowRenderBuffers MainWindowRenderBuffers; + ImGui_ImplVulkan_WindowRenderBuffers MainWindowRenderBuffers; ImGui_ImplVulkan_Data() { @@ -426,7 +426,7 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory buffer_size = buffer_size_aligned; } -static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height) +static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkan_FrameRenderBuffers* rb, int fb_width, int fb_height) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); @@ -485,17 +485,17 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm pipeline = bd->Pipeline; // Allocate array to store enough vertex/index buffers - ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &bd->MainWindowRenderBuffers; + ImGui_ImplVulkan_WindowRenderBuffers* wrb = &bd->MainWindowRenderBuffers; if (wrb->FrameRenderBuffers == nullptr) { wrb->Index = 0; wrb->Count = v->ImageCount; - wrb->FrameRenderBuffers = (ImGui_ImplVulkanH_FrameRenderBuffers*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameRenderBuffers) * wrb->Count); - memset(wrb->FrameRenderBuffers, 0, sizeof(ImGui_ImplVulkanH_FrameRenderBuffers) * wrb->Count); + wrb->FrameRenderBuffers = (ImGui_ImplVulkan_FrameRenderBuffers*)IM_ALLOC(sizeof(ImGui_ImplVulkan_FrameRenderBuffers) * wrb->Count); + memset(wrb->FrameRenderBuffers, 0, sizeof(ImGui_ImplVulkan_FrameRenderBuffers) * wrb->Count); } IM_ASSERT(wrb->Count == v->ImageCount); wrb->Index = (wrb->Index + 1) % wrb->Count; - ImGui_ImplVulkanH_FrameRenderBuffers* rb = &wrb->FrameRenderBuffers[wrb->Index]; + ImGui_ImplVulkan_FrameRenderBuffers* rb = &wrb->FrameRenderBuffers[wrb->Index]; if (draw_data->TotalVtxCount > 0) { @@ -1032,7 +1032,7 @@ void ImGui_ImplVulkan_DestroyDeviceObjects() { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; - ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator); + ImGui_ImplVulkan_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator); ImGui_ImplVulkan_DestroyFontsTexture(); if (bd->FontCommandBuffer) { vkFreeCommandBuffers(v->Device, bd->FontCommandPool, 1, &bd->FontCommandBuffer); bd->FontCommandBuffer = VK_NULL_HANDLE; } @@ -1151,7 +1151,7 @@ void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count) ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; VkResult err = vkDeviceWaitIdle(v->Device); check_vk_result(err); - ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator); + ImGui_ImplVulkan_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator); bd->VulkanInitInfo.MinImageCount = min_image_count; } @@ -1198,6 +1198,26 @@ void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set) vkFreeDescriptorSets(v->Device, v->DescriptorPool, 1, &descriptor_set); } +void ImGui_ImplVulkan_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkan_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator) +{ + if (buffers->VertexBuffer) { vkDestroyBuffer(device, buffers->VertexBuffer, allocator); buffers->VertexBuffer = VK_NULL_HANDLE; } + if (buffers->VertexBufferMemory) { vkFreeMemory(device, buffers->VertexBufferMemory, allocator); buffers->VertexBufferMemory = VK_NULL_HANDLE; } + if (buffers->IndexBuffer) { vkDestroyBuffer(device, buffers->IndexBuffer, allocator); buffers->IndexBuffer = VK_NULL_HANDLE; } + if (buffers->IndexBufferMemory) { vkFreeMemory(device, buffers->IndexBufferMemory, allocator); buffers->IndexBufferMemory = VK_NULL_HANDLE; } + buffers->VertexBufferSize = 0; + buffers->IndexBufferSize = 0; +} + +void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkan_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator) +{ + for (uint32_t n = 0; n < buffers->Count; n++) + ImGui_ImplVulkan_DestroyFrameRenderBuffers(device, &buffers->FrameRenderBuffers[n], allocator); + IM_FREE(buffers->FrameRenderBuffers); + buffers->FrameRenderBuffers = nullptr; + buffers->Index = 0; + buffers->Count = 0; +} + //------------------------------------------------------------------------- // Internal / Miscellaneous Vulkan Helpers // (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own app.) @@ -1562,26 +1582,6 @@ void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH fsd->ImageAcquiredSemaphore = fsd->RenderCompleteSemaphore = VK_NULL_HANDLE; } -void ImGui_ImplVulkanH_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkanH_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator) -{ - if (buffers->VertexBuffer) { vkDestroyBuffer(device, buffers->VertexBuffer, allocator); buffers->VertexBuffer = VK_NULL_HANDLE; } - if (buffers->VertexBufferMemory) { vkFreeMemory(device, buffers->VertexBufferMemory, allocator); buffers->VertexBufferMemory = VK_NULL_HANDLE; } - if (buffers->IndexBuffer) { vkDestroyBuffer(device, buffers->IndexBuffer, allocator); buffers->IndexBuffer = VK_NULL_HANDLE; } - if (buffers->IndexBufferMemory) { vkFreeMemory(device, buffers->IndexBufferMemory, allocator); buffers->IndexBufferMemory = VK_NULL_HANDLE; } - buffers->VertexBufferSize = 0; - buffers->IndexBufferSize = 0; -} - -void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkanH_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator) -{ - for (uint32_t n = 0; n < buffers->Count; n++) - ImGui_ImplVulkanH_DestroyFrameRenderBuffers(device, &buffers->FrameRenderBuffers[n], allocator); - IM_FREE(buffers->FrameRenderBuffers); - buffers->FrameRenderBuffers = nullptr; - buffers->Index = 0; - buffers->Count = 0; -} - //----------------------------------------------------------------------------- #endif // #ifndef IMGUI_DISABLE From 8a3dfda8d082caa4eefa75d8a53ca5074b2c651d Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Jan 2024 11:20:13 +0100 Subject: [PATCH 078/237] Commented out obsolete ImGuiIO::ImeWindowHandle marked obsolete in 1.87, favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'. Amend 3a90dc38 (#2589, #2598, #3108, #3113, #3653, #4642) --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 14 ++------------ imgui.h | 6 +----- imgui_internal.h | 6 +++--- 4 files changed, 9 insertions(+), 20 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 90e00d95a040..20de27acfb1b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,9 @@ HOW TO UPDATE? Breaking changes: +- Commented out ImGuiIO::ImeWindowHandle obsoleted in 1.87 in favor of writing + to 'void* ImGuiViewport::PlatformHandleRaw'. + Other changes: - Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957) diff --git a/imgui.cpp b/imgui.cpp index a8078f1fc53f..2d9ea91baad2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -424,6 +424,7 @@ CODE When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2024/01/15 (1.90.2) - commented out obsolete ImGuiIO::ImeWindowHandle marked obsolete in 1.87, favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'. - 2023/12/19 (1.90.1) - commented out obsolete ImGuiKey_KeyPadEnter redirection to ImGuiKey_KeypadEnter. - 2023/11/06 (1.90.1) - removed CalcListClipping() marked obsolete in 1.86. Prefer using ImGuiListClipper which can return non-contiguous ranges. - 2023/11/05 (1.90.1) - imgui_freetype: commented out ImGuiFreeType::BuildFontAtlas() obsoleted in 1.81. prefer using #define IMGUI_ENABLE_FREETYPE or see commented code for manual calls. @@ -5028,18 +5029,7 @@ void ImGui::EndFrame() { 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); ImGuiViewport* viewport = GetMainViewport(); -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - if (viewport->PlatformHandleRaw == NULL && g.IO.ImeWindowHandle != NULL) - { - viewport->PlatformHandleRaw = g.IO.ImeWindowHandle; - g.IO.SetPlatformImeDataFn(viewport, ime_data); - viewport->PlatformHandleRaw = NULL; - } - else -#endif - { - g.IO.SetPlatformImeDataFn(viewport, ime_data); - } + g.IO.SetPlatformImeDataFn(viewport, ime_data); } // Hide implicit/fallback "Debug" window if it hasn't been used diff --git a/imgui.h b/imgui.h index 1ee1ac53f97b..b079473e2ffe 100644 --- a/imgui.h +++ b/imgui.h @@ -2187,11 +2187,7 @@ struct ImGuiIO int KeyMap[ImGuiKey_COUNT]; // [LEGACY] Input: map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. The first 512 are now unused and should be kept zero. Legacy backend will write into KeyMap[] using ImGuiKey_ indices which are always >512. bool KeysDown[ImGuiKey_COUNT]; // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). This used to be [512] sized. It is now ImGuiKey_COUNT to allow legacy io.KeysDown[GetKeyIndex(...)] to work without an overflow. float NavInputs[ImGuiNavInput_COUNT]; // [LEGACY] Since 1.88, NavInputs[] was removed. Backends from 1.60 to 1.86 won't build. Feed gamepad inputs via io.AddKeyEvent() and ImGuiKey_GamepadXXX enums. -#endif -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - void* ImeWindowHandle; // = NULL // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning. -#else - void* _UnusedPadding; + //void* ImeWindowHandle; // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning. #endif //------------------------------------------------------------------ diff --git a/imgui_internal.h b/imgui_internal.h index 6f9171255bb1..4c9c8479d2bf 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1965,8 +1965,8 @@ struct ImGuiContext #endif // Next window/item data - ImGuiID CurrentFocusScopeId; // == g.FocusScopeStack.back() - ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back() + ImGuiID CurrentFocusScopeId; // Value for currently appending items == g.FocusScopeStack.back(). Not to be mistaken with g.NavFocusScopeId. + ImGuiItemFlags CurrentItemFlags; // Value for currently appending items == g.ItemFlagsStack.back() ImGuiID DebugLocateId; // Storage for DebugLocateItemOnHover() feature: this is read by ItemAdd() so we keep it in a hot/cached location ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions ImGuiLastItemData LastItemData; // Storage for last submitted item (setup by ItemAdd) @@ -1993,7 +1993,7 @@ struct ImGuiContext // Gamepad/keyboard Navigation ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow' ImGuiID NavId; // Focused item for navigation - ImGuiID NavFocusScopeId; // Identify a selection scope (selection code often wants to "clear other items" when landing on an item of the selection set) + ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope) ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem() ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0 ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat) From dd0efdc63716297a8393fa20fccc0e032bfc7a27 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Jan 2024 17:31:44 +0100 Subject: [PATCH 079/237] Fixed SetKeyboardFocusHere() not working when current nav focus is in different scope. (#7226) Amend 70f2aaff --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 20de27acfb1b..fab54b072650 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -46,6 +46,8 @@ Breaking changes: Other changes: +- Fixed SetKeyboardFocusHere() not working when current nav focus is in different scope, + regression from 1.90.1 related to code scoping Tab presses to local scope. (#7226) [@bratpilz] - Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957) - Backends: Vulkan: Fixed handling of ImGui_ImplVulkan_InitInfo::MinAllocationSize field. (#7189, #4238) diff --git a/imgui.cpp b/imgui.cpp index 2d9ea91baad2..8db1bbedc1fe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11383,10 +11383,12 @@ void ImGui::NavProcessItemForTabbingRequest(ImGuiID id, ImGuiItemFlags item_flag ImGuiContext& g = *GImGui; if ((move_flags & ImGuiNavMoveFlags_FocusApi) == 0) + { if (g.NavLayer != g.CurrentWindow->DC.NavLayerCurrent) return; - if (g.NavFocusScopeId != g.CurrentFocusScopeId) - return; + if (g.NavFocusScopeId != g.CurrentFocusScopeId) + return; + } // - Can always land on an item when using API call. // - Tabbing with _NavEnableKeyboard (space/enter/arrows): goes through every item. From 2156db7a07527a758f75e4cd2ce35566409cd6e2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Jan 2024 15:57:14 +0100 Subject: [PATCH 080/237] Debug Log: added InputRouting logging. Made GetKeyChordName() use its own buffer. Fixed debug break in SetShortcutRouting(). (#6798, #2637, #456) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 25 ++++++++++++++++++------- imgui.h | 2 +- imgui_internal.h | 10 +++++++--- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index fab54b072650..39e7b665419f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -48,6 +48,8 @@ Other changes: - Fixed SetKeyboardFocusHere() not working when current nav focus is in different scope, regression from 1.90.1 related to code scoping Tab presses to local scope. (#7226) [@bratpilz] +- Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. +- Debug Tools: Debug Log: Added "Input Routing" logging. - Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957) - Backends: Vulkan: Fixed handling of ImGui_ImplVulkan_InitInfo::MinAllocationSize field. (#7189, #4238) diff --git a/imgui.cpp b/imgui.cpp index 8db1bbedc1fe..71f352eb9f19 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8146,18 +8146,18 @@ const char* ImGui::GetKeyName(ImGuiKey key) } // ImGuiMod_Shortcut is translated to either Ctrl or Super. -const char* ImGui::GetKeyChordName(ImGuiKeyChord key_chord, char* out_buf, int out_buf_size) +const char* ImGui::GetKeyChordName(ImGuiKeyChord key_chord) { ImGuiContext& g = *GImGui; if (key_chord & ImGuiMod_Shortcut) key_chord = ConvertShortcutMod(key_chord); - ImFormatString(out_buf, (size_t)out_buf_size, "%s%s%s%s%s", + ImFormatString(g.TempKeychordName, IM_ARRAYSIZE(g.TempKeychordName), "%s%s%s%s%s", (key_chord & ImGuiMod_Ctrl) ? "Ctrl+" : "", (key_chord & ImGuiMod_Shift) ? "Shift+" : "", (key_chord & ImGuiMod_Alt) ? "Alt+" : "", (key_chord & ImGuiMod_Super) ? (g.IO.ConfigMacOSXBehaviors ? "Cmd+" : "Super+") : "", GetKeyName((ImGuiKey)(key_chord & ~ImGuiMod_Mask_))); - return out_buf; + return g.TempKeychordName; } // t0 = previous time (e.g.: g.Time - g.IO.DeltaTime) @@ -8224,6 +8224,7 @@ static void ImGui::UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt) for (int old_routing_idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; old_routing_idx != -1; old_routing_idx = routing_entry->NextEntryIndex) { routing_entry = &rt->Entries[old_routing_idx]; + routing_entry->RoutingCurrScore = routing_entry->RoutingNextScore; routing_entry->RoutingCurr = routing_entry->RoutingNext; // Update entry routing_entry->RoutingNext = ImGuiKeyOwner_None; routing_entry->RoutingNextScore = 255; @@ -8363,7 +8364,7 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteMask_)); // Check that only 1 routing flag is used // [DEBUG] Debug break requested by user - if (g.DebugBreakInShortcutRouting == key_chord) + if (g.DebugBreakInShortcutRouting != 0 && g.DebugBreakInShortcutRouting == ConvertShortcutMod(key_chord)) IM_DEBUG_BREAK(); if (flags & ImGuiInputFlags_RouteUnlessBgFocused) @@ -8371,9 +8372,13 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI return false; // Note how ImGuiInputFlags_RouteAlways won't set routing and thus won't set owner. May want to rework this? if (flags & ImGuiInputFlags_RouteAlways) + { + IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> always\n", GetKeyChordName(key_chord), owner_id, flags); return true; + } const int score = CalcRoutingScore(g.CurrentWindow, owner_id, flags); + IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> score %d\n", GetKeyChordName(key_chord), owner_id, flags, score); if (score == 255) return false; @@ -8389,6 +8394,8 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI } // Return routing state for CURRENT frame + if (routing_data->RoutingCurr == routing_id) + IMGUI_DEBUG_LOG_INPUTROUTING("--> granting current route\n"); return routing_data->RoutingCurr == routing_id; } @@ -14350,6 +14357,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) { ImGuiDebugAllocInfo* info = &g.DebugAllocInfo; Text("%d current allocations", info->TotalAllocCount - info->TotalFreeCount); + if (SmallButton("GC now")) { g.GcCompactAll = true; } Text("Recent frames with allocations:"); int buf_size = IM_ARRAYSIZE(info->LastEntriesBuf); for (int n = buf_size - 1; n >= 0; n--) @@ -14437,10 +14445,9 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGuiKeyRoutingTable* rt = &g.KeysRoutingTable; for (ImGuiKeyRoutingIndex idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; idx != -1; ) { - char key_chord_name[64]; ImGuiKeyRoutingData* routing_data = &rt->Entries[idx]; ImGuiKeyChord key_chord = key | routing_data->Mods; - Text("%s: 0x%08X", GetKeyChordName(key_chord, key_chord_name, IM_ARRAYSIZE(key_chord_name)), routing_data->RoutingCurr); + Text("%s: 0x%08X (scored %d)", GetKeyChordName(key_chord), routing_data->RoutingCurr, routing_data->RoutingCurrScore); DebugLocateItemOnHover(routing_data->RoutingCurr); if (g.IO.ConfigDebugIsDebuggerPresent) { @@ -15096,7 +15103,10 @@ void ImGui::ShowDebugLogWindow(bool* p_open) return; } - CheckboxFlags("All", &g.DebugLogFlags, ImGuiDebugLogFlags_EventMask_); + ImGuiDebugLogFlags all_enable_flags = ImGuiDebugLogFlags_EventMask_ & ~ImGuiDebugLogFlags_EventInputRouting; + CheckboxFlags("All", &g.DebugLogFlags, all_enable_flags); + SetItemTooltip("(except InputRouting which is spammy)"); + ShowDebugLogFlag("ActiveId", ImGuiDebugLogFlags_EventActiveId); ShowDebugLogFlag("Clipper", ImGuiDebugLogFlags_EventClipper); ShowDebugLogFlag("Focus", ImGuiDebugLogFlags_EventFocus); @@ -15104,6 +15114,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open) ShowDebugLogFlag("Nav", ImGuiDebugLogFlags_EventNav); ShowDebugLogFlag("Popup", ImGuiDebugLogFlags_EventPopup); //ShowDebugLogFlag("Selection", ImGuiDebugLogFlags_EventSelection); + ShowDebugLogFlag("InputRouting", ImGuiDebugLogFlags_EventInputRouting); if (SmallButton("Clear")) { diff --git a/imgui.h b/imgui.h index b079473e2ffe..d9d5d689823a 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.2 WIP" -#define IMGUI_VERSION_NUM 19011 +#define IMGUI_VERSION_NUM 19012 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 4c9c8479d2bf..e11c74814e1e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -234,6 +234,7 @@ namespace ImStb #define IMGUI_DEBUG_LOG_SELECTION(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) +#define IMGUI_DEBUG_LOG_INPUTROUTING(...) do{if (g.DebugLogFlags & ImGuiDebugLogFlags_EventInputRouting)IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) // Static Asserts #define IM_STATIC_ASSERT(_COND) static_assert(_COND, "") @@ -1369,11 +1370,12 @@ struct ImGuiKeyRoutingData { ImGuiKeyRoutingIndex NextEntryIndex; ImU16 Mods; // Technically we'd only need 4-bits but for simplify we store ImGuiMod_ values which need 16-bits. ImGuiMod_Shortcut is already translated to Ctrl/Super. + ImU8 RoutingCurrScore; // [DEBUG] For debug display ImU8 RoutingNextScore; // Lower is better (0: perfect score) ImGuiID RoutingCurr; ImGuiID RoutingNext; - ImGuiKeyRoutingData() { NextEntryIndex = -1; Mods = 0; RoutingNextScore = 255; RoutingCurr = RoutingNext = ImGuiKeyOwner_None; } + ImGuiKeyRoutingData() { NextEntryIndex = -1; Mods = 0; RoutingCurrScore = RoutingNextScore = 255; RoutingCurr = RoutingNext = ImGuiKeyOwner_None; } }; // Routing table: maintain a desired owner for each possible key-chord (key + mods), and setup owner in NewFrame() when mods are matching. @@ -1788,8 +1790,9 @@ enum ImGuiDebugLogFlags_ ImGuiDebugLogFlags_EventClipper = 1 << 4, ImGuiDebugLogFlags_EventSelection = 1 << 5, ImGuiDebugLogFlags_EventIO = 1 << 6, + ImGuiDebugLogFlags_EventInputRouting = 1 << 7, - ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO, + ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventInputRouting, ImGuiDebugLogFlags_OutputToTTY = 1 << 20, // Also send output to TTY ImGuiDebugLogFlags_OutputToTestEngine = 1 << 21, // Also send output to Test Engine }; @@ -2190,6 +2193,7 @@ struct ImGuiContext int WantCaptureKeyboardNextFrame; // " int WantTextInputNextFrame; ImVector TempBuffer; // Temporary text buffer + char TempKeychordName[64]; ImGuiContext(ImFontAtlas* shared_font_atlas) { @@ -3129,7 +3133,7 @@ namespace ImGui IMGUI_API ImGuiKeyData* GetKeyData(ImGuiContext* ctx, ImGuiKey key); inline ImGuiKeyData* GetKeyData(ImGuiKey key) { ImGuiContext& g = *GImGui; return GetKeyData(&g, key); } - IMGUI_API const char* GetKeyChordName(ImGuiKeyChord key_chord, char* out_buf, int out_buf_size); + IMGUI_API const char* GetKeyChordName(ImGuiKeyChord key_chord); inline ImGuiKey MouseButtonToKey(ImGuiMouseButton button) { IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT); return (ImGuiKey)(ImGuiKey_MouseLeft + button); } IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f); IMGUI_API ImVec2 GetKeyMagnitude2d(ImGuiKey key_left, ImGuiKey key_right, ImGuiKey key_up, ImGuiKey key_down); From 4b20a0217eb487d1b1716eef30ec408b800d254b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Jan 2024 11:44:21 +0100 Subject: [PATCH 081/237] Internals: add window to FocusScopeStack. (#6798) --- imgui.cpp | 21 ++++++++++++++------- imgui_internal.h | 26 ++++++++++++++++---------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 71f352eb9f19..3ef0f9bd5638 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3075,7 +3075,7 @@ void ImGui::PopStyleColor(int count) ImGuiContext& g = *GImGui; if (g.ColorStack.Size < count) { - IM_ASSERT_USER_ERROR(g.ColorStack.Size > count, "Calling PopStyleColor() too many times: stack underflow."); + IM_ASSERT_USER_ERROR(g.ColorStack.Size > count, "Calling PopStyleColor() too many times!"); count = g.ColorStack.Size; } while (count > 0) @@ -3138,7 +3138,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) *pvar = val; return; } - IM_ASSERT_USER_ERROR(0, "Called PushStyleVar() variant with wrong type!"); + IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); } void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) @@ -3152,7 +3152,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) *pvar = val; return; } - IM_ASSERT_USER_ERROR(0, "Called PushStyleVar() variant with wrong type!"); + IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); } void ImGui::PopStyleVar(int count) @@ -3160,7 +3160,7 @@ void ImGui::PopStyleVar(int count) ImGuiContext& g = *GImGui; if (g.StyleVarStack.Size < count) { - IM_ASSERT_USER_ERROR(g.StyleVarStack.Size > count, "Calling PopStyleVar() too many times: stack underflow."); + IM_ASSERT_USER_ERROR(g.StyleVarStack.Size > count, "Calling PopStyleVar() too many times!"); count = g.StyleVarStack.Size; } while (count > 0) @@ -7798,16 +7798,23 @@ void ImGui::SetWindowFontScale(float scale) void ImGui::PushFocusScope(ImGuiID id) { ImGuiContext& g = *GImGui; - g.FocusScopeStack.push_back(id); + ImGuiFocusScopeData data; + data.ID = id; + data.WindowID = g.CurrentWindow->ID; + g.FocusScopeStack.push_back(data); g.CurrentFocusScopeId = id; } void ImGui::PopFocusScope() { ImGuiContext& g = *GImGui; - IM_ASSERT(g.FocusScopeStack.Size > 0); // Too many PopFocusScope() ? + if (g.FocusScopeStack.Size == 0) + { + IM_ASSERT_USER_ERROR(g.FocusScopeStack.Size > 0, "Calling PopFocusScope() too many times!"); + return; + } g.FocusScopeStack.pop_back(); - g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back() : 0; + g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back().ID : 0; } // Focus = move navigation cursor, set scrolling, set focus window. diff --git a/imgui_internal.h b/imgui_internal.h index e11c74814e1e..2031535c2cfc 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1571,6 +1571,12 @@ struct ImGuiNavItemData void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; } }; +struct ImGuiFocusScopeData +{ + ImGuiID ID; + ImGuiID WindowID; +}; + //----------------------------------------------------------------------------- // [SECTION] Typing-select support //----------------------------------------------------------------------------- @@ -1977,16 +1983,16 @@ struct ImGuiContext bool DebugShowGroupRects; // Shared stacks - ImGuiCol DebugFlashStyleColorIdx; // (Keep close to ColorStack to share cache line) - ImVector ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin() - ImVector StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin() - ImVector FontStack; // Stack for PushFont()/PopFont() - inherited by Begin() - ImVector FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - inherited by BeginChild(), pushed into by Begin() - ImVector ItemFlagsStack; // Stack for PushItemFlag()/PopItemFlag() - inherited by Begin() - 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. + ImGuiCol DebugFlashStyleColorIdx; // (Keep close to ColorStack to share cache line) + ImVector ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin() + ImVector StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin() + ImVector FontStack; // Stack for PushFont()/PopFont() - inherited by Begin() + ImVector FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - inherited by BeginChild(), pushed into by Begin() + ImVector ItemFlagsStack; // Stack for PushItemFlag()/PopItemFlag() - inherited by Begin() + 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. int BeginMenuCount; From e0c8c80adaadbd25157199dcb5e5eadf84ad6f47 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Jan 2024 14:18:10 +0100 Subject: [PATCH 082/237] Shortcut()/SetShortcutRouting(): focus route testing now use ParentWindowForFocusRoute. Automatically set on child-window, manually configurable otherwise. (#6798, #2637, #456) --- imgui.cpp | 26 ++++++++++++++------------ imgui_internal.h | 1 + 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3ef0f9bd5638..a6b92d44c93b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6432,13 +6432,18 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { UpdateWindowParentAndRootLinks(window, flags, parent_window); window->ParentWindowInBeginStack = parent_window_in_stack; + + // There's little point to expose a flag to set this: because the interesting cases won't be using parent_window_in_stack, + // e.g. linking a tool window in a standalone viewport to a document window, regardless of their Begin() stack parenting. (#6798) + window->ParentWindowForFocusRoute = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window_in_stack : NULL; } // Add to focus scope stack - // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow() if ((flags & ImGuiWindowFlags_NavFlattened) == 0) PushFocusScope(window->ID); window->NavRootFocusScopeId = g.CurrentFocusScopeId; + + // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow() g.CurrentWindow = NULL; // Add to popup stack @@ -8325,25 +8330,19 @@ static int CalcRoutingScore(ImGuiWindow* location, ImGuiID owner_id, ImGuiInputF if (owner_id != 0 && g.ActiveId == owner_id) return 1; - // Early out when not in focus stack - if (focused == NULL || focused->RootWindow != location->RootWindow) - return 255; - // Score based on distance to focused window (lower is better) // Assuming both windows are submitting a routing request, // - When Window....... is focused -> Window scores 3 (best), Window/ChildB scores 255 (no match) // - When Window/ChildB is focused -> Window scores 4, Window/ChildB scores 3 (best) // Assuming only WindowA is submitting a routing request, // - When Window/ChildB is focused -> Window scores 4 (best), Window/ChildB doesn't have a score. - for (int next_score = 3; focused != NULL; next_score++) - { + // FIXME: This could be later abstracted as a focus path + for (int next_score = 3; focused != NULL; next_score++, focused = focused->ParentWindowForFocusRoute) if (focused == location) { IM_ASSERT(next_score < 255); return next_score; } - focused = (focused->RootWindow != focused) ? focused->ParentWindow : NULL; // FIXME: This could be later abstracted as a focus path - } return 255; } @@ -10780,6 +10779,8 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags) if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display) EndPopup(); + //g.CurrentWindow->FocusRouteParentWindow = g.CurrentWindow->ParentWindowInBeginStack; + return is_open; } @@ -14995,9 +14996,10 @@ void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label) for (int layer = 0; layer < ImGuiNavLayer_COUNT; layer++) BulletText("NavPreferredScoringPosRel[%d] = {%.1f,%.1f)", layer, (pr[layer].x == FLT_MAX ? -99999.0f : pr[layer].x), (pr[layer].y == FLT_MAX ? -99999.0f : pr[layer].y)); // Display as 99999.0f so it looks neater. BulletText("NavLayersActiveMask: %X, NavLastChildNavWindow: %s", window->DC.NavLayersActiveMask, window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL"); - if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); } - if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow, "ParentWindow"); } - if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); } + if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); } + if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow, "ParentWindow"); } + if (window->ParentWindowForFocusRoute != NULL) { DebugNodeWindow(window->ParentWindowForFocusRoute, "ParentWindowForFocusRoute"); } + if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); } if (window->ColumnsStorage.Size > 0 && TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size)) { for (ImGuiOldColumns& columns : window->ColumnsStorage) diff --git a/imgui_internal.h b/imgui_internal.h index 2031535c2cfc..50b3e3d61943 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2538,6 +2538,7 @@ struct IMGUI_API ImGuiWindow ImGuiWindow* RootWindowPopupTree; // Point to ourself or first ancestor that is not a child window. Cross through popups parent<>child. ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active. ImGuiWindow* RootWindowForNav; // Point to ourself or first ancestor which doesn't have the NavFlattened flag. + ImGuiWindow* ParentWindowForFocusRoute; // Set to manual link a window to its logical parent so that Shortcut() chain are honoerd (e.g. Tool linked to Document) ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.) ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1) From 46e5f44ec8c2535415e6bc713e16d9baac9de78e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Jan 2024 16:56:29 +0100 Subject: [PATCH 083/237] Shortcut()/SetShortcutRouting(): use mixed current window focus scope + ParentWindowForFocusRoute. (#6798, #2637, #456) Amend d474836 Begin: tweak clearing of CurrentWindow as FocusWindow() relies on it now. Addded SetWindowParentWindowForFocusRoute() helper. --- imgui.cpp | 76 ++++++++++++++++++++++++++++++++++-------------- imgui_internal.h | 3 ++ 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a6b92d44c93b..e75b7d957e18 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6439,13 +6439,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } // Add to focus scope stack - if ((flags & ImGuiWindowFlags_NavFlattened) == 0) - PushFocusScope(window->ID); + PushFocusScope((flags & ImGuiWindowFlags_NavFlattened) ? g.CurrentFocusScopeId : window->ID); window->NavRootFocusScopeId = g.CurrentFocusScopeId; - // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow() - g.CurrentWindow = NULL; - // Add to popup stack if (flags & ImGuiWindowFlags_Popup) { @@ -6510,6 +6506,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (window->Appearing) SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false); + // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow() + g.CurrentWindow = NULL; + // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) { @@ -7083,8 +7082,7 @@ void ImGui::End() if (window->DC.CurrentColumns) EndColumns(); PopClipRect(); // Inner window clip rectangle - if ((window->Flags & ImGuiWindowFlags_NavFlattened) == 0) - PopFocusScope(); + PopFocusScope(); // Stop logging if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging @@ -7209,7 +7207,7 @@ void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags) g.NavMousePosDirty = true; g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId g.NavLayer = ImGuiNavLayer_Main; - g.NavFocusScopeId = window ? window->NavRootFocusScopeId : 0; + SetNavFocusScope(window ? window->NavRootFocusScopeId : 0); g.NavIdIsAlive = false; g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid; @@ -7822,6 +7820,33 @@ void ImGui::PopFocusScope() g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back().ID : 0; } +void ImGui::SetNavFocusScope(ImGuiID focus_scope_id) +{ + ImGuiContext& g = *GImGui; + g.NavFocusScopeId = focus_scope_id; + g.NavFocusScopePath.resize(0); // Invalidate + if (focus_scope_id == 0) + return; + IM_ASSERT(g.NavWindow != NULL); + + // Store current path (in reverse order) + if (focus_scope_id == g.CurrentFocusScopeId) + { + // Top of focus stack contains local focus scopes inside current window + for (int n = g.FocusScopeStack.Size - 1; n >= 0 && g.FocusScopeStack.Data[n].WindowID == g.CurrentWindow->ID; n--) + g.NavFocusScopePath.push_back(g.FocusScopeStack.Data[n]); + } + else if (focus_scope_id == g.NavWindow->NavRootFocusScopeId) + g.NavFocusScopePath.push_back({ focus_scope_id, g.NavWindow->ID }); + else + return; + + // Then follow on manually set ParentWindowForFocusRoute field (#6798) + for (ImGuiWindow* window = g.NavWindow->ParentWindowForFocusRoute; window != NULL; window = window->ParentWindowForFocusRoute) + g.NavFocusScopePath.push_back({ window->NavRootFocusScopeId, window->ID }); + IM_ASSERT(g.NavFocusScopePath.Size < 100); // Maximum depth is technically 251 as per CalcRoutingScore(): 254 - 3 +} + // Focus = move navigation cursor, set scrolling, set focus window. void ImGui::FocusItem() { @@ -8318,12 +8343,11 @@ ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord) // - 254: ImGuiInputFlags_RouteGlobalLow // - 255: never route // 'flags' should include an explicit routing policy -static int CalcRoutingScore(ImGuiWindow* location, ImGuiID owner_id, ImGuiInputFlags flags) +static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInputFlags flags) { if (flags & ImGuiInputFlags_RouteFocused) { ImGuiContext& g = *GImGui; - ImGuiWindow* focused = g.NavWindow; // ActiveID gets top priority // (we don't check g.ActiveIdUsingAllKeys here. Routing is applied but if input ownership is tested later it may discard it) @@ -8336,13 +8360,12 @@ static int CalcRoutingScore(ImGuiWindow* location, ImGuiID owner_id, ImGuiInputF // - When Window/ChildB is focused -> Window scores 4, Window/ChildB scores 3 (best) // Assuming only WindowA is submitting a routing request, // - When Window/ChildB is focused -> Window scores 4 (best), Window/ChildB doesn't have a score. - // FIXME: This could be later abstracted as a focus path - for (int next_score = 3; focused != NULL; next_score++, focused = focused->ParentWindowForFocusRoute) - if (focused == location) - { - IM_ASSERT(next_score < 255); - return next_score; - } + if (focus_scope_id == 0) + return 255; + for (int index_in_focus_path = 0; index_in_focus_path < g.NavFocusScopePath.Size; index_in_focus_path++) + if (g.NavFocusScopePath.Data[index_in_focus_path].ID == focus_scope_id) + return 3 + index_in_focus_path; + return 255; } @@ -8383,7 +8406,7 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI return true; } - const int score = CalcRoutingScore(g.CurrentWindow, owner_id, flags); + const int score = CalcRoutingScore(g.CurrentFocusScopeId, owner_id, flags); IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> score %d\n", GetKeyChordName(key_chord), owner_id, flags, score); if (score == 255) return false; @@ -11095,7 +11118,7 @@ void ImGui::SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id IM_ASSERT(nav_layer == ImGuiNavLayer_Main || nav_layer == ImGuiNavLayer_Menu); g.NavId = id; g.NavLayer = nav_layer; - g.NavFocusScopeId = focus_scope_id; + SetNavFocusScope(focus_scope_id); g.NavWindow->NavLastIds[nav_layer] = id; g.NavWindow->NavRectRel[nav_layer] = rect_rel; @@ -11117,7 +11140,7 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent; g.NavId = id; g.NavLayer = nav_layer; - g.NavFocusScopeId = g.CurrentFocusScopeId; + SetNavFocusScope(g.CurrentFocusScopeId); window->NavLastIds[nav_layer] = id; if (g.LastItemData.ID == id) window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect); @@ -11375,6 +11398,7 @@ static void ImGui::NavProcessItem() if (g.NavWindow != window) SetNavWindow(window); // Always refresh g.NavWindow, because some operations such as FocusItem() may not have a window. g.NavLayer = window->DC.NavLayerCurrent; + SetNavFocusScope(g.CurrentFocusScopeId); // Will set g.NavFocusScopeId AND store g.NavFocusScopePath g.NavFocusScopeId = g.CurrentFocusScopeId; g.NavIdIsAlive = true; if (g.LastItemData.InFlags & ImGuiItemFlags_HasSelectionUserData) @@ -11604,7 +11628,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit) if (window->Flags & ImGuiWindowFlags_NoNavInputs) { g.NavId = 0; - g.NavFocusScopeId = window->NavRootFocusScopeId; + SetNavFocusScope(window->NavRootFocusScopeId); return; } @@ -11623,7 +11647,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit) else { g.NavId = window->NavLastIds[0]; - g.NavFocusScopeId = window->NavRootFocusScopeId; + SetNavFocusScope(window->NavRootFocusScopeId); } } @@ -14507,6 +14531,14 @@ void ImGui::ShowMetricsWindow(bool* p_open) Text("NavActivateFlags: %04X", g.NavActivateFlags); Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId); + Text("NavFocusScopePath[] = "); + for (int path_n = g.NavFocusScopePath.Size - 1; path_n >= 0; path_n--) + { + const ImGuiFocusScopeData& focus_scope = g.NavFocusScopePath[path_n]; + SameLine(0.0f, 0.0f); + Text("0x%08X/", focus_scope.ID); + SetItemTooltip("In window \"%s\"", FindWindowByID(focus_scope.WindowID)->Name); + } Text("NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTarget->Name : "NULL"); Unindent(); diff --git a/imgui_internal.h b/imgui_internal.h index 50b3e3d61943..2d4d4c634eef 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2003,6 +2003,7 @@ struct ImGuiContext ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow' ImGuiID NavId; // Focused item for navigation ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope) + ImVector NavFocusScopePath; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId) ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem() ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0 ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat) @@ -2952,6 +2953,7 @@ namespace ImGui IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0); IMGUI_API void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size); IMGUI_API void SetWindowHiddenAndSkipItemsForCurrentFrame(ImGuiWindow* window); + inline void SetWindowParentWindowForFocusRoute(ImGuiWindow* window, ImGuiWindow* parent_window) { window->ParentWindowForFocusRoute = parent_window; } 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); } @@ -3110,6 +3112,7 @@ namespace ImGui IMGUI_API void NavUpdateCurrentWindowIsScrollPushableX(); IMGUI_API void SetNavWindow(ImGuiWindow* window); IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel); + IMGUI_API void SetNavFocusScope(ImGuiID focus_scope_id); // Focus/Activation // This should be part of a larger set of API: FocusItem(offset = -1), FocusItemByID(id), ActivateItem(offset = -1), ActivateItemByID(id) etc. which are From 69b64e2b73ff583c30f4af0dc4983b07b9fd9451 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 16 Jan 2024 11:50:00 +0100 Subject: [PATCH 084/237] Internals: Docking: revert 32a3c61 in favor of user explicitely calling SetWindowParentWindowForFocusRoute(). (#6798) The revert doesn't look the same as 32a3c61 as since then we are baking focus roue into NavFocusScopePath(). --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 58d30b013e78..f318c7c25bcb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6842,7 +6842,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // There's little point to expose a flag to set this: because the interesting cases won't be using parent_window_in_stack, // e.g. linking a tool window in a standalone viewport to a document window, regardless of their Begin() stack parenting. (#6798) - window->ParentWindowForFocusRoute = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window_in_stack : NULL; + window->ParentWindowForFocusRoute = (window->RootWindow != window) ? parent_window_in_stack : NULL; } // Add to focus scope stack From 1cc0eb4d3221a9bf404335836eaf06dec848a9f2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 16 Jan 2024 12:32:00 +0100 Subject: [PATCH 085/237] Internals: Rename NavFocusScopePath to NavFocusRoute + fixed a static analyzer warning. --- imgui.cpp | 21 +++++++++++---------- imgui_internal.h | 3 ++- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e75b7d957e18..958db4902106 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7824,7 +7824,7 @@ void ImGui::SetNavFocusScope(ImGuiID focus_scope_id) { ImGuiContext& g = *GImGui; g.NavFocusScopeId = focus_scope_id; - g.NavFocusScopePath.resize(0); // Invalidate + g.NavFocusRoute.resize(0); // Invalidate if (focus_scope_id == 0) return; IM_ASSERT(g.NavWindow != NULL); @@ -7834,17 +7834,17 @@ void ImGui::SetNavFocusScope(ImGuiID focus_scope_id) { // Top of focus stack contains local focus scopes inside current window for (int n = g.FocusScopeStack.Size - 1; n >= 0 && g.FocusScopeStack.Data[n].WindowID == g.CurrentWindow->ID; n--) - g.NavFocusScopePath.push_back(g.FocusScopeStack.Data[n]); + g.NavFocusRoute.push_back(g.FocusScopeStack.Data[n]); } else if (focus_scope_id == g.NavWindow->NavRootFocusScopeId) - g.NavFocusScopePath.push_back({ focus_scope_id, g.NavWindow->ID }); + g.NavFocusRoute.push_back({ focus_scope_id, g.NavWindow->ID }); else return; // Then follow on manually set ParentWindowForFocusRoute field (#6798) for (ImGuiWindow* window = g.NavWindow->ParentWindowForFocusRoute; window != NULL; window = window->ParentWindowForFocusRoute) - g.NavFocusScopePath.push_back({ window->NavRootFocusScopeId, window->ID }); - IM_ASSERT(g.NavFocusScopePath.Size < 100); // Maximum depth is technically 251 as per CalcRoutingScore(): 254 - 3 + g.NavFocusRoute.push_back({ window->NavRootFocusScopeId, window->ID }); + IM_ASSERT(g.NavFocusRoute.Size < 100); // Maximum depth is technically 251 as per CalcRoutingScore(): 254 - 3 } // Focus = move navigation cursor, set scrolling, set focus window. @@ -8360,10 +8360,11 @@ static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInput // - When Window/ChildB is focused -> Window scores 4, Window/ChildB scores 3 (best) // Assuming only WindowA is submitting a routing request, // - When Window/ChildB is focused -> Window scores 4 (best), Window/ChildB doesn't have a score. + // This essentially follow the window->ParentWindowForFocusRoute chain. if (focus_scope_id == 0) return 255; - for (int index_in_focus_path = 0; index_in_focus_path < g.NavFocusScopePath.Size; index_in_focus_path++) - if (g.NavFocusScopePath.Data[index_in_focus_path].ID == focus_scope_id) + for (int index_in_focus_path = 0; index_in_focus_path < g.NavFocusRoute.Size; index_in_focus_path++) + if (g.NavFocusRoute.Data[index_in_focus_path].ID == focus_scope_id) return 3 + index_in_focus_path; return 255; @@ -14531,10 +14532,10 @@ void ImGui::ShowMetricsWindow(bool* p_open) Text("NavActivateFlags: %04X", g.NavActivateFlags); Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId); - Text("NavFocusScopePath[] = "); - for (int path_n = g.NavFocusScopePath.Size - 1; path_n >= 0; path_n--) + Text("NavFocusRoute[] = "); + for (int path_n = g.NavFocusRoute.Size - 1; path_n >= 0; path_n--) { - const ImGuiFocusScopeData& focus_scope = g.NavFocusScopePath[path_n]; + const ImGuiFocusScopeData& focus_scope = g.NavFocusRoute[path_n]; SameLine(0.0f, 0.0f); Text("0x%08X/", focus_scope.ID); SetItemTooltip("In window \"%s\"", FindWindowByID(focus_scope.WindowID)->Name); diff --git a/imgui_internal.h b/imgui_internal.h index 2d4d4c634eef..94272e971dfc 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2003,7 +2003,7 @@ struct ImGuiContext ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow' ImGuiID NavId; // Focused item for navigation ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope) - ImVector NavFocusScopePath; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId) + ImVector NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain. ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem() ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0 ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat) @@ -2387,6 +2387,7 @@ struct ImGuiContext FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0; FramerateSecPerFrameAccum = 0.0f; WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1; + memset(TempKeychordName, 0, sizeof(TempKeychordName)); } }; From cceff4684a1915c2f4611e5a6f3eb6aad96e9d5b Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 16 Jan 2024 14:00:21 +0100 Subject: [PATCH 086/237] Docking: added ImGuiWindowClass::FocusRouteParentWindowId as a public facing version of SetWindowParentWindowForFocusRoute() (#6798, #2637, #456) --- docs/CHANGELOG.txt | 6 ++++++ imgui.cpp | 10 +++++++++- imgui.h | 1 + imgui_internal.h | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5c40644d8b32..b8141f498966 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,6 +53,12 @@ Other changes: - Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957) - Backends: Vulkan: Fixed handling of ImGui_ImplVulkan_InitInfo::MinAllocationSize field. (#7189, #4238) +Docking+Viewports Branch: + +- Added ImGuiWindowClass::FocusRouteParentWindowId as a way to connect the focus route between + a tool window to a parent document window, so that Shortcuts in the documents are routed when the + tool is focused (regardless of whether the tool is docked or in a floating viewport, etc.) (#6798) + ----------------------------------------------------------------------- VERSION 1.90.1 (Released 2024-01-10) diff --git a/imgui.cpp b/imgui.cpp index f318c7c25bcb..1a7a8ee62328 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6840,9 +6840,17 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) UpdateWindowParentAndRootLinks(window, flags, parent_window); window->ParentWindowInBeginStack = parent_window_in_stack; + // Focus route // There's little point to expose a flag to set this: because the interesting cases won't be using parent_window_in_stack, - // e.g. linking a tool window in a standalone viewport to a document window, regardless of their Begin() stack parenting. (#6798) + // Use for e.g. linking a tool window in a standalone viewport to a document window, regardless of their Begin() stack parenting. (#6798) window->ParentWindowForFocusRoute = (window->RootWindow != window) ? parent_window_in_stack : NULL; + + // Override with SetNextWindowClass() field or direct call to SetWindowParentWindowForFocusRoute() + if (window->WindowClass.FocusRouteParentWindowId != 0) + { + window->ParentWindowForFocusRoute = FindWindowByID(window->WindowClass.FocusRouteParentWindowId); + IM_ASSERT(window->ParentWindowForFocusRoute != 0); // Invalid value for FocusRouteParentWindowId. + } } // Add to focus scope stack diff --git a/imgui.h b/imgui.h index 2101647b6eb1..bdc9342dfae6 100644 --- a/imgui.h +++ b/imgui.h @@ -2399,6 +2399,7 @@ struct ImGuiWindowClass { ImGuiID ClassId; // User data. 0 = Default class (unclassed). Windows of different classes cannot be docked with each others. ImGuiID ParentViewportId; // Hint for the platform backend. -1: use default. 0: request platform backend to not parent the platform. != 0: request platform backend to create a parent<>child relationship between the platform windows. Not conforming backends are free to e.g. parent every viewport to the main viewport or not. + ImGuiID FocusRouteParentWindowId; // ID of parent window for shortcut focus route evaluation, e.g. Shortcut() call from Parent Window will succeed when this window is focused. ImGuiViewportFlags ViewportFlagsOverrideSet; // Viewport flags to set when a window of this class owns a viewport. This allows you to enforce OS decoration or task bar icon, override the defaults on a per-window basis. ImGuiViewportFlags ViewportFlagsOverrideClear; // Viewport flags to clear when a window of this class owns a viewport. This allows you to enforce OS decoration or task bar icon, override the defaults on a per-window basis. ImGuiTabItemFlags TabItemFlagsOverrideSet; // [EXPERIMENTAL] TabItem flags to set when a window of this class gets submitted into a dock node tab bar. May use with ImGuiTabItemFlags_Leading or ImGuiTabItemFlags_Trailing. diff --git a/imgui_internal.h b/imgui_internal.h index cd9a3219ac17..c1870cb94567 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3196,7 +3196,7 @@ namespace ImGui IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0); IMGUI_API void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size); IMGUI_API void SetWindowHiddenAndSkipItemsForCurrentFrame(ImGuiWindow* window); - inline void SetWindowParentWindowForFocusRoute(ImGuiWindow* window, ImGuiWindow* parent_window) { window->ParentWindowForFocusRoute = parent_window; } + inline void SetWindowParentWindowForFocusRoute(ImGuiWindow* window, ImGuiWindow* parent_window) { window->ParentWindowForFocusRoute = parent_window; } // You may also use SetNextWindowClass()'s FocusRouteParentWindowId field. 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); } From 80c83a4277db0fd1b0bd873e355cc9391ea0a4c1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 16 Jan 2024 14:11:30 +0100 Subject: [PATCH 087/237] Docking: added ImGuiDockNodeFlags_DockedWindowsInFocusRoute to configure a dock node to automatically set ParentWindowForFocusRoute on its docked windows. (#6798, #2637, #456) --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 4 ++++ imgui_internal.h | 1 + 3 files changed, 8 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b8141f498966..02be164b1553 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -58,6 +58,9 @@ Docking+Viewports Branch: - Added ImGuiWindowClass::FocusRouteParentWindowId as a way to connect the focus route between a tool window to a parent document window, so that Shortcuts in the documents are routed when the tool is focused (regardless of whether the tool is docked or in a floating viewport, etc.) (#6798) +- Added ImGuiDockNodeFlags_DockedWindowsInFocusRoute to automatically make a dockspace connect + the focus route of its docked window. This is provided a convenience in case you have windows + where a connection is not explicit. (#6798) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 1a7a8ee62328..0d5325aae0a1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6844,6 +6844,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // There's little point to expose a flag to set this: because the interesting cases won't be using parent_window_in_stack, // Use for e.g. linking a tool window in a standalone viewport to a document window, regardless of their Begin() stack parenting. (#6798) window->ParentWindowForFocusRoute = (window->RootWindow != window) ? parent_window_in_stack : NULL; + if (window->ParentWindowForFocusRoute == NULL && window->DockNode != NULL) + if (window->DockNode->MergedFlags & ImGuiDockNodeFlags_DockedWindowsInFocusRoute) + window->ParentWindowForFocusRoute = window->DockNode->HostWindow; // Override with SetNextWindowClass() field or direct call to SetWindowParentWindowForFocusRoute() if (window->WindowClass.FocusRouteParentWindowId != 0) @@ -20380,6 +20383,7 @@ static void DebugNodeDockNodeFlags(ImGuiDockNodeFlags* p_flags, const char* labe CheckboxFlags("HiddenTabBar", p_flags, ImGuiDockNodeFlags_HiddenTabBar); CheckboxFlags("NoWindowMenuButton", p_flags, ImGuiDockNodeFlags_NoWindowMenuButton); CheckboxFlags("NoCloseButton", p_flags, ImGuiDockNodeFlags_NoCloseButton); + CheckboxFlags("DockedWindowsInFocusRoute", p_flags, ImGuiDockNodeFlags_DockedWindowsInFocusRoute); CheckboxFlags("NoDocking", p_flags, ImGuiDockNodeFlags_NoDocking); // Multiple flags CheckboxFlags("NoDockingSplit", p_flags, ImGuiDockNodeFlags_NoDockingSplit); CheckboxFlags("NoDockingSplitOther", p_flags, ImGuiDockNodeFlags_NoDockingSplitOther); diff --git a/imgui_internal.h b/imgui_internal.h index c1870cb94567..6f184f84447c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1723,6 +1723,7 @@ enum ImGuiDockNodeFlagsPrivate_ ImGuiDockNodeFlags_NoCloseButton = 1 << 15, // Saved // Disable close button ImGuiDockNodeFlags_NoResizeX = 1 << 16, // // ImGuiDockNodeFlags_NoResizeY = 1 << 17, // // + ImGuiDockNodeFlags_DockedWindowsInFocusRoute= 1 << 18, // // Any docked window will be automatically be focus-route chained (window->ParentWindowForFocusRoute set to this) so Shortcut() in this window can run when any docked window is focused. // Disable docking/undocking actions in this dockspace or individual node (existing docked nodes will be preserved) // Those are not exposed in public because the desirable sharing/inheriting/copy-flag-on-split behaviors are quite difficult to design and understand. // The two public flags ImGuiDockNodeFlags_NoDockingOverCentralNode/ImGuiDockNodeFlags_NoDockingSplit don't have those issues. From 80d5cb1ab1fd0cf68ffced2fd67c998e350947d2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 16 Jan 2024 16:25:02 +0100 Subject: [PATCH 088/237] Comments around ImGuiInputFlags. --- imgui.cpp | 1 + imgui_internal.h | 46 ++++++++++++++++++++++++++++------------------ 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 958db4902106..37182fc72fb7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8400,6 +8400,7 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI if (flags & ImGuiInputFlags_RouteUnlessBgFocused) if (g.NavWindow == NULL) return false; + // Note how ImGuiInputFlags_RouteAlways won't set routing and thus won't set owner. May want to rework this? if (flags & ImGuiInputFlags_RouteAlways) { diff --git a/imgui_internal.h b/imgui_internal.h index 94272e971dfc..cf7612e580cb 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1403,17 +1403,19 @@ struct ImGuiKeyOwnerData }; // Flags for extended versions of IsKeyPressed(), IsMouseClicked(), Shortcut(), SetKeyOwner(), SetItemKeyOwner() -// Don't mistake with ImGuiInputTextFlags! (for ImGui::InputText() function) +// Don't mistake with ImGuiInputTextFlags! (which is for ImGui::InputText() function) enum ImGuiInputFlags_ { // Flags for IsKeyPressed(), IsKeyChordPressed(), IsMouseClicked(), Shortcut() ImGuiInputFlags_None = 0, - ImGuiInputFlags_Repeat = 1 << 0, // Return true on successive repeats. Default for legacy IsKeyPressed(). NOT Default for legacy IsMouseClicked(). MUST BE == 1. + + // Repeat mode + ImGuiInputFlags_Repeat = 1 << 0, // Enable repeat. Return true on successive repeats. Default for legacy IsKeyPressed(). NOT Default for legacy IsMouseClicked(). MUST BE == 1. ImGuiInputFlags_RepeatRateDefault = 1 << 1, // Repeat rate: Regular (default) ImGuiInputFlags_RepeatRateNavMove = 1 << 2, // Repeat rate: Fast ImGuiInputFlags_RepeatRateNavTweak = 1 << 3, // Repeat rate: Faster - // Specify when repeating key pressed can be interrupted. + // Repeat mode: Specify when repeating key pressed can be interrupted. // In theory ImGuiInputFlags_RepeatUntilOtherKeyPress may be a desirable default, but it would break too many behavior so everything is opt-in. ImGuiInputFlags_RepeatUntilRelease = 1 << 4, // Stop repeating when released (default for all functions except Shortcut). This only exists to allow overriding Shortcut() default behavior. ImGuiInputFlags_RepeatUntilKeyModsChange = 1 << 5, // Stop repeating when released OR if keyboard mods are changed (default for Shortcut) @@ -1424,38 +1426,46 @@ enum ImGuiInputFlags_ ImGuiInputFlags_CondHovered = 1 << 8, // Only set if item is hovered (default to both) ImGuiInputFlags_CondActive = 1 << 9, // Only set if item is active (default to both) ImGuiInputFlags_CondDefault_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, - ImGuiInputFlags_CondMask_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, // Flags for SetKeyOwner(), SetItemKeyOwner() - ImGuiInputFlags_LockThisFrame = 1 << 10, // Access to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared at end of frame. This is useful to make input-owner-aware code steal keys from non-input-owner-aware code. - ImGuiInputFlags_LockUntilRelease = 1 << 11, // Access to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared when the key is released or at end of each frame if key is released. This is useful to make input-owner-aware code steal keys from non-input-owner-aware code. + // Locking is useful to make input-owner-aware code steal keys from non-input-owner-aware code. If all code is input-owner-aware locking would never be necessary. + ImGuiInputFlags_LockThisFrame = 1 << 10, // Further accesses to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared at end of frame. + ImGuiInputFlags_LockUntilRelease = 1 << 11, // Further accesses to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared when the key is released or at end of each frame if key is released. // Routing policies for Shortcut() + low-level SetShortcutRouting() // - The general idea is that several callers register interest in a shortcut, and only one owner gets it. - // - When a policy (other than _RouteAlways) is set, Shortcut() will register itself with SetShortcutRouting(), + // Parent -> call Shortcut(Ctrl+S) // When Parent is focused, Parent gets the shortcut. + // Child1 -> call Shortcut(Ctrl+S) // When Child1 is focused, Child1 gets the shortcut (Child1 overrides Parent shortcuts) + // Child2 -> no call // When Child2 is focused, Parent gets the shortcut. + // The whole system is order independent, so if Child1 does it calls before Parent results will be identical. + // This is an important property as it facilitate working with foreign code or larger codebase. + // - Visualize registered routes in 'Metrics->Inputs' and submitted routes in 'Debug Log->InputRouting'. + // - When a policy (except for _RouteAlways *) is set, Shortcut() will register itself with SetShortcutRouting(), // allowing the system to decide where to route the input among other route-aware calls. - // - Shortcut() uses ImGuiInputFlags_RouteFocused by default: meaning that a simple Shortcut() poll - // will register a route and only succeed when parent window is in the focus stack and if no-one - // with a higher priority is claiming the shortcut. - // - Using ImGuiInputFlags_RouteAlways is roughly equivalent to doing e.g. IsKeyPressed(key) + testing mods. + // (* Using ImGuiInputFlags_RouteAlways is roughly equivalent to calling IsKeyChordPressed(key)). + // - Shortcut() uses ImGuiInputFlags_RouteFocused by default. Meaning that a Shortcut() call will register + // a route and only succeed when parent window is in the focus-stack and if no-one with a higher priority + // is claiming the same shortcut. + // - You can chain two unrelated windows in the focus stack using SetWindowParentWindowForFocusRoute(). // - Priorities: GlobalHigh > Focused (when owner is active item) > Global > Focused (when focused window) > GlobalLow. // - Can select only 1 policy among all available. - ImGuiInputFlags_RouteFocused = 1 << 12, // (Default) Register focused route: Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window. - ImGuiInputFlags_RouteGlobalLow = 1 << 13, // Register route globally (lowest priority: unless a focused window or active item registered the route) -> recommended Global priority. - ImGuiInputFlags_RouteGlobal = 1 << 14, // Register route globally (medium priority: unless an active item registered the route, e.g. CTRL+A registered by InputText). - ImGuiInputFlags_RouteGlobalHigh = 1 << 15, // Register route globally (highest priority: unlikely you need to use that: will interfere with every active items) - ImGuiInputFlags_RouteMask_ = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteGlobalLow | ImGuiInputFlags_RouteGlobalHigh, // _Always not part of this! + ImGuiInputFlags_RouteFocused = 1 << 12, // (Default) Honor focus route: Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window. + ImGuiInputFlags_RouteGlobalLow = 1 << 13, // Register route globally (lowest priority: unless a focused window or active item registered the route) -> recommended Global priority IF you need a Global priority. + ImGuiInputFlags_RouteGlobal = 1 << 14, // Register route globally (medium priority: unless an active item registered the route, e.g. CTRL+A registered by InputText will take priority over this). + ImGuiInputFlags_RouteGlobalHigh = 1 << 15, // Register route globally (higher priority: unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overiden by this) ImGuiInputFlags_RouteAlways = 1 << 16, // Do not register route, poll keys directly. + // Routing polices: extra options ImGuiInputFlags_RouteUnlessBgFocused= 1 << 17, // Global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. - ImGuiInputFlags_RouteExtraMask_ = ImGuiInputFlags_RouteAlways | ImGuiInputFlags_RouteUnlessBgFocused, // [Internal] Mask of which function support which flags 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, // _Always not part of this! ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_, ImGuiInputFlags_SupportedByIsMouseClicked = ImGuiInputFlags_Repeat, - ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteMask_ | ImGuiInputFlags_RouteExtraMask_, + ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteMask_ | ImGuiInputFlags_RouteAlways | ImGuiInputFlags_RouteUnlessBgFocused, ImGuiInputFlags_SupportedBySetKeyOwner = ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease, ImGuiInputFlags_SupportedBySetItemKeyOwner = ImGuiInputFlags_SupportedBySetKeyOwner | ImGuiInputFlags_CondMask_, }; From 5fdcdf7080aade03b30f742dd9369172460fcfd7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 16 Jan 2024 17:51:14 +0100 Subject: [PATCH 089/237] Shortcut: ImGuiInputFlags_RouteFocused policy can filter Shortcuts conflicting with character input when an item is active. (#456) --- imgui.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++++---- imgui.h | 2 +- imgui_internal.h | 1 + 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 37182fc72fb7..5c3eaaf83be6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3596,6 +3596,14 @@ void ImGui::Initialize() g.Viewports.push_back(viewport); g.TempBuffer.resize(1024 * 3 + 1, 0); + // Build KeysMayBeCharInput[] lookup table (1 bool per named key) + for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) + if ((key >= ImGuiKey_0 && key <= ImGuiKey_9) || (key >= ImGuiKey_A && key <= ImGuiKey_Z) || (key >= ImGuiKey_Keypad0 && key <= ImGuiKey_Keypad9) + || key == ImGuiKey_Tab || key == ImGuiKey_Space || key == ImGuiKey_Apostrophe || key == ImGuiKey_Comma || key == ImGuiKey_Minus || key == ImGuiKey_Period + || key == ImGuiKey_Slash || key == ImGuiKey_Semicolon || key == ImGuiKey_Equal || key == ImGuiKey_LeftBracket || key == ImGuiKey_RightBracket || key == ImGuiKey_GraveAccent + || key == ImGuiKey_KeypadDecimal || key == ImGuiKey_KeypadDivide || key == ImGuiKey_KeypadMultiply || key == ImGuiKey_KeypadSubtract || key == ImGuiKey_KeypadAdd || key == ImGuiKey_KeypadEqual) + g.KeysMayBeCharInput.SetBit(key); + #ifdef IMGUI_HAS_DOCK #endif @@ -8308,13 +8316,11 @@ ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord) ImGuiContext& g = *GImGui; ImGuiKeyRoutingTable* rt = &g.KeysRoutingTable; ImGuiKeyRoutingData* routing_data; - if (key_chord & ImGuiMod_Shortcut) - key_chord = ConvertShortcutMod(key_chord); ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_); if (key == ImGuiKey_None) key = ConvertSingleModFlagToKey(&g, mods); - IM_ASSERT(IsNamedKey(key)); + IM_ASSERT(IsNamedKey(key) && (key_chord & ImGuiMod_Shortcut) == 0); // Please call ConvertShortcutMod() in calling function. // Get (in the majority of case, the linked list will have one element so this should be 2 reads. // Subsequent elements will be contiguous in memory as list is sorted/rebuilt in NewFrame). @@ -8378,6 +8384,24 @@ static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInput return 0; } +// We need this to filter some Shortcut() routes when an item e.g. an InputText() is active +// e.g. ImGuiKey_G won't be considered a shortcut when item is active, but ImGuiMod|ImGuiKey_G can be. +static bool IsKeyChordPotentiallyCharInput(ImGuiKeyChord key_chord) +{ + // Mimic 'ignore_char_inputs' logic in InputText() + ImGuiContext& g = *GImGui; + + // When the right mods are pressed it cannot be a char input so we won't filter the shortcut out. + ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_); + const bool ignore_char_inputs = ((mods & ImGuiMod_Ctrl) && !(mods & ImGuiMod_Alt)) || (g.IO.ConfigMacOSXBehaviors && (mods & ImGuiMod_Super)); + if (ignore_char_inputs) + return false; + + // Return true for A-Z, 0-9 and other keys associated to char inputs. Other keys such as F1-F12 won't be filtered. + ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); + return g.KeysMayBeCharInput.TestBit(key); +} + // Request a desired route for an input chord (key + mods). // Return true if the route is available this frame. // - Routes and key ownership are attributed at the beginning of next frame based on best score and mod state. @@ -8392,9 +8416,11 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI flags |= ImGuiInputFlags_RouteGlobalHigh; // IMPORTANT: This is the default for SetShortcutRouting() but NOT Shortcut() else IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteMask_)); // Check that only 1 routing flag is used + if (key_chord & ImGuiMod_Shortcut) + key_chord = ConvertShortcutMod(key_chord); // [DEBUG] Debug break requested by user - if (g.DebugBreakInShortcutRouting != 0 && g.DebugBreakInShortcutRouting == ConvertShortcutMod(key_chord)) + if (g.DebugBreakInShortcutRouting == key_chord) IM_DEBUG_BREAK(); if (flags & ImGuiInputFlags_RouteUnlessBgFocused) @@ -8408,6 +8434,18 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI return true; } + // Specific culling for shortcuts with no modifiers when there's an active id. + // e.g. Shortcut(ImGuiKey_G) also generates 'g' character, should not trigger when InputText() is active. + // but Shortcut(Ctrl+G) should generally trigger when InputText() is active. + // TL;DR: lettered shortcut with no mods or with only Alt mod will not trigger while an item reading text input is active. + // (We cannot filter based on io.InputQueueCharacters[] contents because of trickling and key<>chars submission order are undefined) + if ((flags & ImGuiInputFlags_RouteFocused) && (g.ActiveId != 0 && g.ActiveId != owner_id)) + if (g.IO.WantTextInput && IsKeyChordPotentiallyCharInput(key_chord)) + { + IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> filtered as potential char input\n", GetKeyChordName(key_chord), owner_id, flags); + return false; + } + const int score = CalcRoutingScore(g.CurrentFocusScopeId, owner_id, flags); IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> score %d\n", GetKeyChordName(key_chord), owner_id, flags, score); if (score == 255) @@ -8435,6 +8473,8 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI bool ImGui::TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id) { const ImGuiID routing_id = GetRoutingIdFromOwnerId(owner_id); + if (key_chord & ImGuiMod_Shortcut) + key_chord = ConvertShortcutMod(key_chord); ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord); // FIXME: Could avoid creating entry. return routing_data->RoutingCurr == routing_id; } diff --git a/imgui.h b/imgui.h index d9d5d689823a..c8054a5c4889 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.2 WIP" -#define IMGUI_VERSION_NUM 19012 +#define IMGUI_VERSION_NUM 19013 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index cf7612e580cb..708e0efa5fc8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1974,6 +1974,7 @@ struct ImGuiContext double LastKeyModsChangeTime; // Record the last time key mods changed (affect repeat delay when using shortcut logic) double LastKeyModsChangeFromNoneTime; // Record the last time key mods changed away from being 0 (affect repeat delay when using shortcut logic) double LastKeyboardKeyPressTime; // Record the last time a keyboard key (ignore mouse/gamepad ones) was pressed. + ImBitArrayForNamedKeys KeysMayBeCharInput; // Lookup to tell if a key can emit char input, see IsKeyChordPotentiallyCharInput(). sizeof() = 20 bytes 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) From 03417cc77d15100b18c486b55db409ee5e9c363e Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 17 Jan 2024 13:26:02 +0100 Subject: [PATCH 090/237] Backends: WebGPU: Filling all WGPUDepthStencilState fields explicitly as a recent Dawn update stopped setting default values. (#7232) --- backends/imgui_impl_wgpu.cpp | 7 +++++++ docs/CHANGELOG.txt | 2 ++ 2 files changed, 9 insertions(+) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 638e9fd2455c..c987c6d131cb 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -16,6 +16,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-01-17: Explicitly fill all of WGPUDepthStencilState since standard removed defaults. // 2023-07-13: Use WGPUShaderModuleWGSLDescriptor's code instead of source. use WGPUMipmapFilterMode_Linear instead of WGPUFilterMode_Linear. (#6602) // 2023-04-11: Align buffer sizes. Use WGSL shaders instead of precompiled SPIR-V. // 2023-04-11: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). @@ -654,7 +655,13 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() depth_stencil_state.depthWriteEnabled = false; depth_stencil_state.depthCompare = WGPUCompareFunction_Always; depth_stencil_state.stencilFront.compare = WGPUCompareFunction_Always; + depth_stencil_state.stencilFront.failOp = WGPUStencilOperation_Keep; + depth_stencil_state.stencilFront.depthFailOp = WGPUStencilOperation_Keep; + depth_stencil_state.stencilFront.passOp = WGPUStencilOperation_Keep; depth_stencil_state.stencilBack.compare = WGPUCompareFunction_Always; + depth_stencil_state.stencilBack.failOp = WGPUStencilOperation_Keep; + depth_stencil_state.stencilBack.depthFailOp = WGPUStencilOperation_Keep; + depth_stencil_state.stencilBack.passOp = WGPUStencilOperation_Keep; // Configure disabled depth-stencil state graphics_pipeline_desc.depthStencil = (bd->depthStencilFormat == WGPUTextureFormat_Undefined) ? nullptr : &depth_stencil_state; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 39e7b665419f..dd5eeb36ec01 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -52,6 +52,8 @@ Other changes: - Debug Tools: Debug Log: Added "Input Routing" logging. - Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957) - Backends: Vulkan: Fixed handling of ImGui_ImplVulkan_InitInfo::MinAllocationSize field. (#7189, #4238) +- Backends: WebGPU: Filling all WGPUDepthStencilState fields explicitly as a recent Dawn + update stopped setting default values. (#7232) [@GrigoryGraborenko] ----------------------------------------------------------------------- From d10641b04a3757884193b64753b9728c686d7aa9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 17 Jan 2024 14:02:07 +0100 Subject: [PATCH 091/237] Nav: keyboard/gamepad activation mark widgets as held to give better visual feedback. --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index dd5eeb36ec01..be244c933331 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -46,6 +46,7 @@ Breaking changes: Other changes: +- Nav: keyboard/gamepad activation mark widgets as held to give better visual feedback. - Fixed SetKeyboardFocusHere() not working when current nav focus is in different scope, regression from 1.90.1 related to code scoping Tab presses to local scope. (#7226) [@bratpilz] - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 6b16f55b9143..2b648a604d6b 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -666,7 +666,9 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) { // When activated using Nav, we hold on the ActiveID until activation button is released - if (g.NavActivateDownId != id) + if (g.NavActivateDownId == id) + held = true; + else ClearActiveID(); } if (pressed) From 095665977f61df056608c6bfca1603ed2d500848 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 17 Jan 2024 14:52:05 +0100 Subject: [PATCH 092/237] Nav: marking NavId as hovered in ButtonBehavior() doesn't check for ActiveId. Aimed at allowing activating another item with a shortcut without losing NavId. Initial logic from c2cb2a69, with minor amends db5f1b79c, cea78cc57. --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index be244c933331..df56d4f2670b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,8 @@ Breaking changes: Other changes: - Nav: keyboard/gamepad activation mark widgets as held to give better visual feedback. +- Nav: tweak to logic marking navigated item as hovered when using keyboard, allowing + the hover highlight to stay even while another item is activated. - Fixed SetKeyboardFocusHere() not working when current nav focus is in different scope, regression from 1.90.1 related to code scoping Tab presses to local scope. (#7226) [@bratpilz] - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 2b648a604d6b..bc71aa6282a7 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -599,7 +599,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool // Gamepad/Keyboard navigation // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse. - if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId)) + if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover) if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus)) hovered = true; if (g.NavActivateDownId == id) From f0d1f61fa51ad144ce70c0884bbcb0abefcd717e Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 17 Jan 2024 15:23:30 +0100 Subject: [PATCH 093/237] Internals: commented out long-time obsoleted FocusableItemRegister()/FocusableItemUnregister() documentaton-only leftovers. + --- imgui_internal.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 708e0efa5fc8..e909594f80b5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3474,13 +3474,12 @@ namespace ImGui inline void SetItemUsingMouseWheel() { SetItemKeyOwner(ImGuiKey_MouseWheelY); } // Changed in 1.89 inline bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0) { return TreeNodeUpdateNextOpen(id, flags); } // Renamed in 1.89 - // Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets that used FocusableItemRegister(): + // Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets which used FocusableItemRegister(): // (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)' - // (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0' - // (New) IMGUI_VERSION_NUM >= 18413: using 'ItemAdd(..., ImGuiItemFlags_Inputable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_FocusedTabbing) != 0 || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))' (WIP) - // Widget code are simplified as there's no need to call FocusableItemUnregister() while managing the transition from regular widget to TempInputText() - inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) { IM_ASSERT(0); IM_UNUSED(window); IM_UNUSED(id); return false; } // -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd() - inline void FocusableItemUnregister(ImGuiWindow* window) { IM_ASSERT(0); IM_UNUSED(window); } // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem + // (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0' + // (New) IMGUI_VERSION_NUM >= 18413: using 'ItemAdd(..., ImGuiItemFlags_Inputable)' and 'bool tab_focused = (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))' + //inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) // -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd() + //inline void FocusableItemUnregister(ImGuiWindow* window) // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem #endif #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // Removed in 1.87: Mapping from named key is always identity! From d431d85839b507a9c9041b0e28de7c2443976292 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 17 Jan 2024 15:33:12 +0100 Subject: [PATCH 094/237] Internals: removed obsolete ImPool::GetSize() (last used by implot 0.10, changed in implot 0.11) --- imgui_internal.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index e909594f80b5..c96e2a564449 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -690,9 +690,6 @@ struct ImPool int GetBufSize() const { return Buf.Size; } int GetMapSize() const { return Map.Data.Size; } // It is the map we need iterate to find valid items, since we don't have "alive" storage anywhere T* TryGetMapData(ImPoolIdx n) { int idx = Map.Data[n].val_i; if (idx == -1) return NULL; return GetByIndex(idx); } -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - int GetSize() { return GetMapSize(); } // For ImPlot: should use GetMapSize() from (IMGUI_VERSION_NUM >= 18304) -#endif }; // Helper: ImChunkStream<> From 33fabdf392d0a34b52a4db3eaf467847604d5167 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 17 Jan 2024 15:45:20 +0100 Subject: [PATCH 095/237] Scrollbar() doesn't forcefully mark itself as hovered when held. Weirdly as old as when dinosaurs roamed earth, aka first commit (per-1.0). + Minor alignment in both sense of the term :) Reduce padding in ImGuiNextItemData. --- docs/CHANGELOG.txt | 2 +- imgui_internal.h | 10 +++++----- imgui_widgets.cpp | 1 - 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index df56d4f2670b..418fdc908601 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -49,7 +49,7 @@ Other changes: - Nav: keyboard/gamepad activation mark widgets as held to give better visual feedback. - Nav: tweak to logic marking navigated item as hovered when using keyboard, allowing the hover highlight to stay even while another item is activated. -- Fixed SetKeyboardFocusHere() not working when current nav focus is in different scope, +- Nav: Fixed SetKeyboardFocusHere() not working when current nav focus is in different scope, regression from 1.90.1 related to code scoping Tab presses to local scope. (#7226) [@bratpilz] - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. - Debug Tools: Debug Log: Added "Input Routing" logging. diff --git a/imgui_internal.h b/imgui_internal.h index c96e2a564449..1b4855374822 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1192,9 +1192,9 @@ typedef ImS64 ImGuiSelectionUserData; enum ImGuiNextItemDataFlags_ { - ImGuiNextItemDataFlags_None = 0, - ImGuiNextItemDataFlags_HasWidth = 1 << 0, - ImGuiNextItemDataFlags_HasOpen = 1 << 1, + ImGuiNextItemDataFlags_None = 0, + ImGuiNextItemDataFlags_HasWidth = 1 << 0, + ImGuiNextItemDataFlags_HasOpen = 1 << 1, }; struct ImGuiNextItemData @@ -1202,10 +1202,10 @@ struct ImGuiNextItemData ImGuiNextItemDataFlags Flags; ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap. // Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem() - float Width; // Set by SetNextItemWidth() ImGuiSelectionUserData SelectionUserData; // Set by SetNextItemSelectionUserData() (note that NULL/0 is a valid value, we use -1 == ImGuiSelectionUserData_Invalid to mark invalid values) - ImGuiCond OpenCond; + float Width; // Set by SetNextItemWidth() bool OpenVal; // Set by SetNextItemOpen() + ImGuiCond OpenCond : 8; ImGuiNextItemData() { memset(this, 0, sizeof(*this)); SelectionUserData = -1; } inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()! diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index bc71aa6282a7..3c6937a92008 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -968,7 +968,6 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6 // Click position in scrollbar normalized space (0.0f->1.0f) const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v); - SetHoveredID(id); bool seek_absolute = false; if (g.ActiveIdIsJustActivated) From 1a48a6344665829dbc818617067ffbd5b8cb1b0c Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 17 Jan 2024 15:55:36 +0100 Subject: [PATCH 096/237] Enclosed a few more remaining sections in ifndef IMGUI_DISABLE_DEBUG_TOOLS for completeness. --- imgui.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5c3eaaf83be6..b06fbd32738d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4147,17 +4147,19 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag return false; } +#ifndef IMGUI_DISABLE_DEBUG_TOOLS if (id != 0) { // [DEBUG] Item Picker tool! - // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making - // the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered - // items if we performed the test in ItemAdd(), but that would incur a small runtime cost. + // We perform the check here because reaching is path is rare (1~ time a frame), + // making the cost of this tool near-zero! We could get better call-stack and support picking non-hovered + // items if we performed the test in ItemAdd(), but that would incur a bigger runtime cost. if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id) GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255)); if (g.DebugItemPickerBreakId == id) IM_DEBUG_BREAK(); } +#endif if (g.NavDisableMouseHover) return false; @@ -4792,6 +4794,7 @@ void ImGui::NewFrame() g.GroupStack.resize(0); // [DEBUG] Update debug features +#ifndef IMGUI_DISABLE_DEBUG_TOOLS UpdateDebugToolItemPicker(); UpdateDebugToolStackQueries(); UpdateDebugToolFlashStyleColor(); @@ -4806,6 +4809,7 @@ void ImGui::NewFrame() g.DebugLogFlags &= ~g.DebugLogAutoDisableFlags; g.DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None; } +#endif // Create implicit/fallback window - which we will only render it if the user has added something to it. // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. @@ -4817,10 +4821,12 @@ void ImGui::NewFrame() // [DEBUG] When io.ConfigDebugBeginReturnValue is set, we make Begin()/BeginChild() return false at different level of the window-stack, // allowing to validate correct Begin/End behavior in user code. +#ifndef IMGUI_DISABLE_DEBUG_TOOLS if (g.IO.ConfigDebugBeginReturnValueLoop) g.DebugBeginReturnValueCullDepth = (g.DebugBeginReturnValueCullDepth == -1) ? 0 : ((g.DebugBeginReturnValueCullDepth + ((g.FrameCount % 4) == 0 ? 1 : 0)) % 10); else g.DebugBeginReturnValueCullDepth = -1; +#endif CallContextHooks(&g, ImGuiContextHookType_NewFramePost); } @@ -7059,12 +7065,15 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // [DEBUG] io.ConfigDebugBeginReturnValue override return value to test Begin/End and BeginChild/EndChild behaviors. // (The implicit fallback window is NOT automatically ended allowing it to always be able to receive commands without crashing) - if (!window->IsFallbackWindow && ((g.IO.ConfigDebugBeginReturnValueOnce && window_just_created) || (g.IO.ConfigDebugBeginReturnValueLoop && g.DebugBeginReturnValueCullDepth == g.CurrentWindowStack.Size))) - { - if (window->AutoFitFramesX > 0) { window->AutoFitFramesX++; } - if (window->AutoFitFramesY > 0) { window->AutoFitFramesY++; } - return false; - } +#ifndef IMGUI_DISABLE_DEBUG_TOOLS + if (!window->IsFallbackWindow) + if ((g.IO.ConfigDebugBeginReturnValueOnce && window_just_created) || (g.IO.ConfigDebugBeginReturnValueLoop && g.DebugBeginReturnValueCullDepth == g.CurrentWindowStack.Size)) + { + if (window->AutoFitFramesX > 0) { window->AutoFitFramesX++; } + if (window->AutoFitFramesY > 0) { window->AutoFitFramesY++; } + return false; + } +#endif return !window->SkipItems; } @@ -15561,9 +15570,6 @@ void ImGui::DebugLogV(const char*, va_list) {} void ImGui::ShowDebugLogWindow(bool*) {} void ImGui::ShowIDStackToolWindow(bool*) {} void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType, const void*, const void*) {} -void ImGui::UpdateDebugToolItemPicker() {} -void ImGui::UpdateDebugToolStackQueries() {} -void ImGui::UpdateDebugToolFlashStyleColor() {} #endif // #ifndef IMGUI_DISABLE_DEBUG_TOOLS From ff5f3aa38b5a67d7df94be477986a42dfa29f6df Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 17 Jan 2024 17:27:04 +0100 Subject: [PATCH 097/237] Refactor: moving ItemAdd() into a section abote ItemSize(). No logic change (part 1) Moved KeepAliveID() as well for increased locality. Adding dummy ItemAdd() placeholder to facilitate diffing (otherwise single commit single diff is a mess). --- imgui.cpp | 53 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b06fbd32738d..bd35586f81a5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -75,6 +75,7 @@ CODE // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!) // [SECTION] INPUTS // [SECTION] ERROR CHECKING +// [SECTION] ITEM SUBMISSION // [SECTION] LAYOUT // [SECTION] SCROLLING // [SECTION] TOOLTIPS @@ -3924,17 +3925,6 @@ ImGuiID ImGui::GetHoveredID() return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame; } -// This is called by ItemAdd(). -// Code not using ItemAdd() may need to call this manually otherwise ActiveId will be cleared. In IMGUI_VERSION_NUM < 18717 this was called by GetID(). -void ImGui::KeepAliveID(ImGuiID id) -{ - ImGuiContext& g = *GImGui; - if (g.ActiveId == id) - g.ActiveIdIsAlive = id; - if (g.ActiveIdPreviousFrame == id) - g.ActiveIdPreviousFrameIsAlive = true; -} - void ImGui::MarkItemEdited(ImGuiID id) { // This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit(). @@ -9728,12 +9718,46 @@ void ImGuiStackSizes::CompareWithContextState(ImGuiContext* ctx) IM_ASSERT(SizeOfFocusScopeStack == g.FocusScopeStack.Size && "PushFocusScope/PopFocusScope Mismatch!"); } +//----------------------------------------------------------------------------- +// [SECTION] ITEM SUBMISSION +//----------------------------------------------------------------------------- +// - KeepAliveID() +// - ItemAdd() +//----------------------------------------------------------------------------- + +// Code not using ItemAdd() may need to call this manually otherwise ActiveId will be cleared. In IMGUI_VERSION_NUM < 18717 this was called by GetID(). +void ImGui::KeepAliveID(ImGuiID id) +{ + ImGuiContext& g = *GImGui; + if (g.ActiveId == id) + g.ActiveIdIsAlive = id; + if (g.ActiveIdPreviousFrame == id) + g.ActiveIdPreviousFrameIsAlive = true; +} + +/* + +// Declare item bounding box for clipping and interaction. +// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface +// declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction. +// THIS IS IN THE PERFORMANCE CRITICAL PATH (UNTIL THE CLIPPING TEST AND EARLY-RETURN) +bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + ... + + return true; +} + +*/ + //----------------------------------------------------------------------------- // [SECTION] LAYOUT //----------------------------------------------------------------------------- // - ItemSize() -// - ItemAdd() // - SameLine() // - GetCursorScreenPos() // - SetCursorScreenPos() @@ -9801,10 +9825,7 @@ void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) SameLine(); } -// Declare item bounding box for clipping and interaction. -// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface -// declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction. -// THIS IS IN THE PERFORMANCE CRITICAL PATH (UNTIL THE CLIPPING TEST AND EARLY-RETURN) + bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags) { ImGuiContext& g = *GImGui; From 3b828d3701e9cfff30de47e203e09075c97fe1a0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 17 Jan 2024 17:34:28 +0100 Subject: [PATCH 098/237] Refactor: moving ItemAdd() into a section abote ItemSize(). No logic change (part 2) Diff not ideal (in Fork it looks like ItemSize is moved) but understandable at a glance. --- imgui.cpp | 159 +++++++++++++++++++++++++----------------------------- 1 file changed, 72 insertions(+), 87 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bd35586f81a5..d4c5e754caec 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9735,97 +9735,10 @@ void ImGui::KeepAliveID(ImGuiID id) g.ActiveIdPreviousFrameIsAlive = true; } -/* - // Declare item bounding box for clipping and interaction. // Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface // declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction. // THIS IS IN THE PERFORMANCE CRITICAL PATH (UNTIL THE CLIPPING TEST AND EARLY-RETURN) -bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - ... - - return true; -} - -*/ - - -//----------------------------------------------------------------------------- -// [SECTION] LAYOUT -//----------------------------------------------------------------------------- -// - ItemSize() -// - SameLine() -// - GetCursorScreenPos() -// - SetCursorScreenPos() -// - GetCursorPos(), GetCursorPosX(), GetCursorPosY() -// - SetCursorPos(), SetCursorPosX(), SetCursorPosY() -// - GetCursorStartPos() -// - Indent() -// - Unindent() -// - SetNextItemWidth() -// - PushItemWidth() -// - PushMultiItemsWidths() -// - PopItemWidth() -// - CalcItemWidth() -// - CalcItemSize() -// - GetTextLineHeight() -// - GetTextLineHeightWithSpacing() -// - GetFrameHeight() -// - GetFrameHeightWithSpacing() -// - GetContentRegionMax() -// - GetContentRegionMaxAbs() [Internal] -// - GetContentRegionAvail(), -// - GetWindowContentRegionMin(), GetWindowContentRegionMax() -// - BeginGroup() -// - EndGroup() -// Also see in imgui_widgets: tab bars, and in imgui_tables: tables, columns. -//----------------------------------------------------------------------------- - -// Advance cursor given item size for layout. -// Register minimum needed size so it can extend the bounding box used for auto-fit calculation. -// See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different. -// THIS IS IN THE PERFORMANCE CRITICAL PATH. -void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return; - - // We increase the height in this function to accommodate for baseline offset. - // In theory we should be offsetting the starting position (window->DC.CursorPos), that will be the topic of a larger refactor, - // but since ItemSize() is not yet an API that moves the cursor (to handle e.g. wrapping) enlarging the height has the same effect. - const float offset_to_match_baseline_y = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f; - - const float line_y1 = window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y; - const float line_height = ImMax(window->DC.CurrLineSize.y, /*ImMax(*/window->DC.CursorPos.y - line_y1/*, 0.0f)*/ + size.y + offset_to_match_baseline_y); - - // Always align ourselves on pixel boundaries - //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG] - window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x; - window->DC.CursorPosPrevLine.y = line_y1; - window->DC.CursorPos.x = IM_TRUNC(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Next line - window->DC.CursorPos.y = IM_TRUNC(line_y1 + line_height + g.Style.ItemSpacing.y); // Next line - window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x); - window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y); - //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG] - - window->DC.PrevLineSize.y = line_height; - window->DC.CurrLineSize.y = 0.0f; - window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y); - window->DC.CurrLineTextBaseOffset = 0.0f; - window->DC.IsSameLine = window->DC.IsSetPos = false; - - // Horizontal layout mode - if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) - SameLine(); -} - - bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags) { ImGuiContext& g = *GImGui; @@ -9910,6 +9823,78 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu return true; } + +//----------------------------------------------------------------------------- +// [SECTION] LAYOUT +//----------------------------------------------------------------------------- +// - ItemSize() +// - SameLine() +// - GetCursorScreenPos() +// - SetCursorScreenPos() +// - GetCursorPos(), GetCursorPosX(), GetCursorPosY() +// - SetCursorPos(), SetCursorPosX(), SetCursorPosY() +// - GetCursorStartPos() +// - Indent() +// - Unindent() +// - SetNextItemWidth() +// - PushItemWidth() +// - PushMultiItemsWidths() +// - PopItemWidth() +// - CalcItemWidth() +// - CalcItemSize() +// - GetTextLineHeight() +// - GetTextLineHeightWithSpacing() +// - GetFrameHeight() +// - GetFrameHeightWithSpacing() +// - GetContentRegionMax() +// - GetContentRegionMaxAbs() [Internal] +// - GetContentRegionAvail(), +// - GetWindowContentRegionMin(), GetWindowContentRegionMax() +// - BeginGroup() +// - EndGroup() +// Also see in imgui_widgets: tab bars, and in imgui_tables: tables, columns. +//----------------------------------------------------------------------------- + +// Advance cursor given item size for layout. +// Register minimum needed size so it can extend the bounding box used for auto-fit calculation. +// See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different. +// THIS IS IN THE PERFORMANCE CRITICAL PATH. +void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (window->SkipItems) + return; + + // We increase the height in this function to accommodate for baseline offset. + // In theory we should be offsetting the starting position (window->DC.CursorPos), that will be the topic of a larger refactor, + // but since ItemSize() is not yet an API that moves the cursor (to handle e.g. wrapping) enlarging the height has the same effect. + const float offset_to_match_baseline_y = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f; + + const float line_y1 = window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y; + const float line_height = ImMax(window->DC.CurrLineSize.y, /*ImMax(*/window->DC.CursorPos.y - line_y1/*, 0.0f)*/ + size.y + offset_to_match_baseline_y); + + // Always align ourselves on pixel boundaries + //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG] + window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x; + window->DC.CursorPosPrevLine.y = line_y1; + window->DC.CursorPos.x = IM_TRUNC(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Next line + window->DC.CursorPos.y = IM_TRUNC(line_y1 + line_height + g.Style.ItemSpacing.y); // Next line + window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x); + window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y); + //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG] + + window->DC.PrevLineSize.y = line_height; + window->DC.CurrLineSize.y = 0.0f; + window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y); + window->DC.CurrLineTextBaseOffset = 0.0f; + window->DC.IsSameLine = window->DC.IsSetPos = false; + + // Horizontal layout mode + if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) + SameLine(); +} + // Gets back to previous line and continue with horizontal layout // offset_from_start_x == 0 : follow right after previous item // offset_from_start_x != 0 : align to specified x position (relative to window/group left) From d7c2a0e38f48e7d162405452dbb996438971b34c Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 17 Jan 2024 18:19:00 +0100 Subject: [PATCH 099/237] Shortcut(): fixed 8323a06 adding _Repeat to all Shortcut() calls. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index d4c5e754caec..6ceee2252f05 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9432,7 +9432,7 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags // Default repeat behavior for Shortcut() // So e.g. pressing Ctrl+W and releasing Ctrl while holding W will not trigger the W shortcut. - if ((flags & ImGuiInputFlags_RepeatUntilMask_) == 0) + if ((flags & ImGuiInputFlags_Repeat) != 0 && (flags & ImGuiInputFlags_RepeatUntilMask_) == 0) flags |= ImGuiInputFlags_RepeatUntilKeyModsChange; if (!IsKeyChordPressed(key_chord, owner_id, flags)) From 2f483373355f77a1591c6ee70eb1d5b77537ba9a Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 19 Jan 2024 14:47:56 +0100 Subject: [PATCH 100/237] Examples: Vulkan: Rename compile-time defies for the examples to remove misleading IMGUI_ prefixes. --- examples/example_glfw_vulkan/main.cpp | 18 +++++++++--------- examples/example_sdl2_vulkan/main.cpp | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index e8027c442a7f..7374ebfa66a1 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -31,9 +31,9 @@ #pragma comment(lib, "legacy_stdio_definitions") #endif -//#define IMGUI_UNLIMITED_FRAME_RATE +//#define APP_USE_UNLIMITED_FRAME_RATE #ifdef _DEBUG -#define IMGUI_VULKAN_DEBUG_REPORT +#define APP_USE_VULKAN_DEBUG_REPORT #endif // Data @@ -64,14 +64,14 @@ static void check_vk_result(VkResult err) abort(); } -#ifdef IMGUI_VULKAN_DEBUG_REPORT +#ifdef APP_USE_VULKAN_DEBUG_REPORT static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData) { (void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage); return VK_FALSE; } -#endif // IMGUI_VULKAN_DEBUG_REPORT +#endif // APP_USE_VULKAN_DEBUG_REPORT static bool IsExtensionAvailable(const ImVector& properties, const char* extension) { @@ -139,7 +139,7 @@ static void SetupVulkan(ImVector instance_extensions) #endif // Enabling validation layers -#ifdef IMGUI_VULKAN_DEBUG_REPORT +#ifdef APP_USE_VULKAN_DEBUG_REPORT const char* layers[] = { "VK_LAYER_KHRONOS_validation" }; create_info.enabledLayerCount = 1; create_info.ppEnabledLayerNames = layers; @@ -153,7 +153,7 @@ static void SetupVulkan(ImVector instance_extensions) check_vk_result(err); // Setup the debug report callback -#ifdef IMGUI_VULKAN_DEBUG_REPORT +#ifdef APP_USE_VULKAN_DEBUG_REPORT auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); IM_ASSERT(vkCreateDebugReportCallbackEXT != nullptr); VkDebugReportCallbackCreateInfoEXT debug_report_ci = {}; @@ -258,7 +258,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace); // Select Present Mode -#ifdef IMGUI_UNLIMITED_FRAME_RATE +#ifdef APP_USE_UNLIMITED_FRAME_RATE VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR }; #else VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR }; @@ -275,11 +275,11 @@ static void CleanupVulkan() { vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator); -#ifdef IMGUI_VULKAN_DEBUG_REPORT +#ifdef APP_USE_VULKAN_DEBUG_REPORT // Remove the debug report callback auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT"); vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator); -#endif // IMGUI_VULKAN_DEBUG_REPORT +#endif // APP_USE_VULKAN_DEBUG_REPORT vkDestroyDevice(g_Device, g_Allocator); vkDestroyInstance(g_Instance, g_Allocator); diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index bbd9eec4284d..0b91b1289d48 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -23,9 +23,9 @@ #include //#include -//#define IMGUI_UNLIMITED_FRAME_RATE +//#define APP_USE_UNLIMITED_FRAME_RATE #ifdef _DEBUG -#define IMGUI_VULKAN_DEBUG_REPORT +#define APP_USE_VULKAN_DEBUG_REPORT #endif // Data @@ -52,14 +52,14 @@ static void check_vk_result(VkResult err) abort(); } -#ifdef IMGUI_VULKAN_DEBUG_REPORT +#ifdef APP_USE_VULKAN_DEBUG_REPORT static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData) { (void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage); return VK_FALSE; } -#endif // IMGUI_VULKAN_DEBUG_REPORT +#endif // APP_USE_VULKAN_DEBUG_REPORT static bool IsExtensionAvailable(const ImVector& properties, const char* extension) { @@ -127,7 +127,7 @@ static void SetupVulkan(ImVector instance_extensions) #endif // Enabling validation layers -#ifdef IMGUI_VULKAN_DEBUG_REPORT +#ifdef APP_USE_VULKAN_DEBUG_REPORT const char* layers[] = { "VK_LAYER_KHRONOS_validation" }; create_info.enabledLayerCount = 1; create_info.ppEnabledLayerNames = layers; @@ -141,7 +141,7 @@ static void SetupVulkan(ImVector instance_extensions) check_vk_result(err); // Setup the debug report callback -#ifdef IMGUI_VULKAN_DEBUG_REPORT +#ifdef APP_USE_VULKAN_DEBUG_REPORT auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); IM_ASSERT(vkCreateDebugReportCallbackEXT != nullptr); VkDebugReportCallbackCreateInfoEXT debug_report_ci = {}; @@ -246,7 +246,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace); // Select Present Mode -#ifdef IMGUI_UNLIMITED_FRAME_RATE +#ifdef APP_UNLIMITED_FRAME_RATE VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR }; #else VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR }; @@ -263,11 +263,11 @@ static void CleanupVulkan() { vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator); -#ifdef IMGUI_VULKAN_DEBUG_REPORT +#ifdef APP_USE_VULKAN_DEBUG_REPORT // Remove the debug report callback auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT"); vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator); -#endif // IMGUI_VULKAN_DEBUG_REPORT +#endif // APP_USE_VULKAN_DEBUG_REPORT vkDestroyDevice(g_Device, g_Allocator); vkDestroyInstance(g_Instance, g_Allocator); From 01b99a974dee45181a8fecc70dfb5360852fdff7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 19 Jan 2024 14:50:32 +0100 Subject: [PATCH 101/237] Backends: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236) --- backends/imgui_impl_vulkan.cpp | 27 +++++++++++++++------------ backends/imgui_impl_vulkan.h | 1 + docs/CHANGELOG.txt | 2 ++ examples/example_glfw_vulkan/main.cpp | 2 +- examples/example_sdl2_vulkan/main.cpp | 2 +- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 9c64cf82ca23..b6ca9be80e3a 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -35,6 +35,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2024-01-19: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236) // 2024-01-11: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size (#3957). Fixed MinAllocationSize handing (#7189). // 2024-01-03: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous "best practice" validation layer. (#7189, #4238) // 2024-01-03: Vulkan: Stoped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them. @@ -1354,15 +1355,13 @@ VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_d void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator) { IM_ASSERT(physical_device != VK_NULL_HANDLE && device != VK_NULL_HANDLE); - (void)physical_device; - (void)allocator; + IM_UNUSED(physical_device); // Create Command Buffers VkResult err; for (uint32_t i = 0; i < wd->ImageCount; i++) { ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i]; - ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i]; { VkCommandPoolCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; @@ -1387,6 +1386,11 @@ void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_devi err = vkCreateFence(device, &info, allocator, &fd->Fence); check_vk_result(err); } + } + + for (uint32_t i = 0; i < wd->SemaphoreCount; i++) + { + ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i]; { VkSemaphoreCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; @@ -1422,10 +1426,9 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V // We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one. // Destroy old Framebuffer for (uint32_t i = 0; i < wd->ImageCount; i++) - { ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator); + for (uint32_t i = 0; i < wd->SemaphoreCount; i++) ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator); - } IM_FREE(wd->Frames); IM_FREE(wd->FrameSemaphores); wd->Frames = nullptr; @@ -1484,11 +1487,12 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers); check_vk_result(err); - IM_ASSERT(wd->Frames == nullptr); + IM_ASSERT(wd->Frames == nullptr && wd->FrameSemaphores == nullptr); + wd->SemaphoreCount = wd->ImageCount + 1; wd->Frames = (ImGui_ImplVulkanH_Frame*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_Frame) * wd->ImageCount); - wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->ImageCount); + wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->SemaphoreCount); memset(wd->Frames, 0, sizeof(wd->Frames[0]) * wd->ImageCount); - memset(wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->ImageCount); + memset(wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->SemaphoreCount); for (uint32_t i = 0; i < wd->ImageCount; i++) wd->Frames[i].Backbuffer = backbuffers[i]; } @@ -1596,10 +1600,9 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui //vkQueueWaitIdle(bd->Queue); for (uint32_t i = 0; i < wd->ImageCount; i++) - { ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator); + for (uint32_t i = 0; i < wd->SemaphoreCount; i++) ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator); - } IM_FREE(wd->Frames); IM_FREE(wd->FrameSemaphores); wd->Frames = nullptr; @@ -1873,8 +1876,8 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*) else check_vk_result(err); - wd->FrameIndex = (wd->FrameIndex + 1) % wd->ImageCount; // This is for the next vkWaitForFences() - wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores + wd->FrameIndex = (wd->FrameIndex + 1) % wd->ImageCount; // This is for the next vkWaitForFences() + wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores } void ImGui_ImplVulkan_InitPlatformInterface() diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 84820db5b61f..66796eaa6d29 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -156,6 +156,7 @@ struct ImGui_ImplVulkanH_Window VkClearValue ClearValue; uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount) uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count) + uint32_t SemaphoreCount; // Number of simultaneous in-flight frames + 1, to be able to use it in vkAcquireNextImageKHR uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data) ImGui_ImplVulkanH_Frame* Frames; ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8ee6035c8448..395a9bbe0028 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,6 +53,8 @@ Other changes: regression from 1.90.1 related to code scoping Tab presses to local scope. (#7226) [@bratpilz] - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. - Debug Tools: Debug Log: Added "Input Routing" logging. +- Backends: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by + allocating one extra semaphore than in-flight frames. (#7236) [@mklefrancois] - Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957) - Backends: Vulkan: Fixed handling of ImGui_ImplVulkan_InitInfo::MinAllocationSize field. (#7189, #4238) - Backends: WebGPU: Filling all WGPUDepthStencilState fields explicitly as a recent Dawn diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 5fb86739c4fa..93872e94fb9b 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -376,7 +376,7 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd) return; } check_vk_result(err); - wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores + wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores } // Main code diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index 017f6588742c..3eba6d7279d2 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -364,7 +364,7 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd) return; } check_vk_result(err); - wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores + wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores } // Main code From 5ddfbb80d8667efd16245e450e109890ac950fbc Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 19 Jan 2024 14:50:32 +0100 Subject: [PATCH 102/237] Backends: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236) --- backends/imgui_impl_vulkan.cpp | 23 +++++++++++++---------- backends/imgui_impl_vulkan.h | 1 + docs/CHANGELOG.txt | 2 ++ examples/example_glfw_vulkan/main.cpp | 2 +- examples/example_sdl2_vulkan/main.cpp | 2 +- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 73213c986e56..91bd43b68bc1 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -33,6 +33,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-01-19: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236) // 2024-01-11: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size (#3957). Fixed MinAllocationSize handing (#7189). // 2024-01-03: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous "best practice" validation layer. (#7189, #4238) // 2024-01-03: Vulkan: Stoped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them. @@ -1305,15 +1306,13 @@ VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_d void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator) { IM_ASSERT(physical_device != VK_NULL_HANDLE && device != VK_NULL_HANDLE); - (void)physical_device; - (void)allocator; + IM_UNUSED(physical_device); // Create Command Buffers VkResult err; for (uint32_t i = 0; i < wd->ImageCount; i++) { ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i]; - ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i]; { VkCommandPoolCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; @@ -1338,6 +1337,11 @@ void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_devi err = vkCreateFence(device, &info, allocator, &fd->Fence); check_vk_result(err); } + } + + for (uint32_t i = 0; i < wd->SemaphoreCount; i++) + { + ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i]; { VkSemaphoreCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; @@ -1373,10 +1377,9 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V // We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one. // Destroy old Framebuffer for (uint32_t i = 0; i < wd->ImageCount; i++) - { ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator); + for (uint32_t i = 0; i < wd->SemaphoreCount; i++) ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator); - } IM_FREE(wd->Frames); IM_FREE(wd->FrameSemaphores); wd->Frames = nullptr; @@ -1435,11 +1438,12 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers); check_vk_result(err); - IM_ASSERT(wd->Frames == nullptr); + IM_ASSERT(wd->Frames == nullptr && wd->FrameSemaphores == nullptr); + wd->SemaphoreCount = wd->ImageCount + 1; wd->Frames = (ImGui_ImplVulkanH_Frame*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_Frame) * wd->ImageCount); - wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->ImageCount); + wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->SemaphoreCount); memset(wd->Frames, 0, sizeof(wd->Frames[0]) * wd->ImageCount); - memset(wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->ImageCount); + memset(wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->SemaphoreCount); for (uint32_t i = 0; i < wd->ImageCount; i++) wd->Frames[i].Backbuffer = backbuffers[i]; } @@ -1546,10 +1550,9 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui //vkQueueWaitIdle(bd->Queue); for (uint32_t i = 0; i < wd->ImageCount; i++) - { ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator); + for (uint32_t i = 0; i < wd->SemaphoreCount; i++) ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator); - } IM_FREE(wd->Frames); IM_FREE(wd->FrameSemaphores); wd->Frames = nullptr; diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 490fbb040dfc..94d0bf27f7a7 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -155,6 +155,7 @@ struct ImGui_ImplVulkanH_Window VkClearValue ClearValue; uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount) uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count) + uint32_t SemaphoreCount; // Number of simultaneous in-flight frames + 1, to be able to use it in vkAcquireNextImageKHR uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data) ImGui_ImplVulkanH_Frame* Frames; ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 418fdc908601..c1eae35b55b2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,6 +53,8 @@ Other changes: regression from 1.90.1 related to code scoping Tab presses to local scope. (#7226) [@bratpilz] - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. - Debug Tools: Debug Log: Added "Input Routing" logging. +- Backends: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by + allocating one extra semaphore than in-flight frames. (#7236) [@mklefrancois] - Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957) - Backends: Vulkan: Fixed handling of ImGui_ImplVulkan_InitInfo::MinAllocationSize field. (#7189, #4238) - Backends: WebGPU: Filling all WGPUDepthStencilState fields explicitly as a recent Dawn diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 7374ebfa66a1..98e8dc270ab4 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -376,7 +376,7 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd) return; } check_vk_result(err); - wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores + wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores } // Main code diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index 0b91b1289d48..6de55701ae7a 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -364,7 +364,7 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd) return; } check_vk_result(err); - wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores + wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores } // Main code From 1844f903d5538323cb8d15b68b19671149142c70 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 19 Jan 2024 15:52:11 +0100 Subject: [PATCH 103/237] Nav: space/enter poll check ownership. InputText: declare ownership of Enter key as it doesn't go through Shortcut InputText: no need to call SetShortcutRouting() directly. Tangential to experiments for #7237 --- imgui.cpp | 10 ++++++---- imgui.h | 2 +- imgui_widgets.cpp | 21 +++++++++++++++------ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6ceee2252f05..6bcfd90c0b97 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8445,6 +8445,7 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI return false; } + // FIXME-SHORTCUT: A way to configure the location/focus-scope to test would render this more flexible. const int score = CalcRoutingScore(g.CurrentFocusScopeId, owner_id, flags); IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> score %d\n", GetKeyChordName(key_chord), owner_id, flags, score); if (score == 255) @@ -11825,10 +11826,10 @@ static void ImGui::NavUpdate() g.NavActivateFlags = ImGuiActivateFlags_None; if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { - const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate)); - const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, false)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, false))); - const bool input_down = (nav_keyboard_active && (IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_KeypadEnter))) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput)); - const bool input_pressed = input_down && ((nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, false) || IsKeyPressed(ImGuiKey_KeypadEnter, false))) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, false))); + const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space, ImGuiKeyOwner_None)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_None)); + const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, ImGuiKeyOwner_None)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_None))); + const bool input_down = (nav_keyboard_active && (IsKeyDown(ImGuiKey_Enter, ImGuiKeyOwner_None) || IsKeyDown(ImGuiKey_KeypadEnter, ImGuiKeyOwner_None))) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput, ImGuiKeyOwner_None)); + const bool input_pressed = input_down && ((nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, ImGuiKeyOwner_None) || IsKeyPressed(ImGuiKey_KeypadEnter, ImGuiKeyOwner_None))) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, ImGuiKeyOwner_None))); if (g.ActiveId == 0 && activate_pressed) { g.NavActivateId = g.NavId; @@ -15304,6 +15305,7 @@ void ImGui::DebugLocateItem(ImGuiID target_id) g.DebugBreakInLocateId = false; } +// FIXME: Doesn't work over through a modal window, because they clear HoveredWindow. void ImGui::DebugLocateItemOnHover(ImGuiID target_id) { if (target_id == 0 || !IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenBlockedByPopup)) diff --git a/imgui.h b/imgui.h index c8054a5c4889..8b4ca04da252 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.2 WIP" -#define IMGUI_VERSION_NUM 19013 +#define IMGUI_VERSION_NUM 19014 #define IMGUI_HAS_TABLE /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3c6937a92008..6f1ab902aaca 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4251,6 +4251,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory)) g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); + SetKeyOwner(ImGuiKey_Enter, id); + SetKeyOwner(ImGuiKey_KeypadEnter, id); SetKeyOwner(ImGuiKey_Home, id); SetKeyOwner(ImGuiKey_End, id); if (is_multiline) @@ -4260,8 +4262,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } if (is_osx) SetKeyOwner(ImGuiMod_Alt, id); - if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out as we will use the \t character. - SetShortcutRouting(ImGuiKey_Tab, id); } // We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function) @@ -4390,11 +4390,20 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // We expect backends to emit a Tab key but some also emit a Tab character which we ignore (#2467, #1336) // (For Tab and Enter: Win32/SFML/Allegro are sending both keys and chars, GLFW and SDL are only sending keys. For Space they all send all threes) - if ((flags & ImGuiInputTextFlags_AllowTabInput) && Shortcut(ImGuiKey_Tab, id, ImGuiInputFlags_Repeat) && !is_readonly) + if ((flags & ImGuiInputTextFlags_AllowTabInput) && !is_readonly) { - unsigned int c = '\t'; // Insert TAB - if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) - state->OnKeyPressed((int)c); + if (Shortcut(ImGuiKey_Tab, id, ImGuiInputFlags_Repeat)) + { + unsigned int c = '\t'; // Insert TAB + if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) + state->OnKeyPressed((int)c); + } + // FIXME: Implement Shift+Tab + /* + if (Shortcut(ImGuiKey_Tab | ImGuiMod_Shift, id, ImGuiInputFlags_Repeat)) + { + } + */ } // Process regular text input (before we check for Return because using some IME will effectively send a Return?) From c7edb446caae0b4a30687408d56f4590c3ac2ae3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 19 Jan 2024 16:38:25 +0100 Subject: [PATCH 104/237] Shortcut(): always test ownership. - It doesn't sense to test route without ownership (which may be overrided by code not using routing) - It also wouldn't be possible to call Shortcut() with _None anyway, since successful routing sets ownership. Tangential to experiments for #7237 --- imgui.cpp | 18 ++++++++++++------ imgui_internal.h | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6bcfd90c0b97..f9297f3c67c7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8406,8 +8406,6 @@ static bool IsKeyChordPotentiallyCharInput(ImGuiKeyChord key_chord) // - Routes and key ownership are attributed at the beginning of next frame based on best score and mod state. // (Conceptually this does a "Submit for next frame" + "Test for current frame". // As such, it could be called TrySetXXX or SubmitXXX, or the Submit and Test operations should be separate.) -// - Using 'owner_id == ImGuiKeyOwner_Any/0': auto-assign an owner based on current focus scope (each window has its focus scope by default) -// - Using 'owner_id == ImGuiKeyOwner_None': allows disabling/locking a shortcut. bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags) { ImGuiContext& g = *GImGui; @@ -8415,6 +8413,8 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI flags |= ImGuiInputFlags_RouteGlobalHigh; // IMPORTANT: This is the default for SetShortcutRouting() but NOT Shortcut() else IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteMask_)); // Check that only 1 routing flag is used + IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_None); + if (key_chord & ImGuiMod_Shortcut) key_chord = ConvertShortcutMod(key_chord); @@ -8454,18 +8454,17 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI // Submit routing for NEXT frame (assuming score is sufficient) // FIXME: Could expose a way to use a "serve last" policy for same score resolution (using <= instead of <). ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord); - const ImGuiID routing_id = GetRoutingIdFromOwnerId(owner_id); //const bool set_route = (flags & ImGuiInputFlags_ServeLast) ? (score <= routing_data->RoutingNextScore) : (score < routing_data->RoutingNextScore); if (score < routing_data->RoutingNextScore) { - routing_data->RoutingNext = routing_id; + routing_data->RoutingNext = owner_id; routing_data->RoutingNextScore = (ImU8)score; } // Return routing state for CURRENT frame - if (routing_data->RoutingCurr == routing_id) + if (routing_data->RoutingCurr == owner_id) IMGUI_DEBUG_LOG_INPUTROUTING("--> granting current route\n"); - return routing_data->RoutingCurr == routing_id; + return routing_data->RoutingCurr == owner_id; } // Currently unused by core (but used by tests) @@ -9428,6 +9427,13 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags // When using (owner_id == 0/Any): SetShortcutRouting() will use CurrentFocusScopeId and filter with this, so IsKeyPressed() is fine with he 0/Any. if ((flags & ImGuiInputFlags_RouteMask_) == 0) flags |= ImGuiInputFlags_RouteFocused; + + // Using 'owner_id == ImGuiKeyOwner_Any/0': auto-assign an owner based on current focus scope (each window has its focus scope by default) + // Effectively makes Shortcut() always input-owner aware. + if (owner_id == ImGuiKeyOwner_Any || owner_id == ImGuiKeyOwner_None) + owner_id = GetRoutingIdFromOwnerId(owner_id); + + // Submit route if (!SetShortcutRouting(key_chord, owner_id, flags)) return false; diff --git a/imgui_internal.h b/imgui_internal.h index 1b4855374822..c51c827998f1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3210,7 +3210,7 @@ namespace ImGui // - Shortcut() submits a route then if currently can be routed calls IsKeyChordPressed() -> function has (desirable) side-effects. IMGUI_API bool IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0); - IMGUI_API bool SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0); + IMGUI_API bool SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags = 0); // owner_id needs to be explicit and cannot be 0 IMGUI_API bool TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id); IMGUI_API ImGuiKeyRoutingData* GetShortcutRoutingData(ImGuiKeyChord key_chord); From 763100b38580dc661e190452b35bf64efd01147e Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 19 Jan 2024 18:37:21 +0100 Subject: [PATCH 105/237] Nav: Fixed pressing Escape while in a child window with _NavFlattened flag. (#7237) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c1eae35b55b2..4c524a73ff9b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,6 +51,7 @@ Other changes: the hover highlight to stay even while another item is activated. - Nav: Fixed SetKeyboardFocusHere() not working when current nav focus is in different scope, regression from 1.90.1 related to code scoping Tab presses to local scope. (#7226) [@bratpilz] +- Nav: Fixed pressing Escape while in a child window with _NavFlattened flag. (#7237) - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. - Debug Tools: Debug Log: Added "Input Routing" logging. - Backends: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by diff --git a/imgui.cpp b/imgui.cpp index f9297f3c67c7..ba3c97b07a8d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12247,15 +12247,14 @@ static void ImGui::NavUpdateCancelRequest() NavRestoreLayer(ImGuiNavLayer_Main); NavRestoreHighlightAfterMove(); } - else if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow) + else if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow && !(g.NavWindow->RootWindowForNav->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->RootWindowForNav->ParentWindow) { // Exit child window - ImGuiWindow* child_window = g.NavWindow; - ImGuiWindow* parent_window = g.NavWindow->ParentWindow; + ImGuiWindow* child_window = g.NavWindow->RootWindowForNav; + ImGuiWindow* parent_window = child_window->ParentWindow; IM_ASSERT(child_window->ChildId != 0); - ImRect child_rect = child_window->Rect(); FocusWindow(parent_window); - SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, WindowRectAbsToRel(parent_window, child_rect)); + SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, WindowRectAbsToRel(parent_window, child_window->Rect())); NavRestoreHighlightAfterMove(); } else if (g.OpenPopupStack.Size > 0 && g.OpenPopupStack.back().Window != NULL && !(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal)) From 788747f86359066d850783ebf8d4ebfad7656fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Cicho=C5=84?= Date: Mon, 22 Jan 2024 10:45:41 +0100 Subject: [PATCH 106/237] Examples: Emscripten+WebGPU: Remove use of deprecated ObjectBase<...>::Release in favor of ::MoveToCHandle (#7251) --- examples/example_emscripten_wgpu/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index 590453c15fcb..73791a54ec40 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -128,7 +128,7 @@ static bool InitWGPU() wgpu::Surface surface = instance.CreateSurface(&surface_desc); wgpu::Adapter adapter = {}; wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter); - wgpu_surface = surface.Release(); + wgpu_surface = surface.MoveToCHandle(); return true; } From 15908502ed6da3ca3a3b72d1a9d8f6097315db1c Mon Sep 17 00:00:00 2001 From: Frank McCoy Date: Mon, 22 Jan 2024 01:03:46 -0800 Subject: [PATCH 107/237] Backends: Vulkan: Define NOMINMAX when VK_USE_PLATFORM_WIN32_KHR is defined. (#7250) --- backends/imgui_impl_vulkan.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 94d0bf27f7a7..94c5b1d30efe 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -46,7 +46,12 @@ #if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES) #define VK_NO_PROTOTYPES #endif +#if defined(VK_USE_PLATFORM_WIN32_KHR) && !defined(NOMINMAX) +#define NOMINMAX #include +#else +#include +#endif // Initialization data, for ImGui_ImplVulkan_Init() // [Please zero-clear before use!] From e3c7ff944d52154c3e5e6db6d3b8fba65b1a1547 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jan 2024 14:20:24 +0100 Subject: [PATCH 108/237] Examples: Emscripten+WebGPU: slightly refactor like other Emscripten compatible Desktop examples, as aiming to make this suppot desktop eventually. Also aimed at reducing diff for https://github.com/ocornut/imgui/pull/7132 tho this will lead in conflict. --- .../{Makefile => Makefile.emscripten} | 0 examples/example_emscripten_wgpu/README.md | 2 +- examples/example_emscripten_wgpu/main.cpp | 289 ++++++++++-------- 3 files changed, 156 insertions(+), 135 deletions(-) rename examples/example_emscripten_wgpu/{Makefile => Makefile.emscripten} (100%) diff --git a/examples/example_emscripten_wgpu/Makefile b/examples/example_emscripten_wgpu/Makefile.emscripten similarity index 100% rename from examples/example_emscripten_wgpu/Makefile rename to examples/example_emscripten_wgpu/Makefile.emscripten diff --git a/examples/example_emscripten_wgpu/README.md b/examples/example_emscripten_wgpu/README.md index c4c4dec76fa3..e60025da2602 100644 --- a/examples/example_emscripten_wgpu/README.md +++ b/examples/example_emscripten_wgpu/README.md @@ -6,7 +6,7 @@ - You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup. -- Then build using `make` while in the `example_emscripten_wgpu/` directory. +- Then build using `make -f Makefile.emscripten` while in the `example_emscripten_wgpu/` directory. - Requires recent Emscripten as WGPU is still a work-in-progress API. diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index 73791a54ec40..cb09d4220a33 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -11,13 +11,20 @@ #include "imgui_impl_glfw.h" #include "imgui_impl_wgpu.h" #include +#ifdef __EMSCRIPTEN__ #include #include #include +#endif #include #include #include +// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details. +#ifdef __EMSCRIPTEN__ +#include "../libs/emscripten/emscripten_mainloop_stub.h" +#endif + // Global WebGPU required states static WGPUDevice wgpu_device = nullptr; static WGPUSurface wgpu_surface = nullptr; @@ -27,15 +34,32 @@ static int wgpu_swap_chain_width = 0; static int wgpu_swap_chain_height = 0; // Forward declarations -static void MainLoopStep(void* window); static bool InitWGPU(); -static void print_glfw_error(int error, const char* description); -static void print_wgpu_error(WGPUErrorType error_type, const char* message, void*); +static void CreateSwapChain(int width, int height); + +static void glfw_error_callback(int error, const char* description) +{ + printf("GLFW Error %d: %s\n", error, description); +} + +static void wgpu_error_callback(WGPUErrorType error_type, const char* message, void*) +{ + const char* error_type_lbl = ""; + switch (error_type) + { + case WGPUErrorType_Validation: error_type_lbl = "Validation"; break; + case WGPUErrorType_OutOfMemory: error_type_lbl = "Out of memory"; break; + case WGPUErrorType_Unknown: error_type_lbl = "Unknown"; break; + case WGPUErrorType_DeviceLost: error_type_lbl = "Device lost"; break; + default: error_type_lbl = "Unknown"; + } + printf("%s error: %s\n", error_type_lbl, message); +} // Main code int main(int, char**) { - glfwSetErrorCallback(print_glfw_error); + glfwSetErrorCallback(glfw_error_callback); if (!glfwInit()) return 1; @@ -43,11 +67,8 @@ int main(int, char**) // This needs to be done explicitly later. glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr); - if (!window) - { - glfwTerminate(); + if (window == nullptr) return 1; - } // Initialize the WebGPU environment if (!InitWGPU()) @@ -66,17 +87,15 @@ int main(int, char**) io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls - // For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file. - // You may manually call LoadIniSettingsFromMemory() to load settings from your own storage. - io.IniFilename = nullptr; - // Setup Dear ImGui style ImGui::StyleColorsDark(); //ImGui::StyleColorsLight(); // Setup Platform/Renderer backends ImGui_ImplGlfw_InitForOther(window, true); +#ifdef __EMSCRIPTEN__ ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback("#canvas"); +#endif ImGui_ImplWGPU_Init(wgpu_device, 3, wgpu_preferred_fmt, WGPUTextureFormat_Undefined); // Load Fonts @@ -99,10 +118,117 @@ int main(int, char**) //IM_ASSERT(font != nullptr); #endif - // This function will directly return and exit the main function. - // Make sure that no required objects get cleaned up. - // This way we can use the browsers 'requestAnimationFrame' to control the rendering. - emscripten_set_main_loop_arg(MainLoopStep, window, 0, false); + // Our state + bool show_demo_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + + // Main loop +#ifdef __EMSCRIPTEN__ + // For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file. + // You may manually call LoadIniSettingsFromMemory() to load settings from your own storage. + io.IniFilename = nullptr; + EMSCRIPTEN_MAINLOOP_BEGIN +#else + while (!glfwWindowShouldClose(window)) +#endif + { + // Poll and handle events (inputs, window resize, etc.) + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + glfwPollEvents(); + + // React to changes in screen size + int width, height; + glfwGetFramebufferSize((GLFWwindow*)window, &width, &height); + if (width != wgpu_swap_chain_width && height != wgpu_swap_chain_height) + { + ImGui_ImplWGPU_InvalidateDeviceObjects(); + CreateSwapChain(width, height); + ImGui_ImplWGPU_CreateDeviceObjects(); + } + + // Start the Dear ImGui frame + ImGui_ImplWGPU_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). + if (show_demo_window) + ImGui::ShowDemoWindow(&show_demo_window); + + // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window. + { + static float f = 0.0f; + static int counter = 0; + + ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. + + ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); + ImGui::End(); + } + + // 3. Show another simple window. + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; + ImGui::End(); + } + + // Rendering + ImGui::Render(); + + WGPURenderPassColorAttachment color_attachments = {}; + color_attachments.loadOp = WGPULoadOp_Clear; + color_attachments.storeOp = WGPUStoreOp_Store; + color_attachments.clearValue = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w }; + color_attachments.view = wgpuSwapChainGetCurrentTextureView(wgpu_swap_chain); + + WGPURenderPassDescriptor render_pass_desc = {}; + render_pass_desc.colorAttachmentCount = 1; + render_pass_desc.colorAttachments = &color_attachments; + render_pass_desc.depthStencilAttachment = nullptr; + + WGPUCommandEncoderDescriptor enc_desc = {}; + WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(wgpu_device, &enc_desc); + + WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &render_pass_desc); + ImGui_ImplWGPU_RenderDrawData(ImGui::GetDrawData(), pass); + wgpuRenderPassEncoderEnd(pass); + + WGPUCommandBufferDescriptor cmd_buffer_desc = {}; + WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc); + WGPUQueue queue = wgpuDeviceGetQueue(wgpu_device); + wgpuQueueSubmit(queue, 1, &cmd_buffer); + } +#ifdef __EMSCRIPTEN__ + EMSCRIPTEN_MAINLOOP_END; +#endif + + // Cleanup + ImGui_ImplWGPU_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + + glfwDestroyWindow(window); + glfwTerminate(); return 0; } @@ -113,7 +239,7 @@ static bool InitWGPU() if (!wgpu_device) return false; - wgpuDeviceSetUncapturedErrorCallback(wgpu_device, print_wgpu_error, nullptr); + wgpuDeviceSetUncapturedErrorCallback(wgpu_device, wgpu_error_callback, nullptr); // Use C++ wrapper due to misbehavior in Emscripten. // Some offset computation for wgpuInstanceCreateSurface in JavaScript @@ -133,122 +259,17 @@ static bool InitWGPU() return true; } -static void MainLoopStep(void* window) +static void CreateSwapChain(int width, int height) { - ImGuiIO& io = ImGui::GetIO(); - - glfwPollEvents(); - - int width, height; - glfwGetFramebufferSize((GLFWwindow*)window, &width, &height); - - // React to changes in screen size - if (width != wgpu_swap_chain_width && height != wgpu_swap_chain_height) - { - ImGui_ImplWGPU_InvalidateDeviceObjects(); - if (wgpu_swap_chain) - wgpuSwapChainRelease(wgpu_swap_chain); - wgpu_swap_chain_width = width; - wgpu_swap_chain_height = height; - WGPUSwapChainDescriptor swap_chain_desc = {}; - swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment; - swap_chain_desc.format = wgpu_preferred_fmt; - swap_chain_desc.width = width; - swap_chain_desc.height = height; - swap_chain_desc.presentMode = WGPUPresentMode_Fifo; - wgpu_swap_chain = wgpuDeviceCreateSwapChain(wgpu_device, wgpu_surface, &swap_chain_desc); - ImGui_ImplWGPU_CreateDeviceObjects(); - } - - // Start the Dear ImGui frame - ImGui_ImplWGPU_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - - // Our state - // (we use static, which essentially makes the variable globals, as a convenience to keep the example code easy to follow) - static bool show_demo_window = true; - static bool show_another_window = false; - static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); - - // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). - if (show_demo_window) - ImGui::ShowDemoWindow(&show_demo_window); - - // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window. - { - static float f = 0.0f; - static int counter = 0; - - ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. - - ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) - ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state - ImGui::Checkbox("Another Window", &show_another_window); - - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color - - if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) - counter++; - ImGui::SameLine(); - ImGui::Text("counter = %d", counter); - - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); - ImGui::End(); - } - - // 3. Show another simple window. - if (show_another_window) - { - ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) - ImGui::Text("Hello from another window!"); - if (ImGui::Button("Close Me")) - show_another_window = false; - ImGui::End(); - } - - // Rendering - ImGui::Render(); - - WGPURenderPassColorAttachment color_attachments = {}; - color_attachments.loadOp = WGPULoadOp_Clear; - color_attachments.storeOp = WGPUStoreOp_Store; - color_attachments.clearValue = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w }; - color_attachments.view = wgpuSwapChainGetCurrentTextureView(wgpu_swap_chain); - WGPURenderPassDescriptor render_pass_desc = {}; - render_pass_desc.colorAttachmentCount = 1; - render_pass_desc.colorAttachments = &color_attachments; - render_pass_desc.depthStencilAttachment = nullptr; - - WGPUCommandEncoderDescriptor enc_desc = {}; - WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(wgpu_device, &enc_desc); - - WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &render_pass_desc); - ImGui_ImplWGPU_RenderDrawData(ImGui::GetDrawData(), pass); - wgpuRenderPassEncoderEnd(pass); - - WGPUCommandBufferDescriptor cmd_buffer_desc = {}; - WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc); - WGPUQueue queue = wgpuDeviceGetQueue(wgpu_device); - wgpuQueueSubmit(queue, 1, &cmd_buffer); -} - -static void print_glfw_error(int error, const char* description) -{ - printf("GLFW Error %d: %s\n", error, description); -} - -static void print_wgpu_error(WGPUErrorType error_type, const char* message, void*) -{ - const char* error_type_lbl = ""; - switch (error_type) - { - case WGPUErrorType_Validation: error_type_lbl = "Validation"; break; - case WGPUErrorType_OutOfMemory: error_type_lbl = "Out of memory"; break; - case WGPUErrorType_Unknown: error_type_lbl = "Unknown"; break; - case WGPUErrorType_DeviceLost: error_type_lbl = "Device lost"; break; - default: error_type_lbl = "Unknown"; - } - printf("%s error: %s\n", error_type_lbl, message); + if (wgpu_swap_chain) + wgpuSwapChainRelease(wgpu_swap_chain); + wgpu_swap_chain_width = width; + wgpu_swap_chain_height = height; + WGPUSwapChainDescriptor swap_chain_desc = {}; + swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment; + swap_chain_desc.format = wgpu_preferred_fmt; + swap_chain_desc.width = width; + swap_chain_desc.height = height; + swap_chain_desc.presentMode = WGPUPresentMode_Fifo; + wgpu_swap_chain = wgpuDeviceCreateSwapChain(wgpu_device, wgpu_surface, &swap_chain_desc); } From 831d42c1ab3df7324328a60ccb544a4dd02aa185 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jan 2024 14:46:41 +0100 Subject: [PATCH 109/237] Backends: WebGPU: ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure instead of variety of parameters, allowing for easier further changes. (#7240) --- backends/imgui_impl_wgpu.cpp | 37 ++++++++++++----------- backends/imgui_impl_wgpu.h | 11 ++++++- docs/CHANGELOG.txt | 2 ++ examples/example_emscripten_wgpu/main.cpp | 7 ++++- 4 files changed, 38 insertions(+), 19 deletions(-) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index c987c6d131cb..565aaad75565 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -16,6 +16,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-01-22: (Breaking) ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure instead of variety of parameters, allowing for easier further changes. // 2024-01-17: Explicitly fill all of WGPUDepthStencilState since standard removed defaults. // 2023-07-13: Use WGPUShaderModuleWGSLDescriptor's code instead of source. use WGPUMipmapFilterMode_Linear instead of WGPUFilterMode_Linear. (#6602) // 2023-04-11: Align buffer sizes. Use WGSL shaders instead of precompiled SPIR-V. @@ -73,16 +74,17 @@ struct Uniforms struct ImGui_ImplWGPU_Data { - WGPUDevice wgpuDevice = nullptr; - WGPUQueue defaultQueue = nullptr; - WGPUTextureFormat renderTargetFormat = WGPUTextureFormat_Undefined; - WGPUTextureFormat depthStencilFormat = WGPUTextureFormat_Undefined; - WGPURenderPipeline pipelineState = nullptr; - - RenderResources renderResources; - FrameResources* pFrameResources = nullptr; - unsigned int numFramesInFlight = 0; - unsigned int frameIndex = UINT_MAX; + ImGui_ImplWGPU_InitInfo initInfo; + WGPUDevice wgpuDevice = nullptr; + WGPUQueue defaultQueue = nullptr; + WGPUTextureFormat renderTargetFormat = WGPUTextureFormat_Undefined; + WGPUTextureFormat depthStencilFormat = WGPUTextureFormat_Undefined; + WGPURenderPipeline pipelineState = nullptr; + + RenderResources renderResources; + FrameResources* pFrameResources = nullptr; + unsigned int numFramesInFlight = 0; + unsigned int frameIndex = UINT_MAX; }; // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts @@ -712,7 +714,7 @@ void ImGui_ImplWGPU_InvalidateDeviceObjects() SafeRelease(bd->pFrameResources[i]); } -bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextureFormat rt_format, WGPUTextureFormat depth_format) +bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info) { ImGuiIO& io = ImGui::GetIO(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); @@ -723,11 +725,12 @@ bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextur io.BackendRendererName = "imgui_impl_webgpu"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. - bd->wgpuDevice = device; + bd->initInfo = *init_info; + bd->wgpuDevice = init_info->Device; bd->defaultQueue = wgpuDeviceGetQueue(bd->wgpuDevice); - bd->renderTargetFormat = rt_format; - bd->depthStencilFormat = depth_format; - bd->numFramesInFlight = num_frames_in_flight; + bd->renderTargetFormat = init_info->RenderTargetFormat; + bd->depthStencilFormat = init_info->DepthStencilFormat; + bd->numFramesInFlight = init_info->NumFramesInFlight; bd->frameIndex = UINT_MAX; bd->renderResources.FontTexture = nullptr; @@ -740,8 +743,8 @@ bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextur bd->renderResources.ImageBindGroupLayout = nullptr; // Create buffers with a default size (they will later be grown as needed) - bd->pFrameResources = new FrameResources[num_frames_in_flight]; - for (int i = 0; i < num_frames_in_flight; i++) + bd->pFrameResources = new FrameResources[bd->numFramesInFlight]; + for (int i = 0; i < bd->numFramesInFlight; i++) { FrameResources* fr = &bd->pFrameResources[i]; fr->IndexBuffer = nullptr; diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h index 14d9fccc1adb..55f96b8e681f 100644 --- a/backends/imgui_impl_wgpu.h +++ b/backends/imgui_impl_wgpu.h @@ -20,7 +20,16 @@ #include -IMGUI_IMPL_API bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextureFormat rt_format, WGPUTextureFormat depth_format = WGPUTextureFormat_Undefined); +// Initialization data, for ImGui_ImplWGPU_Init() +struct ImGui_ImplWGPU_InitInfo +{ + WGPUDevice Device; + int NumFramesInFlight = 3; + WGPUTextureFormat RenderTargetFormat = WGPUTextureFormat_Undefined; + WGPUTextureFormat DepthStencilFormat = WGPUTextureFormat_Undefined; +}; + +IMGUI_IMPL_API bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info); IMGUI_IMPL_API void ImGui_ImplWGPU_Shutdown(); IMGUI_IMPL_API void ImGui_ImplWGPU_NewFrame(); IMGUI_IMPL_API void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4c524a73ff9b..36ad82f491b5 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,8 @@ Breaking changes: - Commented out ImGuiIO::ImeWindowHandle obsoleted in 1.87 in favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'. +- Backends: WebGPU: ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure + instead of variety of parameters, allowing for easier further changes. (#7240) Other changes: diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index cb09d4220a33..910da083396b 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -96,7 +96,12 @@ int main(int, char**) #ifdef __EMSCRIPTEN__ ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback("#canvas"); #endif - ImGui_ImplWGPU_Init(wgpu_device, 3, wgpu_preferred_fmt, WGPUTextureFormat_Undefined); + ImGui_ImplWGPU_InitInfo init_info; + init_info.Device = wgpu_device; + init_info.NumFramesInFlight = 3; + init_info.RenderTargetFormat = wgpu_preferred_fmt; + init_info.DepthStencilFormat = WGPUTextureFormat_Undefined; + ImGui_ImplWGPU_Init(&init_info); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. From 5fc0a361b2467b61c5ea50065fc843a1b84ee4d7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jan 2024 14:54:45 +0100 Subject: [PATCH 110/237] Backends: WebGPU: added ImGui_ImplWGPU_InitInfo::PipelineMultisampleState. (#7240) --- backends/imgui_impl_wgpu.cpp | 5 ++--- backends/imgui_impl_wgpu.h | 8 ++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 565aaad75565..9078287d8332 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -16,6 +16,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-01-22: Added configurable PipelineMultisampleState struct. (#7240) // 2024-01-22: (Breaking) ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure instead of variety of parameters, allowing for easier further changes. // 2024-01-17: Explicitly fill all of WGPUDepthStencilState since standard removed defaults. // 2023-07-13: Use WGPUShaderModuleWGSLDescriptor's code instead of source. use WGPUMipmapFilterMode_Linear instead of WGPUFilterMode_Linear. (#6602) @@ -568,9 +569,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() graphics_pipeline_desc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined; graphics_pipeline_desc.primitive.frontFace = WGPUFrontFace_CW; graphics_pipeline_desc.primitive.cullMode = WGPUCullMode_None; - graphics_pipeline_desc.multisample.count = 1; - graphics_pipeline_desc.multisample.mask = UINT_MAX; - graphics_pipeline_desc.multisample.alphaToCoverageEnabled = false; + graphics_pipeline_desc.multisample = bd->initInfo.PipelineMultisampleState; // Bind group layouts WGPUBindGroupLayoutEntry common_bg_layout_entries[2] = {}; diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h index 55f96b8e681f..9dc3ff290bea 100644 --- a/backends/imgui_impl_wgpu.h +++ b/backends/imgui_impl_wgpu.h @@ -27,6 +27,14 @@ struct ImGui_ImplWGPU_InitInfo int NumFramesInFlight = 3; WGPUTextureFormat RenderTargetFormat = WGPUTextureFormat_Undefined; WGPUTextureFormat DepthStencilFormat = WGPUTextureFormat_Undefined; + WGPUMultisampleState PipelineMultisampleState = {}; + + ImGui_ImplWGPU_InitInfo() + { + PipelineMultisampleState.count = 1; + PipelineMultisampleState.mask = -1u; + PipelineMultisampleState.alphaToCoverageEnabled = false; + } }; IMGUI_IMPL_API bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info); From 6850194f60a28fe9cf7e49554b2320cf68034f94 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jan 2024 15:01:21 +0100 Subject: [PATCH 111/237] CI: Fixes WGPU example build. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 45688c470343..c77e9a8c6096 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -494,7 +494,7 @@ jobs: pushd emsdk-master source ./emsdk_env.sh popd - make -C examples/example_emscripten_wgpu + make -C examples/example_emscripten_wgpu -f Makefile.emscripten Android: runs-on: ubuntu-22.04 From 595eb86624dc92cd19d36af127402ba8daa321c3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jan 2024 15:02:22 +0100 Subject: [PATCH 112/237] Changelog, comment, minor data compaction --- docs/CHANGELOG.txt | 1 + docs/README.md | 2 ++ imgui_internal.h | 5 +++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 36ad82f491b5..d5349d0df101 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -60,6 +60,7 @@ Other changes: allocating one extra semaphore than in-flight frames. (#7236) [@mklefrancois] - Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957) - Backends: Vulkan: Fixed handling of ImGui_ImplVulkan_InitInfo::MinAllocationSize field. (#7189, #4238) +- Backends: WebGPU: Added ImGui_ImplWGPU_InitInfo::PipelineMultisampleState. (#7240) - Backends: WebGPU: Filling all WGPUDepthStencilState fields explicitly as a recent Dawn update stopped setting default values. (#7232) [@GrigoryGraborenko] diff --git a/docs/README.md b/docs/README.md index ef4fb9753a4e..a2be7fde27b0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -139,6 +139,8 @@ Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. ### Gallery +Examples projects using Dear ImGui: [Tracy](https://github.com/wolfpld/tracy) (profiler), [ImHex](https://github.com/WerWolv/ImHex) (hex editor/data analysis), [RemedyBG](https://remedybg.itch.io/remedybg) (debugger) and [hundreds of others](https://github.com/ocornut/imgui/wiki/Software-using-Dear-ImGui). + For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/6897)! For a list of third-party widgets and extensions, check out the [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page. diff --git a/imgui_internal.h b/imgui_internal.h index c51c827998f1..97fe8346b15c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1955,8 +1955,8 @@ struct ImGuiContext bool ActiveIdHasBeenEditedThisFrame; ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; - ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad - int ActiveIdMouseButton; + ImGuiInputSource ActiveIdSource : 16; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad + int ActiveIdMouseButton : 16; ImGuiID ActiveIdPreviousFrame; bool ActiveIdPreviousFrameIsAlive; bool ActiveIdPreviousFrameHasBeenEditedBefore; @@ -2181,6 +2181,7 @@ struct ImGuiContext int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call. // Debug Tools + // (some of the highly frequently used data are interleaved in other structures above: DebugBreakXXX fields, DebugHookIdInfo, DebugLocateId etc.) ImGuiDebugLogFlags DebugLogFlags; ImGuiTextBuffer DebugLogBuf; ImGuiTextIndex DebugLogIndex; From 9266c0d2d1390e50d2d8070896932c2564594407 Mon Sep 17 00:00:00 2001 From: rajveermalviya Date: Sat, 20 Jan 2024 18:44:53 +0530 Subject: [PATCH 113/237] Backends: WebGPU: Avoid leaking pipeline layout. (#7245) --- backends/imgui_impl_wgpu.cpp | 8 ++++++++ docs/CHANGELOG.txt | 1 + 2 files changed, 9 insertions(+) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 9078287d8332..618dbb4ccb84 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -18,6 +18,7 @@ // (minor and older changes stripped away, please see git history for details) // 2024-01-22: Added configurable PipelineMultisampleState struct. (#7240) // 2024-01-22: (Breaking) ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure instead of variety of parameters, allowing for easier further changes. +// 2024-01-22: Fixed pipeline layout leak. (#7245) // 2024-01-17: Explicitly fill all of WGPUDepthStencilState since standard removed defaults. // 2023-07-13: Use WGPUShaderModuleWGSLDescriptor's code instead of source. use WGPUMipmapFilterMode_Linear instead of WGPUFilterMode_Linear. (#6602) // 2023-04-11: Align buffer sizes. Use WGSL shaders instead of precompiled SPIR-V. @@ -183,6 +184,12 @@ static void SafeRelease(WGPUBuffer& res) wgpuBufferRelease(res); res = nullptr; } +static void SafeRelease(WGPUPipelineLayout& res) +{ + if (res) + wgpuPipelineLayoutRelease(res); + res = nullptr; +} static void SafeRelease(WGPURenderPipeline& res) { if (res) @@ -692,6 +699,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() SafeRelease(vertex_shader_desc.module); SafeRelease(pixel_shader_desc.module); + SafeRelease(graphics_pipeline_desc.layout); SafeRelease(bg_layouts[0]); return true; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d5349d0df101..c13132187221 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -63,6 +63,7 @@ Other changes: - Backends: WebGPU: Added ImGui_ImplWGPU_InitInfo::PipelineMultisampleState. (#7240) - Backends: WebGPU: Filling all WGPUDepthStencilState fields explicitly as a recent Dawn update stopped setting default values. (#7232) [@GrigoryGraborenko] +- Backends: WebGPU: Fixed pipeline layout leak. (#7245) [@rajveermalviya] ----------------------------------------------------------------------- From 7c3fa7d049ad752fcb4aed691378a8b90e7d7825 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jan 2024 16:32:08 +0100 Subject: [PATCH 114/237] Refactor: moved section in imgui_internal.h --- imgui.h | 2 + imgui_internal.h | 114 +++++++++++++++++++++++++--------------------- imgui_widgets.cpp | 2 +- 3 files changed, 65 insertions(+), 53 deletions(-) diff --git a/imgui.h b/imgui.h index 8b4ca04da252..0b2fd415149a 100644 --- a/imgui.h +++ b/imgui.h @@ -89,6 +89,8 @@ Index of this file: #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) // Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions. +// (MSVC provides an equivalent mechanism via SAL Annotations but it would require the macros in a different +// location. e.g. #include + void myprintf(_Printf_format_string_ const char* format, ...)) #if !defined(IMGUI_USE_STB_SPRINTF) && defined(__MINGW32__) && !defined(__clang__) #define IM_FMTARGS(FMT) __attribute__((format(gnu_printf, FMT, FMT+1))) #define IM_FMTLIST(FMT) __attribute__((format(gnu_printf, FMT, 0))) diff --git a/imgui_internal.h b/imgui_internal.h index 97fe8346b15c..575bf9f25c1e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -15,6 +15,8 @@ Index of this file: // [SECTION] Generic helpers // [SECTION] ImDrawList support // [SECTION] Widgets support: flags, enums, data structures +// [SECTION] Data types support +// [SECTION] Popup support // [SECTION] Inputs support // [SECTION] Clipper support // [SECTION] Navigation support @@ -983,43 +985,6 @@ enum ImGuiPlotType ImGuiPlotType_Histogram, }; -enum ImGuiPopupPositionPolicy -{ - ImGuiPopupPositionPolicy_Default, - ImGuiPopupPositionPolicy_ComboBox, - ImGuiPopupPositionPolicy_Tooltip, -}; - -struct ImGuiDataVarInfo -{ - ImGuiDataType Type; - ImU32 Count; // 1+ - ImU32 Offset; // Offset in parent structure - void* GetVarPtr(void* parent) const { return (void*)((unsigned char*)parent + Offset); } -}; - -struct ImGuiDataTypeTempStorage -{ - ImU8 Data[8]; // Can fit any data up to ImGuiDataType_COUNT -}; - -// Type information associated to one ImGuiDataType. Retrieve with DataTypeGetInfo(). -struct ImGuiDataTypeInfo -{ - size_t Size; // Size in bytes - const char* Name; // Short descriptive name for the type, for debugging - const char* PrintFmt; // Default printf format for the type - const char* ScanFmt; // Default scanf format for the type -}; - -// Extend ImGuiDataType_ -enum ImGuiDataTypePrivate_ -{ - ImGuiDataType_String = ImGuiDataType_COUNT + 1, - ImGuiDataType_Pointer, - ImGuiDataType_ID, -}; - // Stacked color modifier, backup of modified data so we can restore it struct ImGuiColorMod { @@ -1133,21 +1098,6 @@ struct IMGUI_API ImGuiInputTextState void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; } }; -// Storage for current popup stack -struct ImGuiPopupData -{ - ImGuiID PopupId; // Set on OpenPopup() - ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() - ImGuiWindow* BackupNavWindow;// Set on OpenPopup(), a NavWindow that will be restored on popup close - int ParentNavLayer; // Resolved on BeginPopup(). Actually a ImGuiNavLayer type (declared down below), initialized to -1 which is not part of an enum, but serves well-enough as "not any of layers" value - int OpenFrameCount; // Set on OpenPopup() - ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) - ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse) - ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup - - ImGuiPopupData() { memset(this, 0, sizeof(*this)); ParentNavLayer = OpenFrameCount = -1; } -}; - enum ImGuiNextWindowDataFlags_ { ImGuiNextWindowDataFlags_None = 0, @@ -1277,6 +1227,66 @@ struct ImGuiPtrOrIndex ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; } }; +//----------------------------------------------------------------------------- +// [SECTION] Data types support +//----------------------------------------------------------------------------- + +struct ImGuiDataVarInfo +{ + ImGuiDataType Type; + ImU32 Count; // 1+ + ImU32 Offset; // Offset in parent structure + void* GetVarPtr(void* parent) const { return (void*)((unsigned char*)parent + Offset); } +}; + +struct ImGuiDataTypeTempStorage +{ + ImU8 Data[8]; // Can fit any data up to ImGuiDataType_COUNT +}; + +// Type information associated to one ImGuiDataType. Retrieve with DataTypeGetInfo(). +struct ImGuiDataTypeInfo +{ + size_t Size; // Size in bytes + const char* Name; // Short descriptive name for the type, for debugging + const char* PrintFmt; // Default printf format for the type + const char* ScanFmt; // Default scanf format for the type +}; + +// Extend ImGuiDataType_ +enum ImGuiDataTypePrivate_ +{ + ImGuiDataType_String = ImGuiDataType_COUNT + 1, + ImGuiDataType_Pointer, + ImGuiDataType_ID, +}; + +//----------------------------------------------------------------------------- +// [SECTION] Popup support +//----------------------------------------------------------------------------- + +enum ImGuiPopupPositionPolicy +{ + ImGuiPopupPositionPolicy_Default, + ImGuiPopupPositionPolicy_ComboBox, + ImGuiPopupPositionPolicy_Tooltip, +}; + +// Storage for popup stacks (g.OpenPopupStack and g.BeginPopupStack) +struct ImGuiPopupData +{ + ImGuiID PopupId; // Set on OpenPopup() + ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() + ImGuiWindow* BackupNavWindow;// Set on OpenPopup(), a NavWindow that will be restored on popup close + int ParentNavLayer; // Resolved on BeginPopup(). Actually a ImGuiNavLayer type (declared down below), initialized to -1 which is not part of an enum, but serves well-enough as "not any of layers" value + int OpenFrameCount; // Set on OpenPopup() + ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) + ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse) + ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup + + ImGuiPopupData() { memset(this, 0, sizeof(*this)); ParentNavLayer = OpenFrameCount = -1; } +}; + //----------------------------------------------------------------------------- // [SECTION] Inputs support //----------------------------------------------------------------------------- diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 6f1ab902aaca..8ec0896991d4 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -597,7 +597,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool g.NavDisableHighlight = true; } - // Gamepad/Keyboard navigation + // Gamepad/Keyboard handling // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse. if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover) if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus)) From 5b5e9bd0cb3db1763e0c122c48f2e2c0efea51cb Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jan 2024 17:43:58 +0100 Subject: [PATCH 115/237] Internals: Tweak shallow compaction as Clang complains about MS ABI signage of enums. --- imgui_internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 575bf9f25c1e..ec4f5ca28d97 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1963,10 +1963,10 @@ struct ImGuiContext bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch. bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state. bool ActiveIdHasBeenEditedThisFrame; + int ActiveIdMouseButton : 8; ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; - ImGuiInputSource ActiveIdSource : 16; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad - int ActiveIdMouseButton : 16; + ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad ImGuiID ActiveIdPreviousFrame; bool ActiveIdPreviousFrameIsAlive; bool ActiveIdPreviousFrameHasBeenEditedBefore; From 4c2c09450a6000af122b15cbe62687a50e257076 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jan 2024 17:40:48 +0100 Subject: [PATCH 116/237] Nav: keyboard/gamepad activation feedback properly timed instead of frame buffer. (#456) Amend d10641b --- imgui.cpp | 18 ++++++++++++++++++ imgui_internal.h | 5 +++++ imgui_widgets.cpp | 4 ++++ 3 files changed, 27 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index ba3c97b07a8d..61ac88363aee 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1047,6 +1047,8 @@ CODE static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear +static const float NAV_ACTIVATE_HIGHLIGHT_TIMER = 0.10f; // Time to highlight an item activated by a shortcut. + // Window resizing from edges (when io.ConfigWindowsResizeFromEdges = true and ImGuiBackendFlags_HasMouseCursors is set in io.BackendFlags by backend) static const float WINDOWS_HOVER_PADDING = 4.0f; // Extend outside window for hovering/resizing (maxxed with TouchPadding) and inside windows for borders. Affect FindHoveredWindow(). static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time. @@ -11169,6 +11171,13 @@ void ImGui::SetNavWindow(ImGuiWindow* window) NavUpdateAnyRequestFlag(); } +void ImGui::NavHighlightActivated(ImGuiID id) +{ + ImGuiContext& g = *GImGui; + g.NavHighlightActivatedId = id; + g.NavHighlightActivatedTimer = NAV_ACTIVATE_HIGHLIGHT_TIMER; +} + void ImGui::NavClearPreferredPosForAxis(ImGuiAxis axis) { ImGuiContext& g = *GImGui; @@ -11849,13 +11858,22 @@ static void ImGui::NavUpdate() if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_down || input_down)) g.NavActivateDownId = g.NavId; if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_pressed || input_pressed)) + { g.NavActivatePressedId = g.NavId; + NavHighlightActivated(g.NavId); + } } if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) g.NavDisableHighlight = true; if (g.NavActivateId != 0) IM_ASSERT(g.NavActivateDownId == g.NavActivateId); + // Highlight + if (g.NavHighlightActivatedTimer > 0.0f) + g.NavHighlightActivatedTimer = ImMax(0.0f, g.NavHighlightActivatedTimer - io.DeltaTime); + if (g.NavHighlightActivatedTimer == 0.0f) + g.NavHighlightActivatedId = 0; + // Process programmatic activation request // FIXME-NAV: Those should eventually be queued (unlike focus they don't cancel each others) if (g.NavNextActivateId != 0) diff --git a/imgui_internal.h b/imgui_internal.h index ec4f5ca28d97..283a9d1a8f51 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2026,6 +2026,8 @@ struct ImGuiContext ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0 ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat) ImGuiActivateFlags NavActivateFlags; + ImGuiID NavHighlightActivatedId; + float NavHighlightActivatedTimer; ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest). ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest). ImGuiKeyChord NavJustMovedToKeyMods; @@ -2293,6 +2295,8 @@ struct ImGuiContext NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0; NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0; NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None; + NavHighlightActivatedId = 0; + NavHighlightActivatedTimer = 0.0f; NavJustMovedToKeyMods = ImGuiMod_None; NavInputSource = ImGuiInputSource_Keyboard; NavLayer = ImGuiNavLayer_Main; @@ -3127,6 +3131,7 @@ namespace ImGui IMGUI_API void NavMoveRequestCancel(); IMGUI_API void NavMoveRequestApplyResult(); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); + IMGUI_API void NavHighlightActivated(ImGuiID id); IMGUI_API void NavClearPreferredPosForAxis(ImGuiAxis axis); IMGUI_API void NavRestoreHighlightAfterMove(); IMGUI_API void NavUpdateCurrentWindowIsScrollPushableX(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 8ec0896991d4..538b91b5ab23 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -675,6 +675,10 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool g.ActiveIdHasBeenPressedBefore = true; } + // Activation highlight + if (g.NavHighlightActivatedId == id) + hovered = true; + if (out_hovered) *out_hovered = hovered; if (out_held) *out_held = held; From a201af7354435f1167046bb1fa4c32dd2a6a1c8d Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jan 2024 17:56:34 +0100 Subject: [PATCH 117/237] Added SetNextItemShortcut() wip function. (#456) Mark widget as hovered. Amend d10641b. --- imgui.cpp | 35 ++++++++++++++++++++++++++++++++--- imgui.h | 2 +- imgui_internal.h | 6 ++++++ imgui_widgets.cpp | 13 +++++++++---- 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 61ac88363aee..75050e3551f0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3891,6 +3891,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) g.ActiveIdNoClearOnFocusLoss = false; g.ActiveIdWindow = window; g.ActiveIdHasBeenEditedThisFrame = false; + g.ActiveIdFromShortcut = false; if (id) { g.ActiveIdIsAlive = id; @@ -4100,7 +4101,8 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag if (g.HoveredId != 0 && g.HoveredId != id && !g.HoveredIdAllowOverlap) return false; if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap) - return false; + if (!g.ActiveIdFromShortcut) + return false; // Done with rectangle culling so we can perform heavier checks now. if (!(item_flags & ImGuiItemFlags_NoWindowHoverableCheck) && !IsWindowContentHoverable(window, ImGuiHoveredFlags_None)) @@ -4160,12 +4162,13 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag } // FIXME: This is inlined/duplicated in ItemAdd() +// FIXME: The id != 0 path is not used by our codebase, may get rid of it? bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (!bb.Overlaps(window->ClipRect)) - if (id == 0 || (id != g.ActiveId && id != g.NavId)) + if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId)) if (!g.LogEnabled) return true; return false; @@ -9421,6 +9424,13 @@ bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiIn return true; } +void ImGui::SetNextItemShortcut(ImGuiKeyChord key_chord) +{ + ImGuiContext& g = *GImGui; + g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasShortcut; + g.NextItemData.Shortcut = key_chord; +} + bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags) { //ImGuiContext& g = *GImGui; @@ -9731,6 +9741,7 @@ void ImGuiStackSizes::CompareWithContextState(ImGuiContext* ctx) // [SECTION] ITEM SUBMISSION //----------------------------------------------------------------------------- // - KeepAliveID() +// - ItemHandleShortcut() [Internal] // - ItemAdd() //----------------------------------------------------------------------------- @@ -9744,6 +9755,20 @@ void ImGui::KeepAliveID(ImGuiID id) g.ActiveIdPreviousFrameIsAlive = true; } +static void ItemHandleShortcut(ImGuiID id) +{ + // FIXME: Generalize Activation queue? + ImGuiContext& g = *GImGui; + if (ImGui::Shortcut(g.NextItemData.Shortcut, id, ImGuiInputFlags_None) && g.NavActivateId == 0) + { + g.NavActivateId = id; // Will effectively disable clipping. + g.NavActivateFlags = ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_FromShortcut; + if (g.ActiveId == 0 || g.ActiveId == id) + g.NavActivateDownId = g.NavActivatePressedId = id; + ImGui::NavHighlightActivated(id); + } +} + // Declare item bounding box for clipping and interaction. // Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface // declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction. @@ -9785,6 +9810,9 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) NavProcessItem(); } + + if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasShortcut) + ItemHandleShortcut(id); } // Lightweight clear of SetNextItemXXX data. @@ -9801,9 +9829,10 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu //const bool is_clipped = IsClippedEx(bb, id); //if (is_clipped) // return false; + // g.NavActivateId is not necessarily == g.NavId, in the case of remote activation (e.g. shortcuts) const bool is_rect_visible = bb.Overlaps(window->ClipRect); if (!is_rect_visible) - if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId)) + if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId)) if (!g.LogEnabled) return false; diff --git a/imgui.h b/imgui.h index 0b2fd415149a..88df9491b43c 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.2 WIP" -#define IMGUI_VERSION_NUM 19014 +#define IMGUI_VERSION_NUM 19015 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 283a9d1a8f51..786ea68e76a5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1145,6 +1145,7 @@ enum ImGuiNextItemDataFlags_ ImGuiNextItemDataFlags_None = 0, ImGuiNextItemDataFlags_HasWidth = 1 << 0, ImGuiNextItemDataFlags_HasOpen = 1 << 1, + ImGuiNextItemDataFlags_HasShortcut = 1 << 2, }; struct ImGuiNextItemData @@ -1154,6 +1155,7 @@ struct ImGuiNextItemData // Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem() 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() bool OpenVal; // Set by SetNextItemOpen() ImGuiCond OpenCond : 8; @@ -1518,6 +1520,7 @@ enum ImGuiActivateFlags_ ImGuiActivateFlags_PreferTweak = 1 << 1, // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default for Space key and if keyboard is not used. ImGuiActivateFlags_TryToPreserveState = 1 << 2, // Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection) ImGuiActivateFlags_FromTabbing = 1 << 3, // Activation requested by a tabbing request + ImGuiActivateFlags_FromShortcut = 1 << 4, // Activation requested by an item shortcut via SetNextItemShortcut() function. }; // Early work-in-progress API for ScrollToItem() @@ -1963,6 +1966,7 @@ struct ImGuiContext bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch. bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state. bool ActiveIdHasBeenEditedThisFrame; + bool ActiveIdFromShortcut; int ActiveIdMouseButton : 8; ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; @@ -2267,6 +2271,7 @@ struct ImGuiContext ActiveIdHasBeenPressedBefore = false; ActiveIdHasBeenEditedBefore = false; ActiveIdHasBeenEditedThisFrame = false; + ActiveIdFromShortcut = false; ActiveIdClickOffset = ImVec2(-1, -1); ActiveIdWindow = NULL; ActiveIdSource = ImGuiInputSource_None; @@ -3225,6 +3230,7 @@ namespace ImGui // - IsKeyChordPressed() compares mods + call IsKeyPressed() -> function has no side-effect. // - Shortcut() submits a route then if currently can be routed calls IsKeyChordPressed() -> function has (desirable) side-effects. IMGUI_API bool IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags = 0); + IMGUI_API void SetNextItemShortcut(ImGuiKeyChord key_chord); IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0); IMGUI_API bool SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags = 0); // owner_id needs to be explicit and cannot be 0 IMGUI_API bool TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 538b91b5ab23..93cfa38f07a2 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -477,6 +477,9 @@ void ImGui::BulletTextV(const char* fmt, va_list args) // Frame N + RepeatDelay + RepeatRate*N true true - true //------------------------------------------------------------------------------------------------------------------------------------------------- +// FIXME: For refactor we could output flags, incl mouse hovered vs nav keyboard vs nav triggered etc. +// And better standardize how widgets use 'GetColor32((held && hovered) ? ... : hovered ? ...)' vs 'GetColor32(held ? ... : hovered ? ...);' +// For mouse feedback we typically prefer the 'held && hovered' test, but for nav feedback not always. Outputting hovered=true on Activation may be misleading. bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags) { ImGuiContext& g = *GImGui; @@ -598,7 +601,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } // Gamepad/Keyboard handling - // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse. + // We report navigated and navigation-activated items as hovered but we don't set g.HoveredId to not interfere with mouse. if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover) if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus)) hovered = true; @@ -621,8 +624,10 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool pressed = true; SetActiveID(id, window); g.ActiveIdSource = g.NavInputSource; - if (!(flags & ImGuiButtonFlags_NoNavFocus)) + if (!(flags & ImGuiButtonFlags_NoNavFocus) && !(g.NavActivateFlags & ImGuiActivateFlags_FromShortcut)) SetFocusID(id, window); + if (g.NavActivateFlags & ImGuiActivateFlags_FromShortcut) + g.ActiveIdFromShortcut = true; } } @@ -667,7 +672,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool { // When activated using Nav, we hold on the ActiveID until activation button is released if (g.NavActivateDownId == id) - held = true; + held = true; // hovered == true not true as we are already likely hovered on direct activation. else ClearActiveID(); } @@ -675,7 +680,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool g.ActiveIdHasBeenPressedBefore = true; } - // Activation highlight + // Activation highlight (this may be a remote activation) if (g.NavHighlightActivatedId == id) hovered = true; From 81e0be856a6273c414c456a64fd28879fe81bf45 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jan 2024 14:27:43 +0100 Subject: [PATCH 118/237] Fixed strict-aliasing violation in FormatTextureIDForDebugDisplay(). (#7090, #7256) --- imgui.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 75050e3551f0..4cb27b555a72 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -14787,10 +14787,12 @@ void ImGui::DebugNodeColumns(ImGuiOldColumns* columns) static void FormatTextureIDForDebugDisplay(char* buf, int buf_size, ImTextureID tex_id) { + union { void* ptr; int integer; } tex_id_opaque; + memcpy(&tex_id_opaque, &tex_id, ImMin(sizeof(void*), sizeof(tex_id))); if (sizeof(tex_id) >= sizeof(void*)) - ImFormatString(buf, buf_size, "0x%p", (void*)*(intptr_t*)(void*)&tex_id); + ImFormatString(buf, buf_size, "0x%p", tex_id_opaque.ptr); else - ImFormatString(buf, buf_size, "0x%04X", *(int*)(void*)&tex_id); + ImFormatString(buf, buf_size, "0x%04X", tex_id_opaque.integer); } // [DEBUG] Display contents of ImDrawList From 54ef4092a92f777ee6c855b08875e37a4e282b45 Mon Sep 17 00:00:00 2001 From: actboy168 Date: Tue, 23 Jan 2024 10:22:56 +0800 Subject: [PATCH 119/237] Backends: OSX: Fixed not submitting Monitors info when viewports are not enabled. (#7257) --- backends/imgui_impl_osx.mm | 2 +- docs/CHANGELOG.txt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index f5f554b27851..229f34594f7d 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -435,6 +435,7 @@ bool ImGui_ImplOSX_Init(NSView* view) bd->Window = view.window ?: NSApp.orderedWindows.firstObject; ImGuiViewport* main_viewport = ImGui::GetMainViewport(); main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (__bridge_retained void*)bd->Window; + ImGui_ImplOSX_UpdateMonitors(); if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) ImGui_ImplOSX_InitPlatformInterface(); @@ -1088,7 +1089,6 @@ static void ImGui_ImplOSX_UpdateMonitors() static void ImGui_ImplOSX_InitPlatformInterface() { ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); - ImGui_ImplOSX_UpdateMonitors(); // Register platform interface (will be coupled with a renderer interface) ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index dc0dd2c54487..16bfbf44e356 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -73,6 +73,8 @@ Docking+Viewports Branch: - Added ImGuiDockNodeFlags_DockedWindowsInFocusRoute to automatically make a dockspace connect the focus route of its docked window. This is provided a convenience in case you have windows where a connection is not explicit. (#6798) +- Backends: OSX: Fixed not submitting Monitors info when viewports are not enabled, leading to + missing e.g. DpiScale info. (#7257) [@actboy168] ----------------------------------------------------------------------- From 1ce41f6218d00d6855b08400ea6c04f78b2ace5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Gallet?= Date: Mon, 22 Jan 2024 17:51:24 +0100 Subject: [PATCH 120/237] Backends: OpenGL3: Backup and restore GL_PIXEL_UNPACK_BUFFER. (#7253) Amended with (bd->GlVersion >= 210) checks. --- backends/imgui_impl_opengl3.cpp | 12 ++++++++++++ backends/imgui_impl_opengl3_loader.h | 2 ++ docs/CHANGELOG.txt | 1 + 3 files changed, 15 insertions(+) diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index a36a7ac278b0..1c63641abe65 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -191,6 +191,11 @@ #define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER #endif +// Desktop GL and GL ES 3.0+ have glBindBuffer() with GL_PIXEL_UNPACK_BUFFER target. +#if !defined(IMGUI_IMPL_OPENGL_ES2) +#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK +#endif + // Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1) #define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART @@ -747,6 +752,10 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() GLint last_texture, last_array_buffer; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK + GLint last_pixel_unpack_buffer; + if (bd->GlVersion >= 210) { glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &last_pixel_unpack_buffer); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); } +#endif #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); @@ -920,6 +929,9 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() // Restore modified GL state glBindTexture(GL_TEXTURE_2D, last_texture); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK + if (bd->GlVersion >= 210) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, last_pixel_unpack_buffer); } +#endif #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY glBindVertexArray(last_vertex_array); #endif diff --git a/backends/imgui_impl_opengl3_loader.h b/backends/imgui_impl_opengl3_loader.h index 85c58c4e27c6..4019f937fb24 100644 --- a/backends/imgui_impl_opengl3_loader.h +++ b/backends/imgui_impl_opengl3_loader.h @@ -260,6 +260,8 @@ typedef khronos_intptr_t GLintptr; #define GL_ARRAY_BUFFER_BINDING 0x8894 #define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 #define GL_STREAM_DRAW 0x88E0 +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c13132187221..204dff22dd51 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,7 @@ Other changes: - Backends: WebGPU: Filling all WGPUDepthStencilState fields explicitly as a recent Dawn update stopped setting default values. (#7232) [@GrigoryGraborenko] - Backends: WebGPU: Fixed pipeline layout leak. (#7245) [@rajveermalviya] +- Backends: OpenGL3: Backup and restore GL_PIXEL_UNPACK_BUFFER. (#7253) ----------------------------------------------------------------------- From 1509842107dcded1a596ae1c24e7d74300c65555 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jan 2024 15:15:15 +0100 Subject: [PATCH 121/237] Backends: OpenGL3: Shallow tweak of compile-time extensions detection. Detect polygon mode using same method as others (not define/symbol). IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS -> IMGUI_IMPL_OPENGL_HAS_EXTENSIONS --- backends/imgui_impl_glfw.cpp | 4 +--- backends/imgui_impl_opengl3.cpp | 40 +++++++++++++++------------------ 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index b49c99bb8839..a968fe308a31 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -114,7 +114,7 @@ enum GlfwClientApi { GlfwClientApi_Unknown, GlfwClientApi_OpenGL, - GlfwClientApi_Vulkan + GlfwClientApi_Vulkan, }; struct ImGui_ImplGlfw_Data @@ -674,11 +674,9 @@ static void ImGui_ImplGlfw_UpdateMouseData() ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); - // (those braces are here to reduce diff with multi-viewports support in 'docking' branch) { GLFWwindow* window = bd->Window; - #ifdef __EMSCRIPTEN__ const bool is_window_focused = true; #else diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 1c63641abe65..b3a510bcd525 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -176,22 +176,13 @@ #define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES #endif -// Desktop GL 2.0+ has glPolygonMode() which GL ES and WebGL don't have. -#ifdef GL_POLYGON_MODE -#define IMGUI_IMPL_HAS_POLYGON_MODE -#endif - -// Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have. -#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_2) -#define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET -#endif - -// Desktop GL 3.3+ and GL ES 3.0+ have glBindSampler() -#if !defined(IMGUI_IMPL_OPENGL_ES2) && (defined(IMGUI_IMPL_OPENGL_ES3) || defined(GL_VERSION_3_3)) -#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER +// Desktop GL 2.0+ has extension and glPolygonMode() which GL ES and WebGL don't have.. +#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) +#define IMGUI_IMPL_OPENGL_HAS_EXTENSIONS // has glGetIntegerv(GL_NUM_EXTENSIONS) +#define IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE // has glPolygonMode() #endif -// Desktop GL and GL ES 3.0+ have glBindBuffer() with GL_PIXEL_UNPACK_BUFFER target. +// Desktop GL 2.1+ and GL ES 3.0+ have glBindBuffer() with GL_PIXEL_UNPACK_BUFFER target. #if !defined(IMGUI_IMPL_OPENGL_ES2) #define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK #endif @@ -201,9 +192,14 @@ #define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART #endif -// Desktop GL use extension detection -#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) -#define IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS +// Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have. +#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_2) +#define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET +#endif + +// Desktop GL 3.3+ and GL ES 3.0+ have glBindSampler() +#if !defined(IMGUI_IMPL_OPENGL_ES2) && (defined(IMGUI_IMPL_OPENGL_ES3) || defined(GL_VERSION_3_3)) +#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER #endif // [Debugging] @@ -364,7 +360,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) // Detect extensions we support bd->HasClipOrigin = (bd->GlVersion >= 450); -#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS +#ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS GLint num_extensions = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); for (GLint i = 0; i < num_extensions; i++) @@ -416,7 +412,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid if (bd->GlVersion >= 310) glDisable(GL_PRIMITIVE_RESTART); #endif -#ifdef IMGUI_IMPL_HAS_POLYGON_MODE +#ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif @@ -505,7 +501,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object); #endif -#ifdef IMGUI_IMPL_HAS_POLYGON_MODE +#ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); #endif GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); @@ -644,7 +640,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); } #endif -#ifdef IMGUI_IMPL_HAS_POLYGON_MODE +#ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE // Desktop OpenGL 3.0 and OpenGL 3.1 had separate polygon draw modes for front-facing and back-facing faces of polygons if (bd->GlVersion <= 310 || bd->GlProfileIsCompat) { @@ -655,7 +651,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) { glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); } -#endif // IMGUI_IMPL_HAS_POLYGON_MODE +#endif // IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); From 9176eedf24070649db23ea59d4174bcf6281b640 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jan 2024 17:47:30 +0100 Subject: [PATCH 122/237] Internals: SetShortcutRouting() move code so next commit is easier to read. Should be no-op. --- imgui.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4cb27b555a72..8177e1045816 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8438,17 +8438,20 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI return true; } - // Specific culling for shortcuts with no modifiers when there's an active id. - // e.g. Shortcut(ImGuiKey_G) also generates 'g' character, should not trigger when InputText() is active. - // but Shortcut(Ctrl+G) should generally trigger when InputText() is active. - // TL;DR: lettered shortcut with no mods or with only Alt mod will not trigger while an item reading text input is active. - // (We cannot filter based on io.InputQueueCharacters[] contents because of trickling and key<>chars submission order are undefined) - if ((flags & ImGuiInputFlags_RouteFocused) && (g.ActiveId != 0 && g.ActiveId != owner_id)) - if (g.IO.WantTextInput && IsKeyChordPotentiallyCharInput(key_chord)) + // Specific culling when there's an active. + if (g.ActiveId != 0 && g.ActiveId != owner_id) + { + // Cull shortcuts with no modifiers when it could generate a character. + // e.g. Shortcut(ImGuiKey_G) also generates 'g' character, should not trigger when InputText() is active. + // but Shortcut(Ctrl+G) should generally trigger when InputText() is active. + // TL;DR: lettered shortcut with no mods or with only Alt mod will not trigger while an item reading text input is active. + // (We cannot filter based on io.InputQueueCharacters[] contents because of trickling and key<>chars submission order are undefined) + if ((flags & ImGuiInputFlags_RouteFocused) && g.IO.WantTextInput && IsKeyChordPotentiallyCharInput(key_chord)) { IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> filtered as potential char input\n", GetKeyChordName(key_chord), owner_id, flags); return false; } + } // FIXME-SHORTCUT: A way to configure the location/focus-scope to test would render this more flexible. const int score = CalcRoutingScore(g.CurrentFocusScopeId, owner_id, flags); From 8491cf36adb2663f16975bc4ebcd871daf5ff8b7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jan 2024 17:52:46 +0100 Subject: [PATCH 123/237] Inputs: g.ActiveIdUsingManyKeys[] prevent routes from being claimed. Amend fc134f5 --- imgui.cpp | 10 ++++++++++ imgui.h | 2 +- imgui_internal.h | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8177e1045816..768cf9504c2d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8451,6 +8451,16 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> filtered as potential char input\n", GetKeyChordName(key_chord), owner_id, flags); return false; } + + // ActiveIdUsingAllKeyboardKeys trumps all for ActiveId + if ((flags & ImGuiInputFlags_RouteGlobalHigh) == 0 && g.ActiveIdUsingAllKeyboardKeys) + { + ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); + if (key == ImGuiKey_None) + key = ConvertSingleModFlagToKey(&g, (ImGuiKey)(key_chord & ImGuiMod_Mask_)); + if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END) + return false; + } } // FIXME-SHORTCUT: A way to configure the location/focus-scope to test would render this more flexible. diff --git a/imgui.h b/imgui.h index 88df9491b43c..56b3455e6949 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.2 WIP" -#define IMGUI_VERSION_NUM 19015 +#define IMGUI_VERSION_NUM 19016 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 786ea68e76a5..840b9a04cc0b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1461,7 +1461,7 @@ enum ImGuiInputFlags_ ImGuiInputFlags_RouteFocused = 1 << 12, // (Default) Honor focus route: Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window. ImGuiInputFlags_RouteGlobalLow = 1 << 13, // Register route globally (lowest priority: unless a focused window or active item registered the route) -> recommended Global priority IF you need a Global priority. ImGuiInputFlags_RouteGlobal = 1 << 14, // Register route globally (medium priority: unless an active item registered the route, e.g. CTRL+A registered by InputText will take priority over this). - ImGuiInputFlags_RouteGlobalHigh = 1 << 15, // Register route globally (higher priority: unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overiden by this) + ImGuiInputFlags_RouteGlobalHigh = 1 << 15, // Register route globally (higher priority: unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overriden by this) ImGuiInputFlags_RouteAlways = 1 << 16, // Do not register route, poll keys directly. // Routing polices: extra options ImGuiInputFlags_RouteUnlessBgFocused= 1 << 17, // Global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. From f1960b60c1ae129e401c6582080ea9e6dfcf0b00 Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Thu, 25 Jan 2024 10:16:27 +0000 Subject: [PATCH 124/237] Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) There are two issues here - first, this macro uses AT&T specific syntax with $, which is not necessary. Also, some assemblers (nasm) emit different bytes for "int 3" and "int3", so it's better to use "int3" (cd 03 vs cc) More importantly, GDB has some failing assertion whenever stepping after hitting an "int3" instruction. This makes it practically useless, as is. For some reason, putting a nop afterwards as a workaround is okay. Related discussions: https://sourceware.org/bugzilla/show_bug.cgi?id=31194 https://lists.sr.ht/~skeeto/public-inbox/%3C2d3d7662a361ddd049f7dc65b94cecdd%40disroot.org%3E --- docs/CHANGELOG.txt | 1 + imgui_internal.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 204dff22dd51..c6d0f0bf8c19 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,6 +56,7 @@ Other changes: - Nav: Fixed pressing Escape while in a child window with _NavFlattened flag. (#7237) - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. - Debug Tools: Debug Log: Added "Input Routing" logging. +- Debug Tools: Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) [@Peter0x44] - Backends: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236) [@mklefrancois] - Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957) diff --git a/imgui_internal.h b/imgui_internal.h index 840b9a04cc0b..c256ec22d28a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -300,11 +300,11 @@ namespace ImStb #elif defined(__clang__) #define IM_DEBUG_BREAK() __builtin_debugtrap() #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) -#define IM_DEBUG_BREAK() __asm__ volatile("int $0x03") +#define IM_DEBUG_BREAK() __asm__ volatile("int3;nop") #elif defined(__GNUC__) && defined(__thumb__) #define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xde01") #elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) -#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xe7f001f0"); +#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xe7f001f0") #else #define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger! #endif From 719475637095a2794a2385856abb300e00afc761 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Jan 2024 12:48:04 +0100 Subject: [PATCH 125/237] Shortcut: fixed single mod-key Shortcut from working e.g. Shortcut(ImGuiKey_LeftCtrl) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 34 ++++++++++++++++++++++++++-------- imgui_internal.h | 3 ++- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c6d0f0bf8c19..7278ddb7995b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -66,6 +66,8 @@ Other changes: update stopped setting default values. (#7232) [@GrigoryGraborenko] - Backends: WebGPU: Fixed pipeline layout leak. (#7245) [@rajveermalviya] - Backends: OpenGL3: Backup and restore GL_PIXEL_UNPACK_BUFFER. (#7253) +- Internals: Various improvements related to yet unpublicized shortcut routing and input ownerhip + systems. ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 768cf9504c2d..040e6712c69b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8115,6 +8115,26 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) // - Shortcut() [Internal] //----------------------------------------------------------------------------- +ImGuiKeyChord ImGui::FixupKeyChord(ImGuiContext* ctx, ImGuiKeyChord key_chord) +{ + // Convert ImGuiMod_Shortcut and add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified. + ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); + if (IsModKey(key)) + { + if (key == ImGuiKey_LeftCtrl || key == ImGuiKey_RightCtrl) + key_chord |= ImGuiMod_Ctrl; + if (key == ImGuiKey_LeftShift || key == ImGuiKey_RightShift) + key_chord |= ImGuiMod_Shift; + if (key == ImGuiKey_LeftAlt || key == ImGuiKey_RightAlt) + key_chord |= ImGuiMod_Alt; + if (key == ImGuiKey_LeftSuper || key == ImGuiKey_RightSuper) + key_chord |= ImGuiMod_Super; + } + if (key_chord & ImGuiMod_Shortcut) + return (key_chord & ~ImGuiMod_Shortcut) | (ctx->IO.ConfigMacOSXBehaviors ? ImGuiMod_Super : ImGuiMod_Ctrl); + return key_chord; +} + ImGuiKeyData* ImGui::GetKeyData(ImGuiContext* ctx, ImGuiKey key) { ImGuiContext& g = *ctx; @@ -8198,8 +8218,7 @@ const char* ImGui::GetKeyName(ImGuiKey key) const char* ImGui::GetKeyChordName(ImGuiKeyChord key_chord) { ImGuiContext& g = *GImGui; - if (key_chord & ImGuiMod_Shortcut) - key_chord = ConvertShortcutMod(key_chord); + key_chord = FixupKeyChord(&g, key_chord); ImFormatString(g.TempKeychordName, IM_ARRAYSIZE(g.TempKeychordName), "%s%s%s%s%s", (key_chord & ImGuiMod_Ctrl) ? "Ctrl+" : "", (key_chord & ImGuiMod_Shift) ? "Shift+" : "", @@ -8420,8 +8439,8 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteMask_)); // Check that only 1 routing flag is used IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_None); - if (key_chord & ImGuiMod_Shortcut) - key_chord = ConvertShortcutMod(key_chord); + // Convert ImGuiMod_Shortcut and add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified. + key_chord = FixupKeyChord(&g, key_chord); // [DEBUG] Debug break requested by user if (g.DebugBreakInShortcutRouting == key_chord) @@ -8489,9 +8508,9 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI // Note: this cannot be turned into GetShortcutRouting() because we do the owner_id->routing_id translation, name would be more misleading. bool ImGui::TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id) { + ImGuiContext& g = *GImGui; const ImGuiID routing_id = GetRoutingIdFromOwnerId(owner_id); - if (key_chord & ImGuiMod_Shortcut) - key_chord = ConvertShortcutMod(key_chord); + key_chord = FixupKeyChord(&g, key_chord); ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord); // FIXME: Could avoid creating entry. return routing_data->RoutingCurr == routing_id; } @@ -9422,8 +9441,7 @@ bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord) bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags) { ImGuiContext& g = *GImGui; - if (key_chord & ImGuiMod_Shortcut) - key_chord = ConvertShortcutMod(key_chord); + key_chord = FixupKeyChord(&g, key_chord); ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_); if (g.IO.KeyMods != mods) return false; diff --git a/imgui_internal.h b/imgui_internal.h index c256ec22d28a..f26ebceafae4 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3159,7 +3159,8 @@ namespace ImGui inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; } inline bool IsMouseKey(ImGuiKey key) { return key >= ImGuiKey_Mouse_BEGIN && key < ImGuiKey_Mouse_END; } inline bool IsAliasKey(ImGuiKey key) { return key >= ImGuiKey_Aliases_BEGIN && key < ImGuiKey_Aliases_END; } - inline ImGuiKeyChord ConvertShortcutMod(ImGuiKeyChord key_chord) { ImGuiContext& g = *GImGui; IM_ASSERT_PARANOID(key_chord & ImGuiMod_Shortcut); return (key_chord & ~ImGuiMod_Shortcut) | (g.IO.ConfigMacOSXBehaviors ? ImGuiMod_Super : ImGuiMod_Ctrl); } + inline bool IsModKey(ImGuiKey key) { return key >= ImGuiKey_LeftCtrl && key <= ImGuiKey_RightSuper; } + ImGuiKeyChord FixupKeyChord(ImGuiContext* ctx, ImGuiKeyChord key_chord); inline ImGuiKey ConvertSingleModFlagToKey(ImGuiContext* ctx, ImGuiKey key) { ImGuiContext& g = *ctx; From 96839b445e32e46d87a44fd43a9cdd60c806f7e1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Jan 2024 15:43:19 +0100 Subject: [PATCH 126/237] Nav: Improve handling of Alt key to toggle menu so that key ownership may be claimed on indiviudal left/right alt key without intefering with the other. See test "inputs_owner_single_mod" --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 27 ++++++++++++++++----------- imgui_internal.h | 2 ++ 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7278ddb7995b..5ec7a2edcc5b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,8 @@ Other changes: - Nav: Fixed SetKeyboardFocusHere() not working when current nav focus is in different scope, regression from 1.90.1 related to code scoping Tab presses to local scope. (#7226) [@bratpilz] - Nav: Fixed pressing Escape while in a child window with _NavFlattened flag. (#7237) +- Nav: Improve handling of Alt key to toggle menu so that key ownership may be claimed on + indiviudal left/right alt key without intefering with the other. - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. - Debug Tools: Debug Log: Added "Input Routing" logging. - Debug Tools: Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) [@Peter0x44] diff --git a/imgui.cpp b/imgui.cpp index 040e6712c69b..8bfc66cb223d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12627,28 +12627,33 @@ static void ImGui::NavUpdateWindowing() } // Keyboard: Press and Release ALT to toggle menu layer - // - Testing that only Alt is tested prevents Alt+Shift or AltGR from toggling menu layer. - // - AltGR is normally Alt+Ctrl but we can't reliably detect it (not all backends/systems/layout emit it as Alt+Ctrl). But even on keyboards without AltGR we don't want Alt+Ctrl to open menu anyway. - if (nav_keyboard_active && IsKeyPressed(ImGuiMod_Alt, ImGuiKeyOwner_None)) - { - g.NavWindowingToggleLayer = true; - g.NavInputSource = ImGuiInputSource_Keyboard; - } + const ImGuiKey windowing_toggle_keys[] = { ImGuiKey_LeftAlt, ImGuiKey_RightAlt }; + for (ImGuiKey windowing_toggle_key : windowing_toggle_keys) + if (nav_keyboard_active && IsKeyPressed(windowing_toggle_key, ImGuiKeyOwner_None)) + { + g.NavWindowingToggleLayer = true; + g.NavWindowingToggleKey = windowing_toggle_key; + g.NavInputSource = ImGuiInputSource_Keyboard; + break; + } if (g.NavWindowingToggleLayer && g.NavInputSource == ImGuiInputSource_Keyboard) { // We cancel toggling nav layer when any text has been typed (generally while holding Alt). (See #370) // We cancel toggling nav layer when other modifiers are pressed. (See #4439) + // - AltGR is Alt+Ctrl on some layout but we can't reliably detect it (not all backends/systems/layout emit it as Alt+Ctrl). // We cancel toggling nav layer if an owner has claimed the key. - if (io.InputQueueCharacters.Size > 0 || io.KeyCtrl || io.KeyShift || io.KeySuper || TestKeyOwner(ImGuiMod_Alt, ImGuiKeyOwner_None) == false) + if (io.InputQueueCharacters.Size > 0 || io.KeyCtrl || io.KeyShift || io.KeySuper) + g.NavWindowingToggleLayer = false; + if (TestKeyOwner(g.NavWindowingToggleKey, ImGuiKeyOwner_None) == false || TestKeyOwner(ImGuiMod_Alt, ImGuiKeyOwner_None) == false) g.NavWindowingToggleLayer = false; - // Apply layer toggle on release + // Apply layer toggle on Alt release // Important: as before version <18314 we lacked an explicit IO event for focus gain/loss, we also compare mouse validity to detect old backends clearing mouse pos on focus loss. - if (IsKeyReleased(ImGuiMod_Alt) && g.NavWindowingToggleLayer) + if (IsKeyReleased(g.NavWindowingToggleKey) && g.NavWindowingToggleLayer) if (g.ActiveId == 0 || g.ActiveIdAllowOverlap) if (IsMousePosValid(&io.MousePos) == IsMousePosValid(&io.MousePosPrev)) apply_toggle_layer = true; - if (!IsKeyDown(ImGuiMod_Alt)) + if (!IsKeyDown(g.NavWindowingToggleKey)) g.NavWindowingToggleLayer = false; } diff --git a/imgui_internal.h b/imgui_internal.h index f26ebceafae4..925070629031 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2078,6 +2078,7 @@ struct ImGuiContext float NavWindowingTimer; float NavWindowingHighlightAlpha; bool NavWindowingToggleLayer; + ImGuiKey NavWindowingToggleKey; ImVec2 NavWindowingAccumDeltaPos; ImVec2 NavWindowingAccumDeltaSize; @@ -2329,6 +2330,7 @@ struct ImGuiContext NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL; NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; NavWindowingToggleLayer = false; + NavWindowingToggleKey = ImGuiKey_None; DimBgRatio = 0.0f; From 6172c22c5dc751c617ca51c3ca72cc62472e9449 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Thu, 1 Feb 2024 22:07:29 +0700 Subject: [PATCH 127/237] CI: Update to `actions/checkout` `v4` from `v3`. (#7281) --- .github/workflows/build.yml | 12 ++++++------ .github/workflows/static-analysis.yml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c77e9a8c6096..d332903ed0d9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ jobs: VS_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\ MSBUILD_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\ steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Dependencies shell: powershell @@ -209,7 +209,7 @@ jobs: Linux: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Dependencies run: | @@ -402,7 +402,7 @@ jobs: MacOS: runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Dependencies run: | @@ -462,7 +462,7 @@ jobs: iOS: runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build example_apple_metal run: | @@ -472,7 +472,7 @@ jobs: Emscripten: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Dependencies run: | @@ -499,7 +499,7 @@ jobs: Android: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build example_android_opengl3 run: | diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index caa9b3a4e44f..69df5cdf8031 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -12,7 +12,7 @@ jobs: PVS-Studio: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 1 From f50ddc431e3b8840036e88abc4c3cf74500aa12b Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Fri, 2 Feb 2024 00:30:00 +0700 Subject: [PATCH 128/237] Fixed some typos. (#7282) --- backends/imgui_impl_allegro5.cpp | 2 +- backends/imgui_impl_opengl2.cpp | 2 +- docs/CHANGELOG.txt | 2 +- docs/FONTS.md | 2 +- imgui_draw.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index abb6b9ad0ba8..ef1f13f38ca7 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -27,7 +27,7 @@ // 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+). // 2022-01-17: Inputs: always calling io.AddKeyModsEvent() next and before key event (not in NewFrame) to fix input queue with very low framerates. // 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. -// 2021-12-08: Renderer: Fixed mishandling of the the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86. +// 2021-12-08: Renderer: Fixed mishandling of the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86. // 2021-08-17: Calling io.AddFocusEvent() on ALLEGRO_EVENT_DISPLAY_SWITCH_OUT/ALLEGRO_EVENT_DISPLAY_SWITCH_IN events. // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). // 2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp index 0d7037690843..17935b1f3f0c 100644 --- a/backends/imgui_impl_opengl2.cpp +++ b/backends/imgui_impl_opengl2.cpp @@ -23,7 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. -// 2021-12-08: OpenGL: Fixed mishandling of the the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86. +// 2021-12-08: OpenGL: Fixed mishandling of the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86. // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). // 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) // 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications. diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5ec7a2edcc5b..1625bdc829ac 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,7 +68,7 @@ Other changes: update stopped setting default values. (#7232) [@GrigoryGraborenko] - Backends: WebGPU: Fixed pipeline layout leak. (#7245) [@rajveermalviya] - Backends: OpenGL3: Backup and restore GL_PIXEL_UNPACK_BUFFER. (#7253) -- Internals: Various improvements related to yet unpublicized shortcut routing and input ownerhip +- Internals: Various improvements related to yet unpublicized shortcut routing and input ownership systems. diff --git a/docs/FONTS.md b/docs/FONTS.md index cbf13e13d4b9..df8b610e5639 100644 --- a/docs/FONTS.md +++ b/docs/FONTS.md @@ -53,7 +53,7 @@ All loaded fonts glyphs are rendered into a single texture atlas ahead of time. This is often of byproduct of point 3. If you have large number of glyphs or multiple fonts, the texture may become too big for your graphics API. **The typical result of failing to upload a texture is if every glyph or everything appears as empty black or white rectangle.** Mind the fact that some graphics drivers have texture size limitation. If you are building a PC application, mind the fact that your users may use hardware with lower limitations than yours. Some solutions: -- You may reduce oversampling, e.g. `font_config.OversampleH = 1`, this will half your texture size for a quality looss. +- You may reduce oversampling, e.g. `font_config.OversampleH = 1`, this will half your texture size for a quality loss. Note that while OversampleH = 2 looks visibly very close to 3 in most situations, with OversampleH = 1 the quality drop will be noticeable. Read about oversampling [here](https://github.com/nothings/stb/blob/master/tests/oversample). - Reduce glyphs ranges by calculating them from source localization data. You can use the `ImFontGlyphRangesBuilder` for this purpose and rebuilding your atlas between frames when new characters are needed. This will be the biggest win! diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 9008eb748248..a40ce1688033 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -641,7 +641,7 @@ void ImDrawList::PrimReserve(int idx_count, int vtx_count) _IdxWritePtr = IdxBuffer.Data + idx_buffer_old_size; } -// Release the a number of reserved vertices/indices from the end of the last reservation made with PrimReserve(). +// Release the number of reserved vertices/indices from the end of the last reservation made with PrimReserve(). void ImDrawList::PrimUnreserve(int idx_count, int vtx_count) { IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0); From 06ce312745e0b25bfa8412b324503393964e3812 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 7 Feb 2024 21:35:47 +0100 Subject: [PATCH 129/237] InputText: Internal: added reload from user-buf feature. (#2890) Very highly requested feature (#6962, #5219, #3290, #4627, #5054, #3878, #2881, #1506, #1216, #968). Also useful for interactive completion/selection popups (#2057, #718) Based on @kudaba PR. Design for Inputtext V2 should make this obsolete. --- docs/CHANGELOG.txt | 6 ++++-- imgui.cpp | 2 ++ imgui.h | 2 +- imgui_internal.h | 13 +++++++++++++ imgui_widgets.cpp | 16 ++++++++++++---- 5 files changed, 32 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1625bdc829ac..88d7942162bf 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,8 +68,10 @@ Other changes: update stopped setting default values. (#7232) [@GrigoryGraborenko] - Backends: WebGPU: Fixed pipeline layout leak. (#7245) [@rajveermalviya] - Backends: OpenGL3: Backup and restore GL_PIXEL_UNPACK_BUFFER. (#7253) -- Internals: Various improvements related to yet unpublicized shortcut routing and input ownership - systems. +- Internals: Many improvements related to yet unpublicized shortcut routing and input ownership systems. +- Internals: InputText: Add way to force reload of user-buf when active. (#2890) [@kudaba, @ocornut] + Often requested in some form (#6962, #5219, #3290, #4627, #5054, #3878, #2881, #1506, #1216, #968), + and useful for interactive completion/suggestions popups (#2057, #718) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 8bfc66cb223d..7493fd4a3cdf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12257,6 +12257,8 @@ void ImGui::NavMoveRequestApplyResult() g.NavWindow = result->Window; g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid; } + + // FIXME: Could become optional e.g. ImGuiNavMoveFlags_NoClearActiveId if we later want to apply navigation requests without altering active input. if (g.ActiveId != result->ID) ClearActiveID(); diff --git a/imgui.h b/imgui.h index 56b3455e6949..f8971ad156dc 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.2 WIP" -#define IMGUI_VERSION_NUM 19016 +#define IMGUI_VERSION_NUM 19017 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 925070629031..fb6b7a221fe9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1079,6 +1079,9 @@ struct IMGUI_API ImGuiInputTextState bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection bool Edited; // edited this frame ImGuiInputTextFlags Flags; // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set. + bool ReloadUserBuf; // force a reload of user buf so it may be modified externally. may be automatic in future version. + int ReloadSelectionStart; // POSITIONS ARE IN IMWCHAR units *NOT* UTF-8 this is why this is not exposed yet. + int ReloadSelectionEnd; ImGuiInputTextState() { memset(this, 0, sizeof(*this)); } void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); } @@ -1096,6 +1099,16 @@ struct IMGUI_API ImGuiInputTextState int GetSelectionStart() const { return Stb.select_start; } int GetSelectionEnd() const { return Stb.select_end; } void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; } + + // Reload user buf (WIP #2890) + // If you modify underlying user-passed const char* while active you need to call this (InputText V2 may lift this) + // strcpy(my_buf, "hello"); + // if (ImGuiInputTextState* state = ImGui::GetInputTextState(id)) // id may be ImGui::GetItemID() is last item + // state->ReloadUserBufAndSelectAll(); + void ReloadUserBufAndSelectAll() { ReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; } + void ReloadUserBufAndKeepSelection() { ReloadUserBuf = true; ReloadSelectionStart = Stb.select_start; ReloadSelectionEnd = Stb.select_end; } + void ReloadUserBufAndMoveToEnd() { ReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; } + }; enum ImGuiNextWindowDataFlags_ diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 93cfa38f07a2..ba4d3f5b8067 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4185,14 +4185,16 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX; + const bool init_reload_from_user_buf = (state != NULL && state->ReloadUserBuf); const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); // state != NULL means its our state. const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav); const bool init_state = (init_make_active || user_scroll_active); - if ((init_state && g.ActiveId != id) || init_changed_specs) + if ((init_state && g.ActiveId != id) || init_changed_specs || init_reload_from_user_buf) { // Access state even if we don't own it yet. state = &g.InputTextState; state->CursorAnimReset(); + state->ReloadUserBuf = false; // Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714) InputTextDeactivateHook(state->ID); @@ -4204,8 +4206,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ memcpy(state->InitialTextA.Data, buf, buf_len + 1); // Preserve cursor position and undo/redo stack if we come back to same widget - // FIXME: Since we reworked this on 2022/06, may want to differenciate recycle_cursor vs recycle_undostate? - bool recycle_state = (state->ID == id && !init_changed_specs); + // FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate? + bool recycle_state = (state->ID == id && !init_changed_specs && !init_reload_from_user_buf); if (recycle_state && (state->CurLenA != buf_len || (state->TextAIsValid && strncmp(state->TextA.Data, buf, buf_len) != 0))) recycle_state = false; @@ -4230,7 +4232,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ stb_textedit_initialize_state(&state->Stb, !is_multiline); } - if (!is_multiline) + if (init_reload_from_user_buf) + { + state->Stb.select_start = state->ReloadSelectionStart; + state->Stb.cursor = state->Stb.select_end = state->ReloadSelectionEnd; + state->CursorClamp(); + } + else if (!is_multiline) { if (flags & ImGuiInputTextFlags_AutoSelectAll) select_all = true; From f104967c68f63dc3ffd060f463d45726d6561163 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 7 Feb 2024 22:33:42 +0100 Subject: [PATCH 130/237] Comments --- docs/CHANGELOG.txt | 2 +- imgui.cpp | 2 +- imgui.h | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 88d7942162bf..d98758d06c6f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -69,7 +69,7 @@ Other changes: - Backends: WebGPU: Fixed pipeline layout leak. (#7245) [@rajveermalviya] - Backends: OpenGL3: Backup and restore GL_PIXEL_UNPACK_BUFFER. (#7253) - Internals: Many improvements related to yet unpublicized shortcut routing and input ownership systems. -- Internals: InputText: Add way to force reload of user-buf when active. (#2890) [@kudaba, @ocornut] +- Internals: InputText: Added internal helpers to force reload of user-buf when active. (#2890) [@kudaba, @ocornut] Often requested in some form (#6962, #5219, #3290, #4627, #5054, #3878, #2881, #1506, #1216, #968), and useful for interactive completion/suggestions popups (#2057, #718) diff --git a/imgui.cpp b/imgui.cpp index 7493fd4a3cdf..88ea4e42256d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5401,7 +5401,7 @@ ImVec2 ImGui::GetItemRectSize() } // Prior to v1.90 2023/10/16, the BeginChild() function took a 'bool border = false' parameter instead of 'ImGuiChildFlags child_flags = 0'. -// ImGuiChildFlags_Border is defined as always == 1 in order to allow old code passing 'true'. +// ImGuiChildFlags_Border is defined as always == 1 in order to allow old code passing 'true'. Read comments in imgui.h for details! bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags) { ImGuiID id = GetCurrentWindow()->GetID(str_id); diff --git a/imgui.h b/imgui.h index f8971ad156dc..a1f7c75226fc 100644 --- a/imgui.h +++ b/imgui.h @@ -344,7 +344,7 @@ namespace ImGui // - Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window. Child windows can embed their own child. // - Before 1.90 (November 2023), the "ImGuiChildFlags child_flags = 0" parameter was "bool border = false". // This API is backward compatible with old code, as we guarantee that ImGuiChildFlags_Border == true. - // Consider updating your old call sites: + // Consider updating your old code: // BeginChild("Name", size, false) -> Begin("Name", size, 0); or Begin("Name", size, ImGuiChildFlags_None); // BeginChild("Name", size, true) -> Begin("Name", size, ImGuiChildFlags_Border); // - Manual sizing (each axis can use a different setting e.g. ImVec2(0.0f, 400.0f)): @@ -1027,7 +1027,7 @@ enum ImGuiWindowFlags_ }; // Flags for ImGui::BeginChild() -// (Legacy: bot 0 must always correspond to ImGuiChildFlags_Border to be backward compatible with old API using 'bool border = false'. +// (Legacy: bit 0 must always correspond to ImGuiChildFlags_Border to be backward compatible with old API using 'bool border = false'. // About using AutoResizeX/AutoResizeY flags: // - May be combined with SetNextWindowSizeConstraints() to set a min/max size for each axis (see "Demo->Child->Auto-resize with Constraints"). // - Size measurement for a given axis is only performed when the child window is within visible boundaries, or is just appearing. @@ -1038,7 +1038,7 @@ enum ImGuiWindowFlags_ enum ImGuiChildFlags_ { ImGuiChildFlags_None = 0, - ImGuiChildFlags_Border = 1 << 0, // Show an outer border and enable WindowPadding. (Important: this is always == 1 == true for legacy reason) + ImGuiChildFlags_Border = 1 << 0, // Show an outer border and enable WindowPadding. (IMPORTANT: this is always == 1 == true for legacy reason) ImGuiChildFlags_AlwaysUseWindowPadding = 1 << 1, // Pad with style.WindowPadding even if no border are drawn (no padding by default for non-bordered child windows because it makes more sense) ImGuiChildFlags_ResizeX = 1 << 2, // Allow resize from right border (layout direction). Enable .ini saving (unless ImGuiWindowFlags_NoSavedSettings passed to window flags) ImGuiChildFlags_ResizeY = 1 << 3, // Allow resize from bottom border (layout direction). " @@ -1107,8 +1107,8 @@ enum ImGuiTreeNodeFlags_ }; // Flags for OpenPopup*(), BeginPopupContext*(), IsPopupOpen() functions. -// - To be backward compatible with older API which took an 'int mouse_button = 1' argument, we need to treat -// small flags values as a mouse button index, so we encode the mouse button in the first few bits of the flags. +// - To be backward compatible with older API which took an 'int mouse_button = 1' argument instead of 'ImGuiPopupFlags flags', +// we need to treat small flags values as a mouse button index, so we encode the mouse button in the first few bits of the flags. // It is therefore guaranteed to be legal to pass a mouse button index in ImGuiPopupFlags. // - For the same reason, we exceptionally default the ImGuiPopupFlags argument of BeginPopupContextXXX functions to 1 instead of 0. // IMPORTANT: because the default parameter is 1 (==ImGuiPopupFlags_MouseButtonRight), if you rely on the default parameter From a06dd7a27b6a4d773da9737a29ee725a89fce759 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 8 Feb 2024 15:02:22 +0100 Subject: [PATCH 131/237] OpenPopup(): Added ImGuiPopupFlags_NoReopen. Nav, Menus: Fixed click on a BeginMenu() followed by right-arrow. (#1497, #1533) reopen --- docs/CHANGELOG.txt | 7 +++++++ imgui.cpp | 18 ++++++++++++------ imgui.h | 12 +++++++----- imgui_widgets.cpp | 16 +++++++++++++--- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d98758d06c6f..604e526fa6bb 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,6 +56,13 @@ Other changes: - Nav: Fixed pressing Escape while in a child window with _NavFlattened flag. (#7237) - Nav: Improve handling of Alt key to toggle menu so that key ownership may be claimed on indiviudal left/right alt key without intefering with the other. +- Nav, Menus: Fixed click on a BeginMenu() followed by right-arrow from making the child menu + reopen and flicker (using ImGuiPopupFlags_NoReopen). +- OpenPopup(): Added ImGuiPopupFlags_NoReopen flag to specifically not close nd reopen a popup + when it is already open. (#1497, #1533) + (Note that this differs from specific handling we already have in place for the case of calling + OpenPopup() repeatedly every frame: we already didn't reopen in that specific situation, otherwise + the effect would be very disastrous in term of confusion, as reopening would steal focus). - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. - Debug Tools: Debug Log: Added "Input Routing" logging. - Debug Tools: Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) [@Peter0x44] diff --git a/imgui.cpp b/imgui.cpp index 88ea4e42256d..d99f0b03c07c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10773,16 +10773,22 @@ void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags) } else { - // Gently handle the user mistakenly calling OpenPopup() every frame. It is a programming mistake! However, if we were to run the regular code path, the ui - // would become completely unusable because the popup will always be in hidden-while-calculating-size state _while_ claiming focus. Which would be a very confusing - // situation for the programmer. Instead, we silently allow the popup to proceed, it will keep reappearing and the programming error will be more obvious to understand. - if (g.OpenPopupStack[current_stack_size].PopupId == id && g.OpenPopupStack[current_stack_size].OpenFrameCount == g.FrameCount - 1) - { + // Gently handle the user mistakenly calling OpenPopup() every frames: it is likely a programming mistake! + // However, if we were to run the regular code path, the ui would become completely unusable because the popup will always be + // in hidden-while-calculating-size state _while_ claiming focus. Which is extremely confusing situation for the programmer. + // Instead, for successive frames calls to OpenPopup(), we silently avoid reopening even if ImGuiPopupFlags_NoReopen is not specified. + bool keep_existing = false; + if (g.OpenPopupStack[current_stack_size].PopupId == id) + if ((g.OpenPopupStack[current_stack_size].OpenFrameCount == g.FrameCount - 1) || (popup_flags & ImGuiPopupFlags_NoReopen)) + keep_existing = true; + if (keep_existing) + { + // No reopen g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount; } else { - // Close child popups if any, then flag popup for open/reopen + // Reopen: close child popups if any, then flag popup for open/reopen (set position, focus, init navigation) ClosePopupToLevel(current_stack_size, false); g.OpenPopupStack.push_back(popup_ref); } diff --git a/imgui.h b/imgui.h index a1f7c75226fc..4d79f207eec1 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.2 WIP" -#define IMGUI_VERSION_NUM 19017 +#define IMGUI_VERSION_NUM 19018 #define IMGUI_HAS_TABLE /* @@ -1122,10 +1122,12 @@ enum ImGuiPopupFlags_ ImGuiPopupFlags_MouseButtonMiddle = 2, // For BeginPopupContext*(): open on Middle Mouse release. Guaranteed to always be == 2 (same as ImGuiMouseButton_Middle) ImGuiPopupFlags_MouseButtonMask_ = 0x1F, ImGuiPopupFlags_MouseButtonDefault_ = 1, - ImGuiPopupFlags_NoOpenOverExistingPopup = 1 << 5, // For OpenPopup*(), BeginPopupContext*(): don't open if there's already a popup at the same level of the popup stack - ImGuiPopupFlags_NoOpenOverItems = 1 << 6, // For BeginPopupContextWindow(): don't return true when hovering items, only when hovering empty space - ImGuiPopupFlags_AnyPopupId = 1 << 7, // For IsPopupOpen(): ignore the ImGuiID parameter and test for any popup. - ImGuiPopupFlags_AnyPopupLevel = 1 << 8, // For IsPopupOpen(): search/test at any level of the popup stack (default test in the current level) + ImGuiPopupFlags_NoReopen = 1 << 5, // For OpenPopup*(), BeginPopupContext*(): don't reopen same popup if already open (won't reposition, won't reinitialize navigation) + //ImGuiPopupFlags_NoReopenAlwaysNavInit = 1 << 6, // For OpenPopup*(), BeginPopupContext*(): focus and initialize navigation even when not reopening. + ImGuiPopupFlags_NoOpenOverExistingPopup = 1 << 7, // For OpenPopup*(), BeginPopupContext*(): don't open if there's already a popup at the same level of the popup stack + ImGuiPopupFlags_NoOpenOverItems = 1 << 8, // For BeginPopupContextWindow(): don't return true when hovering items, only when hovering empty space + ImGuiPopupFlags_AnyPopupId = 1 << 10, // For IsPopupOpen(): ignore the ImGuiID parameter and test for any popup. + ImGuiPopupFlags_AnyPopupLevel = 1 << 11, // For IsPopupOpen(): search/test at any level of the popup stack (default test in the current level) ImGuiPopupFlags_AnyPopup = ImGuiPopupFlags_AnyPopupId | ImGuiPopupFlags_AnyPopupLevel, }; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ba4d3f5b8067..0b626cb1a90d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7518,6 +7518,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) PopItemFlag(); bool want_open = false; + bool want_open_nav_init = false; bool want_close = false; if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) { @@ -7560,8 +7561,9 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) want_open = true; if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open { - want_open = true; + want_open = want_open_nav_init = true; NavMoveRequestCancel(); + NavRestoreHighlightAfterMove(); } } else @@ -7593,13 +7595,13 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) if (want_open && !menu_is_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size) { - // Don't reopen/recycle same menu level in the same frame, first close the other menu and yield for a frame. + // Don't reopen/recycle same menu level in the same frame if it is a different menu ID, first close the other menu and yield for a frame. OpenPopup(label); } else if (want_open) { menu_is_open = true; - OpenPopup(label); + OpenPopup(label, ImGuiPopupFlags_NoReopen);// | (want_open_nav_init ? ImGuiPopupFlags_NoReopenAlwaysNavInit : 0)); } if (menu_is_open) @@ -7611,6 +7613,14 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) PopStyleVar(); if (menu_is_open) { + // Implement what ImGuiPopupFlags_NoReopenAlwaysNavInit would do: + // Perform an init request in the case the popup was already open (via a previous mouse hover) + if (want_open && want_open_nav_init && !g.NavInitRequest) + { + FocusWindow(g.CurrentWindow, ImGuiFocusRequestFlags_UnlessBelowModal); + NavInitWindow(g.CurrentWindow, false); + } + // Restore LastItemData so IsItemXXXX functions can work after BeginMenu()/EndMenu() // (This fixes using IsItemClicked() and IsItemHovered(), but IsItemHovered() also relies on its support for ImGuiItemFlags_NoWindowHoverableCheck) g.LastItemData = last_item_in_parent; From 1e8fc01ddd7bdb3479b25e50842d971da02895c2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 8 Feb 2024 15:23:40 +0100 Subject: [PATCH 132/237] InputText: Internal: ReloadUserBufXXX functions don't override revert value. (#2890) + rename --- imgui_internal.h | 2 +- imgui_widgets.cpp | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index fb6b7a221fe9..790490880e75 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1069,7 +1069,7 @@ struct IMGUI_API ImGuiInputTextState int CurLenW, CurLenA; // we need to maintain our buffer length in both UTF-8 and wchar format. UTF-8 length is valid even if TextA is not. ImVector TextW; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer. ImVector TextA; // temporary UTF8 buffer for callbacks and other operations. this is not updated in every code-path! size=capacity. - ImVector InitialTextA; // backup of end-user buffer at the time of focus (in UTF-8, unaltered) + ImVector InitialTextA; // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered) bool TextAIsValid; // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument) int BufCapacityA; // end-user buffer capacity float ScrollX; // horizontal scrolling/offset diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 0b626cb1a90d..e8bb0599263d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4199,11 +4199,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714) InputTextDeactivateHook(state->ID); - // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar) - // From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode) + // From the moment we focused we are normally ignoring the content of 'buf' (unless we are in read-only mode) const int buf_len = (int)strlen(buf); - state->InitialTextA.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string. - memcpy(state->InitialTextA.Data, buf, buf_len + 1); + //if (!init_reload_from_user_buf) + { + // Take a copy of the initial buffer value. + state->InitialTextA.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string. + memcpy(state->InitialTextA.Data, buf, buf_len + 1); + } // Preserve cursor position and undo/redo stack if we come back to same widget // FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate? From a5e0e90c16a4f0c95b7064a8aa7c0247a7536398 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 8 Feb 2024 15:44:46 +0100 Subject: [PATCH 133/237] Nav: tweak RenderNavHighlight() syntax. ImGuiNavHighlightFlags_TypeThin -> ImGuiNavHighlightFlags_Compact. --- imgui.cpp | 20 ++++++++++---------- imgui_internal.h | 5 ++--- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 4 ++-- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d99f0b03c07c..b0137ff76e02 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3452,22 +3452,22 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f : g.Style.FrameRounding; ImRect display_rect = bb; display_rect.ClipWith(window->ClipRect); - if (flags & ImGuiNavHighlightFlags_TypeDefault) + const float thickness = 2.0f; + if (flags & ImGuiNavHighlightFlags_Compact) { - const float THICKNESS = 2.0f; - const float DISTANCE = 3.0f + THICKNESS * 0.5f; - display_rect.Expand(ImVec2(DISTANCE, DISTANCE)); + window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, thickness); + } + else + { + const float distance = 3.0f + thickness * 0.5f; + display_rect.Expand(ImVec2(distance, distance)); bool fully_visible = window->ClipRect.Contains(display_rect); if (!fully_visible) window->DrawList->PushClipRect(display_rect.Min, display_rect.Max); - window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS * 0.5f, THICKNESS * 0.5f), display_rect.Max - ImVec2(THICKNESS * 0.5f, THICKNESS * 0.5f), GetColorU32(ImGuiCol_NavHighlight), rounding, 0, THICKNESS); + window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, thickness); if (!fully_visible) window->DrawList->PopClipRect(); } - if (flags & ImGuiNavHighlightFlags_TypeThin) - { - window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, 1.0f); - } } void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow) @@ -5543,7 +5543,7 @@ void ImGui::EndChild() // When browsing a window that has no activable items (scroll only) we keep a highlight on the child (pass g.NavId to trick into always displaying) if (child_window->DC.NavLayersActiveMask == 0 && child_window == g.NavWindow) - RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_TypeThin); + RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_Compact); } else { diff --git a/imgui_internal.h b/imgui_internal.h index 790490880e75..2d17b828419c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1554,8 +1554,7 @@ enum ImGuiScrollFlags_ enum ImGuiNavHighlightFlags_ { ImGuiNavHighlightFlags_None = 0, - ImGuiNavHighlightFlags_TypeDefault = 1 << 0, - ImGuiNavHighlightFlags_TypeThin = 1 << 1, + ImGuiNavHighlightFlags_Compact = 1 << 1, // Compact highlight, no padding ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2, // Draw rectangular highlight if (g.NavId == id) _even_ when using the mouse. ImGuiNavHighlightFlags_NoRounding = 1 << 3, }; @@ -3377,7 +3376,7 @@ namespace ImGui IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f); IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0); - IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_TypeDefault); // Navigation highlight + IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_None); // Navigation highlight IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. IMGUI_API void RenderMouseCursor(ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 272842e09eeb..a6f331d6a9c1 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -3082,7 +3082,7 @@ void ImGui::TableHeader(const char* label) if ((table->RowFlags & ImGuiTableRowFlags_Headers) == 0) TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_TableHeaderBg), table->CurrentColumn); } - RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); + RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact | ImGuiNavHighlightFlags_NoRounding); if (held) table->HeldHeaderColumn = (ImGuiTableColumnIdx)column_n; window->DC.CursorPos.y -= g.Style.ItemSpacing.y * 0.5f; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e8bb0599263d..6fcf0b7338bf 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6338,7 +6338,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // Render const ImU32 text_col = GetColorU32(ImGuiCol_Text); - ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_TypeThin; + ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_Compact; if (display_frame) { // Framed type @@ -6641,7 +6641,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl RenderFrame(bb.Min, bb.Max, col, false, 0.0f); } if (g.NavId == id) - RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); + RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact | ImGuiNavHighlightFlags_NoRounding); if (span_all_columns) { From 7d67623d15b6514f8fb4f2b1a4e51a0d5ee5aca1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 8 Feb 2024 15:46:17 +0100 Subject: [PATCH 134/237] InputText: Internal: ReloadUserBufXXX functions don't override revert value. (#2890) fix accidental comment. --- imgui_widgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 6fcf0b7338bf..2df1c9f36b1d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4201,7 +4201,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // From the moment we focused we are normally ignoring the content of 'buf' (unless we are in read-only mode) const int buf_len = (int)strlen(buf); - //if (!init_reload_from_user_buf) + if (!init_reload_from_user_buf) { // Take a copy of the initial buffer value. state->InitialTextA.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string. From 3a078466a7afdb4f47964651dbb2c4b2d19e28de Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 8 Feb 2024 16:06:55 +0100 Subject: [PATCH 135/237] Nav: ImGuiWindowFlags_NoNavInputs is tested during scoring so NavFlattened windows can use it. --- docs/CHANGELOG.txt | 3 ++- imgui.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 604e526fa6bb..21fd765399ea 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -58,7 +58,8 @@ Other changes: indiviudal left/right alt key without intefering with the other. - Nav, Menus: Fixed click on a BeginMenu() followed by right-arrow from making the child menu reopen and flicker (using ImGuiPopupFlags_NoReopen). -- OpenPopup(): Added ImGuiPopupFlags_NoReopen flag to specifically not close nd reopen a popup +- Nav: ImGuiWindowFlags_NoNavInputs is tested during scoring so NavFlattened windows can use it. +- OpenPopup(): Added ImGuiPopupFlags_NoReopen flag to specifically not close and reopen a popup when it is already open. (#1497, #1533) (Note that this differs from specific handling we already have in place for the case of calling OpenPopup() repeatedly every frame: we already didn't reopen in that specific situation, otherwise diff --git a/imgui.cpp b/imgui.cpp index b0137ff76e02..39300f9caf97 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11509,7 +11509,7 @@ static void ImGui::NavProcessItem() // Process Move Request (scoring for navigation) // FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRect + scoring from a rect wrapped according to current wrapping policy) - if (g.NavMoveScoringItems && (item_flags & ImGuiItemFlags_Disabled) == 0) + if (g.NavMoveScoringItems && (item_flags & ImGuiItemFlags_Disabled) == 0 && (window->Flags & ImGuiWindowFlags_NoNavInputs) == 0) { const bool is_tabbing = (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0; if (is_tabbing) From 76e09c4b0faed1c7e12ebb660b667b5abfcc6679 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 8 Feb 2024 17:08:01 +0100 Subject: [PATCH 136/237] ClosePopupsOverWindow(): amend to remove _ChildWindow test. Said test seems unnecessary and incorrect as we test hierarchy now. See test "nav_ctrl_tab_popups" in ImGuiTestSuite. --- docs/CHANGELOG.txt | 6 ++++-- imgui.cpp | 9 +++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 21fd765399ea..80f7807ec175 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -59,11 +59,13 @@ Other changes: - Nav, Menus: Fixed click on a BeginMenu() followed by right-arrow from making the child menu reopen and flicker (using ImGuiPopupFlags_NoReopen). - Nav: ImGuiWindowFlags_NoNavInputs is tested during scoring so NavFlattened windows can use it. -- OpenPopup(): Added ImGuiPopupFlags_NoReopen flag to specifically not close and reopen a popup - when it is already open. (#1497, #1533) +- Popups: OpenPopup(): added ImGuiPopupFlags_NoReopen flag to specifically not close and reopen + a popup when it is already open. (#1497, #1533) (Note that this differs from specific handling we already have in place for the case of calling OpenPopup() repeatedly every frame: we already didn't reopen in that specific situation, otherwise the effect would be very disastrous in term of confusion, as reopening would steal focus). +- Popups: Slight change to popup closing logic (e.g. after focusing another window) which skipped + over popups that are also child windows. - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. - Debug Tools: Debug Log: Added "Input Routing" logging. - Debug Tools: Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) [@Peter0x44] diff --git a/imgui.cpp b/imgui.cpp index 39300f9caf97..70de295dce27 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10819,14 +10819,15 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to if (!popup.Window) continue; IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0); - if (popup.Window->Flags & ImGuiWindowFlags_ChildWindow) - continue; // Trim the stack unless the popup is a direct parent of the reference window (the reference window is often the NavWindow) - // - With this stack of window, clicking/focusing Popup1 will close Popup2 and Popup3: - // Window -> Popup1 -> Popup2 -> Popup3 + // - Clicking/Focusing Window2 won't close Popup1: + // Window -> Popup1 -> Window2(Ref) + // - Clicking/focusing Popup1 will close Popup2 and Popup3: + // Window -> Popup1(Ref) -> Popup2 -> Popup3 // - Each popups may contain child windows, which is why we compare ->RootWindow! // Window -> Popup1 -> Popup1_Child -> Popup2 -> Popup2_Child + // We step through every popup from bottom to top to validate their position relative to reference window. bool ref_window_is_descendent_of_popup = false; for (int n = popup_count_to_keep; n < g.OpenPopupStack.Size; n++) if (ImGuiWindow* popup_window = g.OpenPopupStack[n].Window) From 5cdc4a2a413c05f10edcb47cdf0a4338c940fb6c Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 9 Feb 2024 14:20:12 +0100 Subject: [PATCH 137/237] Demo: use ImGui::MemAlloc/MemFree for consistency. (#7300) --- imgui_demo.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 53462be788c4..e73d02f96806 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6997,19 +6997,19 @@ struct ExampleAppConsole { ClearLog(); for (int i = 0; i < History.Size; i++) - free(History[i]); + ImGui::MemFree(History[i]); } // Portable helpers static int Stricmp(const char* s1, const char* s2) { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; } static int Strnicmp(const char* s1, const char* s2, int n) { int d = 0; while (n > 0 && (d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; n--; } return d; } - static char* Strdup(const char* s) { IM_ASSERT(s); size_t len = strlen(s) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); } + static char* Strdup(const char* s) { IM_ASSERT(s); size_t len = strlen(s) + 1; void* buf = ImGui::MemAlloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); } static void Strtrim(char* s) { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; } void ClearLog() { for (int i = 0; i < Items.Size; i++) - free(Items[i]); + ImGui::MemFree(Items[i]); Items.clear(); } @@ -7175,7 +7175,7 @@ struct ExampleAppConsole for (int i = History.Size - 1; i >= 0; i--) if (Stricmp(History[i], command_line) == 0) { - free(History[i]); + ImGui::MemFree(History[i]); History.erase(History.begin() + i); break; } From 70aa717a8e1f8cee34ea265b3ecd53d7ad3fb354 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 9 Feb 2024 15:23:43 +0100 Subject: [PATCH 138/237] Combo: Fixed not reusing windows optimally when used inside a popup stack. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 6 +++--- imgui_internal.h | 6 +++--- imgui_widgets.cpp | 5 ++++- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 80f7807ec175..7d2b1beae001 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -66,6 +66,7 @@ Other changes: the effect would be very disastrous in term of confusion, as reopening would steal focus). - Popups: Slight change to popup closing logic (e.g. after focusing another window) which skipped over popups that are also child windows. +- Combo: Fixed not reusing windows optimally when used inside a popup stack. - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. - Debug Tools: Debug Log: Added "Input Routing" logging. - Debug Tools: Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) [@Peter0x44] diff --git a/imgui.cpp b/imgui.cpp index 70de295dce27..ab03c38d5ddd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6434,7 +6434,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window_stack_data.StackSizesOnBegin.SetToContextState(&g); g.CurrentWindowStack.push_back(window_stack_data); if (flags & ImGuiWindowFlags_ChildMenu) - g.BeginMenuCount++; + g.BeginMenuDepth++; // Update ->RootWindow and others pointers (before any possible call to FocusWindow) if (first_begin_of_the_frame) @@ -7106,7 +7106,7 @@ void ImGui::End() // Pop from window stack g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup; if (window->Flags & ImGuiWindowFlags_ChildMenu) - g.BeginMenuCount--; + g.BeginMenuDepth--; if (window->Flags & ImGuiWindowFlags_Popup) g.BeginPopupStack.pop_back(); g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithContextState(&g); @@ -10926,7 +10926,7 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags) char name[20]; if (flags & ImGuiWindowFlags_ChildMenu) - ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginMenuCount); // Recycle windows based on depth + ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginMenuDepth); // Recycle windows based on depth else ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame diff --git a/imgui_internal.h b/imgui_internal.h index 2d17b828419c..d826fbcd5449 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2028,8 +2028,6 @@ struct ImGuiContext ImVector BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame) ImVector NavTreeNodeStack; // Stack for TreeNode() when a NavLeft requested is emitted. - int BeginMenuCount; - // Viewports ImVector Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData. @@ -2154,6 +2152,8 @@ struct ImGuiContext ImGuiInputTextDeactivatedState InputTextDeactivatedState; ImFont InputTextPasswordFont; ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc. + int BeginMenuDepth; + int BeginComboDepth; ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets ImGuiID ColorEditCurrentID; // Set temporarily while inside of the parent-most ColorEdit4/ColorPicker4 (because they call each others). ImGuiID ColorEditSavedID; // ID we are saving/restoring HS for @@ -2307,7 +2307,6 @@ struct ImGuiContext CurrentFocusScopeId = 0; CurrentItemFlags = ImGuiItemFlags_None; DebugShowGroupRects = false; - BeginMenuCount = 0; NavWindow = NULL; NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0; @@ -2371,6 +2370,7 @@ struct ImGuiContext MouseStationaryTimer = 0.0f; TempInputId = 0; + BeginMenuDepth = BeginComboDepth = 0; ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_; ColorEditCurrentID = ColorEditSavedID = 0; ColorEditSavedHue = ColorEditSavedSat = 0.0f; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 2df1c9f36b1d..daf066c08e42 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1784,7 +1784,7 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags // This is essentially a specialized version of BeginPopupEx() char name[16]; - ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth + ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginComboDepth); // Recycle windows based on depth // Set position given a custom constraint (peak into expected window size so we can position it) // FIXME: This might be easier to express with an hypothetical SetNextWindowPosConstraints() function? @@ -1811,12 +1811,15 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above return false; } + g.BeginComboDepth++; return true; } void ImGui::EndCombo() { + ImGuiContext& g = *GImGui; EndPopup(); + g.BeginComboDepth--; } // Call directly after the BeginCombo/EndCombo block. The preview is designed to only host non-interactive elements From 59c8db69ebd0f99c85a71644c0789c20c2e5b347 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 9 Feb 2024 15:27:35 +0100 Subject: [PATCH 139/237] Demo: reorder Demo->Configuration section with docking/viewports section. --- imgui_demo.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 941cb3961302..127e0deaa4c2 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -477,6 +477,12 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", &io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange); ImGui::SameLine(); HelpMarker("Instruct backend to not alter mouse cursor shape and visibility."); + ImGui::Checkbox("io.ConfigInputTrickleEventQueue", &io.ConfigInputTrickleEventQueue); + ImGui::SameLine(); HelpMarker("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."); + ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); + ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something)."); + + ImGui::SeparatorText("Docking"); ImGui::CheckboxFlags("io.ConfigFlags: DockingEnable", &io.ConfigFlags, ImGuiConfigFlags_DockingEnable); ImGui::SameLine(); if (io.ConfigDockingWithShift) @@ -497,6 +503,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Unindent(); } + ImGui::SeparatorText("Multi-viewports"); ImGui::CheckboxFlags("io.ConfigFlags: ViewportsEnable", &io.ConfigFlags, ImGuiConfigFlags_ViewportsEnable); ImGui::SameLine(); HelpMarker("[beta] Enable beta multi-viewports support. See ImGuiPlatformIO for details."); if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) @@ -513,11 +520,6 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Unindent(); } - ImGui::Checkbox("io.ConfigInputTrickleEventQueue", &io.ConfigInputTrickleEventQueue); - ImGui::SameLine(); HelpMarker("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."); - ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); - ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something)."); - ImGui::SeparatorText("Widgets"); ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink); ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting)."); From 30ba3c347ced6676090496d31d85d3287adcd6da Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 9 Feb 2024 15:40:14 +0100 Subject: [PATCH 140/237] Viewports: Fixed moving accross monitors when io.ConfigWindowsMoveFromTitleBarOnly is set. (#7299, #3071) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 25 +++++++++++++++++++++---- imgui_internal.h | 1 + 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 42526d4a5512..4dd3d4c9b200 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -81,6 +81,7 @@ Docking+Viewports Branch: - Added ImGuiDockNodeFlags_DockedWindowsInFocusRoute to automatically make a dockspace connect the focus route of its docked window. This is provided a convenience in case you have windows where a connection is not explicit. (#6798) +- Viewports: Fixed moving accross monitors when io.ConfigWindowsMoveFromTitleBarOnly is set. (#7299, #3071) - Backends: OSX: Fixed not submitting Monitors info when viewports are not enabled, leading to missing e.g. DpiScale info. (#7257) [@actboy168] diff --git a/imgui.cpp b/imgui.cpp index 3ea3b80a76c6..5fede59fcd3d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7172,10 +7172,19 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } else if (window->ViewportOwned && g.PlatformIO.Monitors.Size > 0) { - // Lost windows (e.g. a monitor disconnected) will naturally moved to the fallback/dummy monitor aka the main viewport. - const ImGuiPlatformMonitor* monitor = GetViewportPlatformMonitor(window->Viewport); - visibility_rect.Min = monitor->WorkPos + visibility_padding; - visibility_rect.Max = monitor->WorkPos + monitor->WorkSize - visibility_padding; + if (g.MovingWindow != NULL && window->RootWindowDockTree == g.MovingWindow->RootWindowDockTree) + { + // While moving windows we allow them to straddle monitors (#7299, #3071) + visibility_rect = g.PlatformMonitorsFullWorkRect; + } + else + { + // When not moving ensure visible in its monitor + // Lost windows (e.g. a monitor disconnected) will naturally moved to the fallback/dummy monitor aka the main viewport. + const ImGuiPlatformMonitor* monitor = GetViewportPlatformMonitor(window->Viewport); + visibility_rect = ImRect(monitor->WorkPos, monitor->WorkPos + monitor->WorkSize); + } + visibility_rect.Expand(-visibility_padding); ClampWindowPos(window, visibility_rect); } } @@ -14818,6 +14827,7 @@ static void ImGui::UpdateViewportsNewFrame() } // Update fallback monitor + g.PlatformMonitorsFullWorkRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX); if (g.PlatformIO.Monitors.Size == 0) { ImGuiPlatformMonitor* monitor = &g.FallbackMonitor; @@ -14826,6 +14836,13 @@ static void ImGui::UpdateViewportsNewFrame() monitor->WorkPos = main_viewport->WorkPos; monitor->WorkSize = main_viewport->WorkSize; monitor->DpiScale = main_viewport->DpiScale; + g.PlatformMonitorsFullWorkRect.Add(monitor->WorkPos); + g.PlatformMonitorsFullWorkRect.Add(monitor->WorkPos + monitor->WorkSize); + } + for (ImGuiPlatformMonitor& monitor : g.PlatformIO.Monitors) + { + g.PlatformMonitorsFullWorkRect.Add(monitor.WorkPos); + g.PlatformMonitorsFullWorkRect.Add(monitor.WorkPos + monitor.WorkSize); } if (!viewports_enabled) diff --git a/imgui_internal.h b/imgui_internal.h index a4b17471bbbd..8094b4e9808a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2230,6 +2230,7 @@ struct ImGuiContext ImGuiViewportP* MouseLastHoveredViewport; // Last known viewport that was hovered by mouse (even if we are not hovering any viewport any more) + honoring the _NoInputs flag. ImGuiID PlatformLastFocusedViewportId; ImGuiPlatformMonitor FallbackMonitor; // Virtual monitor used as fallback if backend doesn't provide monitor information. + ImRect PlatformMonitorsFullWorkRect; // Bounding box of all platform monitors int ViewportCreatedCount; // Unique sequential creation counter (mostly for testing/debugging) int PlatformWindowsCreatedCount; // Unique sequential creation counter (mostly for testing/debugging) int ViewportFocusedStampCount; // Every time the front-most window changes, we stamp its viewport with an incrementing counter From 7b5357d817eddfd375dc3abdcc1474a55950ad00 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 9 Feb 2024 16:17:59 +0100 Subject: [PATCH 141/237] Debug Tools: Metrics: Improved Monitors and Viewports minimap display. Highlight on hover. Added ImGuiViewport ID in Master branch. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 34 +++++++++++++++++++++++----------- imgui.h | 1 + imgui_internal.h | 2 ++ 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7d2b1beae001..76131e58cf14 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,6 +68,7 @@ Other changes: over popups that are also child windows. - Combo: Fixed not reusing windows optimally when used inside a popup stack. - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. +- Debug Tools: Metrics: Improved Monitors and Viewports minimap display. Highlight on hover. - Debug Tools: Debug Log: Added "Input Routing" logging. - Debug Tools: Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) [@Peter0x44] - Backends: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by diff --git a/imgui.cpp b/imgui.cpp index ab03c38d5ddd..716e77096db0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1126,6 +1126,7 @@ static void RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, static void RenderDimmedBackgrounds(); // Viewports +const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbitrary constant instead of e.g. ImHashStr("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter. static void UpdateViewportsNewFrame(); } @@ -3596,6 +3597,7 @@ void ImGui::Initialize() // Create default viewport ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)(); + viewport->ID = IMGUI_VIEWPORT_DEFAULT_ID; g.Viewports.push_back(viewport); g.TempBuffer.resize(1024 * 3 + 1, 0); @@ -13975,7 +13977,7 @@ static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport*, ImGuiPlatformImeDat //----------------------------------------------------------------------------- // [SECTION] METRICS/DEBUGGER WINDOW //----------------------------------------------------------------------------- -// - RenderViewportThumbnail() [Internal] +// - DebugRenderViewportThumbnail() [Internal] // - RenderViewportsThumbnails() [Internal] // - DebugTextEncoding() // - MetricsHelpMarker() [Internal] @@ -14014,7 +14016,7 @@ void ImGui::DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* ImRect thumb_r = thumb_window->Rect(); ImRect title_r = thumb_window->TitleBarRect(); thumb_r = ImRect(ImTrunc(off + thumb_r.Min * scale), ImTrunc(off + thumb_r.Max * scale)); - title_r = ImRect(ImTrunc(off + title_r.Min * scale), ImTrunc(off + ImVec2(title_r.Max.x, title_r.Min.y) * scale) + ImVec2(0,5)); // Exaggerate title bar height + title_r = ImRect(ImTrunc(off + title_r.Min * scale), ImTrunc(off + ImVec2(title_r.Max.x, title_r.Min.y + title_r.GetHeight() * 3.0f) * scale)); // Exaggerate title bar height thumb_r.ClipWithFull(bb); title_r.ClipWithFull(bb); const bool window_is_focused = (g.NavWindow && thumb_window->RootWindowForTitleBarHighlight == g.NavWindow->RootWindowForTitleBarHighlight); @@ -14024,6 +14026,8 @@ void ImGui::DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* window->DrawList->AddText(g.Font, g.FontSize * 1.0f, title_r.Min, GetColorU32(ImGuiCol_Text, alpha_mul), thumb_window->Name, FindRenderedTextEnd(thumb_window->Name)); } draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul)); + if (viewport->ID == g.DebugMetricsConfig.HighlightViewportID) + window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255)); } static void RenderViewportsThumbnails() @@ -14031,13 +14035,12 @@ static void RenderViewportsThumbnails() ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - // We don't display full monitor bounds (we could, but it often looks awkward), instead we display just enough to cover all of our viewports. float SCALE = 1.0f / 8.0f; - ImRect bb_full(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); - for (ImGuiViewportP* viewport : g.Viewports) - bb_full.Add(viewport->GetMainRect()); + ImRect bb_full(g.Viewports[0]->Pos, g.Viewports[0]->Pos + g.Viewports[0]->Size); ImVec2 p = window->DC.CursorPos; ImVec2 off = p - bb_full.Min * SCALE; + + // Draw viewports for (ImGuiViewportP* viewport : g.Viewports) { ImRect viewport_draw_bb(off + (viewport->Pos) * SCALE, off + (viewport->Pos + viewport->Size) * SCALE); @@ -14280,7 +14283,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash."); if (Checkbox("Show Item Picker", &g.DebugItemPickerActive) && g.DebugItemPickerActive) DebugStartItemPicker(); - Checkbox("Show \"Debug Break\" buttons in other sections", &g.IO.ConfigDebugIsDebuggerPresent); + Checkbox("Show \"Debug Break\" buttons in other sections (io.ConfigDebugIsDebuggerPresent)", &g.IO.ConfigDebugIsDebuggerPresent); SeparatorText("Visualize"); @@ -14416,9 +14419,14 @@ void ImGui::ShowMetricsWindow(bool* p_open) // Viewports if (TreeNode("Viewports", "Viewports (%d)", g.Viewports.Size)) { - Indent(GetTreeNodeToLabelSpacing()); - RenderViewportsThumbnails(); - Unindent(GetTreeNodeToLabelSpacing()); + SetNextItemOpen(true, ImGuiCond_Once); + if (TreeNode("Windows Minimap")) + { + RenderViewportsThumbnails(); + TreePop(); + } + cfg->HighlightViewportID = 0; + for (ImGuiViewportP* viewport : g.Viewports) DebugNodeViewport(viewport); TreePop(); @@ -15120,8 +15128,12 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label) void ImGui::DebugNodeViewport(ImGuiViewportP* viewport) { + ImGuiContext& g = *GImGui; SetNextItemOpen(true, ImGuiCond_Once); - if (TreeNode("viewport0", "Viewport #%d", 0)) + bool open = TreeNode("viewport0", "Viewport #%d", 0); + if (IsItemHovered()) + g.DebugMetricsConfig.HighlightViewportID = viewport->ID; + if (open) { ImGuiWindowFlags flags = viewport->Flags; BulletText("Main Pos: (%.0f,%.0f), Size: (%.0f,%.0f)\nWorkArea Offset Left: %.0f Top: %.0f, Right: %.0f, Bottom: %.0f", diff --git a/imgui.h b/imgui.h index 4d79f207eec1..8d05fba2183c 100644 --- a/imgui.h +++ b/imgui.h @@ -3123,6 +3123,7 @@ enum ImGuiViewportFlags_ // - Windows are generally trying to stay within the Work Area of their host viewport. struct ImGuiViewport { + ImGuiID ID; // Unique identifier for the viewport ImGuiViewportFlags Flags; // See ImGuiViewportFlags_ ImVec2 Pos; // Main Area: Position of the viewport (Dear ImGui coordinates are the same as OS desktop/native coordinates) ImVec2 Size; // Main Area: Size of the viewport. diff --git a/imgui_internal.h b/imgui_internal.h index d826fbcd5449..2e55ff389322 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1865,6 +1865,8 @@ struct ImGuiMetricsConfig bool ShowAtlasTintedWithTextColor = false; int ShowWindowsRectsType = -1; int ShowTablesRectsType = -1; + int HighlightMonitorIdx = -1; + ImGuiID HighlightViewportID = 0; }; struct ImGuiStackLevelInfo From 536090303a8fca7d896f77d6d63dc59249bc87f4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 9 Feb 2024 16:33:42 +0100 Subject: [PATCH 142/237] Version 1.90.2 --- docs/CHANGELOG.txt | 6 ++++-- imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 76131e58cf14..1ed9219035b3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -36,9 +36,11 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 1.90.2 WIP (In Progress) + VERSION 1.90.2 (Released 2024-01-09) ----------------------------------------------------------------------- +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90.2 + Breaking changes: - Commented out ImGuiIO::ImeWindowHandle obsoleted in 1.87 in favor of writing @@ -55,7 +57,7 @@ Other changes: regression from 1.90.1 related to code scoping Tab presses to local scope. (#7226) [@bratpilz] - Nav: Fixed pressing Escape while in a child window with _NavFlattened flag. (#7237) - Nav: Improve handling of Alt key to toggle menu so that key ownership may be claimed on - indiviudal left/right alt key without intefering with the other. + individual left/right alt key without interfering with the other. - Nav, Menus: Fixed click on a BeginMenu() followed by right-arrow from making the child menu reopen and flicker (using ImGuiPopupFlags_NoReopen). - Nav: ImGuiWindowFlags_NoNavInputs is tested during scoring so NavFlattened windows can use it. diff --git a/imgui.cpp b/imgui.cpp index 716e77096db0..a3ca2bf624b5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.2 WIP +// dear imgui, v1.90.2 // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 8d05fba2183c..f4c7161640af 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.2 WIP +// dear imgui, v1.90.2 // (headers) // Help: @@ -23,8 +23,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.2 WIP" -#define IMGUI_VERSION_NUM 19018 +#define IMGUI_VERSION "1.90.2" +#define IMGUI_VERSION_NUM 19020 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index e73d02f96806..7e48dd18aaa7 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.2 WIP +// dear imgui, v1.90.2 // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index a40ce1688033..90da08826106 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.2 WIP +// dear imgui, v1.90.2 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 2e55ff389322..1575600d8b9e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.2 WIP +// dear imgui, v1.90.2 // (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. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index a6f331d6a9c1..5052dee1e305 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.2 WIP +// dear imgui, v1.90.2 // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index daf066c08e42..a129d8087619 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.2 WIP +// dear imgui, v1.90.2 // (widgets code) /* From 8490a262c45a27dc5acbc0ef68f81ed4ba784cf1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 9 Feb 2024 16:17:59 +0100 Subject: [PATCH 143/237] Debug Tools: Metrics: Improved Monitors and Viewports minimap display. Highlight on hover. (amends) --- imgui.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index cbc81536f392..5635f19a9e8d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -19646,10 +19646,19 @@ static void RenderViewportsThumbnails() ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; + // Draw monitor and calculate their boundaries float SCALE = 1.0f / 8.0f; - ImRect bb_full(g.Viewports[0]->Pos, g.Viewports[0]->Pos + g.Viewports[0]->Size); + ImRect bb_full(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); + for (ImGuiPlatformMonitor& monitor : g.PlatformIO.Monitors) + bb_full.Add(ImRect(monitor.MainPos, monitor.MainPos + monitor.MainSize)); ImVec2 p = window->DC.CursorPos; ImVec2 off = p - bb_full.Min * SCALE; + for (ImGuiPlatformMonitor& monitor : g.PlatformIO.Monitors) + { + ImRect monitor_draw_bb(off + (monitor.MainPos) * SCALE, off + (monitor.MainPos + monitor.MainSize) * SCALE); + window->DrawList->AddRect(monitor_draw_bb.Min, monitor_draw_bb.Max, (g.DebugMetricsConfig.HighlightMonitorIdx == g.PlatformIO.Monitors.index_from_ptr(&monitor)) ? IM_COL32(255, 255, 0, 255) : ImGui::GetColorU32(ImGuiCol_Border), 4.0f); + window->DrawList->AddRectFilled(monitor_draw_bb.Min, monitor_draw_bb.Max, ImGui::GetColorU32(ImGuiCol_Border, 0.10f), 4.0f); + } // Draw viewports for (ImGuiViewportP* viewport : g.Viewports) @@ -20045,6 +20054,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) // Viewports if (TreeNode("Viewports", "Viewports (%d)", g.Viewports.Size)) { + cfg->HighlightMonitorIdx = -1; bool open = TreeNode("Monitors", "Monitors (%d)", g.PlatformIO.Monitors.Size); SameLine(); MetricsHelpMarker("Dear ImGui uses monitor data:\n- to query DPI settings on a per monitor basis\n- to position popup/tooltips so they don't straddle monitors."); @@ -20057,6 +20067,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) 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); + if (IsItemHovered()) + cfg->HighlightMonitorIdx = i; } TreePop(); } @@ -20078,10 +20090,14 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (viewports.Size > 1) ImQsort(viewports.Data, viewports.Size, sizeof(ImGuiViewport*), ViewportComparerByLastFocusedStampCount); for (ImGuiViewportP* viewport : viewports) + { BulletText("Viewport #%d, ID: 0x%08X, LastFocused = %08d, PlatformFocused = %s, Window: \"%s\"", viewport->Idx, viewport->ID, viewport->LastFocusedStampCount, (g.PlatformIO.Platform_GetWindowFocus && viewport->PlatformWindowCreated) ? (g.PlatformIO.Platform_GetWindowFocus(viewport) ? "1" : "0") : "N/A", viewport->Window ? viewport->Window->Name : "N/A"); + if (IsItemHovered()) + cfg->HighlightViewportID = viewport->ID; + } TreePop(); } From 915c6393ad7eeafc26cb0845e31b17e75d878a1a Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 12 Feb 2024 14:54:48 +0100 Subject: [PATCH 144/237] Version 1.90.3 WIP --- docs/CHANGELOG.txt | 6 ++++++ imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 15 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1ed9219035b3..acf52803b52b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,12 @@ HOW TO UPDATE? and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users. - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.90.3 WIP (In Progress) +----------------------------------------------------------------------- + +Other changes: + ----------------------------------------------------------------------- VERSION 1.90.2 (Released 2024-01-09) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index a3ca2bf624b5..b7e8d95739cb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.2 +// dear imgui, v1.90.3 WIP // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index f4c7161640af..f6740ca35a06 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.2 +// dear imgui, v1.90.3 WIP // (headers) // Help: @@ -23,8 +23,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.2" -#define IMGUI_VERSION_NUM 19020 +#define IMGUI_VERSION "1.90.3 WIP" +#define IMGUI_VERSION_NUM 19021 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 7e48dd18aaa7..39dfa34ca02e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.2 +// dear imgui, v1.90.3 WIP // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 90da08826106..04fb7896845d 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.2 +// dear imgui, v1.90.3 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 1575600d8b9e..f9fb0e91c9cc 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.2 +// dear imgui, v1.90.3 WIP // (internal structures/api) // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 5052dee1e305..538877f9efb2 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.2 +// dear imgui, v1.90.3 WIP // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index a129d8087619..52436ead4e24 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.2 +// dear imgui, v1.90.3 WIP // (widgets code) /* From 2af01baffd1054fc62e577168ef783a4ed7fd87d Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 12 Feb 2024 14:57:39 +0100 Subject: [PATCH 145/237] Backends: SDLRenderer3: query newly added SDL_RenderViewportSet() to not restore a wrong viewport if none was initially set. https://github.com/libsdl-org/SDL/issues/9029 --- backends/imgui_impl_sdlrenderer3.cpp | 9 ++++----- docs/CHANGELOG.txt | 4 ++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/backends/imgui_impl_sdlrenderer3.cpp b/backends/imgui_impl_sdlrenderer3.cpp index fcef4f5df59b..01cd1a30861e 100644 --- a/backends/imgui_impl_sdlrenderer3.cpp +++ b/backends/imgui_impl_sdlrenderer3.cpp @@ -20,6 +20,7 @@ // - Introduction, links and more at the top of imgui.cpp // CHANGELOG +// 2024-02-12: Amend to query SDL_RenderViewportSet() and restore viewport accordingly. // 2023-05-30: Initial version. #include "imgui.h" @@ -129,10 +130,12 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data) struct BackupSDLRendererState { SDL_Rect Viewport; + bool ViewportEnabled; bool ClipEnabled; SDL_Rect ClipRect; }; BackupSDLRendererState old = {}; + old.ViewportEnabled = SDL_RenderViewportSet(bd->SDLRenderer) == SDL_TRUE; old.ClipEnabled = SDL_RenderClipEnabled(bd->SDLRenderer) == SDL_TRUE; SDL_GetRenderViewport(bd->SDLRenderer, &old.Viewport); SDL_GetRenderClipRect(bd->SDLRenderer, &old.ClipRect); @@ -178,11 +181,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data) const float* xy = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, pos)); const float* uv = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, uv)); -#if SDL_VERSION_ATLEAST(2,0,19) const SDL_Color* color = (const SDL_Color*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, col)); // SDL 2.0.19+ -#else - const int* color = (const int*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, col)); // SDL 2.0.17 and 2.0.18 -#endif // Bind texture, Draw SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID(); @@ -197,7 +196,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data) } // Restore modified SDL_Renderer state - SDL_SetRenderViewport(bd->SDLRenderer, &old.Viewport); + SDL_SetRenderViewport(bd->SDLRenderer, old.ViewportEnabled ? &old.Viewport : nullptr); SDL_SetRenderClipRect(bd->SDLRenderer, old.ClipEnabled ? &old.ClipRect : nullptr); } diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index acf52803b52b..ec27103af594 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,10 @@ HOW TO UPDATE? Other changes: +- Backends: SDLRenderer3: query newly added SDL_RenderViewportSet() to not restore + a wrong viewport if none was initially set. + + ----------------------------------------------------------------------- VERSION 1.90.2 (Released 2024-01-09) ----------------------------------------------------------------------- From 3af739a2d176223870cedbe0704a102b07a0885e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 12 Feb 2024 15:21:48 +0100 Subject: [PATCH 146/237] Menus, Popups: fixed menus and popups with child window flag erroneously not displaying a scrollbar when contents is over parent viewport size. (#7287, #7063) Amend f37f6f6 --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ec27103af594..092d0b73c31d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,8 @@ HOW TO UPDATE? Other changes: +- Menus, Popups: fixed menus and popups with child window flag erroneously not displaying + a scrollbar when contents is over parent viewport size. (#7287, #7063) [@ZingBallyhoo] - Backends: SDLRenderer3: query newly added SDL_RenderViewportSet() to not restore a wrong viewport if none was initially set. diff --git a/imgui.cpp b/imgui.cpp index b7e8d95739cb..70d11d3ae102 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5755,7 +5755,7 @@ static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_cont { // Maximum window size is determined by the viewport size or monitor size ImVec2 size_min = CalcWindowMinSize(window); - ImVec2 size_max = (window->Flags & ImGuiWindowFlags_ChildWindow) ? ImVec2(FLT_MAX, FLT_MAX) : ImGui::GetMainViewport()->WorkSize - style.DisplaySafeAreaPadding * 2.0f; + ImVec2 size_max = ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_Popup)) ? ImVec2(FLT_MAX, FLT_MAX) : ImGui::GetMainViewport()->WorkSize - style.DisplaySafeAreaPadding * 2.0f; ImVec2 size_auto_fit = ImClamp(size_desired, size_min, size_max); // When the window cannot fit all contents (either because of constraints, either because screen is too small), From 1d6f0cea0e6bb59519f65e05fe394114dccc49e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=92=80=E5=A2=83=E7=9F=B3?= Date: Thu, 6 Jul 2023 01:48:35 +0800 Subject: [PATCH 147/237] Backends: DX9: use RGBA texture to avoid conversion if supported --- backends/imgui_impl_dx9.cpp | 28 +++++++++++++++++++++++++--- docs/CHANGELOG.txt | 2 ++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp index 48fee4bd5b22..ea0b26ec046f 100644 --- a/backends/imgui_impl_dx9.cpp +++ b/backends/imgui_impl_dx9.cpp @@ -15,6 +15,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-02-12: DirectX9: Using RGBA format when supported by the driver to avoid CPU side conversion. (#6575) // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). // 2021-06-25: DirectX9: Explicitly disable texture state stages after >= 1. @@ -312,6 +313,24 @@ void ImGui_ImplDX9_Shutdown() IM_DELETE(bd); } +static bool ImGui_ImplDX9_CheckFormatSupport(IDirect3DDevice9* pDevice, D3DFORMAT format) +{ + IDirect3D9* pd3d = nullptr; + if (pDevice->GetDirect3D(&pd3d) != D3D_OK) + return false; + D3DDEVICE_CREATION_PARAMETERS param = {}; + D3DDISPLAYMODE mode = {}; + if (pDevice->GetCreationParameters(¶m) != D3D_OK || pDevice->GetDisplayMode(0, &mode) != D3D_OK) + { + pd3d->Release(); + return false; + } + // Font texture should support linear filter, color blend and write to render-target + bool support = (pd3d->CheckDeviceFormat(param.AdapterOrdinal, param.DeviceType, mode.Format, D3DUSAGE_DYNAMIC | D3DUSAGE_QUERY_FILTER | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, format)) == D3D_OK; + pd3d->Release(); + return support; +} + static bool ImGui_ImplDX9_CreateFontsTexture() { // Build texture atlas @@ -323,18 +342,21 @@ static bool ImGui_ImplDX9_CreateFontsTexture() // Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices) #ifndef IMGUI_USE_BGRA_PACKED_COLOR - if (io.Fonts->TexPixelsUseColors) + const bool rgba_support = ImGui_ImplDX9_CheckFormatSupport(bd->pd3dDevice, D3DFMT_A8B8G8R8); + if (!rgba_support && io.Fonts->TexPixelsUseColors) { ImU32* dst_start = (ImU32*)ImGui::MemAlloc((size_t)width * height * bytes_per_pixel); for (ImU32* src = (ImU32*)pixels, *dst = dst_start, *dst_end = dst_start + (size_t)width * height; dst < dst_end; src++, dst++) *dst = IMGUI_COL_TO_DX9_ARGB(*src); pixels = (unsigned char*)dst_start; } +#else + const bool rgba_support = false; #endif // Upload texture to graphics system bd->FontTexture = nullptr; - if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture, nullptr) < 0) + if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, rgba_support ? D3DFMT_A8B8G8R8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture, nullptr) < 0) return false; D3DLOCKED_RECT tex_locked_rect; if (bd->FontTexture->LockRect(0, &tex_locked_rect, nullptr, 0) != D3D_OK) @@ -347,7 +369,7 @@ static bool ImGui_ImplDX9_CreateFontsTexture() io.Fonts->SetTexID((ImTextureID)bd->FontTexture); #ifndef IMGUI_USE_BGRA_PACKED_COLOR - if (io.Fonts->TexPixelsUseColors) + if (!rgba_support && io.Fonts->TexPixelsUseColors) ImGui::MemFree(pixels); #endif diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 092d0b73c31d..70304200d5d9 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -45,6 +45,8 @@ Other changes: a scrollbar when contents is over parent viewport size. (#7287, #7063) [@ZingBallyhoo] - Backends: SDLRenderer3: query newly added SDL_RenderViewportSet() to not restore a wrong viewport if none was initially set. +- Backends: DirectX9: Using RGBA format when allowed by the driver to avoid CPU side + conversion. (#6575) [@Demonese] ----------------------------------------------------------------------- From 89019319ddbb3f03c228a1cde1f8233b121fee0e Mon Sep 17 00:00:00 2001 From: Shawn Hatori Date: Sat, 23 Dec 2023 14:01:48 -0500 Subject: [PATCH 148/237] Backends: Vulkan: use PipelineRenderingCreateInfo for dynamic rendering (#7166, #6855, #5446, #5037) --- backends/imgui_impl_vulkan.cpp | 11 +++++------ backends/imgui_impl_vulkan.h | 22 ++++++++++++++-------- docs/CHANGELOG.txt | 7 +++++++ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 91bd43b68bc1..1c7d5a6c7dec 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -33,10 +33,11 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-02-12: *BREAKING CHANGE*: Dynamic rendering now require filling PipelineRenderingCreateInfo structure. // 2024-01-19: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236) // 2024-01-11: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size (#3957). Fixed MinAllocationSize handing (#7189). // 2024-01-03: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous "best practice" validation layer. (#7189, #4238) -// 2024-01-03: Vulkan: Stoped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them. +// 2024-01-03: Vulkan: Stopped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them. // 2023-11-29: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075) // 2023-11-10: *BREAKING CHANGE*: Removed parameter from ImGui_ImplVulkan_CreateFontsTexture(): backend now creates its own command-buffer to upload fonts. // *BREAKING CHANGE*: Removed ImGui_ImplVulkan_DestroyFontUploadObjects() which is now unecessary as we create and destroy those objects in the backend. @@ -953,13 +954,11 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC info.subpass = subpass; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo = {}; - pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR; - pipelineRenderingCreateInfo.colorAttachmentCount = 1; - pipelineRenderingCreateInfo.pColorAttachmentFormats = &bd->VulkanInitInfo.ColorAttachmentFormat; + IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR"); + IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.pNext == nullptr && "PipelineRenderingCreateInfo pNext must be NULL"); if (bd->VulkanInitInfo.UseDynamicRendering) { - info.pNext = &pipelineRenderingCreateInfo; + info.pNext = &bd->VulkanInitInfo.PipelineRenderingCreateInfo; info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr. } #endif diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 94c5b1d30efe..650576dd750e 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -54,6 +54,9 @@ #endif // Initialization data, for ImGui_ImplVulkan_Init() +// - VkDescriptorPool should be created with VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, +// and must contain a pool size large enough to hold an ImGui VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor. +// - When using dynamic rendering, set UseDynamicRendering=true and fill PipelineRenderingCreateInfo structure. // [Please zero-clear before use!] struct ImGui_ImplVulkan_InitInfo { @@ -62,18 +65,21 @@ struct ImGui_ImplVulkan_InitInfo VkDevice Device; uint32_t QueueFamily; VkQueue Queue; + VkDescriptorPool DescriptorPool; // See requirements in note above + uint32_t MinImageCount; // >= 2 + uint32_t ImageCount; // >= MinImageCount + VkSampleCountFlagBits MSAASamples; // 0 defaults to VK_SAMPLE_COUNT_1_BIT + + // (Optional) VkPipelineCache PipelineCache; - VkDescriptorPool DescriptorPool; uint32_t Subpass; - uint32_t MinImageCount; // >= 2 - uint32_t ImageCount; // >= MinImageCount - VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT (0 -> default to VK_SAMPLE_COUNT_1_BIT) - // Dynamic Rendering (Optional) - bool UseDynamicRendering; // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3. - VkFormat ColorAttachmentFormat; // Required for dynamic rendering + // (Optional) Dynamic Rendering + // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3. + bool UseDynamicRendering; + VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; - // Allocation, Debugging + // (Optional) Allocation, Debugging const VkAllocationCallbacks* Allocator; void (*CheckVkResultFn)(VkResult err); VkDeviceSize MinAllocationSize; // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory. diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 70304200d5d9..15382b4763de 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -39,6 +39,13 @@ HOW TO UPDATE? VERSION 1.90.3 WIP (In Progress) ----------------------------------------------------------------------- +Breaking changes: + +- Backends: Vulkan: Using dynamic rendering now require filling the PipelineRenderingCreateInfo + structure in ImGui_ImplVulkan_InitInfo, allowing to configure color/depth/stencil formats. + Removed ColorAttachmentFormat field previously provided for dynamic rendering. + (#7166, #6855, #5446, #5037) [@shawnhatori] + Other changes: - Menus, Popups: fixed menus and popups with child window flag erroneously not displaying From 11d73f03ee5e33f1847a4b34a6025a040ef0d17e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 12 Feb 2024 17:18:52 +0100 Subject: [PATCH 149/237] Backends: Vulkan: Fix/amend 8901931 --- backends/imgui_impl_vulkan.cpp | 4 ++-- imgui_widgets.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 1c7d5a6c7dec..64cb04fb2df4 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -954,10 +954,10 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC info.subpass = subpass; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR"); - IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.pNext == nullptr && "PipelineRenderingCreateInfo pNext must be NULL"); if (bd->VulkanInitInfo.UseDynamicRendering) { + IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR"); + IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.pNext == nullptr && "PipelineRenderingCreateInfo pNext must be NULL"); info.pNext = &bd->VulkanInitInfo.PipelineRenderingCreateInfo; info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr. } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 52436ead4e24..a53f3e8ef086 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1995,7 +1995,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*old_getter)(void* // - DataTypeGetInfo() // - DataTypeFormatString() // - DataTypeApplyOp() -// - DataTypeApplyOpFromText() +// - DataTypeApplyFromText() // - DataTypeCompare() // - DataTypeClamp() // - GetMinimumStepAtDecimalPrecision From e0ba0d0433ae2cd2b5c6ddf4a87a76259e121fd1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 12 Feb 2024 18:46:01 +0100 Subject: [PATCH 150/237] Backends: Vulkan: Fixes for building with pre Vulkan 1.3. Amend 8901931. (#7166) --- backends/imgui_impl_vulkan.cpp | 3 +-- backends/imgui_impl_vulkan.h | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 64cb04fb2df4..2aa5518d5f2c 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -185,8 +185,7 @@ IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_DEF) #undef IMGUI_VULKAN_FUNC_DEF #endif // VK_NO_PROTOTYPES -#if defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering) -#define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING +#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING static PFN_vkCmdBeginRenderingKHR ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR; static PFN_vkCmdEndRenderingKHR ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR; #endif diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 650576dd750e..c2324449f99d 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -52,6 +52,9 @@ #else #include #endif +#if defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering) +#define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING +#endif // Initialization data, for ImGui_ImplVulkan_Init() // - VkDescriptorPool should be created with VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, @@ -77,7 +80,9 @@ struct ImGui_ImplVulkan_InitInfo // (Optional) Dynamic Rendering // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3. bool UseDynamicRendering; +#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; +#endif // (Optional) Allocation, Debugging const VkAllocationCallbacks* Allocator; From fd8d6dc5d19883fda08641351d912cd9c74b374d Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 13 Feb 2024 15:49:49 +0100 Subject: [PATCH 151/237] Backends: SDL2,SDL3: tidying up. --- backends/imgui_impl_sdl2.cpp | 36 +++++++++++++++++++----------------- backends/imgui_impl_sdl3.cpp | 36 +++++++++++++++++++----------------- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 9f950bb1716f..dfcfa925e10e 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -103,16 +103,18 @@ // SDL Data struct ImGui_ImplSDL2_Data { - SDL_Window* Window; - SDL_Renderer* Renderer; - Uint64 Time; - Uint32 MouseWindowID; - int MouseButtonsDown; - SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT]; - SDL_Cursor* LastMouseCursor; - int PendingMouseLeaveFrame; - char* ClipboardTextData; - bool MouseCanUseGlobalState; + SDL_Window* Window; + SDL_Renderer* Renderer; + Uint64 Time; + char* ClipboardTextData; + + // Mouse handling + Uint32 MouseWindowID; + int MouseButtonsDown; + SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT]; + SDL_Cursor* MouseLastCursor; + int MouseLastLeaveFrame; + bool MouseCanUseGlobalState; ImGui_ImplSDL2_Data() { memset((void*)this, 0, sizeof(*this)); } }; @@ -368,10 +370,10 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) if (window_event == SDL_WINDOWEVENT_ENTER) { bd->MouseWindowID = event->window.windowID; - bd->PendingMouseLeaveFrame = 0; + bd->MouseLastLeaveFrame = 0; } if (window_event == SDL_WINDOWEVENT_LEAVE) - bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1; + bd->MouseLastLeaveFrame = ImGui::GetFrameCount() + 1; if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED) io.AddFocusEvent(true); else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) @@ -511,7 +513,7 @@ void ImGui_ImplSDL2_Shutdown() SDL_free(bd->ClipboardTextData); for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) SDL_FreeCursor(bd->MouseCursors[cursor_n]); - bd->LastMouseCursor = nullptr; + bd->MouseLastCursor = nullptr; io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; @@ -567,10 +569,10 @@ static void ImGui_ImplSDL2_UpdateMouseCursor() { // Show OS mouse cursor SDL_Cursor* expected_cursor = bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]; - if (bd->LastMouseCursor != expected_cursor) + if (bd->MouseLastCursor != expected_cursor) { SDL_SetCursor(expected_cursor); // SDL function doesn't have an early out (see #6113) - bd->LastMouseCursor = expected_cursor; + bd->MouseLastCursor = expected_cursor; } SDL_ShowCursor(SDL_TRUE); } @@ -651,10 +653,10 @@ void ImGui_ImplSDL2_NewFrame() io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f); bd->Time = current_time; - if (bd->PendingMouseLeaveFrame && bd->PendingMouseLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0) + if (bd->MouseLastLeaveFrame && bd->MouseLastLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0) { bd->MouseWindowID = 0; - bd->PendingMouseLeaveFrame = 0; + bd->MouseLastLeaveFrame = 0; io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); } diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index d41a5e461000..e06ef7959e97 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -61,16 +61,18 @@ // SDL Data struct ImGui_ImplSDL3_Data { - SDL_Window* Window; - SDL_Renderer* Renderer; - Uint64 Time; - Uint32 MouseWindowID; - int MouseButtonsDown; - SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT]; - SDL_Cursor* LastMouseCursor; - int PendingMouseLeaveFrame; - char* ClipboardTextData; - bool MouseCanUseGlobalState; + SDL_Window* Window; + SDL_Renderer* Renderer; + Uint64 Time; + char* ClipboardTextData; + + // Mouse handling + Uint32 MouseWindowID; + int MouseButtonsDown; + SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT]; + SDL_Cursor* MouseLastCursor; + int MousePendingLeaveFrame; + bool MouseCanUseGlobalState; ImGui_ImplSDL3_Data() { memset((void*)this, 0, sizeof(*this)); } }; @@ -312,7 +314,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) case SDL_EVENT_WINDOW_MOUSE_ENTER: { bd->MouseWindowID = event->window.windowID; - bd->PendingMouseLeaveFrame = 0; + bd->MousePendingLeaveFrame = 0; return true; } // - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late, @@ -321,7 +323,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) // FIXME: Unconfirmed whether this is still needed with SDL3. case SDL_EVENT_WINDOW_MOUSE_LEAVE: { - bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1; + bd->MousePendingLeaveFrame = ImGui::GetFrameCount() + 1; return true; } case SDL_EVENT_WINDOW_FOCUS_GAINED: @@ -455,7 +457,7 @@ void ImGui_ImplSDL3_Shutdown() SDL_free(bd->ClipboardTextData); for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) SDL_DestroyCursor(bd->MouseCursors[cursor_n]); - bd->LastMouseCursor = nullptr; + bd->MouseLastCursor = nullptr; io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; @@ -514,10 +516,10 @@ static void ImGui_ImplSDL3_UpdateMouseCursor() { // Show OS mouse cursor SDL_Cursor* expected_cursor = bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]; - if (bd->LastMouseCursor != expected_cursor) + if (bd->MouseLastCursor != expected_cursor) { SDL_SetCursor(expected_cursor); // SDL function doesn't have an early out (see #6113) - bd->LastMouseCursor = expected_cursor; + bd->MouseLastCursor = expected_cursor; } SDL_ShowCursor(); } @@ -595,10 +597,10 @@ void ImGui_ImplSDL3_NewFrame() io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f); bd->Time = current_time; - if (bd->PendingMouseLeaveFrame && bd->PendingMouseLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0) + if (bd->MousePendingLeaveFrame && bd->MousePendingLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0) { bd->MouseWindowID = 0; - bd->PendingMouseLeaveFrame = 0; + bd->MousePendingLeaveFrame = 0; io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); } From bf1c96d4fa24b95e8e47585fc8a2705ff982820e Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 13 Feb 2024 16:24:44 +0100 Subject: [PATCH 152/237] Backends: SDL2: Handle gamepad disconnection + fixed increasing refcount. Added ImGui_ImplSDL2_SelectGamepadAuto()/ImGui_ImplSDL2_SelectGamepadExplicit(). (#3884, #6559, #6890) --- backends/imgui_impl_sdl2.cpp | 68 +++++++++++++++++++++++++++++++++--- backends/imgui_impl_sdl2.h | 8 ++++- docs/CHANGELOG.txt | 4 +++ 3 files changed, 74 insertions(+), 6 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index dfcfa925e10e..6fe074677239 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-02-13: Inputs: Handle gamepad disconnection. Added ImGui_ImplSDL2_SelectGamepadAuto()/ImGui_ImplSDL2_SelectGamepadExplicit(). // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys. // 2023-04-06: Inputs: Avoid calling SDL_StartTextInput()/SDL_StopTextInput() as they don't only pertain to IME. It's unclear exactly what their relation is to IME. (#6306) // 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen. (#2702) @@ -116,6 +117,11 @@ struct ImGui_ImplSDL2_Data int MouseLastLeaveFrame; bool MouseCanUseGlobalState; + // Gamepad handling + SDL_GameController* Gamepad; + bool GamepadSelectAuto; + bool WantRefreshGamepads; // Refresh gamepad list + ImGui_ImplSDL2_Data() { memset((void*)this, 0, sizeof(*this)); } }; @@ -380,6 +386,12 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) io.AddFocusEvent(false); return true; } + case SDL_CONTROLLERDEVICEADDED: + case SDL_CONTROLLERDEVICEREMOVED: + { + bd->WantRefreshGamepads = true; + return true; + } } return false; } @@ -416,6 +428,11 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer) io.ClipboardUserData = nullptr; io.SetPlatformImeDataFn = ImGui_ImplSDL2_SetPlatformImeData; + // Gamepad handling + bd->Gamepad = NULL; + bd->GamepadSelectAuto = true; + bd->WantRefreshGamepads = true; + // Load mouse cursors bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); @@ -521,6 +538,24 @@ void ImGui_ImplSDL2_Shutdown() IM_DELETE(bd); } +void ImGui_ImplSDL2_SelectGamepadAuto() +{ + ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); + if (bd->GamepadSelectAuto == false) + bd->Gamepad = NULL; + bd->GamepadSelectAuto = true; + bd->WantRefreshGamepads = true; +} + +void ImGui_ImplSDL2_SelectGamepadExplicit(SDL_GameController* gamepad) +{ + ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); + if (bd->GamepadSelectAuto == true && bd->Gamepad != NULL) + SDL_GameControllerClose(bd->Gamepad); + bd->Gamepad = gamepad; + bd->GamepadSelectAuto = false; +} + static void ImGui_ImplSDL2_UpdateMouseData() { ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); @@ -580,21 +615,44 @@ static void ImGui_ImplSDL2_UpdateMouseCursor() static void ImGui_ImplSDL2_UpdateGamepads() { + ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); - if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. + + // Select a new controller + if (bd->WantRefreshGamepads && bd->GamepadSelectAuto) + { + SDL_GameController* old_gamepad = bd->Gamepad; + SDL_GameController* new_gamepad = NULL; + int joystick_count = SDL_NumJoysticks(); + for (int n = 0; n < joystick_count; n++) + if (SDL_IsGameController(n)) + if (SDL_GameController* gamepad = SDL_GameControllerOpen(n)) + { + new_gamepad = gamepad; + break; + } + + //IMGUI_DEBUG_LOG("ImGui_ImplSDL2_UpdateGamepads(): Gamepad change %p -> %p\n", old_gamepad, new_gamepad); + if (old_gamepad != NULL && new_gamepad != NULL) + SDL_GameControllerClose(old_gamepad); + bd->Gamepad = new_gamepad; + bd->WantRefreshGamepads = false; + } + + // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. + if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) return; // Get gamepad io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; - SDL_GameController* game_controller = SDL_GameControllerOpen(0); - if (!game_controller) + if (bd->Gamepad == NULL) return; io.BackendFlags |= ImGuiBackendFlags_HasGamepad; // Update gamepad inputs #define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V) - #define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0); } - #define MAP_ANALOG(KEY_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); } + #define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, SDL_GameControllerGetButton(bd->Gamepad, BUTTON_NO) != 0); } + #define MAP_ANALOG(KEY_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(bd->Gamepad, AXIS_NO) - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); } const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value. MAP_BUTTON(ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START); MAP_BUTTON(ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK); diff --git a/backends/imgui_impl_sdl2.h b/backends/imgui_impl_sdl2.h index dd5e047e7a00..cd477a89732a 100644 --- a/backends/imgui_impl_sdl2.h +++ b/backends/imgui_impl_sdl2.h @@ -24,6 +24,7 @@ struct SDL_Window; struct SDL_Renderer; +struct _SDL_GameController; typedef union SDL_Event SDL_Event; IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context); @@ -36,8 +37,13 @@ IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown(); IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(); IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event); +// Gamepad selection automatically starts in Auto mode, picking first available SDL_GameController. You may override this. +// When using Explicit selection, caller is responsible for opening/closing gamepad. +IMGUI_IMPL_API void ImGui_ImplSDL2_SelectGamepadAuto(); +IMGUI_IMPL_API void ImGui_ImplSDL2_SelectGamepadExplicit(struct _SDL_GameController* gamepad); + #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS -static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter +static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter #endif #endif // #ifndef IMGUI_DISABLE diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 15382b4763de..5b37b9f20933 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,6 +50,10 @@ Other changes: - Menus, Popups: fixed menus and popups with child window flag erroneously not displaying a scrollbar when contents is over parent viewport size. (#7287, #7063) [@ZingBallyhoo] +- Backends: SDL2: Handle gamepad disconnection + fixed increasing gamepad reference counter + continuously. Added ImGui_ImplSDL2_SelectGamepadAuto()/ImGui_ImplSDL2_SelectGamepadExplicit() + functions to respectively select automatic selection or provide a gamepad to use. + (#3884, #6559, #6890) [@ocornut, @lethal-guitar, @wn2000, @bog-dan-ro] - Backends: SDLRenderer3: query newly added SDL_RenderViewportSet() to not restore a wrong viewport if none was initially set. - Backends: DirectX9: Using RGBA format when allowed by the driver to avoid CPU side From f966da1f8fb569b99dd4220162f2d9bde6f3b153 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 13 Feb 2024 16:31:33 +0100 Subject: [PATCH 153/237] Backends: SDL2: Gamepad handlng: amend bf1c96d. (#3884, #6559, #6890) --- backends/imgui_impl_sdl2.cpp | 4 +++- docs/CHANGELOG.txt | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 6fe074677239..001dced3e42c 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -530,7 +530,9 @@ void ImGui_ImplSDL2_Shutdown() SDL_free(bd->ClipboardTextData); for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) SDL_FreeCursor(bd->MouseCursors[cursor_n]); - bd->MouseLastCursor = nullptr; + + if (bd->Gamepad && bd->GamepadSelectAuto) + SDL_GameControllerClose(bd->Gamepad); io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5b37b9f20933..94457fc867a4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,7 +53,7 @@ Other changes: - Backends: SDL2: Handle gamepad disconnection + fixed increasing gamepad reference counter continuously. Added ImGui_ImplSDL2_SelectGamepadAuto()/ImGui_ImplSDL2_SelectGamepadExplicit() functions to respectively select automatic selection or provide a gamepad to use. - (#3884, #6559, #6890) [@ocornut, @lethal-guitar, @wn2000, @bog-dan-ro] + (#3884, #6559, #6890) [@lethal-guitar, @wn2000, @ocornut, @bog-dan-ro] - Backends: SDLRenderer3: query newly added SDL_RenderViewportSet() to not restore a wrong viewport if none was initially set. - Backends: DirectX9: Using RGBA format when allowed by the driver to avoid CPU side From d15e4100b839acdf701c92644eb804838d891e70 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 13 Feb 2024 18:50:21 +0100 Subject: [PATCH 154/237] Backends: SDL2: Amend new API, all support for multiple gamepads. (#3884, #6559, #6890) --- backends/imgui_impl_sdl2.cpp | 177 +++++++++++++++++++++-------------- backends/imgui_impl_sdl2.h | 7 +- docs/CHANGELOG.txt | 7 +- 3 files changed, 113 insertions(+), 78 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 001dced3e42c..ecd8f9426971 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,7 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2024-02-13: Inputs: Handle gamepad disconnection. Added ImGui_ImplSDL2_SelectGamepadAuto()/ImGui_ImplSDL2_SelectGamepadExplicit(). +// 2024-02-13: Inputs: Handle gamepad disconnection. Added ImGui_ImplSDL2_SetGamepadModeAutoFirst(), ImGui_ImplSDL2_SetGamepadModeAutoAll(), ImGui_ImplSDL2_SetGamepadModeManual(). // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys. // 2023-04-06: Inputs: Avoid calling SDL_StartTextInput()/SDL_StopTextInput() as they don't only pertain to IME. It's unclear exactly what their relation is to IME. (#6306) // 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen. (#2702) @@ -102,6 +102,13 @@ #define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6) // SDL Data +enum ImGui_ImplSDL2_GamepadMode +{ + ImGui_ImplSDL2_GamepadMode_AutoFirst, // (Default) Use first available gamepad + ImGui_ImplSDL2_GamepadMode_AutoAll, // Use all available gamepad + ImGui_ImplSDL2_GamepadMode_Manual, +}; + struct ImGui_ImplSDL2_Data { SDL_Window* Window; @@ -118,9 +125,9 @@ struct ImGui_ImplSDL2_Data bool MouseCanUseGlobalState; // Gamepad handling - SDL_GameController* Gamepad; - bool GamepadSelectAuto; - bool WantRefreshGamepads; // Refresh gamepad list + ImVector Gamepads; + ImGui_ImplSDL2_GamepadMode GamepadMode; + bool WantUpdateGamepadsList; ImGui_ImplSDL2_Data() { memset((void*)this, 0, sizeof(*this)); } }; @@ -389,7 +396,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) case SDL_CONTROLLERDEVICEADDED: case SDL_CONTROLLERDEVICEREMOVED: { - bd->WantRefreshGamepads = true; + bd->WantUpdateGamepadsList = true; return true; } } @@ -429,9 +436,8 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer) io.SetPlatformImeDataFn = ImGui_ImplSDL2_SetPlatformImeData; // Gamepad handling - bd->Gamepad = NULL; - bd->GamepadSelectAuto = true; - bd->WantRefreshGamepads = true; + bd->GamepadMode = ImGui_ImplSDL2_GamepadMode_AutoFirst; + bd->WantUpdateGamepadsList = true; // Load mouse cursors bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); @@ -520,6 +526,8 @@ bool ImGui_ImplSDL2_InitForOther(SDL_Window* window) return ImGui_ImplSDL2_Init(window, nullptr); } +static void ImGui_ImplSDL2_CloseGamepads(); + void ImGui_ImplSDL2_Shutdown() { ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); @@ -530,9 +538,7 @@ void ImGui_ImplSDL2_Shutdown() SDL_free(bd->ClipboardTextData); for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) SDL_FreeCursor(bd->MouseCursors[cursor_n]); - - if (bd->Gamepad && bd->GamepadSelectAuto) - SDL_GameControllerClose(bd->Gamepad); + ImGui_ImplSDL2_CloseGamepads(); io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; @@ -540,24 +546,6 @@ void ImGui_ImplSDL2_Shutdown() IM_DELETE(bd); } -void ImGui_ImplSDL2_SelectGamepadAuto() -{ - ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); - if (bd->GamepadSelectAuto == false) - bd->Gamepad = NULL; - bd->GamepadSelectAuto = true; - bd->WantRefreshGamepads = true; -} - -void ImGui_ImplSDL2_SelectGamepadExplicit(SDL_GameController* gamepad) -{ - ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); - if (bd->GamepadSelectAuto == true && bd->Gamepad != NULL) - SDL_GameControllerClose(bd->Gamepad); - bd->Gamepad = gamepad; - bd->GamepadSelectAuto = false; -} - static void ImGui_ImplSDL2_UpdateMouseData() { ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); @@ -615,30 +603,80 @@ static void ImGui_ImplSDL2_UpdateMouseCursor() } } +static void ImGui_ImplSDL2_CloseGamepads() +{ + ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); + if (bd->GamepadMode != ImGui_ImplSDL2_GamepadMode_Manual) + for (SDL_GameController* gamepad : bd->Gamepads) + SDL_GameControllerClose(gamepad); + bd->Gamepads.resize(0); +} + +void ImGui_ImplSDL2_SetGamepadModeAutoFirst() +{ + ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); + ImGui_ImplSDL2_CloseGamepads(); + bd->GamepadMode = ImGui_ImplSDL2_GamepadMode_AutoFirst; + bd->WantUpdateGamepadsList = true; +} + +void ImGui_ImplSDL2_SetGamepadModeAutoAll() +{ + ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); + ImGui_ImplSDL2_CloseGamepads(); + bd->GamepadMode = ImGui_ImplSDL2_GamepadMode_AutoAll; + bd->WantUpdateGamepadsList = true; +} + +void ImGui_ImplSDL2_SetGamepadModeManual(struct _SDL_GameController** gamepads_array, int gamepads_count) +{ + ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); + ImGui_ImplSDL2_CloseGamepads(); + for (int n = 0; n < gamepads_count; n++) + bd->Gamepads.push_back(gamepads_array[n]); + bd->GamepadMode = ImGui_ImplSDL2_GamepadMode_Manual; +} + +static void ImGui_ImplSDL2_UpdateGamepadButton(ImGui_ImplSDL2_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GameControllerButton button_no) +{ + bool merged_value = false; + for (SDL_GameController* gamepad : bd->Gamepads) + merged_value |= SDL_GameControllerGetButton(gamepad, button_no) != 0; + io.AddKeyEvent(key, merged_value); +} + +static void ImGui_ImplSDL2_UpdateGamepadAnalog(ImGui_ImplSDL2_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GameControllerAxis axis_no, float v0, float v1) +{ + float merged_value = 0.0f; + for (SDL_GameController* gamepad : bd->Gamepads) + { + float vn = (float)(SDL_GameControllerGetAxis(gamepad, axis_no) - v0) / (float)(v1 - v0); + vn = (vn < 0.0f) ? 0.0f : (vn > 1.0f) ? 1.0f : vn; + if (merged_value < vn) + merged_value = vn; + } + io.AddKeyAnalogEvent(key, merged_value > 0.1f, merged_value); +} + static void ImGui_ImplSDL2_UpdateGamepads() { ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); - // Select a new controller - if (bd->WantRefreshGamepads && bd->GamepadSelectAuto) + // Update list of controller(s) to use + if (bd->WantUpdateGamepadsList && bd->GamepadMode != ImGui_ImplSDL2_GamepadMode_Manual) { - SDL_GameController* old_gamepad = bd->Gamepad; - SDL_GameController* new_gamepad = NULL; + ImGui_ImplSDL2_CloseGamepads(); int joystick_count = SDL_NumJoysticks(); for (int n = 0; n < joystick_count; n++) if (SDL_IsGameController(n)) if (SDL_GameController* gamepad = SDL_GameControllerOpen(n)) { - new_gamepad = gamepad; - break; + bd->Gamepads.push_back(gamepad); + if (bd->GamepadMode == ImGui_ImplSDL2_GamepadMode_AutoFirst) + break; } - - //IMGUI_DEBUG_LOG("ImGui_ImplSDL2_UpdateGamepads(): Gamepad change %p -> %p\n", old_gamepad, new_gamepad); - if (old_gamepad != NULL && new_gamepad != NULL) - SDL_GameControllerClose(old_gamepad); - bd->Gamepad = new_gamepad; - bd->WantRefreshGamepads = false; + bd->WantUpdateGamepadsList = false; } // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. @@ -647,41 +685,36 @@ static void ImGui_ImplSDL2_UpdateGamepads() // Get gamepad io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; - if (bd->Gamepad == NULL) + if (bd->Gamepads.Size == 0) return; io.BackendFlags |= ImGuiBackendFlags_HasGamepad; // Update gamepad inputs - #define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V) - #define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, SDL_GameControllerGetButton(bd->Gamepad, BUTTON_NO) != 0); } - #define MAP_ANALOG(KEY_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(bd->Gamepad, AXIS_NO) - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); } - const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value. - MAP_BUTTON(ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START); - MAP_BUTTON(ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK); - MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square - MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle - MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle - MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross - MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); - MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); - MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); - MAP_BUTTON(ImGuiKey_GamepadDpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN); - MAP_BUTTON(ImGuiKey_GamepadL1, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); - MAP_BUTTON(ImGuiKey_GamepadR1, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); - MAP_ANALOG(ImGuiKey_GamepadL2, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 0.0f, 32767); - MAP_ANALOG(ImGuiKey_GamepadR2, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 0.0f, 32767); - MAP_BUTTON(ImGuiKey_GamepadL3, SDL_CONTROLLER_BUTTON_LEFTSTICK); - MAP_BUTTON(ImGuiKey_GamepadR3, SDL_CONTROLLER_BUTTON_RIGHTSTICK); - MAP_ANALOG(ImGuiKey_GamepadLStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768); - MAP_ANALOG(ImGuiKey_GamepadLStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767); - MAP_ANALOG(ImGuiKey_GamepadLStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32768); - MAP_ANALOG(ImGuiKey_GamepadLStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767); - MAP_ANALOG(ImGuiKey_GamepadRStickLeft, SDL_CONTROLLER_AXIS_RIGHTX, -thumb_dead_zone, -32768); - MAP_ANALOG(ImGuiKey_GamepadRStickRight, SDL_CONTROLLER_AXIS_RIGHTX, +thumb_dead_zone, +32767); - MAP_ANALOG(ImGuiKey_GamepadRStickUp, SDL_CONTROLLER_AXIS_RIGHTY, -thumb_dead_zone, -32768); - MAP_ANALOG(ImGuiKey_GamepadRStickDown, SDL_CONTROLLER_AXIS_RIGHTY, +thumb_dead_zone, +32767); - #undef MAP_BUTTON - #undef MAP_ANALOG + const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value. + ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START); + ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK); + ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square + ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle + ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle + ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross + ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); + ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); + ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); + ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN); + ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL1, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); + ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR1, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); + ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadL2, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 0.0f, 32767); + ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadR2, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 0.0f, 32767); + ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL3, SDL_CONTROLLER_BUTTON_LEFTSTICK); + ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR3, SDL_CONTROLLER_BUTTON_RIGHTSTICK); + ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768); + ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767); + ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32768); + ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767); + ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickLeft, SDL_CONTROLLER_AXIS_RIGHTX, -thumb_dead_zone, -32768); + ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickRight, SDL_CONTROLLER_AXIS_RIGHTX, +thumb_dead_zone, +32767); + ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickUp, SDL_CONTROLLER_AXIS_RIGHTY, -thumb_dead_zone, -32768); + ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickDown, SDL_CONTROLLER_AXIS_RIGHTY, +thumb_dead_zone, +32767); } void ImGui_ImplSDL2_NewFrame() diff --git a/backends/imgui_impl_sdl2.h b/backends/imgui_impl_sdl2.h index cd477a89732a..1d8d6e28c682 100644 --- a/backends/imgui_impl_sdl2.h +++ b/backends/imgui_impl_sdl2.h @@ -38,9 +38,10 @@ IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(); IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event); // Gamepad selection automatically starts in Auto mode, picking first available SDL_GameController. You may override this. -// When using Explicit selection, caller is responsible for opening/closing gamepad. -IMGUI_IMPL_API void ImGui_ImplSDL2_SelectGamepadAuto(); -IMGUI_IMPL_API void ImGui_ImplSDL2_SelectGamepadExplicit(struct _SDL_GameController* gamepad); +// When using manual mode, caller is responsible for opening/closing gamepad. +IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadModeAutoFirst(); // Use first available gamepad (default) +IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadModeAutoAll(); +IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadModeManual(struct _SDL_GameController** gamepads_array, int gamepads_count); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 94457fc867a4..fc57af2d7996 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,9 +51,10 @@ Other changes: - Menus, Popups: fixed menus and popups with child window flag erroneously not displaying a scrollbar when contents is over parent viewport size. (#7287, #7063) [@ZingBallyhoo] - Backends: SDL2: Handle gamepad disconnection + fixed increasing gamepad reference counter - continuously. Added ImGui_ImplSDL2_SelectGamepadAuto()/ImGui_ImplSDL2_SelectGamepadExplicit() - functions to respectively select automatic selection or provide a gamepad to use. - (#3884, #6559, #6890) [@lethal-guitar, @wn2000, @ocornut, @bog-dan-ro] + continuously. Added support for multiple simultaneous gamepads. + Added ImGui_ImplSDL2_SetGamepadModeXXX() functions to select whether to automatically pick + first available gamepad, all gamepads, or specific gamepads. + (#3884, #6559, #6890) [@ocornut, @lethal-guitar, @wn2000, @bog-dan-ro] - Backends: SDLRenderer3: query newly added SDL_RenderViewportSet() to not restore a wrong viewport if none was initially set. - Backends: DirectX9: Using RGBA format when allowed by the driver to avoid CPU side From 9dfa2397deb17cf4fff5302c4ea6ee7eb41917fa Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 14 Feb 2024 11:02:24 +0100 Subject: [PATCH 155/237] Internals: Fixed ImFileOpen not working before context is created. (#7314, #7315) Amend daf49e9d8 --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index fc57af2d7996..915d02d08cfa 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -59,6 +59,8 @@ Other changes: a wrong viewport if none was initially set. - Backends: DirectX9: Using RGBA format when allowed by the driver to avoid CPU side conversion. (#6575) [@Demonese] +- Internals: Fixed ImFileOpen not working before context is created, preventing creation + of a font atlas before main context creation. (#7314, #7315) [@PathogenDavid, @ocornut] ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 70d11d3ae102..2eb6159310b8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2063,12 +2063,18 @@ ImFileHandle ImFileOpen(const char* filename, const char* mode) // Previously we used ImTextCountCharsFromUtf8/ImTextStrFromUtf8 here but we now need to support ImWchar16 and ImWchar32! const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0); const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0); - ImGuiContext& g = *GImGui; - g.TempBuffer.reserve((filename_wsize + mode_wsize) * sizeof(wchar_t)); - wchar_t* buf = (wchar_t*)(void*)g.TempBuffer.Data; - ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, (wchar_t*)&buf[0], filename_wsize); - ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, (wchar_t*)&buf[filename_wsize], mode_wsize); - return ::_wfopen((const wchar_t*)&buf[0], (const wchar_t*)&buf[filename_wsize]); + + // Use stack buffer if possible, otherwise heap buffer. Sizes include zero terminator. + // We don't rely on current ImGuiContext as this is implied to be a helper function which doesn't depend on it (see #7314). + wchar_t local_temp_stack[FILENAME_MAX]; + ImVector local_temp_heap; + if (filename_wsize + mode_wsize > IM_ARRAYSIZE(local_temp_stack)) + local_temp_heap.resize(filename_wsize + mode_wsize); + wchar_t* filename_wbuf = local_temp_heap.Data ? local_temp_heap.Data : local_temp_stack; + wchar_t* mode_wbuf = filename_wbuf + filename_wsize; + ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, filename_wbuf, filename_wsize); + ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, mode_wbuf, mode_wsize); + return ::_wfopen(filename_wbuf, mode_wbuf); #else return fopen(filename, mode); #endif From 262e30e300197b499a102b450984217fb494fc4f Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 14 Feb 2024 11:30:43 +0100 Subject: [PATCH 156/237] Backends: SDL2: rework new API as ImGui_ImplSDL2_SetGamepadMode(). (#3884, #6559, #6890, #7180) Code is simpler this way. --- backends/imgui_impl_sdl2.cpp | 48 ++++++++++++------------------------ backends/imgui_impl_sdl2.h | 7 +++--- docs/CHANGELOG.txt | 2 +- 3 files changed, 20 insertions(+), 37 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index ecd8f9426971..7abeb0e89fbd 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,7 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2024-02-13: Inputs: Handle gamepad disconnection. Added ImGui_ImplSDL2_SetGamepadModeAutoFirst(), ImGui_ImplSDL2_SetGamepadModeAutoAll(), ImGui_ImplSDL2_SetGamepadModeManual(). +// 2024-02-14: Inputs: Handle gamepad disconnection. Added ImGui_ImplSDL2_SetGamepadMode(). // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys. // 2023-04-06: Inputs: Avoid calling SDL_StartTextInput()/SDL_StopTextInput() as they don't only pertain to IME. It's unclear exactly what their relation is to IME. (#6306) // 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen. (#2702) @@ -102,13 +102,6 @@ #define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6) // SDL Data -enum ImGui_ImplSDL2_GamepadMode -{ - ImGui_ImplSDL2_GamepadMode_AutoFirst, // (Default) Use first available gamepad - ImGui_ImplSDL2_GamepadMode_AutoAll, // Use all available gamepad - ImGui_ImplSDL2_GamepadMode_Manual, -}; - struct ImGui_ImplSDL2_Data { SDL_Window* Window; @@ -612,29 +605,22 @@ static void ImGui_ImplSDL2_CloseGamepads() bd->Gamepads.resize(0); } -void ImGui_ImplSDL2_SetGamepadModeAutoFirst() -{ - ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); - ImGui_ImplSDL2_CloseGamepads(); - bd->GamepadMode = ImGui_ImplSDL2_GamepadMode_AutoFirst; - bd->WantUpdateGamepadsList = true; -} - -void ImGui_ImplSDL2_SetGamepadModeAutoAll() -{ - ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); - ImGui_ImplSDL2_CloseGamepads(); - bd->GamepadMode = ImGui_ImplSDL2_GamepadMode_AutoAll; - bd->WantUpdateGamepadsList = true; -} - -void ImGui_ImplSDL2_SetGamepadModeManual(struct _SDL_GameController** gamepads_array, int gamepads_count) +void ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode mode, struct _SDL_GameController** manual_gamepads_array, int manual_gamepads_count) { ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); ImGui_ImplSDL2_CloseGamepads(); - for (int n = 0; n < gamepads_count; n++) - bd->Gamepads.push_back(gamepads_array[n]); - bd->GamepadMode = ImGui_ImplSDL2_GamepadMode_Manual; + if (mode == ImGui_ImplSDL2_GamepadMode_Manual) + { + IM_ASSERT(manual_gamepads_array != nullptr && manual_gamepads_count > 0); + for (int n = 0; n < manual_gamepads_count; n++) + bd->Gamepads.push_back(manual_gamepads_array[n]); + } + else + { + IM_ASSERT(manual_gamepads_array == nullptr && manual_gamepads_count <= 0); + bd->WantUpdateGamepadsList = true; + } + bd->GamepadMode = mode; } static void ImGui_ImplSDL2_UpdateGamepadButton(ImGui_ImplSDL2_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GameControllerButton button_no) @@ -645,13 +631,13 @@ static void ImGui_ImplSDL2_UpdateGamepadButton(ImGui_ImplSDL2_Data* bd, ImGuiIO& io.AddKeyEvent(key, merged_value); } +static inline float Saturate(float v) { return v < 0.0f ? 0.0f : v > 1.0f ? 1.0f : v; } static void ImGui_ImplSDL2_UpdateGamepadAnalog(ImGui_ImplSDL2_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GameControllerAxis axis_no, float v0, float v1) { float merged_value = 0.0f; for (SDL_GameController* gamepad : bd->Gamepads) { - float vn = (float)(SDL_GameControllerGetAxis(gamepad, axis_no) - v0) / (float)(v1 - v0); - vn = (vn < 0.0f) ? 0.0f : (vn > 1.0f) ? 1.0f : vn; + float vn = Saturate((float)(SDL_GameControllerGetAxis(gamepad, axis_no) - v0) / (float)(v1 - v0)); if (merged_value < vn) merged_value = vn; } @@ -682,8 +668,6 @@ static void ImGui_ImplSDL2_UpdateGamepads() // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) return; - - // Get gamepad io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; if (bd->Gamepads.Size == 0) return; diff --git a/backends/imgui_impl_sdl2.h b/backends/imgui_impl_sdl2.h index 1d8d6e28c682..d330da281088 100644 --- a/backends/imgui_impl_sdl2.h +++ b/backends/imgui_impl_sdl2.h @@ -37,11 +37,10 @@ IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown(); IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(); IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event); -// Gamepad selection automatically starts in Auto mode, picking first available SDL_GameController. You may override this. +// Gamepad selection automatically starts in AutoFirst mode, picking first available SDL_Gamepad. You may override this. // When using manual mode, caller is responsible for opening/closing gamepad. -IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadModeAutoFirst(); // Use first available gamepad (default) -IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadModeAutoAll(); -IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadModeManual(struct _SDL_GameController** gamepads_array, int gamepads_count); +enum ImGui_ImplSDL2_GamepadMode { ImGui_ImplSDL2_GamepadMode_AutoFirst, ImGui_ImplSDL2_GamepadMode_AutoAll, ImGui_ImplSDL2_GamepadMode_Manual }; +IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode mode, struct _SDL_GameController** manual_gamepads_array = NULL, int manual_gamepads_count = -1); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 915d02d08cfa..861ab7b28236 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -52,7 +52,7 @@ Other changes: a scrollbar when contents is over parent viewport size. (#7287, #7063) [@ZingBallyhoo] - Backends: SDL2: Handle gamepad disconnection + fixed increasing gamepad reference counter continuously. Added support for multiple simultaneous gamepads. - Added ImGui_ImplSDL2_SetGamepadModeXXX() functions to select whether to automatically pick + Added ImGui_ImplSDL2_SetGamepadMode()) function to select whether to automatically pick first available gamepad, all gamepads, or specific gamepads. (#3884, #6559, #6890) [@ocornut, @lethal-guitar, @wn2000, @bog-dan-ro] - Backends: SDLRenderer3: query newly added SDL_RenderViewportSet() to not restore From 891b81fc5d77aeeeb462d17921c881e7d095ae73 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 14 Feb 2024 11:37:18 +0100 Subject: [PATCH 157/237] Backends: SDL3: Fixed gamepad. Added support for disconnection. Added support for multiple gamepads. Added ImGui_ImplSDL3_SetGamepadMode(). (#7180, #3884, #6559, #6890) --- backends/imgui_impl_sdl3.cpp | 149 ++++++++++++++++++++++++++--------- backends/imgui_impl_sdl3.h | 6 ++ docs/CHANGELOG.txt | 3 +- 3 files changed, 121 insertions(+), 37 deletions(-) diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index e06ef7959e97..2e261ef1a070 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -22,6 +22,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-02-13: Inputs: Fixed gamepad support. Handle gamepad disconnection. Added ImGui_ImplSDL3_SetGamepadMode(). // 2023-11-13: Updated for recent SDL3 API changes. // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys. // 2023-05-04: Fixed build on Emscripten/iOS/Android. (#6391) @@ -74,6 +75,11 @@ struct ImGui_ImplSDL3_Data int MousePendingLeaveFrame; bool MouseCanUseGlobalState; + // Gamepad handling + ImVector Gamepads; + ImGui_ImplSDL3_GamepadMode GamepadMode; + bool WantUpdateGamepadsList; + ImGui_ImplSDL3_Data() { memset((void*)this, 0, sizeof(*this)); } }; @@ -332,6 +338,12 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) case SDL_EVENT_WINDOW_FOCUS_LOST: io.AddFocusEvent(false); return true; + case SDL_EVENT_GAMEPAD_ADDED: + case SDL_EVENT_GAMEPAD_REMOVED: + { + bd->WantUpdateGamepadsList = true; + return true; + } } return false; } @@ -380,6 +392,10 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void io.ClipboardUserData = nullptr; io.SetPlatformImeDataFn = ImGui_ImplSDL3_SetPlatformImeData; + // Gamepad handling + bd->GamepadMode = ImGui_ImplSDL3_GamepadMode_AutoFirst; + bd->WantUpdateGamepadsList = true; + // Load mouse cursors bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); @@ -447,6 +463,8 @@ bool ImGui_ImplSDL3_InitForOther(SDL_Window* window) return ImGui_ImplSDL3_Init(window, nullptr, nullptr); } +static void ImGui_ImplSDL3_CloseGamepads(); + void ImGui_ImplSDL3_Shutdown() { ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); @@ -457,7 +475,7 @@ void ImGui_ImplSDL3_Shutdown() SDL_free(bd->ClipboardTextData); for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) SDL_DestroyCursor(bd->MouseCursors[cursor_n]); - bd->MouseLastCursor = nullptr; + ImGui_ImplSDL3_CloseGamepads(); io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; @@ -525,50 +543,109 @@ static void ImGui_ImplSDL3_UpdateMouseCursor() } } +static void ImGui_ImplSDL3_CloseGamepads() +{ + ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); + if (bd->GamepadMode != ImGui_ImplSDL3_GamepadMode_Manual) + for (SDL_Gamepad* gamepad : bd->Gamepads) + SDL_CloseGamepad(gamepad); + bd->Gamepads.resize(0); +} + +void ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode mode, SDL_Gamepad** manual_gamepads_array, int manual_gamepads_count) +{ + ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); + ImGui_ImplSDL3_CloseGamepads(); + if (mode == ImGui_ImplSDL3_GamepadMode_Manual) + { + IM_ASSERT(manual_gamepads_array != nullptr && manual_gamepads_count > 0); + for (int n = 0; n < manual_gamepads_count; n++) + bd->Gamepads.push_back(manual_gamepads_array[n]); + } + else + { + IM_ASSERT(manual_gamepads_array == nullptr && manual_gamepads_count <= 0); + bd->WantUpdateGamepadsList = true; + } + bd->GamepadMode = mode; +} + +static void ImGui_ImplSDL3_UpdateGamepadButton(ImGui_ImplSDL3_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GamepadButton button_no) +{ + bool merged_value = false; + for (SDL_Gamepad* gamepad : bd->Gamepads) + merged_value |= SDL_GetGamepadButton(gamepad, button_no) != 0; + io.AddKeyEvent(key, merged_value); +} + +static inline float Saturate(float v) { return v < 0.0f ? 0.0f : v > 1.0f ? 1.0f : v; } +static void ImGui_ImplSDL3_UpdateGamepadAnalog(ImGui_ImplSDL3_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GamepadAxis axis_no, float v0, float v1) +{ + float merged_value = 0.0f; + for (SDL_Gamepad* gamepad : bd->Gamepads) + { + float vn = Saturate((float)(SDL_GetGamepadAxis(gamepad, axis_no) - v0) / (float)(v1 - v0)); + if (merged_value < vn) + merged_value = vn; + } + io.AddKeyAnalogEvent(key, merged_value > 0.1f, merged_value); +} + static void ImGui_ImplSDL3_UpdateGamepads() { ImGuiIO& io = ImGui::GetIO(); - if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. - return; + ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); - // Get gamepad + // Update list of gamepads to use + if (bd->WantUpdateGamepadsList && bd->GamepadMode != ImGui_ImplSDL3_GamepadMode_Manual) + { + ImGui_ImplSDL3_CloseGamepads(); + int sdl_gamepads_count = 0; + SDL_JoystickID* sdl_gamepads = SDL_GetGamepads(&sdl_gamepads_count); + for (int n = 0; n < sdl_gamepads_count; n++) + if (SDL_Gamepad* gamepad = SDL_OpenGamepad(sdl_gamepads[n])) + { + bd->Gamepads.push_back(gamepad); + if (bd->GamepadMode == ImGui_ImplSDL3_GamepadMode_AutoFirst) + break; + } + bd->WantUpdateGamepadsList = false; + } + + // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. + if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) + return; io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; - SDL_Gamepad* gamepad = SDL_OpenGamepad(0); - if (!gamepad) + if (bd->Gamepads.Size == 0) return; io.BackendFlags |= ImGuiBackendFlags_HasGamepad; // Update gamepad inputs - #define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V) - #define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, SDL_GetGamepadButton(gamepad, BUTTON_NO) != 0); } - #define MAP_ANALOG(KEY_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GetGamepadAxis(gamepad, AXIS_NO) - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); } - const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value. - MAP_BUTTON(ImGuiKey_GamepadStart, SDL_GAMEPAD_BUTTON_START); - MAP_BUTTON(ImGuiKey_GamepadBack, SDL_GAMEPAD_BUTTON_BACK); - MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_GAMEPAD_BUTTON_WEST); // Xbox X, PS Square - MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_GAMEPAD_BUTTON_EAST); // Xbox B, PS Circle - MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_GAMEPAD_BUTTON_NORTH); // Xbox Y, PS Triangle - MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_GAMEPAD_BUTTON_SOUTH); // Xbox A, PS Cross - MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_GAMEPAD_BUTTON_DPAD_LEFT); - MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_GAMEPAD_BUTTON_DPAD_RIGHT); - MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_GAMEPAD_BUTTON_DPAD_UP); - MAP_BUTTON(ImGuiKey_GamepadDpadDown, SDL_GAMEPAD_BUTTON_DPAD_DOWN); - MAP_BUTTON(ImGuiKey_GamepadL1, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER); - MAP_BUTTON(ImGuiKey_GamepadR1, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER); - MAP_ANALOG(ImGuiKey_GamepadL2, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0.0f, 32767); - MAP_ANALOG(ImGuiKey_GamepadR2, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0.0f, 32767); - MAP_BUTTON(ImGuiKey_GamepadL3, SDL_GAMEPAD_BUTTON_LEFT_STICK); - MAP_BUTTON(ImGuiKey_GamepadR3, SDL_GAMEPAD_BUTTON_RIGHT_STICK); - MAP_ANALOG(ImGuiKey_GamepadLStickLeft, SDL_GAMEPAD_AXIS_LEFTX, -thumb_dead_zone, -32768); - MAP_ANALOG(ImGuiKey_GamepadLStickRight, SDL_GAMEPAD_AXIS_LEFTX, +thumb_dead_zone, +32767); - MAP_ANALOG(ImGuiKey_GamepadLStickUp, SDL_GAMEPAD_AXIS_LEFTY, -thumb_dead_zone, -32768); - MAP_ANALOG(ImGuiKey_GamepadLStickDown, SDL_GAMEPAD_AXIS_LEFTY, +thumb_dead_zone, +32767); - MAP_ANALOG(ImGuiKey_GamepadRStickLeft, SDL_GAMEPAD_AXIS_RIGHTX, -thumb_dead_zone, -32768); - MAP_ANALOG(ImGuiKey_GamepadRStickRight, SDL_GAMEPAD_AXIS_RIGHTX, +thumb_dead_zone, +32767); - MAP_ANALOG(ImGuiKey_GamepadRStickUp, SDL_GAMEPAD_AXIS_RIGHTY, -thumb_dead_zone, -32768); - MAP_ANALOG(ImGuiKey_GamepadRStickDown, SDL_GAMEPAD_AXIS_RIGHTY, +thumb_dead_zone, +32767); - #undef MAP_BUTTON - #undef MAP_ANALOG + const int thumb_dead_zone = 8000; // SDL_gamepad.h suggests using this value. + ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadStart, SDL_GAMEPAD_BUTTON_START); + ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadBack, SDL_GAMEPAD_BUTTON_BACK); + ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceLeft, SDL_GAMEPAD_BUTTON_WEST); // Xbox X, PS Square + ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceRight, SDL_GAMEPAD_BUTTON_EAST); // Xbox B, PS Circle + ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceUp, SDL_GAMEPAD_BUTTON_NORTH); // Xbox Y, PS Triangle + ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceDown, SDL_GAMEPAD_BUTTON_SOUTH); // Xbox A, PS Cross + ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadLeft, SDL_GAMEPAD_BUTTON_DPAD_LEFT); + ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadRight, SDL_GAMEPAD_BUTTON_DPAD_RIGHT); + ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadUp, SDL_GAMEPAD_BUTTON_DPAD_UP); + ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadDown, SDL_GAMEPAD_BUTTON_DPAD_DOWN); + ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL1, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER); + ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR1, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER); + ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadL2, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0.0f, 32767); + ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadR2, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0.0f, 32767); + ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL3, SDL_GAMEPAD_BUTTON_LEFT_STICK); + ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR3, SDL_GAMEPAD_BUTTON_RIGHT_STICK); + ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickLeft, SDL_GAMEPAD_AXIS_LEFTX, -thumb_dead_zone, -32768); + ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickRight, SDL_GAMEPAD_AXIS_LEFTX, +thumb_dead_zone, +32767); + ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickUp, SDL_GAMEPAD_AXIS_LEFTY, -thumb_dead_zone, -32768); + ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickDown, SDL_GAMEPAD_AXIS_LEFTY, +thumb_dead_zone, +32767); + ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickLeft, SDL_GAMEPAD_AXIS_RIGHTX, -thumb_dead_zone, -32768); + ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickRight, SDL_GAMEPAD_AXIS_RIGHTX, +thumb_dead_zone, +32767); + ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickUp, SDL_GAMEPAD_AXIS_RIGHTY, -thumb_dead_zone, -32768); + ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickDown, SDL_GAMEPAD_AXIS_RIGHTY, +thumb_dead_zone, +32767); } void ImGui_ImplSDL3_NewFrame() diff --git a/backends/imgui_impl_sdl3.h b/backends/imgui_impl_sdl3.h index 9baa7e68c492..4898729d4a70 100644 --- a/backends/imgui_impl_sdl3.h +++ b/backends/imgui_impl_sdl3.h @@ -26,6 +26,7 @@ struct SDL_Window; struct SDL_Renderer; +struct SDL_Gamepad; typedef union SDL_Event SDL_Event; IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForOpenGL(SDL_Window* window, void* sdl_gl_context); @@ -38,4 +39,9 @@ IMGUI_IMPL_API void ImGui_ImplSDL3_Shutdown(); IMGUI_IMPL_API void ImGui_ImplSDL3_NewFrame(); IMGUI_IMPL_API bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event); +// Gamepad selection automatically starts in AutoFirst mode, picking first available SDL_Gamepad. You may override this. +// When using manual mode, caller is responsible for opening/closing gamepad. +enum ImGui_ImplSDL3_GamepadMode { ImGui_ImplSDL3_GamepadMode_AutoFirst, ImGui_ImplSDL3_GamepadMode_AutoAll, ImGui_ImplSDL3_GamepadMode_Manual }; +IMGUI_IMPL_API void ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode mode, SDL_Gamepad** manual_gamepads_array = NULL, int manual_gamepads_count = -1); + #endif // #ifndef IMGUI_DISABLE diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 861ab7b28236..f79dd8d3b1d0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,7 +54,8 @@ Other changes: continuously. Added support for multiple simultaneous gamepads. Added ImGui_ImplSDL2_SetGamepadMode()) function to select whether to automatically pick first available gamepad, all gamepads, or specific gamepads. - (#3884, #6559, #6890) [@ocornut, @lethal-guitar, @wn2000, @bog-dan-ro] + (#3884, #6559, #6890, #7180) [@ocornut, @lethal-guitar, @wn2000, @bog-dan-ro] +- BackendsL SDL3: Fixed gamepad handling. (#7180) [@bog-dan-ro] - Backends: SDLRenderer3: query newly added SDL_RenderViewportSet() to not restore a wrong viewport if none was initially set. - Backends: DirectX9: Using RGBA format when allowed by the driver to avoid CPU side From 3cc37170ca71fae26aab14eb765325221f5fcef9 Mon Sep 17 00:00:00 2001 From: Tom Seddon Date: Tue, 13 Feb 2024 22:31:03 +0000 Subject: [PATCH 158/237] Examples: GLFW+Metal: Add -I and -L paths for MacPorts. --- examples/example_glfw_metal/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/example_glfw_metal/Makefile b/examples/example_glfw_metal/Makefile index 82d5ac962b9c..32a7aeca2395 100644 --- a/examples/example_glfw_metal/Makefile +++ b/examples/example_glfw_metal/Makefile @@ -14,10 +14,10 @@ SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore -LIBS += -L/usr/local/lib -L/opt/homebrew/lib +LIBS += -L/usr/local/lib -L/opt/homebrew/lib -L/opt/local/lib LIBS += -lglfw -CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include -I/opt/homebrew/include +CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include -I/opt/homebrew/include -I/opt/local/include CXXFLAGS += -Wall -Wformat CFLAGS = $(CXXFLAGS) From 829f45df994cc5eea5484fe2d135f5717ee40b2a Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 14 Feb 2024 12:06:21 +0100 Subject: [PATCH 159/237] Backends: SDL2: removed obsolete ImGui_ImplSDL2_NewFrame(SDL_Window*) signature which was obsoleted in 1.84.. --- backends/imgui_impl_sdl2.h | 4 ---- docs/CHANGELOG.txt | 2 ++ 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_sdl2.h b/backends/imgui_impl_sdl2.h index d330da281088..7020a29e0605 100644 --- a/backends/imgui_impl_sdl2.h +++ b/backends/imgui_impl_sdl2.h @@ -42,8 +42,4 @@ IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event); enum ImGui_ImplSDL2_GamepadMode { ImGui_ImplSDL2_GamepadMode_AutoFirst, ImGui_ImplSDL2_GamepadMode_AutoAll, ImGui_ImplSDL2_GamepadMode_Manual }; IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode mode, struct _SDL_GameController** manual_gamepads_array = NULL, int manual_gamepads_count = -1); -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS -static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter -#endif - #endif // #ifndef IMGUI_DISABLE diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f79dd8d3b1d0..94b4dc6e461d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,8 @@ HOW TO UPDATE? Breaking changes: +- Backends: SDL2: removed obsolete ImGui_ImplSDL2_NewFrame(SDL_Window*) signature which + was obsoleted in 1.84. Calling ImGui_ImplSDL2_NewFrame() is fine. - Backends: Vulkan: Using dynamic rendering now require filling the PipelineRenderingCreateInfo structure in ImGui_ImplVulkan_InitInfo, allowing to configure color/depth/stencil formats. Removed ColorAttachmentFormat field previously provided for dynamic rendering. From f80e65a406885beedf68856057b278343d5c1407 Mon Sep 17 00:00:00 2001 From: Shawn Hatori Date: Mon, 12 Feb 2024 14:51:24 -0500 Subject: [PATCH 160/237] Backends:,Examples: Vulkan: moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. (#7308) --- backends/imgui_impl_vulkan.cpp | 13 +++++-------- backends/imgui_impl_vulkan.h | 3 ++- docs/CHANGELOG.txt | 2 ++ examples/example_glfw_vulkan/main.cpp | 3 ++- examples/example_sdl2_vulkan/main.cpp | 3 ++- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 2aa5518d5f2c..a8962ecd252e 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -33,6 +33,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-02-14: *BREAKING CHANGE*: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering. // 2024-02-12: *BREAKING CHANGE*: Dynamic rendering now require filling PipelineRenderingCreateInfo structure. // 2024-01-19: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236) // 2024-01-11: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size (#3957). Fixed MinAllocationSize handing (#7189). @@ -215,13 +216,11 @@ struct ImGui_ImplVulkan_WindowRenderBuffers struct ImGui_ImplVulkan_Data { ImGui_ImplVulkan_InitInfo VulkanInitInfo; - VkRenderPass RenderPass; VkDeviceSize BufferMemoryAlignment; VkPipelineCreateFlags PipelineCreateFlags; VkDescriptorSetLayout DescriptorSetLayout; VkPipelineLayout PipelineLayout; VkPipeline Pipeline; - uint32_t Subpass; VkShaderModule ShaderModuleVert; VkShaderModule ShaderModuleFrag; @@ -1022,7 +1021,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() check_vk_result(err); } - ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, bd->RenderPass, v->MSAASamples, &bd->Pipeline, bd->Subpass); + ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, v->RenderPass, v->MSAASamples, &bd->Pipeline, v->Subpass); return true; } @@ -1072,7 +1071,7 @@ bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const ch return true; } -bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass) +bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) { IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!"); @@ -1107,11 +1106,9 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend IM_ASSERT(info->MinImageCount >= 2); IM_ASSERT(info->ImageCount >= info->MinImageCount); if (info->UseDynamicRendering == false) - IM_ASSERT(render_pass != VK_NULL_HANDLE); + IM_ASSERT(info->RenderPass != VK_NULL_HANDLE); bd->VulkanInitInfo = *info; - bd->RenderPass = render_pass; - bd->Subpass = info->Subpass; ImGui_ImplVulkan_CreateDeviceObjects(); @@ -1487,7 +1484,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V // We do not create a pipeline by default as this is also used by examples' main.cpp, // but secondary viewport in multi-viewport mode may want to create one with: - //ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, bd->Subpass); + //ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, v->Subpass); } // Create The Image Views diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index c2324449f99d..f77fc235ba6d 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -69,6 +69,7 @@ struct ImGui_ImplVulkan_InitInfo uint32_t QueueFamily; VkQueue Queue; VkDescriptorPool DescriptorPool; // See requirements in note above + VkRenderPass RenderPass; // Ignored if using dynamic rendering uint32_t MinImageCount; // >= 2 uint32_t ImageCount; // >= MinImageCount VkSampleCountFlagBits MSAASamples; // 0 defaults to VK_SAMPLE_COUNT_1_BIT @@ -91,7 +92,7 @@ struct ImGui_ImplVulkan_InitInfo }; // Called by user code -IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass); +IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info); IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown(); IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame(); IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 94b4dc6e461d..f6508cd8fc09 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,8 @@ Breaking changes: - Backends: SDL2: removed obsolete ImGui_ImplSDL2_NewFrame(SDL_Window*) signature which was obsoleted in 1.84. Calling ImGui_ImplSDL2_NewFrame() is fine. +- Backends: Vulkan: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to + ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering. (#7308) [@shawnhatori] - Backends: Vulkan: Using dynamic rendering now require filling the PipelineRenderingCreateInfo structure in ImGui_ImplVulkan_InitInfo, allowing to configure color/depth/stencil formats. Removed ColorAttachmentFormat field previously provided for dynamic rendering. diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 98e8dc270ab4..b1c596dd38fc 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -434,13 +434,14 @@ int main(int, char**) init_info.Queue = g_Queue; init_info.PipelineCache = g_PipelineCache; init_info.DescriptorPool = g_DescriptorPool; + init_info.RenderPass = wd->RenderPass; init_info.Subpass = 0; init_info.MinImageCount = g_MinImageCount; init_info.ImageCount = wd->ImageCount; init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.Allocator = g_Allocator; init_info.CheckVkResultFn = check_vk_result; - ImGui_ImplVulkan_Init(&init_info, wd->RenderPass); + ImGui_ImplVulkan_Init(&init_info); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index 6de55701ae7a..633f8bb8b699 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -434,13 +434,14 @@ int main(int, char**) init_info.Queue = g_Queue; init_info.PipelineCache = g_PipelineCache; init_info.DescriptorPool = g_DescriptorPool; + init_info.RenderPass = wd->RenderPass; init_info.Subpass = 0; init_info.MinImageCount = g_MinImageCount; init_info.ImageCount = wd->ImageCount; init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.Allocator = g_Allocator; init_info.CheckVkResultFn = check_vk_result; - ImGui_ImplVulkan_Init(&init_info, wd->RenderPass); + ImGui_ImplVulkan_Init(&init_info); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. From 5b6f03213dde8c6ca9bea4707321cca79f2265ec Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 14 Feb 2024 13:57:26 +0100 Subject: [PATCH 161/237] Version 1.90.3 --- docs/CHANGELOG.txt | 14 ++++++++------ imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 17 insertions(+), 15 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f6508cd8fc09..57151f2a0915 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -36,12 +36,14 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 1.90.3 WIP (In Progress) + VERSION 1.90.3 (Released 2024-02-14) ----------------------------------------------------------------------- +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90.3 + Breaking changes: -- Backends: SDL2: removed obsolete ImGui_ImplSDL2_NewFrame(SDL_Window*) signature which +- Backends: SDL2: Removed obsolete ImGui_ImplSDL2_NewFrame(SDL_Window*) signature which was obsoleted in 1.84. Calling ImGui_ImplSDL2_NewFrame() is fine. - Backends: Vulkan: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering. (#7308) [@shawnhatori] @@ -52,10 +54,10 @@ Breaking changes: Other changes: -- Menus, Popups: fixed menus and popups with child window flag erroneously not displaying +- Menus, Popups: Fixed menus and popups with ChildWindow flag erroneously not displaying a scrollbar when contents is over parent viewport size. (#7287, #7063) [@ZingBallyhoo] -- Backends: SDL2: Handle gamepad disconnection + fixed increasing gamepad reference counter - continuously. Added support for multiple simultaneous gamepads. +- Backends: SDL2, SDL3: Handle gamepad disconnection + fixed increasing gamepad reference + counter continuously. Added support for multiple simultaneous gamepads. Added ImGui_ImplSDL2_SetGamepadMode()) function to select whether to automatically pick first available gamepad, all gamepads, or specific gamepads. (#3884, #6559, #6890, #7180) [@ocornut, @lethal-guitar, @wn2000, @bog-dan-ro] @@ -69,7 +71,7 @@ Other changes: ----------------------------------------------------------------------- - VERSION 1.90.2 (Released 2024-01-09) + VERSION 1.90.2 (Released 2024-02-09) ----------------------------------------------------------------------- Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90.2 diff --git a/imgui.cpp b/imgui.cpp index 2eb6159310b8..05f578316f12 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.3 WIP +// dear imgui, v1.90.3 // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index f6740ca35a06..1346ecacdcc9 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.3 WIP +// dear imgui, v1.90.3 // (headers) // Help: @@ -23,8 +23,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.3 WIP" -#define IMGUI_VERSION_NUM 19021 +#define IMGUI_VERSION "1.90.3" +#define IMGUI_VERSION_NUM 19030 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 39dfa34ca02e..bbed7424407f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.3 WIP +// dear imgui, v1.90.3 // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 04fb7896845d..ca1fe7d0f2d7 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.3 WIP +// dear imgui, v1.90.3 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index f9fb0e91c9cc..3caef13b6039 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.3 WIP +// dear imgui, v1.90.3 // (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. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 538877f9efb2..36c4c95b7b27 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.3 WIP +// dear imgui, v1.90.3 // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index a53f3e8ef086..e2fab9cdc012 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.3 WIP +// dear imgui, v1.90.3 // (widgets code) /* From c66a1e7d51951dcb121aee1404a069ac6f8d84d5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 14 Feb 2024 14:39:26 +0100 Subject: [PATCH 162/237] Backends: Vulkan: ImGui_ImplVulkan_CreateWindow() amend merge to take account of PipelineRenderingCreateInfo change. (#7166, #6855, #5446, #5037) --- backends/imgui_impl_vulkan.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 505c2a779749..e7f7c8d82559 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -1667,13 +1667,17 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport) } // Select Surface Format - const VkFormat requestSurfaceImageFormat[] = { -#if defined(IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING) - v->UseDynamicRendering && v->ColorAttachmentFormat ? v->ColorAttachmentFormat : VK_FORMAT_B8G8R8A8_UNORM, + ImVector requestSurfaceImageFormats; +#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING + for (uint32_t n = 0; n < v->PipelineRenderingCreateInfo.colorAttachmentCount; n++) + requestSurfaceImageFormats.push_back(v->PipelineRenderingCreateInfo.pColorAttachmentFormats[n]); #endif - VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; + const VkFormat defaultFormats[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; + for (VkFormat format : defaultFormats) + requestSurfaceImageFormats.push_back(format); + const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; - wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(v->PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace); + wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(v->PhysicalDevice, wd->Surface, requestSurfaceImageFormats.Data, (size_t)requestSurfaceImageFormats.Size, requestSurfaceColorSpace); // Select Present Mode // FIXME-VULKAN: Even thought mailbox seems to get us maximum framerate with a single window, it halves framerate with a second window etc. (w/ Nvidia and SDK 1.82.1) From 8048b52498a9bf2a9f87b080d43b0bfd7a5d51d8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 15 Feb 2024 14:50:45 +0100 Subject: [PATCH 163/237] Backends: GLFW: enable ImGuiBackendFlags_HasMouseHoveredViewport support with GLFW 3.3.x. (#7316) --- backends/imgui_impl_glfw.cpp | 11 ++++++----- docs/CHANGELOG.txt | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 53303e93ce40..1df78a5480fc 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -581,7 +581,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw #ifndef __EMSCRIPTEN__ io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional) #endif -#if GLFW_HAS_MOUSE_PASSTHROUGH || (GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)) +#if GLFW_HAS_MOUSE_PASSTHROUGH || GLFW_HAS_WINDOW_HOVERED io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can call io.AddMouseViewportEvent() with correct data (optional) #endif @@ -748,7 +748,8 @@ static void ImGui_ImplGlfw_UpdateMouseData() // (Optional) When using multiple viewports: call io.AddMouseViewportEvent() with the viewport the OS mouse cursor is hovering. // If ImGuiBackendFlags_HasMouseHoveredViewport is not set by the backend, Dear imGui will ignore this field and infer the information using its flawed heuristic. - // - [X] GLFW >= 3.3 backend ON WINDOWS ONLY does correctly ignore viewports with the _NoInputs flag. + // - [X] GLFW >= 3.3 backend ON WINDOWS ONLY does correctly ignore viewports with the _NoInputs flag (since we implement hit via our WndProc hook) + // On other platforms we rely on the library fallbacking to its own search when reporting a viewport with _NoInputs flag. // - [!] GLFW <= 3.2 backend CANNOT correctly ignore viewports with the _NoInputs flag, and CANNOT reported Hovered Viewport because of mouse capture. // Some backend are not able to handle that correctly. If a backend report an hovered viewport that has the _NoInputs flag (e.g. when dragging a window // for docking, the viewport has the _NoInputs flag in order to allow us to find the viewport under), then Dear ImGui is forced to ignore the value reported @@ -756,12 +757,12 @@ static void ImGui_ImplGlfw_UpdateMouseData() // - [X] GLFW backend correctly reports this regardless of another viewport behind focused and dragged from (we need this to find a useful drag and drop target). // FIXME: This is currently only correct on Win32. See what we do below with the WM_NCHITTEST, missing an equivalent for other systems. // See https://github.com/glfw/glfw/issues/1236 if you want to help in making this a GLFW feature. -#if GLFW_HAS_MOUSE_PASSTHROUGH || (GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)) - const bool window_no_input = (viewport->Flags & ImGuiViewportFlags_NoInputs) != 0; #if GLFW_HAS_MOUSE_PASSTHROUGH + const bool window_no_input = (viewport->Flags & ImGuiViewportFlags_NoInputs) != 0; glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, window_no_input); #endif - if (glfwGetWindowAttrib(window, GLFW_HOVERED) && !window_no_input) +#if GLFW_HAS_MOUSE_PASSTHROUGH || GLFW_HAS_WINDOW_HOVERED + if (glfwGetWindowAttrib(window, GLFW_HOVERED)) mouse_viewport_id = viewport->ID; #else // We cannot use bd->MouseWindow maintained from CursorEnter/Leave callbacks, because it is locked to the window capturing mouse. diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5d25f80f97b3..08cde83b2779 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,22 @@ HOW TO UPDATE? and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users. - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.90.4 (In Progress) +----------------------------------------------------------------------- + +Breaking changes: + +Other changes: + +Docking+Viewports Branch: + +- Backends: GLFW: enable ImGuiBackendFlags_HasMouseHoveredViewport support with GLFW 3.3.x, + as required specs for it was relaxed in 1.87. This enable better viewport hovering detection + without GLFW 3.4's GLFW_MOUSE_PASSTHROUGH, with less reliance on dear imgui's own heuristic + of platform windows order. (#7316) + + ----------------------------------------------------------------------- VERSION 1.90.3 (Released 2024-02-14) ----------------------------------------------------------------------- From b19a4c5f2b3d1482d86f658c7f388732e3f780ab Mon Sep 17 00:00:00 2001 From: John Melas Date: Thu, 15 Feb 2024 15:57:37 +0200 Subject: [PATCH 164/237] Backends: OSX: remove legacy clearing of io.NavInputs in ImGui_ImplOSX_UpdateGamepads(). (#7320) --- backends/imgui_impl_osx.mm | 1 - 1 file changed, 1 deletion(-) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index b1ca5b03673b..b13d15aef508 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -534,7 +534,6 @@ static void ImGui_ImplOSX_UpdateMouseCursor() static void ImGui_ImplOSX_UpdateGamepads() { ImGuiIO& io = ImGui::GetIO(); - memset(io.NavInputs, 0, sizeof(io.NavInputs)); if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. return; From 8a14b71f2284bbc13fd2900ecefe3f346618702b Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 15 Feb 2024 16:51:57 +0100 Subject: [PATCH 165/237] Version 1.90.4 WIP --- docs/CHANGELOG.txt | 9 +++++++++ imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 18 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 57151f2a0915..0fa8e6d710ba 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,15 @@ HOW TO UPDATE? and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users. - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.90.4 WIP (In Progress) +----------------------------------------------------------------------- + +Breaking changes: + +Other changes: + + ----------------------------------------------------------------------- VERSION 1.90.3 (Released 2024-02-14) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 05f578316f12..0998968f74bc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.3 +// dear imgui, v1.90.4 WIP // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 1346ecacdcc9..13d39775e962 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.3 +// dear imgui, v1.90.4 WIP // (headers) // Help: @@ -23,8 +23,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.3" -#define IMGUI_VERSION_NUM 19030 +#define IMGUI_VERSION "1.90.4 WIP" +#define IMGUI_VERSION_NUM 19031 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index bbed7424407f..164fb62e7e54 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.3 +// dear imgui, v1.90.4 WIP // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index ca1fe7d0f2d7..2be8202142cc 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.3 +// dear imgui, v1.90.4 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 3caef13b6039..574e22159d68 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.3 +// dear imgui, v1.90.4 WIP // (internal structures/api) // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 36c4c95b7b27..b81e9695d3f3 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.3 +// dear imgui, v1.90.4 WIP // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e2fab9cdc012..cf61d60db755 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.3 +// dear imgui, v1.90.4 WIP // (widgets code) /* From ccc5347e45119ca4773c1ae33e3964346c4d545d Mon Sep 17 00:00:00 2001 From: cvionis Date: Sun, 18 Feb 2024 06:50:51 -0500 Subject: [PATCH 166/237] Fix typos (#7332) --- docs/CONTRIBUTING.md | 2 +- imgui.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 7d6738dc9260..5cc9cdb53f40 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -58,7 +58,7 @@ Steps: - Be mindful that messages are being sent to the mailbox of "Watching" users. Try to proofread your messages before sending them. Edits are not seen by those users unless they browse the site. **Some unfortunate words of warning** -- If you are involved in cheating schemes (e.g. DLL injection) for competitive online multiplayer games, please don't post here. We won't answer and you will be blocked. It doesn't matter if your question relates to said project. We've had too many of you and need to project our time and sanity. +- If you are involved in cheating schemes (e.g. DLL injection) for competitive online multiplayer games, please don't post here. We won't answer and you will be blocked. It doesn't matter if your question relates to said project. We've had too many of you and need to protect our time and sanity. - Due to frequent abuse of this service from the aforementioned users, if your GitHub account is anonymous and was created five minutes ago please understand that your post will receive more scrutiny and incomplete questions will be harshly dismissed. If you have been using Dear ImGui for a while or have been using C/C++ for several years or have demonstrated good behavior here, it is ok to not fulfill every item to the letter. Those are guidelines and experienced users or members of the community will know which information is useful in a given context. diff --git a/imgui.cpp b/imgui.cpp index 0998968f74bc..a1b88c820a51 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -15000,7 +15000,7 @@ void ImGui::DebugNodeFont(ImFont* font) SetNextItemWidth(GetFontSize() * 8); DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); SameLine(); MetricsHelpMarker( - "Note than the default embedded font is NOT meant to be scaled.\n\n" + "Note that the default embedded font is NOT meant to be scaled.\n\n" "Font are currently rendered into bitmaps at a given size at the time of building the atlas. " "You may oversample them to get some flexibility with scaling. " "You can also render at multiple sizes and select which one to use at runtime.\n\n" From 9159cd7b4ac4369349c9c26f8341cb2b388913e6 Mon Sep 17 00:00:00 2001 From: Tim-Rex Date: Sun, 18 Feb 2024 22:51:32 +1100 Subject: [PATCH 167/237] Updated invalid documentation link (#7331) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index a1b88c820a51..e4d0bcba03e0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -917,7 +917,7 @@ CODE Q: How can I easily use icons in my application? Q: How can I load multiple fonts? Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? - >> See https://www.dearimgui.com/faq and https://github.com/ocornut/imgui/edit/master/docs/FONTS.md + >> See https://www.dearimgui.com/faq and https://github.com/ocornut/imgui/blob/master/docs/FONTS.md Q&A: Concerns ============= From 6655ab2e43ff237edfde5fa56355e8fe07e49c7b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 19 Feb 2024 13:48:09 +0100 Subject: [PATCH 168/237] Tables: Angled Headers: fixed TableAngledHeadersRow() incorrect background fill drawn too low. Fixed row geometry with non-small values of CellPadding. (#6917) --- docs/CHANGELOG.txt | 5 ++++- imgui_internal.h | 4 ++-- imgui_tables.cpp | 31 ++++++++++++++++++++++--------- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0fa8e6d710ba..d15033ca964f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,9 @@ Breaking changes: Other changes: +- Tables: Angled headers: fixed TableAngledHeadersRow() incorrect background fill + drawn too low, particularly visible with tables that have no scrolling. (#6917) + ----------------------------------------------------------------------- VERSION 1.90.3 (Released 2024-02-14) @@ -355,7 +358,7 @@ Other changes: with ImGuiDragDropFlags_AcceptNoPreviewTooltip and submitting a tooltip manually. - Tables: - Added angled headers support. You need to set ImGuiTableColumnFlags_AngledHeader on selected - columns and call TableAngledHeadersRow(). Added style.TableAngledHeadersAngle style option. + columns and call TableAngledHeadersRow(). Added style.TableAngledHeadersAngle style option. (#6917) - Added ImGuiTableFlags_HighlightHoveredColumn flag, currently highlighting column header. - Fixed an edge-case when no columns are visible + table scrollbar is visible + user code is always testing return value of TableSetColumnIndex() to coarse clip. With an active diff --git a/imgui_internal.h b/imgui_internal.h index 574e22159d68..906887c930ad 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2916,7 +2916,7 @@ struct IMGUI_API ImGuiTableTempData { int TableIndex; // Index in g.Tables.Buf[] pool float LastTimeActive; // Last timestamp this structure was used - float AngledheadersExtraWidth; // Used in EndTable() + float AngledHeadersExtraWidth; // Used in EndTable() ImVec2 UserOuterSize; // outer_size.x passed to BeginTable() ImDrawListSplitter DrawSplitter; @@ -3300,7 +3300,7 @@ namespace ImGui IMGUI_API float TableGetHeaderAngledMaxLabelWidth(); IMGUI_API void TablePushBackgroundChannel(); IMGUI_API void TablePopBackgroundChannel(); - IMGUI_API void TableAngledHeadersRowEx(float angle, float label_width = 0.0f); + IMGUI_API void TableAngledHeadersRowEx(float angle, float max_label_width = 0.0f); // Tables: Internals inline ImGuiTable* GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; } diff --git a/imgui_tables.cpp b/imgui_tables.cpp index b81e9695d3f3..6bce0adb3d4e 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -498,7 +498,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG table->DeclColumnsCount = table->AngledHeadersCount = 0; if (previous_frame_active + 1 < g.FrameCount) table->IsActiveIdInTable = false; - temp_data->AngledheadersExtraWidth = 0.0f; + temp_data->AngledHeadersExtraWidth = 0.0f; // Using opaque colors facilitate overlapping lines of the grid, otherwise we'd need to improve TableDrawBorders() table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong); @@ -1344,7 +1344,7 @@ void ImGui::EndTable() max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].WorkMaxX + table->CellPaddingX + table->OuterPaddingX - outer_padding_for_border); if (table->ResizedColumn != -1) max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2); - table->InnerWindow->DC.CursorMaxPos.x = max_pos_x + table->TempData->AngledheadersExtraWidth; + table->InnerWindow->DC.CursorMaxPos.x = max_pos_x + table->TempData->AngledHeadersExtraWidth; } // Pop clipping rect @@ -1462,7 +1462,7 @@ void ImGui::EndTable() } else if (temp_data->UserOuterSize.x <= 0.0f) { - const float decoration_size = table->TempData->AngledheadersExtraWidth + ((table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f); + const float decoration_size = table->TempData->AngledHeadersExtraWidth + ((table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f); outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth + decoration_size - temp_data->UserOuterSize.x); outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth)); } @@ -1567,6 +1567,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo } // Store name (append with zero-terminator in contiguous buffer) + // FIXME: If we recorded the number of \n in names we could compute header row height column->NameOffset = -1; if (label != NULL && label[0] != 0) { @@ -2154,6 +2155,8 @@ void ImGui::TableEndCell(ImGuiTable* table) // - TableSetColumnWidthAutoAll() [Internal] // - TableUpdateColumnsWeightFromWidth() [Internal] //------------------------------------------------------------------------- +// Note that actual columns widths are computed in TableUpdateLayout(). +//------------------------------------------------------------------------- // Maximum column content width given current layout. Use column->MinX so this value on a per-column basis. float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n) @@ -2927,6 +2930,7 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table) // [SECTION] Tables: Headers //------------------------------------------------------------------------- // - TableGetHeaderRowHeight() [Internal] +// - TableGetHeaderAngledMaxLabelWidth() [Internal] // - TableHeadersRow() // - TableHeader() // - TableAngledHeadersRow() @@ -3180,25 +3184,25 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width) // Calculate our base metrics and set angled headers data _before_ the first call to TableNextRow() // FIXME-STYLE: Would it be better for user to submit 'max_label_width' or 'row_height' ? One can be derived from the other. - const float header_height = table->RowCellPaddingY * 2.0f + g.FontSize; + const float header_height = g.FontSize + g.Style.CellPadding.x * 2.0f; const float row_height = ImFabs(ImRotate(ImVec2(max_label_width, flip_label ? +header_height : -header_height), cos_a, sin_a).y); - const ImVec2 header_angled_vector = unit_right * (row_height / -sin_a); table->AngledHeadersHeight = row_height; table->AngledHeadersSlope = (sin_a != 0.0f) ? (cos_a / sin_a) : 0.0f; + const ImVec2 header_angled_vector = unit_right * (row_height / -sin_a); // vector from bottom-left to top-left, and from bottom-right to top-right // Declare row, override and draw our own background TableNextRow(ImGuiTableRowFlags_Headers, row_height); TableNextColumn(); + const ImRect row_r(table->WorkRect.Min.x, table->BgClipRect.Min.y, table->WorkRect.Max.x, table->RowPosY2); table->DrawSplitter->SetCurrentChannel(draw_list, TABLE_DRAW_CHANNEL_BG0); float clip_rect_min_x = table->BgClipRect.Min.x; if (table->FreezeColumnsCount > 0) clip_rect_min_x = ImMax(clip_rect_min_x, table->Columns[table->FreezeColumnsCount - 1].MaxX); TableSetBgColor(ImGuiTableBgTarget_RowBg0, 0); // Cancel PushClipRect(table->BgClipRect.Min, table->BgClipRect.Max, false); // Span all columns - draw_list->AddRectFilled(table->BgClipRect.Min, table->BgClipRect.Max, GetColorU32(ImGuiCol_TableHeaderBg, 0.25f)); // FIXME-STYLE: Change row background with an arbitrary color. + draw_list->AddRectFilled(ImVec2(table->BgClipRect.Min.x, row_r.Min.y), ImVec2(table->BgClipRect.Max.x, row_r.Max.y), GetColorU32(ImGuiCol_TableHeaderBg, 0.25f)); // FIXME-STYLE: Change row background with an arbitrary color. PushClipRect(ImVec2(clip_rect_min_x, table->BgClipRect.Min.y), table->BgClipRect.Max, true); // Span all columns - const ImRect row_r(table->WorkRect.Min.x, table->BgClipRect.Min.y, table->WorkRect.Max.x, window->DC.CursorPos.y + row_height); const ImGuiID row_id = GetID("##AngledHeaders"); ButtonBehavior(row_r, row_id, NULL, NULL); KeepAliveID(row_id); @@ -3209,6 +3213,7 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width) if (table_instance->HoveredRowLast == 0 && table->HoveredColumnBorder == -1 && (g.ActiveId == 0 || g.ActiveId == row_id || (table->IsActiveIdInTable || g.DragDropActive))) highlight_column_n = table->HoveredColumnBody; + // Draw background and labels in first pass, then all borders. float max_x = 0.0f; for (int pass = 0; pass < 2; pass++) for (int order_n = 0; order_n < table->ColumnsCount; order_n++) @@ -3243,13 +3248,21 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width) ImVec2 label_off = ImVec2(flip_label ? ImMax(0.0f, max_label_width - label_size.x - table->CellPaddingX) : table->CellPaddingX, table->RowCellPaddingY); int vtx_idx_begin = draw_list->_VtxCurrentIdx; RenderTextEllipsis(draw_list, label_r.Min + label_off, label_r.Max, label_r.Max.x, label_r.Max.x, label_name, NULL, &label_size); - //if (g.IO.KeyShift) { draw_list->AddRect(label_r.Min, label_r.Max, IM_COL32(0, 255, 0, 255), 0.0f, 0, 2.0f); } int vtx_idx_end = draw_list->_VtxCurrentIdx; // Rotate and offset label ImVec2 pivot_in = label_r.GetBL(); ImVec2 pivot_out = ImVec2(column->WorkMinX, row_r.Max.y) + (flip_label ? (unit_right * clip_width) : ImVec2(header_height, 0.0f)); ShadeVertsTransformPos(draw_list, vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out); // Rotate and offset + + // Debug draw + /*if (g.IO.KeyShift) + { + vtx_idx_begin = GetForegroundDrawList()->_VtxCurrentIdx; + GetForegroundDrawList()->AddRect(label_r.Min, label_r.Max, IM_COL32(0, 255, 0, 255), 0.0f, 0, 2.0f); + vtx_idx_end = GetForegroundDrawList()->_VtxCurrentIdx; + ShadeVertsTransformPos(GetForegroundDrawList(), vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out); // Rotate and offset + }*/ } if (pass == 1) { @@ -3259,7 +3272,7 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width) } PopClipRect(); PopClipRect(); - table->TempData->AngledheadersExtraWidth = ImMax(0.0f, max_x - table->Columns[table->RightMostEnabledColumn].MaxX); + table->TempData->AngledHeadersExtraWidth = ImMax(0.0f, max_x - table->Columns[table->RightMostEnabledColumn].MaxX); } //------------------------------------------------------------------------- From 405e54ebd50c9b9129db6cbfa7e5f94233aa47d7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 19 Feb 2024 20:24:07 +0100 Subject: [PATCH 169/237] Tables: Angled Headers: fixed support for multi-line labels. various padding/layout fixes. (#6917) --- docs/CHANGELOG.txt | 4 ++++ imgui_demo.cpp | 5 +++- imgui_tables.cpp | 59 +++++++++++++++++++++++++++------------------- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d15033ca964f..8509a35bda0e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,10 @@ Breaking changes: Other changes: +- Tables: Angled headers: fixed support for multi-line labels. (#6917) +- Tables: Angled headers: various fixes to accurately handle CellPadding changes. (#6917) +- Tables: Angled headers: properly registers horizontal component of angled headers + for auto-resizing of columns. (#6917) - Tables: Angled headers: fixed TableAngledHeadersRow() incorrect background fill drawn too low, particularly visible with tables that have no scrolling. (#6917) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 164fb62e7e54..3a7a818a357f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -5307,23 +5307,26 @@ static void ShowDemoWindowTables() const int rows_count = 12; static ImGuiTableFlags table_flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_Hideable | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_HighlightHoveredColumn; + static ImGuiTableColumnFlags column_flags = ImGuiTableColumnFlags_AngledHeader | ImGuiTableColumnFlags_WidthFixed; static bool bools[columns_count * rows_count] = {}; // Dummy storage selection storage static int frozen_cols = 1; static int frozen_rows = 2; ImGui::CheckboxFlags("_ScrollX", &table_flags, ImGuiTableFlags_ScrollX); ImGui::CheckboxFlags("_ScrollY", &table_flags, ImGuiTableFlags_ScrollY); + ImGui::CheckboxFlags("_Resizable", &table_flags, ImGuiTableFlags_Resizable); ImGui::CheckboxFlags("_NoBordersInBody", &table_flags, ImGuiTableFlags_NoBordersInBody); ImGui::CheckboxFlags("_HighlightHoveredColumn", &table_flags, ImGuiTableFlags_HighlightHoveredColumn); ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); ImGui::SliderInt("Frozen columns", &frozen_cols, 0, 2); ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); ImGui::SliderInt("Frozen rows", &frozen_rows, 0, 2); + ImGui::CheckboxFlags("Disable header contributing to column width", &column_flags, ImGuiTableColumnFlags_NoHeaderWidth); if (ImGui::BeginTable("table_angled_headers", columns_count, table_flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 12))) { ImGui::TableSetupColumn(column_names[0], ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoReorder); for (int n = 1; n < columns_count; n++) - ImGui::TableSetupColumn(column_names[n], ImGuiTableColumnFlags_AngledHeader | ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn(column_names[n], column_flags); ImGui::TableSetupScrollFreeze(frozen_cols, frozen_rows); ImGui::TableAngledHeadersRow(); // Draw angled headers for all columns with the ImGuiTableColumnFlags_AngledHeader flag. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 6bce0adb3d4e..28d0ee2be54a 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -2962,7 +2962,7 @@ float ImGui::TableGetHeaderAngledMaxLabelWidth() if (IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n)) if (table->Columns[column_n].Flags & ImGuiTableColumnFlags_AngledHeader) width = ImMax(width, CalcTextSize(TableGetColumnName(table, column_n), NULL, true).x); - return width + g.Style.CellPadding.x * 2.0f; + return width + g.Style.CellPadding.y * 2.0f; // Swap padding } // [Public] This is a helper to output TableHeader() calls based on the column names declared in TableSetupColumn(). @@ -3215,6 +3215,7 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width) // Draw background and labels in first pass, then all borders. float max_x = 0.0f; + ImVec2 padding = g.Style.CellPadding; // We will always use swapped component for (int pass = 0; pass < 2; pass++) for (int order_n = 0; order_n < table->ColumnsCount; order_n++) { @@ -3236,33 +3237,43 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width) draw_list->AddQuadFilled(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], GetColorU32(ImGuiCol_TableHeaderBg)); if (column_n == highlight_column_n) draw_list->AddQuadFilled(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], GetColorU32(ImGuiCol_Header)); // Highlight on hover - //draw_list->AddQuad(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], GetColorU32(ImGuiCol_TableBorderLight), 1.0f); max_x = ImMax(max_x, bg_shape[3].x); - // Draw label (first draw at an offset where RenderTextXXX() function won't meddle with applying current ClipRect, then transform to final offset) - // FIXME: May be worth tidying up all those operations to make them easier to understand. + // Draw label + // - First draw at an offset where RenderTextXXX() function won't meddle with applying current ClipRect, then transform to final offset. + // - Handle multiple lines manually, as we want each lines to follow on the horizontal border, rather than see a whole block rotated. const char* label_name = TableGetColumnName(table, column_n); - const float clip_width = max_label_width - (sin_a * table->RowCellPaddingY); - ImRect label_r(window->ClipRect.Min, window->ClipRect.Min + ImVec2(clip_width + (flip_label ? 0.0f : table->CellPaddingX), header_height + table->RowCellPaddingY)); - ImVec2 label_size = CalcTextSize(label_name, NULL, true); - ImVec2 label_off = ImVec2(flip_label ? ImMax(0.0f, max_label_width - label_size.x - table->CellPaddingX) : table->CellPaddingX, table->RowCellPaddingY); - int vtx_idx_begin = draw_list->_VtxCurrentIdx; - RenderTextEllipsis(draw_list, label_r.Min + label_off, label_r.Max, label_r.Max.x, label_r.Max.x, label_name, NULL, &label_size); - int vtx_idx_end = draw_list->_VtxCurrentIdx; - - // Rotate and offset label - ImVec2 pivot_in = label_r.GetBL(); - ImVec2 pivot_out = ImVec2(column->WorkMinX, row_r.Max.y) + (flip_label ? (unit_right * clip_width) : ImVec2(header_height, 0.0f)); - ShadeVertsTransformPos(draw_list, vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out); // Rotate and offset - - // Debug draw - /*if (g.IO.KeyShift) + const char* label_name_end = FindRenderedTextEnd(label_name); + const float line_off_step_x = g.FontSize / -sin_a; + float line_off_curr_x = 0.0f; + while (label_name < label_name_end) { - vtx_idx_begin = GetForegroundDrawList()->_VtxCurrentIdx; - GetForegroundDrawList()->AddRect(label_r.Min, label_r.Max, IM_COL32(0, 255, 0, 255), 0.0f, 0, 2.0f); - vtx_idx_end = GetForegroundDrawList()->_VtxCurrentIdx; - ShadeVertsTransformPos(GetForegroundDrawList(), vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out); // Rotate and offset - }*/ + const char* label_name_eol = strchr(label_name, '\n'); + if (label_name_eol == NULL) + label_name_eol = label_name_end; + + ImVec2 label_size = CalcTextSize(label_name, label_name_eol); + float clip_width = max_label_width - padding.y; // Using padding.y*2.0f would be symetrical but hide more text. + ImRect clip_r(window->ClipRect.Min, window->ClipRect.Min + ImVec2(clip_width, label_size.y)); + int vtx_idx_begin = draw_list->_VtxCurrentIdx; + RenderTextEllipsis(draw_list, clip_r.Min, clip_r.Max, clip_r.Max.x, clip_r.Max.x, label_name, label_name_eol, &label_size); + int vtx_idx_end = draw_list->_VtxCurrentIdx; + + // Rotate and offset label + ImVec2 pivot_in = ImVec2(window->ClipRect.Min.x, window->ClipRect.Min.y + label_size.y); + ImVec2 pivot_out = ImVec2(column->WorkMinX, row_r.Max.y); + line_off_curr_x += line_off_step_x; + pivot_out += unit_right * padding.y; + if (flip_label) + pivot_out += unit_right * (clip_width - ImMax(0.0f, clip_width - label_size.x)); + pivot_out.x += flip_label ? line_off_curr_x - line_off_step_x : line_off_curr_x; + ShadeVertsTransformPos(draw_list, vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out); // Rotate and offset + //if (g.IO.KeyShift) { ImDrawList* fg_dl = GetForegroundDrawList(); vtx_idx_begin = fg_dl->_VtxCurrentIdx; fg_dl->AddRect(clip_r.Min, clip_r.Max, IM_COL32(0, 255, 0, 255), 0.0f, 0, 2.0f); ShadeVertsTransformPos(fg_dl, vtx_idx_begin, fg_dl->_VtxCurrentIdx, pivot_in, label_cos_a, label_sin_a, pivot_out); } + + // Register header width + column->ContentMaxXHeadersUsed = column->ContentMaxXHeadersIdeal = column->WorkMinX + ImCeil(line_off_curr_x); + label_name = label_name_eol + 1; + } } if (pass == 1) { From c16043c1d580a20202c8ceee79b0a6002e3b1dff Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 19 Feb 2024 20:49:52 +0100 Subject: [PATCH 170/237] Tables: Angled headers: improve clipping of text since multi-line labels makes clipping issues visible. (#6917) --- imgui_tables.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 28d0ee2be54a..9d5dafdc78ae 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -3252,9 +3252,11 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width) if (label_name_eol == NULL) label_name_eol = label_name_end; + // FIXME: Individual line clipping for right-most column is broken for negative angles. ImVec2 label_size = CalcTextSize(label_name, label_name_eol); float clip_width = max_label_width - padding.y; // Using padding.y*2.0f would be symetrical but hide more text. - ImRect clip_r(window->ClipRect.Min, window->ClipRect.Min + ImVec2(clip_width, label_size.y)); + float clip_height = ImMin(label_size.y, column->ClipRect.Max.x - column->WorkMinX - line_off_curr_x); + ImRect clip_r(window->ClipRect.Min, window->ClipRect.Min + ImVec2(clip_width, clip_height)); int vtx_idx_begin = draw_list->_VtxCurrentIdx; RenderTextEllipsis(draw_list, clip_r.Min, clip_r.Max, clip_r.Max.x, clip_r.Max.x, label_name, label_name_eol, &label_size); int vtx_idx_end = draw_list->_VtxCurrentIdx; From 014e0ac8c92b57c55073ae05fd6e8bd371a94aea Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 20 Feb 2024 14:01:24 +0100 Subject: [PATCH 171/237] Menus, Popups: Fixed an issue where hovering a parent-menu upward would erroneously close the window. (#7325, #7287, #7063) Amend 76e09c4b0. Initial call to ClosePopupToLevel d31fe97f7 (#2880). See "widgets_menu_reopen_2" in TestSuite. --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 2 +- imgui.h | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8509a35bda0e..f394b9da0ab0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,8 @@ Breaking changes: Other changes: +- Menus, Popups: Fixed an issue where hovering a parent-menu upward would + erroneously close the window. (#7325, #7287, #7063) - Tables: Angled headers: fixed support for multi-line labels. (#6917) - Tables: Angled headers: various fixes to accurately handle CellPadding changes. (#6917) - Tables: Angled headers: properly registers horizontal component of angled headers diff --git a/imgui.cpp b/imgui.cpp index e4d0bcba03e0..c48c1ebefee4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10797,7 +10797,7 @@ void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags) else { // Reopen: close child popups if any, then flag popup for open/reopen (set position, focus, init navigation) - ClosePopupToLevel(current_stack_size, false); + ClosePopupToLevel(current_stack_size, true); g.OpenPopupStack.push_back(popup_ref); } diff --git a/imgui.h b/imgui.h index 13d39775e962..615e34039cfb 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.4 WIP" -#define IMGUI_VERSION_NUM 19031 +#define IMGUI_VERSION_NUM 19032 #define IMGUI_HAS_TABLE /* From e78ce72eb6df891acc509862dfb546ba313838c7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 20 Feb 2024 15:00:01 +0100 Subject: [PATCH 172/237] Popups: Fixed resizable popup minimum size being too small. Standardized CalcWindowMinSize() logic a bit more. (#73290 Amend e2035a514, 623bff23ce, 923535240, etc. --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 14 +++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f394b9da0ab0..cd4817990994 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -45,6 +45,8 @@ Other changes: - Menus, Popups: Fixed an issue where hovering a parent-menu upward would erroneously close the window. (#7325, #7287, #7063) +- Popups: Fixed resizable popup minimum size being too small. Standardized minimum + size logic. (#7329). - Tables: Angled headers: fixed support for multi-line labels. (#6917) - Tables: Angled headers: various fixes to accurately handle CellPadding changes. (#6917) - Tables: Angled headers: properly registers horizontal component of angled headers diff --git a/imgui.cpp b/imgui.cpp index c48c1ebefee4..a47cb0ee4dda 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5676,22 +5676,25 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags) static inline ImVec2 CalcWindowMinSize(ImGuiWindow* window) { - // Popups, menus and childs bypass style.WindowMinSize by default, but we give then a non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups) - // FIXME: the if/else could probably be removed, "reduce artifacts" section for all windows. + // We give windows non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups) + // FIXME: Essentially we want to restrict manual resizing to WindowMinSize+Decoration, and allow api resizing to be smaller. + // Perhaps should tend further a neater test for this. ImGuiContext& g = *GImGui; ImVec2 size_min; - if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_ChildWindow)) + if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_Popup)) { size_min.x = (window->ChildFlags & ImGuiChildFlags_ResizeX) ? g.Style.WindowMinSize.x : 4.0f; size_min.y = (window->ChildFlags & ImGuiChildFlags_ResizeY) ? g.Style.WindowMinSize.y : 4.0f; } else { - ImGuiWindow* window_for_height = window; size_min.x = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ? g.Style.WindowMinSize.x : 4.0f; size_min.y = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ? g.Style.WindowMinSize.y : 4.0f; - size_min.y = ImMax(size_min.y, window_for_height->TitleBarHeight() + window_for_height->MenuBarHeight() + ImMax(0.0f, g.Style.WindowRounding - 1.0f)); // Reduce artifacts with very small windows } + + // Reduce artifacts with very small windows + ImGuiWindow* window_for_height = window; + size_min.y = ImMax(size_min.y, window_for_height->TitleBarHeight() + window_for_height->MenuBarHeight() + ImMax(0.0f, g.Style.WindowRounding - 1.0f)); return size_min; } @@ -6755,6 +6758,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) #endif // Handle manual resize: Resize Grips, Borders, Gamepad + // FIXME: _ChildWindow + _Popup windows may want resize grips. int border_hovered = -1, border_held = -1; ImU32 resize_grip_col[4] = {}; const int resize_grip_count = (window->Flags & ImGuiWindowFlags_ChildWindow) ? 0 : g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it. From d3f1a7165cb5f6b0a7509e6829bbabe3a20dec8b Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 20 Feb 2024 15:03:09 +0100 Subject: [PATCH 173/237] Popups: allow Child Popups to be resizable if not explicitly disabling. --- imgui.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a47cb0ee4dda..ae042a0d97eb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6758,10 +6758,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) #endif // Handle manual resize: Resize Grips, Borders, Gamepad - // FIXME: _ChildWindow + _Popup windows may want resize grips. int border_hovered = -1, border_held = -1; ImU32 resize_grip_col[4] = {}; - const int resize_grip_count = (window->Flags & ImGuiWindowFlags_ChildWindow) ? 0 : g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it. + const int resize_grip_count = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) ? 0 : g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it. const float resize_grip_draw_size = IM_TRUNC(ImMax(g.FontSize * 1.10f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); if (!window->Collapsed) if (int auto_fit_mask = UpdateWindowManualResize(window, size_auto_fit, &border_hovered, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect)) From 3b6d924acd044d7d513cb61cd4597f121d7a0333 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 20 Feb 2024 16:02:04 +0100 Subject: [PATCH 174/237] ProgressBar: Fixed a minor tesselation issue when rendering rounded progress bars. Incidentally, the auto-tesselation path of PathArcTo() wasn't much tested. --- docs/CHANGELOG.txt | 2 ++ imgui_draw.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index cd4817990994..c393981cbfda 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,6 +53,8 @@ Other changes: for auto-resizing of columns. (#6917) - Tables: Angled headers: fixed TableAngledHeadersRow() incorrect background fill drawn too low, particularly visible with tables that have no scrolling. (#6917) +- ProgressBar: Fixed a minor tesselation issue when rendering rounded progress bars, + where in some situations the rounded section wouldn't follow regular tesselation rules. ----------------------------------------------------------------------- diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 2be8202142cc..84700958f19e 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3997,8 +3997,8 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im } else { - draw_list->PathArcTo(ImVec2(x0, p1.y - rounding), rounding, IM_PI - arc0_e, IM_PI - arc0_b, 3); // BL - draw_list->PathArcTo(ImVec2(x0, p0.y + rounding), rounding, IM_PI + arc0_b, IM_PI + arc0_e, 3); // TR + draw_list->PathArcTo(ImVec2(x0, p1.y - rounding), rounding, IM_PI - arc0_e, IM_PI - arc0_b); // BL + draw_list->PathArcTo(ImVec2(x0, p0.y + rounding), rounding, IM_PI + arc0_b, IM_PI + arc0_e); // TR } if (p1.x > rect.Min.x + rounding) { @@ -4017,8 +4017,8 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im } else { - draw_list->PathArcTo(ImVec2(x1, p0.y + rounding), rounding, -arc1_e, -arc1_b, 3); // TR - draw_list->PathArcTo(ImVec2(x1, p1.y - rounding), rounding, +arc1_b, +arc1_e, 3); // BR + draw_list->PathArcTo(ImVec2(x1, p0.y + rounding), rounding, -arc1_e, -arc1_b); // TR + draw_list->PathArcTo(ImVec2(x1, p1.y - rounding), rounding, +arc1_b, +arc1_e); // BR } } draw_list->PathFillConvex(col); From 198c38f0b114d9c2059b201a872e2ef1ee102b93 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 20 Feb 2024 16:33:54 +0100 Subject: [PATCH 175/237] Demo: Custom Rendering: better demonstrate PathArcTo(), PathBezierQuadraticCurveTo(), PathBezierCubicCurveTo(), PathStroke(), PathFillConvex() functions. --- docs/CHANGELOG.txt | 2 ++ imgui.h | 3 ++- imgui_demo.cpp | 37 ++++++++++++++++++++++++++++++++----- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c393981cbfda..7b481dbc4712 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,8 @@ Other changes: drawn too low, particularly visible with tables that have no scrolling. (#6917) - ProgressBar: Fixed a minor tesselation issue when rendering rounded progress bars, where in some situations the rounded section wouldn't follow regular tesselation rules. +- Demo: Custom Rendering: better demonstrate PathArcTo(), PathBezierQuadraticCurveTo(), + PathBezierCubicCurveTo(), PathStroke(), PathFillConvex() functions. ----------------------------------------------------------------------- diff --git a/imgui.h b/imgui.h index 615e34039cfb..9c04e4f91892 100644 --- a/imgui.h +++ b/imgui.h @@ -2765,7 +2765,8 @@ struct ImDrawList IMGUI_API void AddImageRounded(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 = 0); // Stateful path API, add points then finish with PathFillConvex() or PathStroke() - // - Filled shapes must always use clockwise winding order. The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing. + // - Important: filled shapes must always use clockwise winding order! The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing. + // so e.g. 'PathArcTo(center, radius, PI * -0.5f, PI)' is ok, whereas 'PathArcTo(center, radius, PI, PI * -0.5f)' won't have correct anti-aliasing when followed by PathFillConvex(). inline void PathClear() { _Path.Size = 0; } inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3a7a818a357f..960215024d26 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -8030,6 +8030,9 @@ static void ShowExampleAppCustomRendering(bool* p_open) const float rounding = sz / 5.0f; const int circle_segments = circle_segments_override ? circle_segments_override_v : 0; const int curve_segments = curve_segments_override ? curve_segments_override_v : 0; + const ImVec2 cp3[3] = { ImVec2(0.0f, sz * 0.6f), ImVec2(sz * 0.5f, -sz * 0.4f), ImVec2(sz, sz) }; // Control points for curves + const ImVec2 cp4[4] = { ImVec2(0.0f, 0.0f), ImVec2(sz * 1.3f, sz * 0.3f), ImVec2(sz - sz * 1.3f, sz - sz * 0.3f), ImVec2(sz, sz) }; + float x = p.x + 4.0f; float y = p.y + 4.0f; for (int n = 0; n < 2; n++) @@ -8048,17 +8051,23 @@ static void ShowExampleAppCustomRendering(bool* p_open) draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!) draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th); x += sz + spacing; // Diagonal line + // Path + draw_list->PathArcTo(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, 3.141592f, 3.141592f * -0.5f); + draw_list->PathStroke(col, ImDrawFlags_None, th); + x += sz + spacing; + // Quadratic Bezier Curve (3 control points) - ImVec2 cp3[3] = { ImVec2(x, y + sz * 0.6f), ImVec2(x + sz * 0.5f, y - sz * 0.4f), ImVec2(x + sz, y + sz) }; - draw_list->AddBezierQuadratic(cp3[0], cp3[1], cp3[2], col, th, curve_segments); x += sz + spacing; + draw_list->AddBezierQuadratic(ImVec2(x + cp3[0].x, y + cp3[0].y), ImVec2(x + cp3[1].x, y + cp3[1].y), ImVec2(x + cp3[2].x, y + cp3[2].y), col, th, curve_segments); + x += sz + spacing; // Cubic Bezier Curve (4 control points) - ImVec2 cp4[4] = { ImVec2(x, y), ImVec2(x + sz * 1.3f, y + sz * 0.3f), ImVec2(x + sz - sz * 1.3f, y + sz - sz * 0.3f), ImVec2(x + sz, y + sz) }; - draw_list->AddBezierCubic(cp4[0], cp4[1], cp4[2], cp4[3], col, th, curve_segments); + draw_list->AddBezierCubic(ImVec2(x + cp4[0].x, y + cp4[0].y), ImVec2(x + cp4[1].x, y + cp4[1].y), ImVec2(x + cp4[2].x, y + cp4[2].y), ImVec2(x + cp4[3].x, y + cp4[3].y), col, th, curve_segments); x = p.x + 4; y += sz + spacing; } + + // Filled shapes draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, ngon_sides); x += sz + spacing; // N-gon draw_list->AddCircleFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, circle_segments); x += sz + spacing; // Circle draw_list->AddEllipseFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, sz * 0.3f, col, -0.3f, circle_segments); x += sz + spacing;// Ellipse @@ -8070,9 +8079,27 @@ static void ShowExampleAppCustomRendering(bool* p_open) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + thickness), col); x += sz + spacing; // Horizontal line (faster than AddLine, but only handle integer thickness) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + thickness, y + sz), col); x += spacing * 2.0f;// Vertical line (faster than AddLine, but only handle integer thickness) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col); x += sz; // Pixel (faster than AddLine) + + // Path + draw_list->PathArcTo(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, 3.141592f * -0.5f, 3.141592f); + draw_list->PathFillConvex(col); + x += sz + spacing; + + // Quadratic Bezier Curve (3 control points) + draw_list->PathLineTo(ImVec2(x + cp3[0].x, y + cp3[0].y)); + draw_list->PathBezierQuadraticCurveTo(ImVec2(x + cp3[1].x, y + cp3[1].y), ImVec2(x + cp3[2].x, y + cp3[2].y), curve_segments); + draw_list->PathFillConvex(col); + x += sz + spacing; + + // Cubic Bezier Curve (4 control points): this is concave so not drawing it yet + //draw_list->PathLineTo(ImVec2(x + cp4[0].x, y + cp4[0].y)); + //draw_list->PathBezierCubicCurveTo(ImVec2(x + cp4[1].x, y + cp4[1].y), ImVec2(x + cp4[2].x, y + cp4[2].y), ImVec2(x + cp4[3].x, y + cp4[3].y), curve_segments); + //draw_list->PathFillConvex(col); + //x += sz + spacing; + draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x + sz, y + sz), IM_COL32(0, 0, 0, 255), IM_COL32(255, 0, 0, 255), IM_COL32(255, 255, 0, 255), IM_COL32(0, 255, 0, 255)); - ImGui::Dummy(ImVec2((sz + spacing) * 11.2f, (sz + spacing) * 3.0f)); + ImGui::Dummy(ImVec2((sz + spacing) * 12.2f, (sz + spacing) * 3.0f)); ImGui::PopItemWidth(); ImGui::EndTabItem(); } From 659fb41d0a23efbb9ea6cf74f51ecae0a51575b5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 20 Feb 2024 17:31:25 +0100 Subject: [PATCH 176/237] Debug Tools: moved DebugStartItemPicker() to public API. Added to Demo->Tools menu. (#2673) --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 9 ++++++++- imgui.h | 1 + imgui_demo.cpp | 6 ++++++ imgui_internal.h | 1 - 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7b481dbc4712..c371d18de28c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,9 @@ Other changes: drawn too low, particularly visible with tables that have no scrolling. (#6917) - ProgressBar: Fixed a minor tesselation issue when rendering rounded progress bars, where in some situations the rounded section wouldn't follow regular tesselation rules. +- Debug Tools: Item Picker: Promoted ImGui::DebugStartItemPicker() to public API. (#2673) +- Debug Tools: Item Picker: Menu entry visible in Demo->Tools but greyed out unless + io.ConfigDebugIsDebuggerPresent is set. (#2673) - Demo: Custom Rendering: better demonstrate PathArcTo(), PathBezierQuadraticCurveTo(), PathBezierCubicCurveTo(), PathStroke(), PathFillConvex() functions. diff --git a/imgui.cpp b/imgui.cpp index ae042a0d97eb..fd55eb01fe7d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -15462,6 +15462,12 @@ void ImGui::DebugLocateItemResolveWithLastItem() draw_list->AddLine(p1, p2, DEBUG_LOCATE_ITEM_COLOR); } +void ImGui::DebugStartItemPicker() +{ + ImGuiContext& g = *GImGui; + g.DebugItemPickerActive = true; +} + // [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack. void ImGui::UpdateDebugToolItemPicker() { @@ -15630,7 +15636,7 @@ void ImGui::ShowIDStackToolWindow(bool* p_open) Checkbox("Ctrl+C: copy path to clipboard", &tool->CopyToClipboardOnCtrlC); SameLine(); TextColored((time_since_copy >= 0.0f && time_since_copy < 0.75f && ImFmod(time_since_copy, 0.25f) < 0.25f * 0.5f) ? ImVec4(1.f, 1.f, 0.3f, 1.f) : ImVec4(), "*COPIED*"); - if (tool->CopyToClipboardOnCtrlC && IsKeyDown(ImGuiMod_Ctrl) && IsKeyPressed(ImGuiKey_C)) + if (tool->CopyToClipboardOnCtrlC && Shortcut(ImGuiMod_Ctrl | ImGuiKey_C, 0, ImGuiInputFlags_RouteGlobal)) { tool->CopyToClipboardLastTime = (float)g.Time; char* p = g.TempBuffer.Data; @@ -15697,6 +15703,7 @@ void ImGui::DebugLog(const char*, ...) {} void ImGui::DebugLogV(const char*, va_list) {} void ImGui::ShowDebugLogWindow(bool*) {} void ImGui::ShowIDStackToolWindow(bool*) {} +void ImGui::DebugStartItemPicker() {} void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType, const void*, const void*) {} #endif // #ifndef IMGUI_DISABLE_DEBUG_TOOLS diff --git a/imgui.h b/imgui.h index 9c04e4f91892..2a49e8df4ca8 100644 --- a/imgui.h +++ b/imgui.h @@ -967,6 +967,7 @@ namespace ImGui // - Your main debugging friend is the ShowMetricsWindow() function, which is also accessible from Demo->Tools->Metrics Debugger IMGUI_API void DebugTextEncoding(const char* text); 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. // Memory Allocators diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 960215024d26..0386673a6521 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -401,6 +401,12 @@ void ImGui::ShowDemoWindow(bool* p_open) 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(); } diff --git a/imgui_internal.h b/imgui_internal.h index 906887c930ad..cce49a96ce70 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3483,7 +3483,6 @@ namespace ImGui IMGUI_API void DebugBreakClearData(); IMGUI_API bool DebugBreakButton(const char* label, const char* description_of_location); IMGUI_API void DebugBreakButtonTooltip(bool keyboard_only, const char* description_of_location); - inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); IMGUI_API void DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end); IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns); From 34965cf23a7020dcfdc11ab12e5b841fe241f987 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 22 Feb 2024 14:53:33 +0100 Subject: [PATCH 177/237] Modals: Temporary changes of ImGuiCol_ModalWindowDimBg are properly handled by BeginPopupModal(). (#7340) + Misc: Added optional alpha multiplier parameter to GetColorU32(ImU32) variant. --- docs/CHANGELOG.txt | 5 ++++- imgui.cpp | 11 +++++++---- imgui.h | 2 +- imgui_internal.h | 1 + 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c371d18de28c..3bd286b49d6d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,8 @@ Other changes: erroneously close the window. (#7325, #7287, #7063) - Popups: Fixed resizable popup minimum size being too small. Standardized minimum size logic. (#7329). +- Modals: Temporary changes of ImGuiCol_ModalWindowDimBg are properly handled by + BeginPopupModal(). (#7340) - Tables: Angled headers: fixed support for multi-line labels. (#6917) - Tables: Angled headers: various fixes to accurately handle CellPadding changes. (#6917) - Tables: Angled headers: properly registers horizontal component of angled headers @@ -58,6 +60,7 @@ Other changes: - Debug Tools: Item Picker: Promoted ImGui::DebugStartItemPicker() to public API. (#2673) - Debug Tools: Item Picker: Menu entry visible in Demo->Tools but greyed out unless io.ConfigDebugIsDebuggerPresent is set. (#2673) +- Misc: Added optional alpha multiplier parameter to GetColorU32(ImU32) variant. - Demo: Custom Rendering: better demonstrate PathArcTo(), PathBezierQuadraticCurveTo(), PathBezierCubicCurveTo(), PathStroke(), PathFillConvex() functions. @@ -88,7 +91,7 @@ Other changes: Added ImGui_ImplSDL2_SetGamepadMode()) function to select whether to automatically pick first available gamepad, all gamepads, or specific gamepads. (#3884, #6559, #6890, #7180) [@ocornut, @lethal-guitar, @wn2000, @bog-dan-ro] -- BackendsL SDL3: Fixed gamepad handling. (#7180) [@bog-dan-ro] +- Backends: SDL3: Fixed gamepad handling. (#7180) [@bog-dan-ro] - Backends: SDLRenderer3: query newly added SDL_RenderViewportSet() to not restore a wrong viewport if none was initially set. - Backends: DirectX9: Using RGBA format when allowed by the driver to avoid CPU side diff --git a/imgui.cpp b/imgui.cpp index fd55eb01fe7d..cd6d7144c9bf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3047,13 +3047,14 @@ const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx) return style.Colors[idx]; } -ImU32 ImGui::GetColorU32(ImU32 col) +ImU32 ImGui::GetColorU32(ImU32 col, float alpha_mul) { ImGuiStyle& style = GImGui->Style; - if (style.Alpha >= 1.0f) + alpha_mul *= style.Alpha; + if (alpha_mul >= 1.0f) return col; ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT; - a = (ImU32)(a * style.Alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range. + a = (ImU32)(a * alpha_mul); // We don't need to clamp 0..255 because alpha is in 0..1 range. return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT); } @@ -5002,7 +5003,7 @@ static void ImGui::RenderDimmedBackgrounds() { // Draw dimming behind modal or a begin stack child, whichever comes first in draw order. ImGuiWindow* dim_behind_window = FindBottomMostVisibleWindowWithinBeginStack(modal_window); - RenderDimmedBackgroundBehindWindow(dim_behind_window, GetColorU32(ImGuiCol_ModalWindowDimBg, g.DimBgRatio)); + RenderDimmedBackgroundBehindWindow(dim_behind_window, GetColorU32(modal_window->DC.ModalDimBgColor, g.DimBgRatio)); } else if (dim_bg_for_window_list) { @@ -6960,6 +6961,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.TextWrapPos = -1.0f; // disabled window->DC.ItemWidthStack.resize(0); window->DC.TextWrapPosStack.resize(0); + if (flags & ImGuiWindowFlags_Modal) + window->DC.ModalDimBgColor = ColorConvertFloat4ToU32(GetStyleColorVec4(ImGuiCol_ModalWindowDimBg)); if (window->AutoFitFramesX > 0) window->AutoFitFramesX--; diff --git a/imgui.h b/imgui.h index 2a49e8df4ca8..c4a2bd0a34c4 100644 --- a/imgui.h +++ b/imgui.h @@ -445,7 +445,7 @@ namespace ImGui IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier, packed as a 32-bit value suitable for ImDrawList IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList - IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList + IMGUI_API ImU32 GetColorU32(ImU32 col, float alpha_mul = 1.0f); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwise use GetColorU32() to get style color with style alpha baked in. // Layout cursor positioning diff --git a/imgui_internal.h b/imgui_internal.h index cce49a96ce70..50c79f727c42 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2481,6 +2481,7 @@ struct IMGUI_API ImGuiWindowTempData int CurrentTableIdx; // Current table index (into g.Tables) ImGuiLayoutType LayoutType; ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin() + ImU32 ModalDimBgColor; // Local parameters stacks // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. From 13d91ff9188a28ab9c906a44d6fad646fbb244e7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 22 Feb 2024 19:39:10 +0100 Subject: [PATCH 178/237] Nav: Fixed SetKeyboardFocusHere() or programmatic tabbing API from not working on windows with the ImGuiWindowFlags_NoNavInputs flag. Amend/fix 3a078466a --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 37 ++++++++++++++++++++----------------- imgui.h | 2 +- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3bd286b49d6d..18ef6260aadf 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,9 @@ Breaking changes: Other changes: +- Nav: Fixed SetKeyboardFocusHere() or programmatic tabbing API from not working on + windows with the ImGuiWindowFlags_NoNavInputs flag (regression in 1.90.2, which + among other things broke imgui_memory_editor). - Menus, Popups: Fixed an issue where hovering a parent-menu upward would erroneously close the window. (#7325, #7287, #7063) - Popups: Fixed resizable popup minimum size being too small. Standardized minimum diff --git a/imgui.cpp b/imgui.cpp index cd6d7144c9bf..6cee66526c18 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11524,25 +11524,28 @@ static void ImGui::NavProcessItem() // Process Move Request (scoring for navigation) // FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRect + scoring from a rect wrapped according to current wrapping policy) - if (g.NavMoveScoringItems && (item_flags & ImGuiItemFlags_Disabled) == 0 && (window->Flags & ImGuiWindowFlags_NoNavInputs) == 0) + if (g.NavMoveScoringItems && (item_flags & ImGuiItemFlags_Disabled) == 0) { - const bool is_tabbing = (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0; - if (is_tabbing) + if ((g.NavMoveFlags & ImGuiNavMoveFlags_FocusApi) || (window->Flags & ImGuiWindowFlags_NoNavInputs) != 0) { - NavProcessItemForTabbingRequest(id, item_flags, g.NavMoveFlags); - } - else if (g.NavId != id || (g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) - { - ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; - if (NavScoreItem(result)) - NavApplyItemToResult(result); - - // Features like PageUp/PageDown need to maintain a separate score for the visible set of items. - const float VISIBLE_RATIO = 0.70f; - if ((g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb)) - if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO) - if (NavScoreItem(&g.NavMoveResultLocalVisible)) - NavApplyItemToResult(&g.NavMoveResultLocalVisible); + const bool is_tabbing = (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0; + if (is_tabbing) + { + NavProcessItemForTabbingRequest(id, item_flags, g.NavMoveFlags); + } + else if (g.NavId != id || (g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) + { + ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; + if (NavScoreItem(result)) + NavApplyItemToResult(result); + + // Features like PageUp/PageDown need to maintain a separate score for the visible set of items. + const float VISIBLE_RATIO = 0.70f; + if ((g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb)) + if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO) + if (NavScoreItem(&g.NavMoveResultLocalVisible)) + NavApplyItemToResult(&g.NavMoveResultLocalVisible); + } } } diff --git a/imgui.h b/imgui.h index c4a2bd0a34c4..acefaaeeddeb 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.4 WIP" -#define IMGUI_VERSION_NUM 19032 +#define IMGUI_VERSION_NUM 19033 #define IMGUI_HAS_TABLE /* From f5be90523d6d1f2c1104be1e097de330faa5fcf5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 22 Feb 2024 19:43:03 +0100 Subject: [PATCH 179/237] Nav: Fixed SetKeyboardFocusHere() or programmatic tabbing API from not working on windows with the ImGuiWindowFlags_NoNavInputs flag. Amend/fix 13d91ff 3a078466 --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 6cee66526c18..404b743c1c15 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11526,7 +11526,7 @@ static void ImGui::NavProcessItem() // FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRect + scoring from a rect wrapped according to current wrapping policy) if (g.NavMoveScoringItems && (item_flags & ImGuiItemFlags_Disabled) == 0) { - if ((g.NavMoveFlags & ImGuiNavMoveFlags_FocusApi) || (window->Flags & ImGuiWindowFlags_NoNavInputs) != 0) + if ((g.NavMoveFlags & ImGuiNavMoveFlags_FocusApi) || (window->Flags & ImGuiWindowFlags_NoNavInputs) == 0) { const bool is_tabbing = (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0; if (is_tabbing) From 277ae93c41314ba5f4c7444f37c4319cdf07e8cf Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 22 Feb 2024 19:55:40 +0100 Subject: [PATCH 180/237] Version 1.90.4 --- docs/CHANGELOG.txt | 4 ++-- imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 18ef6260aadf..1266dde59793 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -36,10 +36,10 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 1.90.4 WIP (In Progress) + VERSION 1.90.4 (Released 2024-02-22) ----------------------------------------------------------------------- -Breaking changes: +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90.4 Other changes: diff --git a/imgui.cpp b/imgui.cpp index 404b743c1c15..4f01703799d5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.4 WIP +// dear imgui, v1.90.4 // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index acefaaeeddeb..386fb5831913 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.4 WIP +// dear imgui, v1.90.4 // (headers) // Help: @@ -23,8 +23,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.4 WIP" -#define IMGUI_VERSION_NUM 19033 +#define IMGUI_VERSION "1.90.4" +#define IMGUI_VERSION_NUM 19040 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0386673a6521..707c14d38f40 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.4 WIP +// dear imgui, v1.90.4 // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 84700958f19e..1319a6e1d784 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.4 WIP +// dear imgui, v1.90.4 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 50c79f727c42..4ac8b1c943e1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.4 WIP +// dear imgui, v1.90.4 // (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. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 9d5dafdc78ae..260df1a92747 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.4 WIP +// dear imgui, v1.90.4 // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index cf61d60db755..734950d77da2 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.4 WIP +// dear imgui, v1.90.4 // (widgets code) /* From e46d1e69ac3578ef0635c2322385a83e971559f4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 26 Feb 2024 13:31:10 +0100 Subject: [PATCH 181/237] Version 1.90.5 WIP --- docs/CHANGELOG.txt | 7 +++++++ imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 16 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1266dde59793..cf4667c72b2e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,13 @@ HOW TO UPDATE? and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users. - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.90.5 WIP (In Progress) +----------------------------------------------------------------------- + +Other changes: + + ----------------------------------------------------------------------- VERSION 1.90.4 (Released 2024-02-22) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 4f01703799d5..a608ed7c5cb3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.4 +// dear imgui, v1.90.5 WIP // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 386fb5831913..2c50eb77a8e7 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.4 +// dear imgui, v1.90.5 WIP // (headers) // Help: @@ -23,8 +23,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.4" -#define IMGUI_VERSION_NUM 19040 +#define IMGUI_VERSION "1.90.5 WIP" +#define IMGUI_VERSION_NUM 19041 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 707c14d38f40..d60afd045739 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.4 +// dear imgui, v1.90.5 WIP // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 1319a6e1d784..218498f1a1e6 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.4 +// dear imgui, v1.90.5 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 4ac8b1c943e1..5e027a849cd9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.4 +// dear imgui, v1.90.5 WIP // (internal structures/api) // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 260df1a92747..0a1d3df7f4d5 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.4 +// dear imgui, v1.90.5 WIP // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 734950d77da2..7fec23e2e5bc 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.4 +// dear imgui, v1.90.5 WIP // (widgets code) /* From 725f91922d53d30572a38b306bb29c65eca89fd0 Mon Sep 17 00:00:00 2001 From: GamingMinds-DanielC Date: Mon, 26 Feb 2024 13:33:32 +0100 Subject: [PATCH 182/237] Tables: fixed TableGetHoveredRow() with overlapping frozen rows (#7350, #6588, #6347, #6250) --- imgui_tables.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 0a1d3df7f4d5..5dbd0972aaf0 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1890,7 +1890,7 @@ void ImGui::TableEndRow(ImGuiTable* table) if (is_visible) { // Update data for TableGetHoveredRow() - if (table->HoveredColumnBody != -1 && g.IO.MousePos.y >= bg_y1 && g.IO.MousePos.y < bg_y2) + if (table->HoveredColumnBody != -1 && g.IO.MousePos.y >= bg_y1 && g.IO.MousePos.y < bg_y2 && table_instance->HoveredRowNext < 0) table_instance->HoveredRowNext = table->CurrentRow; // Decide of background color for the row From 9877941775110b7f277c3a225576591bf569d10e Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 27 Feb 2024 17:47:52 +0100 Subject: [PATCH 183/237] Popups, Menus: rename ImGuiPopupData::BackupNavWindow > RestoreNavWindow and minor tweaks. Should be functionally a no-op. This is expected to clear the noise so next commit can be cleared to read. (#7325) Last renamed in b3ea01d86 --- imgui.cpp | 17 +++++++++-------- imgui_internal.h | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a608ed7c5cb3..4a576b428026 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6463,7 +6463,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) PushFocusScope((flags & ImGuiWindowFlags_NavFlattened) ? g.CurrentFocusScopeId : window->ID); window->NavRootFocusScopeId = g.CurrentFocusScopeId; - // Add to popup stack + // Add to popup stacks: update OpenPopupStack[] data, push to BeginPopupStack[] if (flags & ImGuiWindowFlags_Popup) { ImGuiPopupData& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size]; @@ -10774,7 +10774,7 @@ void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags) ImGuiPopupData popup_ref; // Tagged as new ref as Window will be set back to NULL if we write this into OpenPopupStack. popup_ref.PopupId = id; popup_ref.Window = NULL; - popup_ref.BackupNavWindow = g.NavWindow; // When popup closes focus may be restored to NavWindow (depend on window type). + popup_ref.RestoreNavWindow = g.NavWindow; // When popup closes focus may be restored to NavWindow (depend on window type). popup_ref.OpenFrameCount = g.FrameCount; popup_ref.OpenParentId = parent_window->IDStack.back(); popup_ref.OpenPopupPos = NavCalcPreferredRefPos(); @@ -10823,6 +10823,7 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to return; // Don't close our own child popup windows. + //IMGUI_DEBUG_LOG_POPUP("[popup] ClosePopupsOverWindow(\"%s\") restore_under=%d\n", ref_window ? ref_window->Name : "", restore_focus_to_window_under_popup); int popup_count_to_keep = 0; if (ref_window) { @@ -10879,17 +10880,17 @@ void ImGui::ClosePopupsExceptModals() void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup) { ImGuiContext& g = *GImGui; - IMGUI_DEBUG_LOG_POPUP("[popup] ClosePopupToLevel(%d), restore_focus_to_window_under_popup=%d\n", remaining, restore_focus_to_window_under_popup); + IMGUI_DEBUG_LOG_POPUP("[popup] ClosePopupToLevel(%d), restore_under=%d\n", remaining, restore_focus_to_window_under_popup); IM_ASSERT(remaining >= 0 && remaining < g.OpenPopupStack.Size); // Trim open popup stack - ImGuiWindow* popup_window = g.OpenPopupStack[remaining].Window; - ImGuiWindow* popup_backup_nav_window = g.OpenPopupStack[remaining].BackupNavWindow; + ImGuiPopupData prev_popup = g.OpenPopupStack[remaining]; g.OpenPopupStack.resize(remaining); if (restore_focus_to_window_under_popup) { - ImGuiWindow* focus_window = (popup_window && popup_window->Flags & ImGuiWindowFlags_ChildMenu) ? popup_window->ParentWindow : popup_backup_nav_window; + ImGuiWindow* popup_window = prev_popup.Window; + ImGuiWindow* focus_window = (popup_window && popup_window->Flags & ImGuiWindowFlags_ChildMenu) ? popup_window->ParentWindow : prev_popup.RestoreNavWindow; if (focus_window && !focus_window->WasActive && popup_window) FocusTopMostWindowUnderOne(popup_window, NULL, NULL, ImGuiFocusRequestFlags_RestoreFocusedChild); // Fallback else @@ -14454,9 +14455,9 @@ void ImGui::ShowMetricsWindow(bool* p_open) { // As it's difficult to interact with tree nodes while popups are open, we display everything inline. ImGuiWindow* window = popup_data.Window; - BulletText("PopupID: %08x, Window: '%s' (%s%s), BackupNavWindow '%s', ParentWindow '%s'", + BulletText("PopupID: %08x, Window: '%s' (%s%s), RestoreNavWindow '%s', ParentWindow '%s'", popup_data.PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? "Child;" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? "Menu;" : "", - popup_data.BackupNavWindow ? popup_data.BackupNavWindow->Name : "NULL", window && window->ParentWindow ? window->ParentWindow->Name : "NULL"); + popup_data.RestoreNavWindow ? popup_data.RestoreNavWindow->Name : "NULL", window && window->ParentWindow ? window->ParentWindow->Name : "NULL"); } TreePop(); } diff --git a/imgui_internal.h b/imgui_internal.h index 5e027a849cd9..610db3467589 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1292,7 +1292,7 @@ struct ImGuiPopupData { ImGuiID PopupId; // Set on OpenPopup() ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() - ImGuiWindow* BackupNavWindow;// Set on OpenPopup(), a NavWindow that will be restored on popup close + ImGuiWindow* RestoreNavWindow;// Set on OpenPopup(), a NavWindow that will be restored on popup close int ParentNavLayer; // Resolved on BeginPopup(). Actually a ImGuiNavLayer type (declared down below), initialized to -1 which is not part of an enum, but serves well-enough as "not any of layers" value int OpenFrameCount; // Set on OpenPopup() ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) From c3f8f4de257d8c0e703f33e99bf6ab1a38c2fab6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 27 Feb 2024 18:36:20 +0100 Subject: [PATCH 184/237] Menus, Popups: Fixed an issue where sibling menu popups re-opening in successive frames would erroneously close the window. (#7325, #7287, #7063) Amend 014e0ac8 --- docs/CHANGELOG.txt | 5 +++++ imgui.cpp | 3 ++- imgui.h | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index cf4667c72b2e..48ccc0cf3817 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,11 @@ HOW TO UPDATE? Other changes: +- Menus, Popups: Fixed an issue where sibling menu popups re-opening in successive + frames would erroneously close the window. While it is technically a popup issue + it would generally manifest when fast moving the mouse bottom to top in a sub-menu. + (#7325, #7287, #7063) + ----------------------------------------------------------------------- VERSION 1.90.4 (Released 2024-02-22) diff --git a/imgui.cpp b/imgui.cpp index 4a576b428026..9648c79761dd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10887,7 +10887,8 @@ void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_ ImGuiPopupData prev_popup = g.OpenPopupStack[remaining]; g.OpenPopupStack.resize(remaining); - if (restore_focus_to_window_under_popup) + // Restore focus (unless popup window was not yet submitted, and didn't have a chance to take focus anyhow. See #7325 for an edge case) + if (restore_focus_to_window_under_popup && prev_popup.Window) { ImGuiWindow* popup_window = prev_popup.Window; ImGuiWindow* focus_window = (popup_window && popup_window->Flags & ImGuiWindowFlags_ChildMenu) ? popup_window->ParentWindow : prev_popup.RestoreNavWindow; diff --git a/imgui.h b/imgui.h index 2c50eb77a8e7..307834fff242 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.5 WIP" -#define IMGUI_VERSION_NUM 19041 +#define IMGUI_VERSION_NUM 19042 #define IMGUI_HAS_TABLE /* From 44c7dfca0304ba5ab22caf351203f84a16d206d9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 27 Feb 2024 19:42:20 +0100 Subject: [PATCH 185/237] Menus, Popup: Amend c3f8f4d for static analyzer warning ("condition always true"). (#7325) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9648c79761dd..6a14012c3df6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10891,8 +10891,8 @@ void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_ if (restore_focus_to_window_under_popup && prev_popup.Window) { ImGuiWindow* popup_window = prev_popup.Window; - ImGuiWindow* focus_window = (popup_window && popup_window->Flags & ImGuiWindowFlags_ChildMenu) ? popup_window->ParentWindow : prev_popup.RestoreNavWindow; - if (focus_window && !focus_window->WasActive && popup_window) + ImGuiWindow* focus_window = (popup_window->Flags & ImGuiWindowFlags_ChildMenu) ? popup_window->ParentWindow : prev_popup.RestoreNavWindow; + if (focus_window && !focus_window->WasActive) FocusTopMostWindowUnderOne(popup_window, NULL, NULL, ImGuiFocusRequestFlags_RestoreFocusedChild); // Fallback else FocusWindow(focus_window, (g.NavLayer == ImGuiNavLayer_Main) ? ImGuiFocusRequestFlags_RestoreFocusedChild : ImGuiFocusRequestFlags_None); From 4e8c43f6b7f91d993751754dfc3089c3bc5db1b2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 27 Feb 2024 20:02:26 +0100 Subject: [PATCH 186/237] Backends: Win32: made it so that an appearing viewport showing up doesn't bring its parent viewport to front. (#7354) --- backends/imgui_impl_win32.cpp | 10 ++++++++++ docs/CHANGELOG.txt | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index b14ae1abb748..8cc0d9a11f8b 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -1067,10 +1067,20 @@ static void ImGui_ImplWin32_ShowWindow(ImGuiViewport* viewport) { ImGui_ImplWin32_ViewportData* vd = (ImGui_ImplWin32_ViewportData*)viewport->PlatformUserData; IM_ASSERT(vd->Hwnd != 0); + + // ShowParent() also brings parent to front, which is not always desirable, + // so we temporarily disable parenting. (#7354) + if (vd->HwndParent != NULL) + ::SetWindowLongPtr(vd->Hwnd, GWLP_HWNDPARENT, (LONG_PTR)nullptr); + if (viewport->Flags & ImGuiViewportFlags_NoFocusOnAppearing) ::ShowWindow(vd->Hwnd, SW_SHOWNA); else ::ShowWindow(vd->Hwnd, SW_SHOW); + + // Restore + if (vd->HwndParent != NULL) + ::SetWindowLongPtr(vd->Hwnd, GWLP_HWNDPARENT, (LONG_PTR)vd->HwndParent); } static void ImGui_ImplWin32_UpdateWindow(ImGuiViewport* viewport) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2b24d0a6b289..bdce7ab6a5bf 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -46,6 +46,11 @@ Other changes: it would generally manifest when fast moving the mouse bottom to top in a sub-menu. (#7325, #7287, #7063) +Docking+Viewports Branch: + +- Backends: Win32: made it so that an appearing viewport showing up doesn't bring + its parent to front. (#7354) + ----------------------------------------------------------------------- VERSION 1.90.4 (Released 2024-02-22) From 77dff5a735afd821fea1ac54dda63ef5d8bded96 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 28 Feb 2024 11:03:44 +0100 Subject: [PATCH 187/237] Backends: comments. --- backends/imgui_impl_glfw.cpp | 3 +-- backends/imgui_impl_glfw.h | 5 ++--- backends/imgui_impl_osx.h | 4 +++- backends/imgui_impl_osx.mm | 4 +++- backends/imgui_impl_sdl2.cpp | 5 +++-- backends/imgui_impl_sdl2.h | 5 +++-- backends/imgui_impl_sdl3.cpp | 5 +++-- backends/imgui_impl_sdl3.h | 5 +++-- 8 files changed, 21 insertions(+), 15 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 1df78a5480fc..c3cd91c1ac05 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -10,9 +10,8 @@ // [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. - // Issues: -// [ ] Platform: Multi-viewport support: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). +// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index 14e6ee6a7a3b..6fe6882cbe03 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -8,11 +8,10 @@ // [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only). // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. -// [x] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). +// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. - // Issues: -// [ ] Platform: Multi-viewport support: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). +// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_osx.h b/backends/imgui_impl_osx.h index f2c704fd84a6..1f2254bcc5ab 100644 --- a/backends/imgui_impl_osx.h +++ b/backends/imgui_impl_osx.h @@ -11,7 +11,9 @@ // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: IME support. // [x] Platform: Multi-viewport / platform windows. -// - [ ] Window size not correctly reported when enabling io.ConfigViewportsNoDecoration +// Issues: +// [ ] Platform: Multi-viewport: Window size not correctly reported when enabling io.ConfigViewportsNoDecoration +// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 8656bfe45893..e570c81aa95c 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -11,7 +11,9 @@ // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: IME support. // [x] Platform: Multi-viewport / platform windows. -// - [ ] Window size not correctly reported when enabling io.ConfigViewportsNoDecoration +// Issues: +// [ ] Platform: Multi-viewport: Window size not correctly reported when enabling io.ConfigViewportsNoDecoration +// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index f101cf3e5421..296ec05b1f35 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -10,8 +10,9 @@ // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. -// Missing features: -// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows). +// Issues: +// [ ] Platform: Multi-viewport: Minimized windows seems to break mouse wheel events (at least under Windows). +// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). // [x] Platform: Basic IME support. App needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. diff --git a/backends/imgui_impl_sdl2.h b/backends/imgui_impl_sdl2.h index 2970772efecf..1fba66c2eb40 100644 --- a/backends/imgui_impl_sdl2.h +++ b/backends/imgui_impl_sdl2.h @@ -9,8 +9,9 @@ // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. -// Missing features: -// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows). +// Issues: +// [ ] Platform: Multi-viewport: Minimized windows seems to break mouse wheel events (at least under Windows). +// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). // [x] Platform: Basic IME support. App needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 8eccaa89b89b..01cf1027092e 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -10,8 +10,9 @@ // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [x] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable' -> the OS animation effect when window gets created/destroyed is problematic. SDL2 backend doesn't have issue. -// Missing features: -// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows). +// Issues: +// [ ] Platform: Multi-viewport: Minimized windows seems to break mouse wheel events (at least under Windows). +// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). // [x] Platform: Basic IME support. Position somehow broken in SDL3 + app needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. diff --git a/backends/imgui_impl_sdl3.h b/backends/imgui_impl_sdl3.h index 18ab945afb5f..c6979b9d6079 100644 --- a/backends/imgui_impl_sdl3.h +++ b/backends/imgui_impl_sdl3.h @@ -10,8 +10,9 @@ // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [x] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable' -> the OS animation effect when window gets created/destroyed is problematic. SDL2 backend doesn't have issue. -// Missing features: -// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows). +// Issues: +// [ ] Platform: Multi-viewport: Minimized windows seems to break mouse wheel events (at least under Windows). +// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). // [x] Platform: Basic IME support. Position somehow broken in SDL3 + app needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. From 0573513d6df54fc7cff93a640dc8bb05b05b949d Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 28 Feb 2024 17:09:20 +0100 Subject: [PATCH 188/237] Windows: Scrollbar visibility decision uses current size when both size and contents size are submitted by API. (#7252) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 6 ++++++ imgui.h | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 48ccc0cf3817..3468c0a1d236 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,8 @@ HOW TO UPDATE? Other changes: +- Windows: Scrollbar visibility decision uses current size when both size and contents + size are submitted by API. (#7252) - Menus, Popups: Fixed an issue where sibling menu popups re-opening in successive frames would erroneously close the window. While it is technically a popup issue it would generally manifest when fast moving the mouse bottom to top in a sub-menu. diff --git a/imgui.cpp b/imgui.cpp index 6a14012c3df6..45d551ab99a6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6610,8 +6610,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x); window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y; + // Depending on condition we use previous or current window size to compare against contents size to decide if a scrollbar should be visible. + // Those flags will be altered further down in the function depending on more conditions. bool use_current_size_for_scrollbar_x = window_just_created; bool use_current_size_for_scrollbar_y = window_just_created; + if (window_size_x_set_by_api && window->ContentSizeExplicit.x != 0.0f) + use_current_size_for_scrollbar_x = true; + if (window_size_y_set_by_api && window->ContentSizeExplicit.y != 0.0f) // #7252 + use_current_size_for_scrollbar_y = true; // Collapse window by double-clicking on title bar // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing diff --git a/imgui.h b/imgui.h index 307834fff242..cd707b40f5d8 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.5 WIP" -#define IMGUI_VERSION_NUM 19042 +#define IMGUI_VERSION_NUM 19043 #define IMGUI_HAS_TABLE /* From c6236699671b2e5f94481c051cd19afe00cda583 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 28 Feb 2024 19:21:13 +0100 Subject: [PATCH 189/237] Added link to crawlable wiki --- docs/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/README.md b/docs/README.md index a2be7fde27b0..6aac61b5a9e9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -162,6 +162,8 @@ See: [Upcoming Changes](https://github.com/ocornut/imgui/wiki/Upcoming-Changes). See: [Dear ImGui Test Engine + Test Suite](https://github.com/ocornut/imgui_test_engine) for Automation & Testing. +For the purposes of getting search engines to crawl the wiki, here's a link to the [Crawable Wiki](https://github-wiki-see.page/m/ocornut/imgui/wiki) (not for humans, [here's why](https://github-wiki-see.page/)). + Getting started? For first-time users having issues compiling/linking/running or issues loading fonts, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions). For ANY other questions, bug reports, requests, feedback, please post on [GitHub Issues](https://github.com/ocornut/imgui/issues). Please read and fill the New Issue template carefully. Private support is available for paying business customers (E-mail: _contact @ dearimgui dot com_). From 04f40014a62898d325cbc987c9f56073b2d17e73 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 29 Feb 2024 15:17:08 +0100 Subject: [PATCH 190/237] Docs: added a mini wiki index in main source files. --- docs/CHANGELOG.txt | 6 ++++++ imgui.cpp | 22 +++++++++++++--------- imgui.h | 22 +++++++++++++--------- imgui_demo.cpp | 2 +- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3468c0a1d236..291d1f10d763 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,12 @@ Other changes: frames would erroneously close the window. While it is technically a popup issue it would generally manifest when fast moving the mouse bottom to top in a sub-menu. (#7325, #7287, #7063) +- Docs: added more wiki links to headers of imgui.h/imgui.cpp to facilitate discovery + of interesting resources, because github doesn't allow Wiki to be crawled by search engines. + - This is the main wiki: https://github.com/ocornut/imgui/wiki + - This is the crawlable version: https://github-wiki-see.page/m/ocornut/imgui/wiki + Adding a link to the crawlable version, even though it is not indended for humans, + to increase its search rank. ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 45d551ab99a6..31c6d25123f3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7,15 +7,19 @@ // - Read top of imgui.cpp for more details, links and comments. // Resources: -// - FAQ https://dearimgui.com/faq -// - Getting Started https://dearimgui.com/getting-started -// - Homepage https://github.com/ocornut/imgui -// - Releases & changelog https://github.com/ocornut/imgui/releases -// - Gallery https://github.com/ocornut/imgui/issues/6897 (please post your screenshots/video there!) -// - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there) -// - Glossary https://github.com/ocornut/imgui/wiki/Glossary -// - Issues & support https://github.com/ocornut/imgui/issues -// - Tests & Automation https://github.com/ocornut/imgui_test_engine +// - FAQ ........................ https://dearimgui.com/faq (in repository as docs/FAQ.md) +// - Homepage ................... https://github.com/ocornut/imgui +// - Releases & changelog ....... https://github.com/ocornut/imgui/releases +// - Gallery .................... https://github.com/ocornut/imgui/issues/6897 (please post your screenshots/video there!) +// - Wiki ....................... https://github.com/ocornut/imgui/wiki (lots of good stuff there) +// - Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started (how to integrate in an existing app by adding ~25 lines of code) +// - Third-party Extensions https://github.com/ocornut/imgui/wiki/Useful-Extensions (ImPlot & many more) +// - Bindings/Backends https://github.com/ocornut/imgui/wiki/Bindings (language bindings, backends for various tech/engines) +// - Glossary https://github.com/ocornut/imgui/wiki/Glossary +// - Debug Tools https://github.com/ocornut/imgui/wiki/Debug-Tools +// - Software using Dear ImGui https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui +// - Issues & support ........... https://github.com/ocornut/imgui/issues +// - Test Engine & Automation ... https://github.com/ocornut/imgui_test_engine (test suite, test engine to automate your apps) // For first-time users having issues compiling/linking/running/loading fonts: // please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above. diff --git a/imgui.h b/imgui.h index cd707b40f5d8..a6a3ec8b77c3 100644 --- a/imgui.h +++ b/imgui.h @@ -7,15 +7,19 @@ // - Read top of imgui.cpp for more details, links and comments. // Resources: -// - FAQ https://dearimgui.com/faq -// - Getting Started https://dearimgui.com/getting-started -// - Homepage https://github.com/ocornut/imgui -// - Releases & changelog https://github.com/ocornut/imgui/releases -// - Gallery https://github.com/ocornut/imgui/issues/6897 (please post your screenshots/video there!) -// - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there) -// - Glossary https://github.com/ocornut/imgui/wiki/Glossary -// - Issues & support https://github.com/ocornut/imgui/issues -// - Tests & Automation https://github.com/ocornut/imgui_test_engine +// - FAQ ........................ https://dearimgui.com/faq (in repository as docs/FAQ.md) +// - Homepage ................... https://github.com/ocornut/imgui +// - Releases & changelog ....... https://github.com/ocornut/imgui/releases +// - Gallery .................... https://github.com/ocornut/imgui/issues/6897 (please post your screenshots/video there!) +// - Wiki ....................... https://github.com/ocornut/imgui/wiki (lots of good stuff there) +// - Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started (how to integrate in an existing app by adding ~25 lines of code) +// - Third-party Extensions https://github.com/ocornut/imgui/wiki/Useful-Extensions (ImPlot & many more) +// - Bindings/Backends https://github.com/ocornut/imgui/wiki/Bindings (language bindings, backends for various tech/engines) +// - Glossary https://github.com/ocornut/imgui/wiki/Glossary +// - Debug Tools https://github.com/ocornut/imgui/wiki/Debug-Tools +// - Software using Dear ImGui https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui +// - Issues & support ........... https://github.com/ocornut/imgui/issues +// - Test Engine & Automation ... https://github.com/ocornut/imgui_test_engine (test suite, test engine to automate your apps) // For first-time users having issues compiling/linking/running/loading fonts: // please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index d60afd045739..f275abc4b3d8 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7,7 +7,7 @@ // - Need help integrating Dear ImGui in your codebase? // - Read Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started // - Read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. -// Read imgui.cpp for more details, documentation and comments. +// Read top of imgui.cpp and imgui.h for many details, documentation, comments, links. // Get the latest version at https://github.com/ocornut/imgui //--------------------------------------------------- From 1ff90c52d5f0d57566ba6054393817a1f8a81fe4 Mon Sep 17 00:00:00 2001 From: thedmd Date: Wed, 3 Jan 2024 14:31:45 +0100 Subject: [PATCH 191/237] ImDrawList: add PathFillConcave(), AddConcavePolyFilled() (#760) Extracted from 2023/12/29 post. WIP add PathFillConcave(), AddConcavePolyFilled() * remove use of 'auto' * IsConvex -> ImPathIsConvex * Triangulator -> ImTriangulator * ImTriangulator: split declaration from definition, ImTriangulator can be put in the header if necessary * ImTriangulator: Add node list flip to reverse winding order and handle degenerate cases * ImTriangulator: Remove _HeapStorage, always require scratch buffer to be provided * ImTriangulator: Use ImTriangleContainsPoint * AddConcavePolyFilled: Clone AddConvexPolyFilled and use triangulator * AddConcavePolyFilled: Remove ImDrawListEx_AddPolyFilled_xxx * AddConcavePolyFilled: Use _Data->TempBuffer in triangulator * AddConcavePolyFilled: --- imgui.h | 8 +- imgui_draw.cpp | 434 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 440 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index a6a3ec8b77c3..4d5a8f0127eb 100644 --- a/imgui.h +++ b/imgui.h @@ -2756,11 +2756,14 @@ struct ImDrawList IMGUI_API void AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0); IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL); IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); - IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness); - IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0); // Cubic Bezier (4 control points) IMGUI_API void AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments = 0); // Quadratic Bezier (3 control points) + // General polygon + IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness); + IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); + IMGUI_API void AddConcavePolyFilled(const ImVec2* points, const int points_count, ImU32 col); + // Image primitives // - Read FAQ to understand what ImTextureID is. // - "p_min" and "p_max" represent the upper-left and lower-right corners of the rectangle. @@ -2776,6 +2779,7 @@ struct ImDrawList inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); } inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; } + inline void PathFillConcave(ImU32 col) { AddConcavePolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; } inline void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, flags, thickness); _Path.Size = 0; } IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 0); IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 218498f1a1e6..1bb7cfed9d73 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -8,6 +8,7 @@ Index of this file: // [SECTION] STB libraries implementation // [SECTION] Style functions // [SECTION] ImDrawList +// [SECTION] ImDrawList concave polygon fill // [SECTION] ImDrawListSplitter // [SECTION] ImDrawData // [SECTION] Helpers ShadeVertsXXX functions @@ -1700,6 +1701,439 @@ void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_mi PopTextureID(); } +//----------------------------------------------------------------------------- +// [SECTION] ImDrawList concave polygon fill +//----------------------------------------------------------------------------- + +static bool ImPathIsConvex(const ImVec2& a, const ImVec2& b, const ImVec2& c) +{ + const float dx0 = b.x - a.x; + const float dy0 = b.y - a.y; + + const float dx1 = c.x - b.x; + const float dy1 = c.y - b.y; + + return dx0 * dy1 - dx1 * dy0 > 0.0f; +} + +struct ImTriangulator +{ + struct Triangle { int Index[3]; }; + + static int EstimateTriangleCount(int points_count); + static int EstimateScratchBufferSize(int points_count); + + ImTriangulator(const ImVec2* points, int points_count, void* scratch_buffer); + ImTriangulator(const ImVec2* points, int points_count, int points_stride_bytes, void* scratch_buffer); + + bool HasNext() const; + + Triangle Next(); + +private: + enum Type { Convex, Ear, Reflex }; + + struct Node; + struct alignas(void*) Span + { + Node** Data = nullptr; + int Size = 0; + + void PushBack(Node* node); + void RemoveByIndex(int index); + }; + + void BuildNodes(); + void BuildReflexes(); + void BuildEars(); + void FlipNodeList(); + bool IsEar(const Node* node, int i0, int i1, int i2, const ImVec2& v0, const ImVec2& v1, const ImVec2& v2) const; + Type ClassifyNode(const Node* node) const; + void ReclasifyNode(Node* node); + + const ImVec2* _Points = nullptr; + int _PointsCount = 0; + int _PointsStrideBytes = 0; + int _TrianglesLeft = 0; + + Node* _Nodes = nullptr; + Span _Ears; + Span _Reflexes; +}; + +struct alignas(void*) ImTriangulator::Node +{ + Type Type = Convex; + int Index = 0; + const ImVec2* Point = nullptr; + Node* Next = nullptr; + Node* Prev = nullptr; + + void Unlink() + { + Next->Prev = Prev; + Prev->Next = Next; + } +}; + +int ImTriangulator::EstimateTriangleCount(int points_count) +{ + if (points_count < 3) + return 0; + + return points_count - 2; +} + +int ImTriangulator::EstimateScratchBufferSize(int points_count) +{ + return sizeof(Node*) * points_count * 2 + sizeof(Node) * points_count; +} + +ImTriangulator::ImTriangulator(const ImVec2* points, int points_count, void* scratch_buffer) + : ImTriangulator(points, points_count, sizeof(ImVec2), scratch_buffer) +{ +} + +ImTriangulator::ImTriangulator(const ImVec2* points, int points_count, int points_stride_bytes, void* scratch_buffer) + : _Points(points) + , _PointsCount(points_count) + , _PointsStrideBytes(points_stride_bytes) + , _TrianglesLeft(EstimateTriangleCount(points_count)) +{ + IM_ASSERT(scratch_buffer != nullptr && "Must provide scratch buffer."); + IM_ASSERT(points_count >= 3); + + // Disable triangulator if scratch buffer isn't provided. + if (scratch_buffer == nullptr) + { + _TrianglesLeft = 0; + points_count = 0; + return; + } + + // Distribute storage for nodes, ears and reflexes. + _Nodes = reinterpret_cast(scratch_buffer); + _Ears.Data = reinterpret_cast(_Nodes + points_count); + _Reflexes.Data = _Ears.Data + points_count; + + BuildNodes(); + BuildReflexes(); + BuildEars(); +} + +void ImTriangulator::BuildNodes() +{ +# define IM_POINT_PTR(idx) reinterpret_cast(reinterpret_cast(_Points) + (idx) * _PointsStrideBytes) + + for (int i = 0; i < _PointsCount; ++i) + { + _Nodes[i].Type = Convex; + _Nodes[i].Index = static_cast(i); + _Nodes[i].Point = IM_POINT_PTR(i); + _Nodes[i].Next = _Nodes + i + 1; + _Nodes[i].Prev = _Nodes + i - 1; + } + _Nodes[0].Prev = _Nodes + _PointsCount - 1; + _Nodes[_PointsCount - 1].Next = _Nodes; + +# undef IM_POINT_PTR +} + +void ImTriangulator::BuildReflexes() +{ + Node* node = _Nodes; + for (int i = 0; i < _TrianglesLeft; ++i, node = node->Next) + { + const ImVec2& v0 = *node->Prev->Point; + const ImVec2& v1 = *node->Point; + const ImVec2& v2 = *node->Next->Point; + + if (ImPathIsConvex(v0, v1, v2)) + continue; + + node->Type = Reflex; + _Reflexes.PushBack(node); + } +} + +void ImTriangulator::BuildEars() +{ + Node* node = _Nodes; + for (int i = 0; i < _TrianglesLeft; ++i, node = node->Next) + { + if (node->Type != Convex) + continue; + + const int i0 = node->Prev->Index; + const int i1 = node->Index; + const int i2 = node->Next->Index; + + const ImVec2& v0 = *node->Prev->Point; + const ImVec2& v1 = *node->Point; + const ImVec2& v2 = *node->Next->Point; + + if (!IsEar(node, i0, i1, i2, v0, v1, v2)) + continue; + + node->Type = Ear; + _Ears.PushBack(node); + } +} + +bool ImTriangulator::HasNext() const +{ + return _TrianglesLeft > 0; +} + +ImTriangulator::Triangle ImTriangulator::Next() +{ + IM_ASSERT(_TrianglesLeft > 0 && "Do not call Next() until HasNext() return true"); + + if (_Ears.Size == 0) + { + FlipNodeList(); + + Node* node = _Nodes; + for (int i = 0; i < _TrianglesLeft; ++i, node = node->Next) + node->Type = Convex; + _Reflexes.Size = 0; + BuildReflexes(); + BuildEars(); + + // If we still don't have ears, it means geometry is degenerated. + if (_Ears.Size == 0) + { + IM_ASSERT(_TrianglesLeft > 0 && "Geometry is degenerated"); + + // Return first triangle available, mimicking the behavior of convex fill. + _Ears.Data[0] = _Nodes; + _Ears.Size = 1; + } + } + + Node* ear = _Ears.Data[--_Ears.Size]; + + const int i0 = ear->Prev->Index; + const int i1 = ear->Index; + const int i2 = ear->Next->Index; + + ear->Unlink(); + if (ear == _Nodes) + _Nodes = ear->Next; + + ReclasifyNode(ear->Prev); + ReclasifyNode(ear->Next); + + --_TrianglesLeft; + + return Triangle{ { i0, i1, i2 } }; +} + +void ImTriangulator::Span::PushBack(Node* node) +{ + Data[Size++] = node; +} + +void ImTriangulator::Span::RemoveByIndex(int index) +{ + for (int i = Size - 1; i >= 0; --i) + { + if (Data[i]->Index == index) + { + Data[i] = Data[Size - 1]; + --Size; + break; + } + } +} + +void ImTriangulator::FlipNodeList() +{ + Node* prev = _Nodes; + Node* temp = _Nodes; + Node* current = _Nodes->Next; + + prev->Next = prev; + prev->Prev = prev; + + while (current != _Nodes) + { + temp = current->Next; + + current->Next = prev; + prev->Prev = current; + _Nodes->Next = current; + current->Prev = _Nodes; + + prev = current; + current = temp; + } + + _Nodes = prev; +} + +bool ImTriangulator::IsEar(const Node* node, int i0, int i1, int i2, const ImVec2& v0, const ImVec2& v1, const ImVec2& v2) const +{ + for (int i = 0; i < _Reflexes.Size; ++i) + { + Node* reflex = _Reflexes.Data[i]; + + if (reflex->Index == i0 || reflex->Index == i1 || reflex->Index == i2) + continue; + + if (ImTriangleContainsPoint(v0, v1, v2, *reflex->Point)) + return false; + } + + return true; +} + +ImTriangulator::Type ImTriangulator::ClassifyNode(const Node* node) const +{ + const int i0 = node->Prev->Index; + const int i1 = node->Index; + const int i2 = node->Next->Index; + + const ImVec2& v0 = *node->Prev->Point; + const ImVec2& v1 = *node->Point; + const ImVec2& v2 = *node->Next->Point; + + if (ImPathIsConvex(v0, v1, v2)) + { + if (IsEar(node, i0, i1, i2, v0, v1, v2)) + return Ear; + else + return Convex; + } + else + { + return Reflex; + } +} + +void ImTriangulator::ReclasifyNode(Node* node) +{ + Type type = ClassifyNode(node); + + if (type == node->Type) + return; + + if (node->Type == Reflex) + _Reflexes.RemoveByIndex(node->Index); + else if (node->Type == Ear) + _Ears.RemoveByIndex(node->Index); + + if (type == Reflex) + _Reflexes.PushBack(node); + else if (type == Ear) + _Ears.PushBack(node); + + node->Type = type; +} + +void ImDrawList::AddConcavePolyFilled(const ImVec2* points, const int points_count, ImU32 col) +{ + if (points_count < 3 || (col & IM_COL32_A_MASK) == 0) + return; + + // coarse culling against viewport to avoid processing triangles outside of the visible area + ImVec2 bounds_min = ImVec2(FLT_MAX, FLT_MAX); + ImVec2 bounds_max = ImVec2(-FLT_MAX, -FLT_MAX); + + for (int i = 0; i < points_count; ++i) + { + const ImVec2& pos = points[i]; + + bounds_min = ImMin(bounds_min, pos); + bounds_max = ImMax(bounds_max, pos); + } + + if (!ImRect(_ClipRectStack.back()).Overlaps(ImRect(bounds_min, bounds_max))) + return; + + const ImVec2 uv = _Data->TexUvWhitePixel; + + if (Flags & ImDrawListFlags_AntiAliasedFill) + { + // Anti-aliased Fill + const float AA_SIZE = _FringeScale; + const ImU32 col_trans = col & ~IM_COL32_A_MASK; + const int idx_count = (points_count - 2)*3 + points_count * 6; + const int vtx_count = (points_count * 2); + PrimReserve(idx_count, vtx_count); + + // Add indexes for fill + unsigned int vtx_inner_idx = _VtxCurrentIdx; + unsigned int vtx_outer_idx = _VtxCurrentIdx + 1; + + _Data->TempBuffer.reserve_discard((ImTriangulator::EstimateScratchBufferSize(points_count) + sizeof(ImVec2)) / sizeof(ImVec2)); + ImTriangulator triangulator = ImTriangulator(points, points_count, _Data->TempBuffer.Data); + while (triangulator.HasNext()) + { + ImTriangulator::Triangle triangle = triangulator.Next(); + _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (triangle.Index[0] << 1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (triangle.Index[1] << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx + (triangle.Index[2] << 1)); + _IdxWritePtr += 3; + } + + // Compute normals + _Data->TempBuffer.reserve_discard(points_count); + ImVec2* temp_normals = _Data->TempBuffer.Data; + for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++) + { + const ImVec2& p0 = points[i0]; + const ImVec2& p1 = points[i1]; + float dx = p1.x - p0.x; + float dy = p1.y - p0.y; + IM_NORMALIZE2F_OVER_ZERO(dx, dy); + temp_normals[i0].x = dy; + temp_normals[i0].y = -dx; + } + + for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++) + { + // Average normals + const ImVec2& n0 = temp_normals[i0]; + const ImVec2& n1 = temp_normals[i1]; + float dm_x = (n0.x + n1.x) * 0.5f; + float dm_y = (n0.y + n1.y) * 0.5f; + IM_FIXNORMAL2F(dm_x, dm_y); + dm_x *= AA_SIZE * 0.5f; + dm_y *= AA_SIZE * 0.5f; + + // Add vertices + _VtxWritePtr[0].pos.x = (points[i1].x - dm_x); _VtxWritePtr[0].pos.y = (points[i1].y - dm_y); _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; // Inner + _VtxWritePtr[1].pos.x = (points[i1].x + dm_x); _VtxWritePtr[1].pos.y = (points[i1].y + dm_y); _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans; // Outer + _VtxWritePtr += 2; + + // Add indexes for fringes + _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (i0 << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1)); + _IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1)); _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx + (i1 << 1)); _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1)); + _IdxWritePtr += 6; + } + _VtxCurrentIdx += (ImDrawIdx)vtx_count; + } + else + { + // Non Anti-aliased Fill + const int idx_count = (points_count - 2)*3; + const int vtx_count = points_count; + PrimReserve(idx_count, vtx_count); + for (int i = 0; i < vtx_count; i++) + { + _VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; + _VtxWritePtr++; + } + _Data->TempBuffer.reserve_discard((ImTriangulator::EstimateScratchBufferSize(points_count) + sizeof(ImVec2)) / sizeof(ImVec2)); + ImTriangulator triangulator = ImTriangulator(points, points_count, _Data->TempBuffer.Data); + while (triangulator.HasNext()) + { + ImTriangulator::Triangle triangle = triangulator.Next(); + _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx + triangle.Index[0]); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + triangle.Index[1]); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + triangle.Index[2]); + _IdxWritePtr += 3; + } + _VtxCurrentIdx += (ImDrawIdx)vtx_count; + } +} //----------------------------------------------------------------------------- // [SECTION] ImDrawListSplitter From fbf45ad149b10ff8d9cb97aefe0dc5a9562fd66e Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 9 Jan 2024 23:36:26 +0100 Subject: [PATCH 192/237] ImDrawList: add PathFillConcave(), AddConcavePolyFilled(): amends (#760) - Simplify and compact some code. Shallow tweaks. - Add comments. - Add concave shape demo. - Remove coarse culling. - Remove nested types to match coding style and for consistent type nams when translated to other languages. - Merged ClassifyNode() and ReclassifyNode(). - Extracted ImTriangleIsClockwise(). - Hold copy of points inside nodes instead of pointing to them. --- docs/CHANGELOG.txt | 2 + imgui.h | 6 +- imgui_demo.cpp | 20 ++- imgui_draw.cpp | 405 ++++++++++++++++----------------------------- imgui_internal.h | 3 +- 5 files changed, 162 insertions(+), 274 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 291d1f10d763..0cb8982ed7ef 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,8 @@ Other changes: frames would erroneously close the window. While it is technically a popup issue it would generally manifest when fast moving the mouse bottom to top in a sub-menu. (#7325, #7287, #7063) +- DrawList: Added AddConcavePolyFilled(), PathFillConcave() concave filling. (#760) [@thedmd] + Note that only simple polygons (no self-intersections, no holes) are supported. - Docs: added more wiki links to headers of imgui.h/imgui.cpp to facilitate discovery of interesting resources, because github doesn't allow Wiki to be crawled by search engines. - This is the main wiki: https://github.com/ocornut/imgui/wiki diff --git a/imgui.h b/imgui.h index 4d5a8f0127eb..598f565a4c4d 100644 --- a/imgui.h +++ b/imgui.h @@ -28,7 +28,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.5 WIP" -#define IMGUI_VERSION_NUM 19043 +#define IMGUI_VERSION_NUM 19044 #define IMGUI_HAS_TABLE /* @@ -2760,9 +2760,11 @@ struct ImDrawList IMGUI_API void AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments = 0); // Quadratic Bezier (3 control points) // General polygon + // - Only simple polygons are supported by filling functions (no self-intersections, no holes). + // - Concave polygon fill is more expensive than convex one: it has O(N^2) complexity. Provided as a convenience fo user but not used by main library. IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness); IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); - IMGUI_API void AddConcavePolyFilled(const ImVec2* points, const int points_count, ImU32 col); + IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col); // Image primitives // - Read FAQ to understand what ImTextureID is. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index f275abc4b3d8..635606404938 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7964,6 +7964,14 @@ static void ShowExampleAppWindowTitles(bool*) // [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering() //----------------------------------------------------------------------------- +// Add a |_| looking shape +static void PathConcaveShape(ImDrawList* draw_list, float x, float y, float sz) +{ + const ImVec2 pos_norms[] = { { 0.0f, 0.0f }, { 0.3f, 0.0f }, { 0.3f, 0.7f }, { 0.7f, 0.7f }, { 0.7f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f } }; + for (const ImVec2& p : pos_norms) + draw_list->PathLineTo(ImVec2(x + 0.5f + (int)(sz * p.x), y + 0.5f + (int)(sz * p.y))); +} + // Demonstrate using the low-level ImDrawList to draw custom shapes. static void ShowExampleAppCustomRendering(bool* p_open) { @@ -8053,6 +8061,8 @@ static void ShowExampleAppCustomRendering(bool* p_open) draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners draw_list->AddTriangle(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col, th);x += sz + spacing; // Triangle //draw_list->AddTriangle(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col, th);x+= sz*0.4f + spacing; // Thin triangle + PathConcaveShape(draw_list, x, y, sz); draw_list->PathStroke(col, ImDrawFlags_Closed, th); x += sz + spacing; // Concave Shape + //draw_list->AddPolyline(concave_shape, IM_ARRAYSIZE(concave_shape), col, ImDrawFlags_Closed, th); draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y), col, th); x += sz + spacing; // Horizontal line (note: drawing a filled rectangle will be faster!) draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!) draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th); x += sz + spacing; // Diagonal line @@ -8082,6 +8092,7 @@ static void ShowExampleAppCustomRendering(bool* p_open) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br); x += sz + spacing; // Square with two rounded corners draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col); x += sz + spacing; // Triangle //draw_list->AddTriangleFilled(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col); x += sz*0.4f + spacing; // Thin triangle + PathConcaveShape(draw_list, x, y, sz); draw_list->PathFillConcave(col); x += sz + spacing; // Concave shape draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + thickness), col); x += sz + spacing; // Horizontal line (faster than AddLine, but only handle integer thickness) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + thickness, y + sz), col); x += spacing * 2.0f;// Vertical line (faster than AddLine, but only handle integer thickness) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col); x += sz; // Pixel (faster than AddLine) @@ -8097,15 +8108,10 @@ static void ShowExampleAppCustomRendering(bool* p_open) draw_list->PathFillConvex(col); x += sz + spacing; - // Cubic Bezier Curve (4 control points): this is concave so not drawing it yet - //draw_list->PathLineTo(ImVec2(x + cp4[0].x, y + cp4[0].y)); - //draw_list->PathBezierCubicCurveTo(ImVec2(x + cp4[1].x, y + cp4[1].y), ImVec2(x + cp4[2].x, y + cp4[2].y), ImVec2(x + cp4[3].x, y + cp4[3].y), curve_segments); - //draw_list->PathFillConvex(col); - //x += sz + spacing; - draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x + sz, y + sz), IM_COL32(0, 0, 0, 255), IM_COL32(255, 0, 0, 255), IM_COL32(255, 255, 0, 255), IM_COL32(0, 255, 0, 255)); + x += sz + spacing; - ImGui::Dummy(ImVec2((sz + spacing) * 12.2f, (sz + spacing) * 3.0f)); + ImGui::Dummy(ImVec2((sz + spacing) * 13.2f, (sz + spacing) * 3.0f)); ImGui::PopItemWidth(); ImGui::EndTabItem(); } diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 1bb7cfed9d73..ad3fda90ecd7 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -8,7 +8,7 @@ Index of this file: // [SECTION] STB libraries implementation // [SECTION] Style functions // [SECTION] ImDrawList -// [SECTION] ImDrawList concave polygon fill +// [SECTION] ImTriangulator, ImDrawList concave polygon fill // [SECTION] ImDrawListSplitter // [SECTION] ImDrawData // [SECTION] Helpers ShadeVertsXXX functions @@ -1702,200 +1702,130 @@ void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_mi } //----------------------------------------------------------------------------- -// [SECTION] ImDrawList concave polygon fill +// [SECTION] ImTriangulator, ImDrawList concave polygon fill +//----------------------------------------------------------------------------- +// Triangulate concave polygons. Based on "Triangulation by Ear Clipping" paper, O(N^2) complexity. +// Reference: https://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf +// Provided as a convenience for user but not used by main library. +//----------------------------------------------------------------------------- +// - ImTriangulator [Internal] +// - AddConcavePolyFilled() //----------------------------------------------------------------------------- -static bool ImPathIsConvex(const ImVec2& a, const ImVec2& b, const ImVec2& c) -{ - const float dx0 = b.x - a.x; - const float dy0 = b.y - a.y; - - const float dx1 = c.x - b.x; - const float dy1 = c.y - b.y; - - return dx0 * dy1 - dx1 * dy0 > 0.0f; -} - -struct ImTriangulator +enum ImTriangulatorNodeType { - struct Triangle { int Index[3]; }; - - static int EstimateTriangleCount(int points_count); - static int EstimateScratchBufferSize(int points_count); - - ImTriangulator(const ImVec2* points, int points_count, void* scratch_buffer); - ImTriangulator(const ImVec2* points, int points_count, int points_stride_bytes, void* scratch_buffer); - - bool HasNext() const; - - Triangle Next(); - -private: - enum Type { Convex, Ear, Reflex }; - - struct Node; - struct alignas(void*) Span - { - Node** Data = nullptr; - int Size = 0; - - void PushBack(Node* node); - void RemoveByIndex(int index); - }; - - void BuildNodes(); - void BuildReflexes(); - void BuildEars(); - void FlipNodeList(); - bool IsEar(const Node* node, int i0, int i1, int i2, const ImVec2& v0, const ImVec2& v1, const ImVec2& v2) const; - Type ClassifyNode(const Node* node) const; - void ReclasifyNode(Node* node); - - const ImVec2* _Points = nullptr; - int _PointsCount = 0; - int _PointsStrideBytes = 0; - int _TrianglesLeft = 0; - - Node* _Nodes = nullptr; - Span _Ears; - Span _Reflexes; + ImTriangulatorNodeType_Convex, + ImTriangulatorNodeType_Ear, + ImTriangulatorNodeType_Reflex }; -struct alignas(void*) ImTriangulator::Node +struct ImTriangulatorNode { - Type Type = Convex; - int Index = 0; - const ImVec2* Point = nullptr; - Node* Next = nullptr; - Node* Prev = nullptr; + ImTriangulatorNodeType Type; + int Index; + ImVec2 Pos; + ImTriangulatorNode* Next; + ImTriangulatorNode* Prev; - void Unlink() - { - Next->Prev = Prev; - Prev->Next = Next; - } + void Unlink() { Next->Prev = Prev; Prev->Next = Next; } }; -int ImTriangulator::EstimateTriangleCount(int points_count) -{ - if (points_count < 3) - return 0; - - return points_count - 2; -} - -int ImTriangulator::EstimateScratchBufferSize(int points_count) +struct ImTriangulatorNodeSpan { - return sizeof(Node*) * points_count * 2 + sizeof(Node) * points_count; -} + ImTriangulatorNode** Data = NULL; + int Size = 0; -ImTriangulator::ImTriangulator(const ImVec2* points, int points_count, void* scratch_buffer) - : ImTriangulator(points, points_count, sizeof(ImVec2), scratch_buffer) -{ -} + void push_back(ImTriangulatorNode* node) { Data[Size++] = node; } + void find_erase_unsorted(int idx) { for (int i = Size - 1; i >= 0; i--) if (Data[i]->Index == idx) { Data[i] = Data[Size - 1]; Size--; return; } } +}; -ImTriangulator::ImTriangulator(const ImVec2* points, int points_count, int points_stride_bytes, void* scratch_buffer) - : _Points(points) - , _PointsCount(points_count) - , _PointsStrideBytes(points_stride_bytes) - , _TrianglesLeft(EstimateTriangleCount(points_count)) +struct ImTriangulator { - IM_ASSERT(scratch_buffer != nullptr && "Must provide scratch buffer."); - IM_ASSERT(points_count >= 3); - - // Disable triangulator if scratch buffer isn't provided. - if (scratch_buffer == nullptr) - { - _TrianglesLeft = 0; - points_count = 0; - return; - } - - // Distribute storage for nodes, ears and reflexes. - _Nodes = reinterpret_cast(scratch_buffer); - _Ears.Data = reinterpret_cast(_Nodes + points_count); - _Reflexes.Data = _Ears.Data + points_count; + static int EstimateTriangleCount(int points_count) { return (points_count < 3) ? 0 : points_count - 2; } + static int EstimateScratchBufferSize(int points_count) { return sizeof(ImTriangulatorNode) * points_count + sizeof(ImTriangulatorNode*) * points_count * 2; } + + void Init(const ImVec2* points, int points_count, void* scratch_buffer); + void GetNextTriangle(unsigned int out_triangle[3]); // Return relative indexes for next triangle + + // Internal functions + void BuildNodes(const ImVec2* points, int points_count); + void BuildReflexes(); + void BuildEars(); + void FlipNodeList(); + bool IsEar(int i0, int i1, int i2, const ImVec2& v0, const ImVec2& v1, const ImVec2& v2) const; + void ReclassifyNode(ImTriangulatorNode* node); + + // Internal members + int _TrianglesLeft = 0; + ImTriangulatorNode* _Nodes = NULL; + ImTriangulatorNodeSpan _Ears; + ImTriangulatorNodeSpan _Reflexes; +}; - BuildNodes(); +// Distribute storage for nodes, ears and reflexes. +// FIXME-OPT: if everything is convex, we could report it to caller and let it switch to an convex renderer +// (this would require first building reflexes to bail to convex if empty, without even building nodes) +void ImTriangulator::Init(const ImVec2* points, int points_count, void* scratch_buffer) +{ + IM_ASSERT(scratch_buffer != NULL && points_count >= 3); + _TrianglesLeft = EstimateTriangleCount(points_count); + _Nodes = (ImTriangulatorNode*)scratch_buffer; // points_count x Node + _Ears.Data = (ImTriangulatorNode**)(_Nodes + points_count); // points_count x Node* + _Reflexes.Data = (ImTriangulatorNode**)(_Nodes + points_count) + points_count; // points_count x Node* + BuildNodes(points, points_count); BuildReflexes(); BuildEars(); } -void ImTriangulator::BuildNodes() +void ImTriangulator::BuildNodes(const ImVec2* points, int points_count) { -# define IM_POINT_PTR(idx) reinterpret_cast(reinterpret_cast(_Points) + (idx) * _PointsStrideBytes) - - for (int i = 0; i < _PointsCount; ++i) + for (int i = 0; i < points_count; i++) { - _Nodes[i].Type = Convex; - _Nodes[i].Index = static_cast(i); - _Nodes[i].Point = IM_POINT_PTR(i); - _Nodes[i].Next = _Nodes + i + 1; - _Nodes[i].Prev = _Nodes + i - 1; + _Nodes[i].Type = ImTriangulatorNodeType_Convex; + _Nodes[i].Index = i; + _Nodes[i].Pos = points[i]; + _Nodes[i].Next = _Nodes + i + 1; + _Nodes[i].Prev = _Nodes + i - 1; } - _Nodes[0].Prev = _Nodes + _PointsCount - 1; - _Nodes[_PointsCount - 1].Next = _Nodes; - -# undef IM_POINT_PTR + _Nodes[0].Prev = _Nodes + points_count - 1; + _Nodes[points_count - 1].Next = _Nodes; } void ImTriangulator::BuildReflexes() { - Node* node = _Nodes; - for (int i = 0; i < _TrianglesLeft; ++i, node = node->Next) + ImTriangulatorNode* n1 = _Nodes; + for (int i = _TrianglesLeft; i >= 0; i--, n1 = n1->Next) { - const ImVec2& v0 = *node->Prev->Point; - const ImVec2& v1 = *node->Point; - const ImVec2& v2 = *node->Next->Point; - - if (ImPathIsConvex(v0, v1, v2)) + if (ImTriangleIsClockwise(n1->Prev->Pos, n1->Pos, n1->Next->Pos)) continue; - - node->Type = Reflex; - _Reflexes.PushBack(node); + n1->Type = ImTriangulatorNodeType_Reflex; + _Reflexes.push_back(n1); } } void ImTriangulator::BuildEars() { - Node* node = _Nodes; - for (int i = 0; i < _TrianglesLeft; ++i, node = node->Next) + ImTriangulatorNode* n1 = _Nodes; + for (int i = _TrianglesLeft; i >= 0; i--, n1 = n1->Next) { - if (node->Type != Convex) + if (n1->Type != ImTriangulatorNodeType_Convex) continue; - - const int i0 = node->Prev->Index; - const int i1 = node->Index; - const int i2 = node->Next->Index; - - const ImVec2& v0 = *node->Prev->Point; - const ImVec2& v1 = *node->Point; - const ImVec2& v2 = *node->Next->Point; - - if (!IsEar(node, i0, i1, i2, v0, v1, v2)) + if (!IsEar(n1->Prev->Index, n1->Index, n1->Next->Index, n1->Prev->Pos, n1->Pos, n1->Next->Pos)) continue; - - node->Type = Ear; - _Ears.PushBack(node); + n1->Type = ImTriangulatorNodeType_Ear; + _Ears.push_back(n1); } } -bool ImTriangulator::HasNext() const -{ - return _TrianglesLeft > 0; -} - -ImTriangulator::Triangle ImTriangulator::Next() +void ImTriangulator::GetNextTriangle(unsigned int out_triangle[3]) { - IM_ASSERT(_TrianglesLeft > 0 && "Do not call Next() until HasNext() return true"); - if (_Ears.Size == 0) { FlipNodeList(); - Node* node = _Nodes; - for (int i = 0; i < _TrianglesLeft; ++i, node = node->Next) - node->Type = Convex; + ImTriangulatorNode* node = _Nodes; + for (int i = _TrianglesLeft; i >= 0; i--, node = node->Next) + node->Type = ImTriangulatorNodeType_Convex; _Reflexes.Size = 0; BuildReflexes(); BuildEars(); @@ -1903,59 +1833,34 @@ ImTriangulator::Triangle ImTriangulator::Next() // If we still don't have ears, it means geometry is degenerated. if (_Ears.Size == 0) { - IM_ASSERT(_TrianglesLeft > 0 && "Geometry is degenerated"); - // Return first triangle available, mimicking the behavior of convex fill. + IM_ASSERT(_TrianglesLeft > 0); // Geometry is degenerated _Ears.Data[0] = _Nodes; _Ears.Size = 1; } } - Node* ear = _Ears.Data[--_Ears.Size]; - - const int i0 = ear->Prev->Index; - const int i1 = ear->Index; - const int i2 = ear->Next->Index; + ImTriangulatorNode* ear = _Ears.Data[--_Ears.Size]; + out_triangle[0] = ear->Prev->Index; + out_triangle[1] = ear->Index; + out_triangle[2] = ear->Next->Index; ear->Unlink(); if (ear == _Nodes) _Nodes = ear->Next; - ReclasifyNode(ear->Prev); - ReclasifyNode(ear->Next); - - --_TrianglesLeft; - - return Triangle{ { i0, i1, i2 } }; -} - -void ImTriangulator::Span::PushBack(Node* node) -{ - Data[Size++] = node; -} - -void ImTriangulator::Span::RemoveByIndex(int index) -{ - for (int i = Size - 1; i >= 0; --i) - { - if (Data[i]->Index == index) - { - Data[i] = Data[Size - 1]; - --Size; - break; - } - } + ReclassifyNode(ear->Prev); + ReclassifyNode(ear->Next); + _TrianglesLeft--; } void ImTriangulator::FlipNodeList() { - Node* prev = _Nodes; - Node* temp = _Nodes; - Node* current = _Nodes->Next; - + ImTriangulatorNode* prev = _Nodes; + ImTriangulatorNode* temp = _Nodes; + ImTriangulatorNode* current = _Nodes->Next; prev->Next = prev; prev->Prev = prev; - while (current != _Nodes) { temp = current->Next; @@ -1968,97 +1873,69 @@ void ImTriangulator::FlipNodeList() prev = current; current = temp; } - _Nodes = prev; } -bool ImTriangulator::IsEar(const Node* node, int i0, int i1, int i2, const ImVec2& v0, const ImVec2& v1, const ImVec2& v2) const +// A triangle is an ear is no other vertex is inside it. We can test reflexes vertices only (see reference algorithm) +bool ImTriangulator::IsEar(int i0, int i1, int i2, const ImVec2& v0, const ImVec2& v1, const ImVec2& v2) const { - for (int i = 0; i < _Reflexes.Size; ++i) + ImTriangulatorNode** p_end = _Reflexes.Data + _Reflexes.Size; + for (ImTriangulatorNode** p = _Reflexes.Data; p < p_end; p++) { - Node* reflex = _Reflexes.Data[i]; - - if (reflex->Index == i0 || reflex->Index == i1 || reflex->Index == i2) - continue; - - if (ImTriangleContainsPoint(v0, v1, v2, *reflex->Point)) - return false; + ImTriangulatorNode* reflex = *p; + if (reflex->Index != i0 && reflex->Index != i1 && reflex->Index != i2) + if (ImTriangleContainsPoint(v0, v1, v2, reflex->Pos)) + return false; } - return true; } -ImTriangulator::Type ImTriangulator::ClassifyNode(const Node* node) const +void ImTriangulator::ReclassifyNode(ImTriangulatorNode* n1) { - const int i0 = node->Prev->Index; - const int i1 = node->Index; - const int i2 = node->Next->Index; - - const ImVec2& v0 = *node->Prev->Point; - const ImVec2& v1 = *node->Point; - const ImVec2& v2 = *node->Next->Point; - - if (ImPathIsConvex(v0, v1, v2)) - { - if (IsEar(node, i0, i1, i2, v0, v1, v2)) - return Ear; - else - return Convex; - } + // Classify node + ImTriangulatorNodeType type; + const ImTriangulatorNode* n0 = n1->Prev; + const ImTriangulatorNode* n2 = n1->Next; + if (!ImTriangleIsClockwise(n0->Pos, n1->Pos, n2->Pos)) + type = ImTriangulatorNodeType_Reflex; + else if (IsEar(n0->Index, n1->Index, n2->Index, n0->Pos, n1->Pos, n2->Pos)) + type = ImTriangulatorNodeType_Ear; else - { - return Reflex; - } -} - -void ImTriangulator::ReclasifyNode(Node* node) -{ - Type type = ClassifyNode(node); + type = ImTriangulatorNodeType_Convex; - if (type == node->Type) + // Update lists when a type changes + if (type == n1->Type) return; - - if (node->Type == Reflex) - _Reflexes.RemoveByIndex(node->Index); - else if (node->Type == Ear) - _Ears.RemoveByIndex(node->Index); - - if (type == Reflex) - _Reflexes.PushBack(node); - else if (type == Ear) - _Ears.PushBack(node); - - node->Type = type; -} - + if (n1->Type == ImTriangulatorNodeType_Reflex) + _Reflexes.find_erase_unsorted(n1->Index); + else if (n1->Type == ImTriangulatorNodeType_Ear) + _Ears.find_erase_unsorted(n1->Index); + if (type == ImTriangulatorNodeType_Reflex) + _Reflexes.push_back(n1); + else if (type == ImTriangulatorNodeType_Ear) + _Ears.push_back(n1); + n1->Type = type; +} + +// Use ear-clipping algorithm to triangulate a simple polygon (no self-interaction, no holes). +// (Reminder: we don't perform any coarse clipping/culling in ImDrawList layer! +// It is up to caller to ensure not making costly calls that will be outside of visible area. +// As concave fill is noticeably more expensive than other primitives, be mindful of this... +// Caller can build AABB of points, and avoid filling if 'draw_list->_CmdHeader.ClipRect.Overlays(points_bb) == false') void ImDrawList::AddConcavePolyFilled(const ImVec2* points, const int points_count, ImU32 col) { if (points_count < 3 || (col & IM_COL32_A_MASK) == 0) return; - // coarse culling against viewport to avoid processing triangles outside of the visible area - ImVec2 bounds_min = ImVec2(FLT_MAX, FLT_MAX); - ImVec2 bounds_max = ImVec2(-FLT_MAX, -FLT_MAX); - - for (int i = 0; i < points_count; ++i) - { - const ImVec2& pos = points[i]; - - bounds_min = ImMin(bounds_min, pos); - bounds_max = ImMax(bounds_max, pos); - } - - if (!ImRect(_ClipRectStack.back()).Overlaps(ImRect(bounds_min, bounds_max))) - return; - const ImVec2 uv = _Data->TexUvWhitePixel; - + ImTriangulator triangulator; + unsigned int triangle[3]; if (Flags & ImDrawListFlags_AntiAliasedFill) { // Anti-aliased Fill const float AA_SIZE = _FringeScale; const ImU32 col_trans = col & ~IM_COL32_A_MASK; - const int idx_count = (points_count - 2)*3 + points_count * 6; + const int idx_count = (points_count - 2) * 3 + points_count * 6; const int vtx_count = (points_count * 2); PrimReserve(idx_count, vtx_count); @@ -2067,11 +1944,11 @@ void ImDrawList::AddConcavePolyFilled(const ImVec2* points, const int points_cou unsigned int vtx_outer_idx = _VtxCurrentIdx + 1; _Data->TempBuffer.reserve_discard((ImTriangulator::EstimateScratchBufferSize(points_count) + sizeof(ImVec2)) / sizeof(ImVec2)); - ImTriangulator triangulator = ImTriangulator(points, points_count, _Data->TempBuffer.Data); - while (triangulator.HasNext()) + triangulator.Init(points, points_count, _Data->TempBuffer.Data); + while (triangulator._TrianglesLeft > 0) { - ImTriangulator::Triangle triangle = triangulator.Next(); - _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (triangle.Index[0] << 1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (triangle.Index[1] << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx + (triangle.Index[2] << 1)); + triangulator.GetNextTriangle(triangle); + _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (triangle[0] << 1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (triangle[1] << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx + (triangle[2] << 1)); _IdxWritePtr += 3; } @@ -2115,7 +1992,7 @@ void ImDrawList::AddConcavePolyFilled(const ImVec2* points, const int points_cou else { // Non Anti-aliased Fill - const int idx_count = (points_count - 2)*3; + const int idx_count = (points_count - 2) * 3; const int vtx_count = points_count; PrimReserve(idx_count, vtx_count); for (int i = 0; i < vtx_count; i++) @@ -2124,11 +2001,11 @@ void ImDrawList::AddConcavePolyFilled(const ImVec2* points, const int points_cou _VtxWritePtr++; } _Data->TempBuffer.reserve_discard((ImTriangulator::EstimateScratchBufferSize(points_count) + sizeof(ImVec2)) / sizeof(ImVec2)); - ImTriangulator triangulator = ImTriangulator(points, points_count, _Data->TempBuffer.Data); - while (triangulator.HasNext()) + triangulator.Init(points, points_count, _Data->TempBuffer.Data); + while (triangulator._TrianglesLeft > 0) { - ImTriangulator::Triangle triangle = triangulator.Next(); - _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx + triangle.Index[0]); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + triangle.Index[1]); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + triangle.Index[2]); + triangulator.GetNextTriangle(triangle); + _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx + triangle[0]); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + triangle[1]); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + triangle[2]); _IdxWritePtr += 3; } _VtxCurrentIdx += (ImDrawIdx)vtx_count; diff --git a/imgui_internal.h b/imgui_internal.h index 610db3467589..2039f748dfdd 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -498,7 +498,8 @@ IMGUI_API ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const IMGUI_API bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p); IMGUI_API ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p); IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w); -inline float ImTriangleArea(const ImVec2& a, const ImVec2& b, const ImVec2& c) { return ImFabs((a.x * (b.y - c.y)) + (b.x * (c.y - a.y)) + (c.x * (a.y - b.y))) * 0.5f; } +inline float ImTriangleArea(const ImVec2& a, const ImVec2& b, const ImVec2& c) { return ImFabs((a.x * (b.y - c.y)) + (b.x * (c.y - a.y)) + (c.x * (a.y - b.y))) * 0.5f; } +inline bool ImTriangleIsClockwise(const ImVec2& a, const ImVec2& b, const ImVec2& c) { return ((b.x - a.x) * (c.y - b.y)) - ((c.x - b.x) * (b.y - a.y)) > 0.0f; } // Helper: ImVec1 (1D vector) // (this odd construct is used to facilitate the transition between 1D and 2D, and the maintenance of some branches/patches) From 6b7358e9f36b7faa37ae40704aafc4341eb62020 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 4 Mar 2024 11:30:22 +0100 Subject: [PATCH 193/237] InputText: adding clarifying note about ImGuiInputTextCallbackData::Buf. (#7363) --- imgui.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui.h b/imgui.h index 598f565a4c4d..eab7c57e4fc8 100644 --- a/imgui.h +++ b/imgui.h @@ -2268,6 +2268,8 @@ struct ImGuiInputTextCallbackData void* UserData; // What user passed to InputText() // Read-only // Arguments for the different callback events + // - During Resize callback, Buf will be same as your input buffer. + // - However, during Completion/History/Always callback, Buf always points to our own internal data (it is not the same as your buffer)! Changes to it will be reflected into your own buffer shortly after the callback. // - To modify the text buffer in a callback, prefer using the InsertChars() / DeleteChars() function. InsertChars() will take care of calling the resize callback if necessary. // - If you know your edits are not going to resize the underlying buffer allocation, you may modify the contents of 'Buf[]' directly. You need to update 'BufTextLen' accordingly (0 <= BufTextLen < BufSize) and set 'BufDirty'' to true so InputText can update its internal state. ImWchar EventChar; // Character input // Read-write // [CharFilter] Replace character with another one, or set to zero to drop. return 1 is equivalent to setting EventChar=0; From 65dc67f63c60201d18d3ab3b26f2595ce6f3ed18 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 5 Mar 2024 17:34:34 +0100 Subject: [PATCH 194/237] Windows: Double-click to collapse may be disabled via key-ownership mechanism. (#7369) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0cb8982ed7ef..050bde82dc57 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,7 @@ Other changes: - Windows: Scrollbar visibility decision uses current size when both size and contents size are submitted by API. (#7252) +- Windows: Double-click to collapse may be disabled via key-ownership mechanism. (#7369) - Menus, Popups: Fixed an issue where sibling menu popups re-opening in successive frames would erroneously close the window. While it is technically a popup issue it would generally manifest when fast moving the mouse bottom to top in a sub-menu. diff --git a/imgui.cpp b/imgui.cpp index 31c6d25123f3..a4ecdefe6dc4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6629,8 +6629,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { // We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed), so verify that we don't have items over the title bar. ImRect title_bar_rect = window->TitleBarRect(); - if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseClickedCount[0] == 2) - window->WantCollapseToggle = true; + if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max)) + if (g.IO.MouseClickedCount[0] == 2 && GetKeyOwner(ImGuiKey_MouseLeft) == ImGuiKeyOwner_None) + window->WantCollapseToggle = true; if (window->WantCollapseToggle) { window->Collapsed = !window->Collapsed; From fc570ac9225b0ef2895da5e299527b8953c79cb7 Mon Sep 17 00:00:00 2001 From: Kevin Leonardic Date: Wed, 6 Mar 2024 13:44:37 +0100 Subject: [PATCH 195/237] Examples: WGPU: fixed initialization of WGPURenderPassColorAttachment (#7371) --- examples/example_emscripten_wgpu/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index 910da083396b..43e93a2ad06d 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -201,6 +201,7 @@ int main(int, char**) ImGui::Render(); WGPURenderPassColorAttachment color_attachments = {}; + color_attachments.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED; color_attachments.loadOp = WGPULoadOp_Clear; color_attachments.storeOp = WGPUStoreOp_Store; color_attachments.clearValue = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w }; From 286cd5bd41e8bf0062a9a5f6373dc1a091fe6ed2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 Mar 2024 15:00:07 +0100 Subject: [PATCH 196/237] Internals, InputText: removed ImGuiInputSource_Clipboard. (#4005) Added by f08566b4d --- imgui.cpp | 2 +- imgui_internal.h | 1 - imgui_widgets.cpp | 19 +++++++++---------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a4ecdefe6dc4..25896554d0d4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9206,7 +9206,7 @@ void ImGui::SetNextFrameWantCaptureMouse(bool want_capture_mouse) #ifndef IMGUI_DISABLE_DEBUG_TOOLS static const char* GetInputSourceName(ImGuiInputSource source) { - const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamepad", "Clipboard" }; + const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT && source >= 0 && source < ImGuiInputSource_COUNT); return input_source_names[source]; } diff --git a/imgui_internal.h b/imgui_internal.h index 2039f748dfdd..cb2518367a0e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1350,7 +1350,6 @@ enum ImGuiInputSource ImGuiInputSource_Mouse, // Note: may be Mouse or TouchScreen or Pen. See io.MouseSource to distinguish them. ImGuiInputSource_Keyboard, ImGuiInputSource_Gamepad, - ImGuiInputSource_Clipboard, // Currently only used by InputText() ImGuiInputSource_COUNT }; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 7fec23e2e5bc..d83a080f5496 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -122,9 +122,9 @@ static const ImU64 IM_U64_MAX = (2ULL * 9223372036854775807LL + 1); //------------------------------------------------------------------------- // For InputTextEx() -static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, ImGuiInputSource input_source); -static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end); -static ImVec2 InputTextCalcTextSizeW(ImGuiContext* ctx, const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false); +static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, bool input_source_is_clipboard = false); +static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end); +static ImVec2 InputTextCalcTextSizeW(ImGuiContext* ctx, const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false); //------------------------------------------------------------------------- // [SECTION] Widgets: Text, etc. @@ -3916,9 +3916,8 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons } // Return false to discard a character. -static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, ImGuiInputSource input_source) +static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, bool input_source_is_clipboard) { - IM_ASSERT(input_source == ImGuiInputSource_Keyboard || input_source == ImGuiInputSource_Clipboard); unsigned int c = *p_char; // Filter non-printable (NB: isprint is unreliable! see #2467) @@ -3933,7 +3932,7 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im apply_named_filters = false; // Override named filters below so newline and tabs can still be inserted. } - if (input_source != ImGuiInputSource_Clipboard) + if (input_source_is_clipboard == false) { // We ignore Ascii representation of delete (emitted from Backspace on OSX, see #2578, #2817) if (c == 127) @@ -4418,7 +4417,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (Shortcut(ImGuiKey_Tab, id, ImGuiInputFlags_Repeat)) { unsigned int c = '\t'; // Insert TAB - if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) + if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data)) state->OnKeyPressed((int)c); } // FIXME: Implement Shift+Tab @@ -4441,7 +4440,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ unsigned int c = (unsigned int)io.InputQueueCharacters[n]; if (c == '\t') // Skip Tab, see above. continue; - if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) + if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data)) state->OnKeyPressed((int)c); } @@ -4524,7 +4523,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ else if (!is_readonly) { unsigned int c = '\n'; // Insert new line - if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) + if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data)) state->OnKeyPressed((int)c); } } @@ -4591,7 +4590,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ { unsigned int c; s += ImTextCharFromUtf8(&c, s, NULL); - if (!InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Clipboard)) + if (!InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, true)) continue; clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c; } From 3c435c029788cc26c52e835e2feb262a3057addc Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 8 Mar 2024 12:12:21 +0100 Subject: [PATCH 197/237] Inputs: (Breaking) More formally obsoleted GetKeyIndex() when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is set. (#4921) --- docs/CHANGELOG.txt | 11 +++++++++-- imgui.cpp | 2 ++ imgui.h | 14 ++++---------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 050bde82dc57..48d592182869 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -39,6 +39,13 @@ HOW TO UPDATE? VERSION 1.90.5 WIP (In Progress) ----------------------------------------------------------------------- +Breaking changes: + +- More formally obsoleted GetKeyIndex() when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is set. + It has been unnecessary and a no-op since 1.87 (it returns the same value as passed + when used with a 1.87+ backend using io.AddKeyEvent() function). (#4921) + - IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) --> IsKeyPressed(ImGuiKey_XXX) + Other changes: - Windows: Scrollbar visibility decision uses current size when both size and contents @@ -81,8 +88,8 @@ Other changes: for auto-resizing of columns. (#6917) - Tables: Angled headers: fixed TableAngledHeadersRow() incorrect background fill drawn too low, particularly visible with tables that have no scrolling. (#6917) -- ProgressBar: Fixed a minor tesselation issue when rendering rounded progress bars, - where in some situations the rounded section wouldn't follow regular tesselation rules. +- ProgressBar: Fixed a minor tessellation issue when rendering rounded progress bars, + where in some situations the rounded section wouldn't follow regular tessellation rules. - Debug Tools: Item Picker: Promoted ImGui::DebugStartItemPicker() to public API. (#2673) - Debug Tools: Item Picker: Menu entry visible in Demo->Tools but greyed out unless io.ConfigDebugIsDebuggerPresent is set. (#2673) diff --git a/imgui.cpp b/imgui.cpp index 25896554d0d4..c60e89f8bf2e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -429,6 +429,8 @@ CODE When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2024/03/08 (1.90.5) - inputs: more formally obsoleted GetKeyIndex() when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is set. It has been unnecessary and a no-op since 1.87 (it returns the same value as passed when used with a 1.87+ backend using io.AddKeyEvent() function). (#4921) + - IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) -> use IsKeyPressed(ImGuiKey_XXX) - 2024/01/15 (1.90.2) - commented out obsolete ImGuiIO::ImeWindowHandle marked obsolete in 1.87, favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'. - 2023/12/19 (1.90.1) - commented out obsolete ImGuiKey_KeyPadEnter redirection to ImGuiKey_KeypadEnter. - 2023/11/06 (1.90.1) - removed CalcListClipping() marked obsolete in 1.86. Prefer using ImGuiListClipper which can return non-contiguous ranges. diff --git a/imgui.h b/imgui.h index eab7c57e4fc8..3918de1165fc 100644 --- a/imgui.h +++ b/imgui.h @@ -28,7 +28,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.5 WIP" -#define IMGUI_VERSION_NUM 19044 +#define IMGUI_VERSION_NUM 19045 #define IMGUI_HAS_TABLE /* @@ -3174,15 +3174,6 @@ struct ImGuiPlatformImeData // Please keep your copy of dear imgui up to date! Occasionally set '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' in imconfig.h to stay ahead. //----------------------------------------------------------------------------- -namespace ImGui -{ -#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO - IMGUI_API ImGuiKey GetKeyIndex(ImGuiKey key); // map ImGuiKey_* values into legacy native key index. == io.KeyMap[key] -#else - static inline ImGuiKey GetKeyIndex(ImGuiKey key) { IM_ASSERT(key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END && "ImGuiKey and native_index was merged together and native_index is disabled by IMGUI_DISABLE_OBSOLETE_KEYIO. Please switch to ImGuiKey."); return key; } -#endif -} - #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { @@ -3204,6 +3195,9 @@ namespace ImGui // 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. + // OBSOLETED in 1.87 (from February 2022) + 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.86 (from November 2021) From da29b776eed289db16a8527e5f16a0e1fa540251 Mon Sep 17 00:00:00 2001 From: Robert Edmonds Date: Mon, 11 Mar 2024 10:04:56 +0000 Subject: [PATCH 198/237] Backends: SDL3: Fix leak of SDL_GetGamepads() return value (#7381) --- backends/imgui_impl_sdl3.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 2e261ef1a070..2669b71f7461 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -609,6 +609,7 @@ static void ImGui_ImplSDL3_UpdateGamepads() if (bd->GamepadMode == ImGui_ImplSDL3_GamepadMode_AutoFirst) break; } + SDL_free(sdl_gamepads); bd->WantUpdateGamepadsList = false; } From 9d9ca37a8479fe682936b7a97e1a9a9030945b90 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 11 Mar 2024 14:41:02 +0100 Subject: [PATCH 199/237] Docking: Fix C++26 zealous warnings (#7383, #7089) --- imgui_internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index da97d8c2dfcc..b6f02ad6a26c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1767,9 +1767,9 @@ enum ImGuiDockNodeFlagsPrivate_ ImGuiDockNodeFlags_NoDocking = ImGuiDockNodeFlags_NoDockingOverMe | ImGuiDockNodeFlags_NoDockingOverOther | ImGuiDockNodeFlags_NoDockingOverEmpty | ImGuiDockNodeFlags_NoDockingSplit | ImGuiDockNodeFlags_NoDockingSplitOther, // Masks ImGuiDockNodeFlags_SharedFlagsInheritMask_ = ~0, - ImGuiDockNodeFlags_NoResizeFlagsMask_ = ImGuiDockNodeFlags_NoResize | ImGuiDockNodeFlags_NoResizeX | ImGuiDockNodeFlags_NoResizeY, + ImGuiDockNodeFlags_NoResizeFlagsMask_ = (ImGuiDockNodeFlagsPrivate_)ImGuiDockNodeFlags_NoResize | ImGuiDockNodeFlags_NoResizeX | ImGuiDockNodeFlags_NoResizeY, // When splitting, those local flags are moved to the inheriting child, never duplicated - ImGuiDockNodeFlags_LocalFlagsTransferMask_ = ImGuiDockNodeFlags_NoDockingSplit | ImGuiDockNodeFlags_NoResizeFlagsMask_ | ImGuiDockNodeFlags_AutoHideTabBar | ImGuiDockNodeFlags_CentralNode | ImGuiDockNodeFlags_NoTabBar | ImGuiDockNodeFlags_HiddenTabBar | ImGuiDockNodeFlags_NoWindowMenuButton | ImGuiDockNodeFlags_NoCloseButton, + ImGuiDockNodeFlags_LocalFlagsTransferMask_ = (ImGuiDockNodeFlagsPrivate_)ImGuiDockNodeFlags_NoDockingSplit | ImGuiDockNodeFlags_NoResizeFlagsMask_ | (ImGuiDockNodeFlagsPrivate_)ImGuiDockNodeFlags_AutoHideTabBar | ImGuiDockNodeFlags_CentralNode | ImGuiDockNodeFlags_NoTabBar | ImGuiDockNodeFlags_HiddenTabBar | ImGuiDockNodeFlags_NoWindowMenuButton | ImGuiDockNodeFlags_NoCloseButton, ImGuiDockNodeFlags_SavedFlagsMask_ = ImGuiDockNodeFlags_NoResizeFlagsMask_ | ImGuiDockNodeFlags_DockSpace | ImGuiDockNodeFlags_CentralNode | ImGuiDockNodeFlags_NoTabBar | ImGuiDockNodeFlags_HiddenTabBar | ImGuiDockNodeFlags_NoWindowMenuButton | ImGuiDockNodeFlags_NoCloseButton, }; From adcc3217c38142e965eae679a299a34ce1c963d5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 11 Mar 2024 15:05:36 +0100 Subject: [PATCH 200/237] Revert "Docking: Fix C++26 zealous warnings (#7383, #7089)" + Disable warnings This reverts commit 9d9ca37a8479fe682936b7a97e1a9a9030945b90. --- imgui_internal.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index b6f02ad6a26c..9e39ea739ce7 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -87,10 +87,12 @@ Index of this file: #pragma clang diagnostic ignored "-Wdouble-promotion" #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #pragma clang diagnostic ignored "-Wmissing-noreturn" // warning: function 'xxx' could be declared with attribute 'noreturn' +#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated #elif defined(__GNUC__) #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind -#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead +#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind +#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead +#pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated #endif // In 1.89.4, we moved the implementation of "courtesy maths operators" from imgui_internal.h in imgui.h @@ -1767,9 +1769,9 @@ enum ImGuiDockNodeFlagsPrivate_ ImGuiDockNodeFlags_NoDocking = ImGuiDockNodeFlags_NoDockingOverMe | ImGuiDockNodeFlags_NoDockingOverOther | ImGuiDockNodeFlags_NoDockingOverEmpty | ImGuiDockNodeFlags_NoDockingSplit | ImGuiDockNodeFlags_NoDockingSplitOther, // Masks ImGuiDockNodeFlags_SharedFlagsInheritMask_ = ~0, - ImGuiDockNodeFlags_NoResizeFlagsMask_ = (ImGuiDockNodeFlagsPrivate_)ImGuiDockNodeFlags_NoResize | ImGuiDockNodeFlags_NoResizeX | ImGuiDockNodeFlags_NoResizeY, + ImGuiDockNodeFlags_NoResizeFlagsMask_ = ImGuiDockNodeFlags_NoResize | ImGuiDockNodeFlags_NoResizeX | ImGuiDockNodeFlags_NoResizeY, // When splitting, those local flags are moved to the inheriting child, never duplicated - ImGuiDockNodeFlags_LocalFlagsTransferMask_ = (ImGuiDockNodeFlagsPrivate_)ImGuiDockNodeFlags_NoDockingSplit | ImGuiDockNodeFlags_NoResizeFlagsMask_ | (ImGuiDockNodeFlagsPrivate_)ImGuiDockNodeFlags_AutoHideTabBar | ImGuiDockNodeFlags_CentralNode | ImGuiDockNodeFlags_NoTabBar | ImGuiDockNodeFlags_HiddenTabBar | ImGuiDockNodeFlags_NoWindowMenuButton | ImGuiDockNodeFlags_NoCloseButton, + ImGuiDockNodeFlags_LocalFlagsTransferMask_ = ImGuiDockNodeFlags_NoDockingSplit | ImGuiDockNodeFlags_NoResizeFlagsMask_ | ImGuiDockNodeFlags_AutoHideTabBar | ImGuiDockNodeFlags_CentralNode | ImGuiDockNodeFlags_NoTabBar | ImGuiDockNodeFlags_HiddenTabBar | ImGuiDockNodeFlags_NoWindowMenuButton | ImGuiDockNodeFlags_NoCloseButton, ImGuiDockNodeFlags_SavedFlagsMask_ = ImGuiDockNodeFlags_NoResizeFlagsMask_ | ImGuiDockNodeFlags_DockSpace | ImGuiDockNodeFlags_CentralNode | ImGuiDockNodeFlags_NoTabBar | ImGuiDockNodeFlags_HiddenTabBar | ImGuiDockNodeFlags_NoWindowMenuButton | ImGuiDockNodeFlags_NoCloseButton, }; From 40df3db1a2a0f034257efad3c817c7ead5930257 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 17 Mar 2024 19:46:12 +0900 Subject: [PATCH 201/237] Tweaking terminology --- docs/FAQ.md | 4 ++-- docs/README.md | 12 ++++++------ imgui.cpp | 4 ++-- imgui_demo.cpp | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index c86cc1368bbe..65824781e1cc 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -621,7 +621,7 @@ You may take a look at: - [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) -- [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) +- [Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding) - [Gallery](https://github.com/ocornut/imgui/issues/6897) ##### [Return to Index](#index) @@ -664,7 +664,7 @@ There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/ci # Q&A: Community ### Q: How can I help? -- Businesses: please reach out to `omar AT dearimgui.com` if you work in a place using Dear ImGui! We can discuss ways for your company to fund development via invoiced technical support, maintenance, or sponsoring contacts. This is among the most useful thing you can do for Dear ImGui. With increased funding, we can hire more people to work on this project. +- Businesses: please reach out to `omar AT dearimgui.com` if you work in a place using Dear ImGui! We can discuss ways for your company to fund development via invoiced technical support, maintenance, or sponsoring contacts. This is among the most useful thing you can do for Dear ImGui. With increased funding, we can hire more people to work on this project. Please see [Funding](https://github.com/ocornut/imgui/wiki/Funding) page. - Individuals: you can support continued maintenance and development via PayPal donations. See [README](https://github.com/ocornut/imgui/blob/master/docs/README.md). - If you are experienced with Dear ImGui and C++, look at [GitHub Issues](https://github.com/ocornut/imgui/issues), [GitHub Discussions](https://github.com/ocornut/imgui/discussions), the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt), and see how you want to help and can help! - Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere, etc. diff --git a/docs/README.md b/docs/README.md index 6aac61b5a9e9..37267d39b410 100644 --- a/docs/README.md +++ b/docs/README.md @@ -11,11 +11,11 @@ Dear ImGui Businesses: support continued development and maintenance via invoiced sponsoring/support contracts:
  _E-mail: contact @ dearimgui dot com_ -
Individuals: support continued development and maintenance [here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WGHNC6MBFLZ2S). Also see [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) page. +
Individuals: support continued development and maintenance [here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WGHNC6MBFLZ2S). Also see [Funding](https://github.com/ocornut/imgui/wiki/Funding) page. | [The Pitch](#the-pitch) - [Usage](#usage) - [How it works](#how-it-works) - [Releases & Changelogs](#releases--changelogs) - [Demo](#demo) - [Integration](#integration) | :----------------------------------------------------------: | -| [Gallery](#gallery) - [Support, FAQ](#support-frequently-asked-questions-faq) - [How to help](#how-to-help) - [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) - [Credits](#credits) - [License](#license) | +| [Gallery](#gallery) - [Support, FAQ](#support-frequently-asked-questions-faq) - [How to help](#how-to-help) - **[Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding)** - [Credits](#credits) - [License](#license) | | [Wiki](https://github.com/ocornut/imgui/wiki) - [Extensions](https://github.com/ocornut/imgui/wiki/Useful-Extensions) - [Languages bindings & frameworks backends](https://github.com/ocornut/imgui/wiki/Bindings) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [User quotes](https://github.com/ocornut/imgui/wiki/Quotes) | ### The Pitch @@ -174,7 +174,7 @@ We occasionally tag [Releases](https://github.com/ocornut/imgui/releases) (with **Who uses Dear ImGui?** -See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors), and [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also, see the [Gallery Threads](https://github.com/ocornut/imgui/issues/6897)! +See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding), and [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also, see the [Gallery Threads](https://github.com/ocornut/imgui/issues/6897)! How to help ----------- @@ -184,13 +184,13 @@ How to help - See [GitHub Forum/Issues](https://github.com/ocornut/imgui/issues). - You may help with development and submit pull requests! Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest of the end-users and also to ease the maintainer into understanding and accepting it. - See [Help wanted](https://github.com/ocornut/imgui/wiki/Help-Wanted) on the [Wiki](https://github.com/ocornut/imgui/wiki/) for some more ideas. -- Be a [sponsor](https://github.com/ocornut/imgui/wiki/Sponsors)! Have your company financially support this project via invoiced sponsors/maintenance or by buying a license for [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine) (please reach out: omar AT dearimgui DOT com). +- Be a [Funding Supporter](https://github.com/ocornut/imgui/wiki/Funding)! Have your company financially support this project via invoiced sponsors/maintenance or by buying a license for [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine) (please reach out: omar AT dearimgui DOT com). Sponsors -------- Ongoing Dear ImGui development is and has been financially supported by users and private sponsors. -
Please see the **[detailed list of current and past Dear ImGui supporters](https://github.com/ocornut/imgui/wiki/Sponsors)** for details. +
Please see the **[detailed list of current and past Dear ImGui funding supporters and sponsors](https://github.com/ocornut/imgui/wiki/Funding)** for details.
From November 2014 to December 2019, ongoing development has also been financially supported by its users on Patreon and through individual donations. **THANK YOU to all past and present supporters for helping to keep this project alive and thriving!** @@ -207,7 +207,7 @@ Developed by [Omar Cornut](https://www.miracleworld.net) and every direct or ind Recurring contributors include Rokas Kupstys [@rokups](https://github.com/rokups) (2020-2022): a good portion of work on automation system and regression tests now available in [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine). -Sponsoring, maintenance/support contracts and other B2B transactions are hosted and handled by [Disco Hello](https://www.discohello.com). +Maintenance/support contracts, sponsoring invoices and other B2B transactions are hosted and handled by [Disco Hello](https://www.discohello.com). Omar: "I first discovered the IMGUI paradigm at [Q-Games](https://www.q-games.com) where Atman Binstock had dropped his own simple implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating and improving it." diff --git a/imgui.cpp b/imgui.cpp index c60e89f8bf2e..6a83fd2e75e8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -30,7 +30,7 @@ // See LICENSE.txt for copyright and licensing details (standard MIT License). // This library is free but needs your support to sustain development and maintenance. // Businesses: you can support continued development via B2B invoiced technical support, maintenance and sponsoring contracts. -// PLEASE reach out at omar AT dearimgui DOT com. See https://github.com/ocornut/imgui/wiki/Sponsors +// PLEASE reach out at omar AT dearimgui DOT com. See https://github.com/ocornut/imgui/wiki/Funding // Businesses: you can also purchase licenses for the Dear ImGui Automation/Test Engine. // It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library. @@ -941,7 +941,7 @@ CODE A: - Businesses: please reach out to "omar AT dearimgui DOT com" if you work in a place using Dear ImGui! We can discuss ways for your company to fund development via invoiced technical support, maintenance or sponsoring contacts. This is among the most useful thing you can do for Dear ImGui. With increased funding, we sustain and grow work on this project. - Also see https://github.com/ocornut/imgui/wiki/Sponsors + >>> See https://github.com/ocornut/imgui/wiki/Funding - Businesses: you can also purchase licenses for the Dear ImGui Automation/Test Engine. - If you are experienced with Dear ImGui and C++, look at the GitHub issues, look at the Wiki, and see how you want to help and can help! - Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 635606404938..ed296493ec25 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6351,7 +6351,7 @@ void ImGui::ShowAboutWindow(bool* p_open) 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."); - ImGui::Text("If your company uses this, please consider sponsoring the project!"); + ImGui::Text("If your company uses this, please consider funding the project."); static bool show_config_info = false; ImGui::Checkbox("Config/Build Information", &show_config_info); From 0a1f5b94e3129c1205e99eaa06f983c5abf9ac61 Mon Sep 17 00:00:00 2001 From: Christian Fillion Date: Mon, 18 Mar 2024 02:29:10 -0400 Subject: [PATCH 202/237] Demo: Two minor fixes (unchecked BeginTooltip + incorrect height constraint) (#7410)l --- imgui_demo.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index ed296493ec25..8e8c17c14bae 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2481,9 +2481,7 @@ static void ShowDemoWindowWidgets() { IM_UNUSED(payload); ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed); - ImGui::BeginTooltip(); - ImGui::Text("Cannot drop here!"); - ImGui::EndTooltip(); + ImGui::SetTooltip("Cannot drop here!"); } ImGui::EndDragDropTarget(); } @@ -7789,7 +7787,7 @@ static void ShowExampleAppConstrainedResize(bool* p_open) if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Resize vertical + lock current width if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Resize horizontal + lock current height if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); // Width Between and 400 and 500 - if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 500), ImVec2(-1, FLT_MAX)); // Height at least 400 + if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, FLT_MAX)); // Height at least 400 if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::AspectRatio, (void*)&aspect_ratio); // Aspect ratio if (type == 7) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square if (type == 8) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)&fixed_step); // Fixed Step From 868facff9ded2d61425c67deeba354eb24275bd1 Mon Sep 17 00:00:00 2001 From: cfillion Date: Mon, 18 Mar 2024 04:55:33 -0400 Subject: [PATCH 203/237] ImDrawList: (Breaking) merge float radius_x/radius_y parameters into ImVec2 radius in PathEllipticalArcTo(), AddEllipse(), AddEllipseFilled(). (#2743, #7417) --- docs/CHANGELOG.txt | 4 ++++ imgui.cpp | 1 + imgui.h | 11 +++++++---- imgui_demo.cpp | 4 ++-- imgui_draw.cpp | 25 ++++++++++++------------- 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 48d592182869..20e12f251eea 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -45,6 +45,10 @@ Breaking changes: It has been unnecessary and a no-op since 1.87 (it returns the same value as passed when used with a 1.87+ backend using io.AddKeyEvent() function). (#4921) - IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) --> IsKeyPressed(ImGuiKey_XXX) +- ImDrawList: Merged the radius_x/radius_y parameters in AddEllipse(), AddEllipseFilled() + and PathEllipticalArcTo() into a single ImVec2 parameter. Exceptionally, because those + functions were added in 1.90, we are not adding inline redirection functions. + The transition is easy and should affect few users. (#2743, #7417) [@cfillion] Other changes: diff --git a/imgui.cpp b/imgui.cpp index 6a83fd2e75e8..5d8db20c44a1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -429,6 +429,7 @@ CODE When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2024/03/18 (1.90.5) - merged the radius_x/radius_y parameters in ImDrawList::AddEllipse(), AddEllipseFilled() and PathEllipticalArcTo() into a single ImVec2 parameter. Exceptionally, because those functions were added in 1.90, we are not adding inline redirection functions. The transition is easy and should affect few users. (#2743, #7417) - 2024/03/08 (1.90.5) - inputs: more formally obsoleted GetKeyIndex() when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is set. It has been unnecessary and a no-op since 1.87 (it returns the same value as passed when used with a 1.87+ backend using io.AddKeyEvent() function). (#4921) - IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) -> use IsKeyPressed(ImGuiKey_XXX) - 2024/01/15 (1.90.2) - commented out obsolete ImGuiIO::ImeWindowHandle marked obsolete in 1.87, favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'. diff --git a/imgui.h b/imgui.h index 3918de1165fc..cb833a1c2c75 100644 --- a/imgui.h +++ b/imgui.h @@ -28,7 +28,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.5 WIP" -#define IMGUI_VERSION_NUM 19045 +#define IMGUI_VERSION_NUM 19046 #define IMGUI_HAS_TABLE /* @@ -2754,8 +2754,8 @@ struct ImDrawList IMGUI_API void AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments = 0); IMGUI_API void AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness = 1.0f); IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments); - IMGUI_API void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f); - IMGUI_API void AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0); + IMGUI_API void AddEllipse(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f); + IMGUI_API void AddEllipseFilled(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot = 0.0f, int num_segments = 0); IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL); IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0); // Cubic Bezier (4 control points) @@ -2787,7 +2787,7 @@ struct ImDrawList inline void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, flags, thickness); _Path.Size = 0; } IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 0); IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle - IMGUI_API void PathEllipticalArcTo(const ImVec2& center, float radius_x, float radius_y, float rot, float a_min, float a_max, int num_segments = 0); // Ellipse + IMGUI_API void PathEllipticalArcTo(const ImVec2& center, const ImVec2& radius, float rot, float a_min, float a_max, int num_segments = 0); // Ellipse IMGUI_API void PathBezierCubicCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0); // Cubic Bezier (4 control points) IMGUI_API void PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3, int num_segments = 0); // Quadratic Bezier (3 control points) IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, ImDrawFlags flags = 0); @@ -2820,6 +2820,9 @@ struct ImDrawList inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); } // Write vertex with unique index // Obsolete names + //inline void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f) { AddEllipse(center, ImVec2(radius_x, radius_y), col, rot, num_segments, thickness); } // OBSOLETED in 1.90.5 (Mar 2024) + //inline void AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0) { AddEllipseFilled(center, ImVec2(radius_x, radius_y), col, rot, num_segments); } // OBSOLETED in 1.90.5 (Mar 2024) + //inline void PathEllipticalArcTo(const ImVec2& center, float radius_x, float radius_y, float rot, float a_min, float a_max, int num_segments = 0) { PathEllipticalArcTo(center, ImVec2(radius_x, radius_y), rot, a_min, a_max, num_segments); } // OBSOLETED in 1.90.5 (Mar 2024) //inline void AddBezierCurve(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0) { AddBezierCubic(p1, p2, p3, p4, col, thickness, num_segments); } // OBSOLETED in 1.80 (Jan 2021) //inline void PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0) { PathBezierCubicCurveTo(p2, p3, p4, num_segments); } // OBSOLETED in 1.80 (Jan 2021) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8e8c17c14bae..a191a1df505e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -8053,7 +8053,7 @@ static void ShowExampleAppCustomRendering(bool* p_open) float th = (n == 0) ? 1.0f : thickness; draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // N-gon draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th); x += sz + spacing; // Circle - draw_list->AddEllipse(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, sz*0.3f, col, -0.3f, circle_segments, th); x += sz + spacing; // Ellipse + draw_list->AddEllipse(ImVec2(x + sz*0.5f, y + sz*0.5f), ImVec2(sz*0.5f, sz*0.3f), col, -0.3f, circle_segments, th); x += sz + spacing; // Ellipse draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, ImDrawFlags_None, th); x += sz + spacing; // Square draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, ImDrawFlags_None, th); x += sz + spacing; // Square with all rounded corners draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners @@ -8084,7 +8084,7 @@ static void ShowExampleAppCustomRendering(bool* p_open) // Filled shapes draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, ngon_sides); x += sz + spacing; // N-gon draw_list->AddCircleFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, circle_segments); x += sz + spacing; // Circle - draw_list->AddEllipseFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, sz * 0.3f, col, -0.3f, circle_segments); x += sz + spacing;// Ellipse + draw_list->AddEllipseFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), ImVec2(sz * 0.5f, sz * 0.3f), col, -0.3f, circle_segments); x += sz + spacing;// Ellipse draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col); x += sz + spacing; // Square draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f); x += sz + spacing; // Square with all rounded corners draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br); x += sz + spacing; // Square with two rounded corners diff --git a/imgui_draw.cpp b/imgui_draw.cpp index ad3fda90ecd7..405684f54482 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1218,10 +1218,10 @@ void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, floa } } -void ImDrawList::PathEllipticalArcTo(const ImVec2& center, float radius_x, float radius_y, float rot, float a_min, float a_max, int num_segments) +void ImDrawList::PathEllipticalArcTo(const ImVec2& center, const ImVec2& radius, float rot, float a_min, float a_max, int num_segments) { if (num_segments <= 0) - num_segments = _CalcCircleAutoSegmentCount(ImMax(radius_x, radius_y)); // A bit pessimistic, maybe there's a better computation to do here. + num_segments = _CalcCircleAutoSegmentCount(ImMax(radius.x, radius.y)); // A bit pessimistic, maybe there's a better computation to do here. _Path.reserve(_Path.Size + (num_segments + 1)); @@ -1230,11 +1230,10 @@ void ImDrawList::PathEllipticalArcTo(const ImVec2& center, float radius_x, float for (int i = 0; i <= num_segments; i++) { const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min); - ImVec2 point(ImCos(a) * radius_x, ImSin(a) * radius_y); - const float rel_x = (point.x * cos_rot) - (point.y * sin_rot); - const float rel_y = (point.x * sin_rot) + (point.y * cos_rot); - point.x = rel_x + center.x; - point.y = rel_y + center.y; + ImVec2 point(ImCos(a) * radius.x, ImSin(a) * radius.y); + const ImVec2 rel((point.x * cos_rot) - (point.y * sin_rot), (point.x * sin_rot) + (point.y * cos_rot)); + point.x = rel.x + center.x; + point.y = rel.y + center.y; _Path.push_back(point); } } @@ -1559,31 +1558,31 @@ void ImDrawList::AddNgonFilled(const ImVec2& center, float radius, ImU32 col, in } // Ellipse -void ImDrawList::AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot, int num_segments, float thickness) +void ImDrawList::AddEllipse(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot, int num_segments, float thickness) { if ((col & IM_COL32_A_MASK) == 0) return; if (num_segments <= 0) - num_segments = _CalcCircleAutoSegmentCount(ImMax(radius_x, radius_y)); // A bit pessimistic, maybe there's a better computation to do here. + num_segments = _CalcCircleAutoSegmentCount(ImMax(radius.x, radius.y)); // A bit pessimistic, maybe there's a better computation to do here. // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments; - PathEllipticalArcTo(center, radius_x, radius_y, rot, 0.0f, a_max, num_segments - 1); + PathEllipticalArcTo(center, radius, rot, 0.0f, a_max, num_segments - 1); PathStroke(col, true, thickness); } -void ImDrawList::AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot, int num_segments) +void ImDrawList::AddEllipseFilled(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot, int num_segments) { if ((col & IM_COL32_A_MASK) == 0) return; if (num_segments <= 0) - num_segments = _CalcCircleAutoSegmentCount(ImMax(radius_x, radius_y)); // A bit pessimistic, maybe there's a better computation to do here. + num_segments = _CalcCircleAutoSegmentCount(ImMax(radius.x, radius.y)); // A bit pessimistic, maybe there's a better computation to do here. // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments; - PathEllipticalArcTo(center, radius_x, radius_y, rot, 0.0f, a_max, num_segments - 1); + PathEllipticalArcTo(center, radius, rot, 0.0f, a_max, num_segments - 1); PathFillConvex(col); } From 8be48a44f786dc16163112a6a17d4934ada625f9 Mon Sep 17 00:00:00 2001 From: Elie Michel Date: Mon, 25 Mar 2024 03:10:38 +0100 Subject: [PATCH 204/237] Backends: WebGPU: Avoid using -1u literal (#7436) --- backends/imgui_impl_wgpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h index 9dc3ff290bea..2e19ea36ea9f 100644 --- a/backends/imgui_impl_wgpu.h +++ b/backends/imgui_impl_wgpu.h @@ -32,7 +32,7 @@ struct ImGui_ImplWGPU_InitInfo ImGui_ImplWGPU_InitInfo() { PipelineMultisampleState.count = 1; - PipelineMultisampleState.mask = -1u; + PipelineMultisampleState.mask = UINT32_MAX; PipelineMultisampleState.alphaToCoverageEnabled = false; } }; From 38ddfb24f09f34022d457c71c3a4fbfc7a44c970 Mon Sep 17 00:00:00 2001 From: cfillion Date: Mon, 18 Mar 2024 01:39:36 -0400 Subject: [PATCH 205/237] Tables: Angled headers: fixed border hit box extending beyond non-scrollable tables. (#7416) --- docs/CHANGELOG.txt | 2 ++ imgui_tables.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 20e12f251eea..2399932f9422 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,8 @@ Other changes: - Windows: Scrollbar visibility decision uses current size when both size and contents size are submitted by API. (#7252) - Windows: Double-click to collapse may be disabled via key-ownership mechanism. (#7369) +- Tables: Angled headers: fixed border hit box extending beyond when used within + non-scrollable tables. (#7416) [@cfillion] - Menus, Popups: Fixed an issue where sibling menu popups re-opening in successive frames would erroneously close the window. While it is technically a popup issue it would generally manifest when fast moving the mouse bottom to top in a sub-menu. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 5dbd0972aaf0..b8e0d862829e 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1240,7 +1240,7 @@ void ImGui::TableUpdateBorders(ImGuiTable* table) ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); const float hit_half_width = TABLE_RESIZE_SEPARATOR_HALF_THICKNESS; const float hit_y1 = (table->FreezeRowsCount >= 1 ? table->OuterRect.Min.y : table->WorkRect.Min.y) + table->AngledHeadersHeight; - const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table_instance->LastOuterHeight); + const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table_instance->LastOuterHeight - table->AngledHeadersHeight); const float hit_y2_head = hit_y1 + table_instance->LastTopHeadersRowHeight; for (int order_n = 0; order_n < table->ColumnsCount; order_n++) From 29ff159f941d3ea68512166193bfdf4cc71a8687 Mon Sep 17 00:00:00 2001 From: cfillion Date: Mon, 18 Mar 2024 02:10:46 -0400 Subject: [PATCH 206/237] Tables: Angled headers: fixed borders not moving back up after TableAngleHeadersRow stops being called. (#7416) --- docs/CHANGELOG.txt | 2 ++ imgui_tables.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2399932f9422..a12cdbf1e428 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,6 +57,8 @@ Other changes: - Windows: Double-click to collapse may be disabled via key-ownership mechanism. (#7369) - Tables: Angled headers: fixed border hit box extending beyond when used within non-scrollable tables. (#7416) [@cfillion] +- Tables: Angled headers: fixed borders not moving back up after TableAngleHeadersRow() + stops being called. (#7416) [@cfillion] - Menus, Popups: Fixed an issue where sibling menu popups re-opening in successive frames would erroneously close the window. While it is technically a popup issue it would generally manifest when fast moving the mouse bottom to top in a sub-menu. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index b8e0d862829e..82d1050253db 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -498,6 +498,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG table->DeclColumnsCount = table->AngledHeadersCount = 0; if (previous_frame_active + 1 < g.FrameCount) table->IsActiveIdInTable = false; + table->AngledHeadersHeight = 0.0f; temp_data->AngledHeadersExtraWidth = 0.0f; // Using opaque colors facilitate overlapping lines of the grid, otherwise we'd need to improve TableDrawBorders() From f0802287db52d153d86f9be7a1b9fdc96a84662c Mon Sep 17 00:00:00 2001 From: cfillion Date: Mon, 18 Mar 2024 02:45:38 -0400 Subject: [PATCH 207/237] Tables: Angled headers: fixed table contents overflowing when a list clipper is used. (#7416) --- docs/CHANGELOG.txt | 2 ++ imgui_tables.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a12cdbf1e428..24f3586655a3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -59,6 +59,8 @@ Other changes: non-scrollable tables. (#7416) [@cfillion] - Tables: Angled headers: fixed borders not moving back up after TableAngleHeadersRow() stops being called. (#7416) [@cfillion] +- Tables: Angled headers: rounding header size to nearest integers, fixes some issues + when using clipper. - Menus, Popups: Fixed an issue where sibling menu popups re-opening in successive frames would erroneously close the window. While it is technically a popup issue it would generally manifest when fast moving the mouse bottom to top in a sub-menu. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 82d1050253db..951b2479c763 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -3186,7 +3186,7 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width) // Calculate our base metrics and set angled headers data _before_ the first call to TableNextRow() // FIXME-STYLE: Would it be better for user to submit 'max_label_width' or 'row_height' ? One can be derived from the other. const float header_height = g.FontSize + g.Style.CellPadding.x * 2.0f; - const float row_height = ImFabs(ImRotate(ImVec2(max_label_width, flip_label ? +header_height : -header_height), cos_a, sin_a).y); + const float row_height = ImTrunc(ImFabs(ImRotate(ImVec2(max_label_width, flip_label ? +header_height : -header_height), cos_a, sin_a).y)); table->AngledHeadersHeight = row_height; table->AngledHeadersSlope = (sin_a != 0.0f) ? (cos_a / sin_a) : 0.0f; const ImVec2 header_angled_vector = unit_right * (row_height / -sin_a); // vector from bottom-left to top-left, and from bottom-right to top-right From cf4c10bef74888005c6c80091760d0a2f48a1b92 Mon Sep 17 00:00:00 2001 From: cfillion Date: Sun, 17 Mar 2024 08:48:52 -0400 Subject: [PATCH 208/237] Style: added ImGuiStyleVar_TabBorderSize, ImGuiStyleVar_TableAngledHeadersAngle. (#7411) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 2 ++ imgui.h | 2 ++ 3 files changed, 6 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 24f3586655a3..fcaa4665ca65 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -65,6 +65,8 @@ Other changes: frames would erroneously close the window. While it is technically a popup issue it would generally manifest when fast moving the mouse bottom to top in a sub-menu. (#7325, #7287, #7063) +- Style: Added ImGuiStyleVar_TabBorderSize, ImGuiStyleVar_TableAngledHeadersAngle for + consistency. (#7411) [@cfillion] - DrawList: Added AddConcavePolyFilled(), PathFillConcave() concave filling. (#760) [@thedmd] Note that only simple polygons (no self-intersections, no holes) are supported. - Docs: added more wiki links to headers of imgui.h/imgui.cpp to facilitate discovery diff --git a/imgui.cpp b/imgui.cpp index 5d8db20c44a1..ca0dc4a8f5ce 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3130,7 +3130,9 @@ static const ImGuiDataVarInfo GStyleVarInfo[] = { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding { 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, TableAngledHeadersAngle)},// ImGuiStyleVar_TableAngledHeadersAngle { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, SeparatorTextBorderSize)},// ImGuiStyleVar_SeparatorTextBorderSize diff --git a/imgui.h b/imgui.h index cb833a1c2c75..3dd0a5e2aea0 100644 --- a/imgui.h +++ b/imgui.h @@ -1576,7 +1576,9 @@ enum ImGuiStyleVar_ ImGuiStyleVar_GrabMinSize, // float GrabMinSize ImGuiStyleVar_GrabRounding, // float GrabRounding ImGuiStyleVar_TabRounding, // float TabRounding + ImGuiStyleVar_TabBorderSize, // float TabBorderSize ImGuiStyleVar_TabBarBorderSize, // float TabBarBorderSize + ImGuiStyleVar_TableAngledHeadersAngle,// float TableAngledHeadersAngle ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign ImGuiStyleVar_SeparatorTextBorderSize,// float SeparatorTextBorderSize From 5c5ae806aa1dfac9ebb01984d565fd8fe8b04b94 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 26 Mar 2024 14:15:35 +0900 Subject: [PATCH 209/237] Comments --- imgui.h | 18 ++++++++++++------ imgui_demo.cpp | 5 +++-- imgui_tables.cpp | 5 +++-- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/imgui.h b/imgui.h index 3dd0a5e2aea0..b65b6973c46f 100644 --- a/imgui.h +++ b/imgui.h @@ -175,8 +175,9 @@ struct ImGuiViewport; // A Platform Window (always only one in 'ma // Enumerations // - We don't use strongly typed enums much because they add constraints (can't extend in private code, can't store typed in bit fields, extra casting on iteration) // - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists! -// In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. -// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. +// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. +// - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments. +// - In Visual Studio Code: CTRL+click can follow symbols inside comments. enum ImGuiKey : int; // -> enum ImGuiKey // Enum: A key identifier (ImGuiKey_XXX or ImGuiMod_XXX value) enum ImGuiMouseSource : int; // -> enum ImGuiMouseSource // Enum; A mouse input source identifier (Mouse, TouchScreen, Pen) typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling @@ -191,8 +192,9 @@ typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A // Flags (declared as int to allow using as flags without overhead, and to not pollute the top of this file) // - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists! -// In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. -// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. +// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. +// - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments. +// - In Visual Studio Code: CTRL+click can follow symbols inside comments. typedef int ImDrawFlags; // -> enum ImDrawFlags_ // Flags: for ImDrawList functions typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: for ImDrawList instance typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: for ImFontAtlas build @@ -1547,8 +1549,9 @@ enum ImGuiCol_ // - The enum only refers to fields of ImGuiStyle which makes sense to be pushed/popped inside UI code. // During initialization or between frames, feel free to just poke into ImGuiStyle directly. // - Tip: Use your programming IDE navigation facilities on the names in the _second column_ below to find the actual members and their description. -// In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. -// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. +// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. +// - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments. +// - In Visual Studio Code: CTRL+click can follow symbols inside comments. // - When changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type. enum ImGuiStyleVar_ { @@ -2045,6 +2048,9 @@ struct ImGuiStyle //----------------------------------------------------------------------------- // Communicate most settings and inputs/outputs to Dear ImGui using this structure. // Access via ImGui::GetIO(). Read 'Programmer guide' section in .cpp file for general usage. +// It is generally expected that: +// - initialization: backends and user code writes to ImGuiIO. +// - main loop: backends writes to ImGuiIO, user code and imgui code reads from ImGuiIO. //----------------------------------------------------------------------------- // [Internal] Storage used by IsKeyDown(), IsKeyPressed() etc functions. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a191a1df505e..5c33c0a1f90c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -54,8 +54,9 @@ // Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp. // Navigating this file: -// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. -// - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. +// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. +// - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments. +// - In Visual Studio Code: CTRL+click can follow symbols inside comments. /* diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 951b2479c763..443321cd88d4 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -24,8 +24,9 @@ Index of this file: */ // Navigating this file: -// - In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. -// - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. +// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. +// - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments. +// - In Visual Studio Code: CTRL+click can follow symbols inside comments. //----------------------------------------------------------------------------- // [SECTION] Commentary From 37b37fc2a3ed2fda41cdac42b21b95fe7372202f Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 27 Mar 2024 10:50:55 +0900 Subject: [PATCH 210/237] DrawList: Allow AddText() to accept null ranges. (#3615, 7391) --- docs/CHANGELOG.txt | 1 + imgui.h | 8 ++++---- imgui_demo.cpp | 2 +- imgui_draw.cpp | 5 +++-- imgui_tables.cpp | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index fcaa4665ca65..05b0f9af8ebd 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -69,6 +69,7 @@ Other changes: consistency. (#7411) [@cfillion] - DrawList: Added AddConcavePolyFilled(), PathFillConcave() concave filling. (#760) [@thedmd] Note that only simple polygons (no self-intersections, no holes) are supported. +- DrawList: Allow AddText() to accept null ranges. (#3615, 7391) - Docs: added more wiki links to headers of imgui.h/imgui.cpp to facilitate discovery of interesting resources, because github doesn't allow Wiki to be crawled by search engines. - This is the main wiki: https://github.com/ocornut/imgui/wiki diff --git a/imgui.h b/imgui.h index b65b6973c46f..782bf891f918 100644 --- a/imgui.h +++ b/imgui.h @@ -28,7 +28,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.5 WIP" -#define IMGUI_VERSION_NUM 19046 +#define IMGUI_VERSION_NUM 19047 #define IMGUI_HAS_TABLE /* @@ -177,7 +177,7 @@ struct ImGuiViewport; // A Platform Window (always only one in 'ma // - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists! // - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments. -// - In Visual Studio Code: CTRL+click can follow symbols inside comments. +// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments. enum ImGuiKey : int; // -> enum ImGuiKey // Enum: A key identifier (ImGuiKey_XXX or ImGuiMod_XXX value) enum ImGuiMouseSource : int; // -> enum ImGuiMouseSource // Enum; A mouse input source identifier (Mouse, TouchScreen, Pen) typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling @@ -194,7 +194,7 @@ typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A // - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists! // - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments. -// - In Visual Studio Code: CTRL+click can follow symbols inside comments. +// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments. typedef int ImDrawFlags; // -> enum ImDrawFlags_ // Flags: for ImDrawList functions typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: for ImDrawList instance typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: for ImFontAtlas build @@ -1551,7 +1551,7 @@ enum ImGuiCol_ // - Tip: Use your programming IDE navigation facilities on the names in the _second column_ below to find the actual members and their description. // - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments. -// - In Visual Studio Code: CTRL+click can follow symbols inside comments. +// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments. // - When changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type. enum ImGuiStyleVar_ { diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 5c33c0a1f90c..f739dfabe92c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -56,7 +56,7 @@ // Navigating this file: // - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments. -// - In Visual Studio Code: CTRL+click can follow symbols inside comments. +// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments. /* diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 405684f54482..83e29e10f50d 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1613,10 +1613,11 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, if ((col & IM_COL32_A_MASK) == 0) return; + // Accept null ranges + if (text_begin == text_end || text_begin[0] == 0) + return; if (text_end == NULL) text_end = text_begin + strlen(text_begin); - if (text_begin == text_end) - return; // Pull default font/size from the shared ImDrawListSharedData instance if (font == NULL) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 443321cd88d4..88433da28750 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -26,7 +26,7 @@ Index of this file: // Navigating this file: // - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments. -// - In Visual Studio Code: CTRL+click can follow symbols inside comments. +// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments. //----------------------------------------------------------------------------- // [SECTION] Commentary From 976dc239656295094709f107c8a3e1974328c605 Mon Sep 17 00:00:00 2001 From: cfillion Date: Mon, 25 Mar 2024 10:02:40 -0400 Subject: [PATCH 211/237] Windows: extend outer resize borders to the edges when there are no corner grips. (#7440, #1710) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 05b0f9af8ebd..12aa33f5803c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,8 @@ Other changes: - Windows: Scrollbar visibility decision uses current size when both size and contents size are submitted by API. (#7252) - Windows: Double-click to collapse may be disabled via key-ownership mechanism. (#7369) +- Windows: Extend outer resize borders to the edges when there are no corner grips. + Essentially affects resizable child windows. (#7440, #1710) [@cfillion] - Tables: Angled headers: fixed border hit box extending beyond when used within non-scrollable tables. (#7416) [@cfillion] - Tables: Angled headers: fixed borders not moving back up after TableAngleHeadersRow() diff --git a/imgui.cpp b/imgui.cpp index ca0dc4a8f5ce..c7da9d3a47d3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5901,7 +5901,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si int ret_auto_fit_mask = 0x00; const float grip_draw_size = IM_TRUNC(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); - const float grip_hover_inner_size = IM_TRUNC(grip_draw_size * 0.75f); + const float grip_hover_inner_size = (resize_grip_count > 0) ? IM_TRUNC(grip_draw_size * 0.75f) : 0.0f; const float grip_hover_outer_size = g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_HOVER_PADDING : 0.0f; ImRect clamp_rect = visibility_rect; From 515b437c0845dc696e60aaca890f9ee54903aa95 Mon Sep 17 00:00:00 2001 From: cfillion Date: Mon, 25 Mar 2024 13:31:46 -0400 Subject: [PATCH 212/237] Child windows: look at the parent window's flags to decide whether to clamp child resizes. (#7440, #1710) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 10 ++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 12aa33f5803c..e6f53f105309 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,6 +57,8 @@ Other changes: - Windows: Double-click to collapse may be disabled via key-ownership mechanism. (#7369) - Windows: Extend outer resize borders to the edges when there are no corner grips. Essentially affects resizable child windows. (#7440, #1710) [@cfillion] +- Windows: Resizing logic for child windows evaluates whether per-axis clamping should be + applied based on parent scrollbars, not child scrollbars. (#7440, #1710) [@cfillion] - Tables: Angled headers: fixed border hit box extending beyond when used within non-scrollable tables. (#7416) [@cfillion] - Tables: Angled headers: fixed borders not moving back up after TableAngleHeadersRow() diff --git a/imgui.cpp b/imgui.cpp index c7da9d3a47d3..bf5765b47b6e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6029,10 +6029,12 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si border_target = ImClamp(border_target, clamp_min, clamp_max); if (flags & ImGuiWindowFlags_ChildWindow) // Clamp resizing of childs within parent { - if ((flags & (ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar)) == 0 || (flags & ImGuiWindowFlags_NoScrollbar)) - border_target.x = ImClamp(border_target.x, window->ParentWindow->InnerClipRect.Min.x, window->ParentWindow->InnerClipRect.Max.x); - if (flags & ImGuiWindowFlags_NoScrollbar) - border_target.y = ImClamp(border_target.y, window->ParentWindow->InnerClipRect.Min.y, window->ParentWindow->InnerClipRect.Max.y); + ImGuiWindowFlags parent_flags = window->ParentWindow->Flags; + const ImRect parent_rect = window->ParentWindow->InnerClipRect; + if ((parent_flags & (ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar)) == 0 || (parent_flags & ImGuiWindowFlags_NoScrollbar)) + border_target.x = ImClamp(border_target.x, parent_rect.Min.x, parent_rect.Max.x); + if (parent_flags & ImGuiWindowFlags_NoScrollbar) + border_target.y = ImClamp(border_target.y, parent_rect.Min.y, parent_rect.Max.y); } if (!ignore_resize) CalcResizePosSizeFromAnyCorner(window, border_target, ImMin(def.SegmentN1, def.SegmentN2), &pos_target, &size_target); From 742e53434f4389536b1c723f5d232b7f15415a11 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 27 Mar 2024 11:36:57 +0900 Subject: [PATCH 213/237] Child Windows: adjust resizing limits to match window padding rather than inner clipping rectangle. (#7440) --- docs/CHANGELOG.txt | 9 +++++---- imgui.cpp | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e6f53f105309..74a201a6a206 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,10 +55,11 @@ Other changes: - Windows: Scrollbar visibility decision uses current size when both size and contents size are submitted by API. (#7252) - Windows: Double-click to collapse may be disabled via key-ownership mechanism. (#7369) -- Windows: Extend outer resize borders to the edges when there are no corner grips. - Essentially affects resizable child windows. (#7440, #1710) [@cfillion] -- Windows: Resizing logic for child windows evaluates whether per-axis clamping should be - applied based on parent scrollbars, not child scrollbars. (#7440, #1710) [@cfillion] +- Windows: BeginChild(): Extend outer resize borders to the edges when there are no corner + grips. Essentially affects resizable child windows. (#7440, #1710) [@cfillion] +- Windows: BeginChild(): Resizing logic for child windows evaluates whether per-axis clamping + should be applied based on parent scrollbars, not child scrollbars. (#7440, #1710) [@cfillion] + Adjust those resizing limits to match window padding rather than inner clipping rectangle. - Tables: Angled headers: fixed border hit box extending beyond when used within non-scrollable tables. (#7416) [@cfillion] - Tables: Angled headers: fixed borders not moving back up after TableAngleHeadersRow() diff --git a/imgui.cpp b/imgui.cpp index bf5765b47b6e..5832b502f987 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6030,11 +6030,12 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si if (flags & ImGuiWindowFlags_ChildWindow) // Clamp resizing of childs within parent { ImGuiWindowFlags parent_flags = window->ParentWindow->Flags; - const ImRect parent_rect = window->ParentWindow->InnerClipRect; + ImRect border_limit_rect = window->ParentWindow->InnerRect; + border_limit_rect.Expand(ImVec2(-ImMax(window->WindowPadding.x, window->WindowBorderSize), -ImMax(window->WindowPadding.y, window->WindowBorderSize))); if ((parent_flags & (ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar)) == 0 || (parent_flags & ImGuiWindowFlags_NoScrollbar)) - border_target.x = ImClamp(border_target.x, parent_rect.Min.x, parent_rect.Max.x); + border_target.x = ImClamp(border_target.x, border_limit_rect.Min.x, border_limit_rect.Max.x); if (parent_flags & ImGuiWindowFlags_NoScrollbar) - border_target.y = ImClamp(border_target.y, parent_rect.Min.y, parent_rect.Max.y); + border_target.y = ImClamp(border_target.y, border_limit_rect.Min.y, border_limit_rect.Max.y); } if (!ignore_resize) CalcResizePosSizeFromAnyCorner(window, border_target, ImMin(def.SegmentN1, def.SegmentN2), &pos_target, &size_target); From 9638c2839a12602321be73926aa93fcc0bc37480 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 27 Mar 2024 12:00:50 +0900 Subject: [PATCH 214/237] Internals: adding ImGuiNavMoveFlags_NoClearActiveId even though there's currently no satisfying way to take advantage of it. (#1418) --- imgui.cpp | 6 ++++-- imgui_internal.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5832b502f987..0b0c583c7446 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12303,8 +12303,10 @@ void ImGui::NavMoveRequestApplyResult() g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid; } - // FIXME: Could become optional e.g. ImGuiNavMoveFlags_NoClearActiveId if we later want to apply navigation requests without altering active input. - if (g.ActiveId != result->ID) + // Clear active id unless requested not to + // FIXME: ImGuiNavMoveFlags_NoClearActiveId is currently unused as we don't have a clear strategy to preserve active id after interaction, + // so this is mostly provided as a gateway for further experiments (see #1418, #2890) + if (g.ActiveId != result->ID && (g.NavMoveFlags & ImGuiNavMoveFlags_NoClearActiveId) == 0) ClearActiveID(); // Don't set NavJustMovedToId if just landed on the same spot (which may happen with ImGuiNavMoveFlags_AllowCurrentNavId) diff --git a/imgui_internal.h b/imgui_internal.h index cb2518367a0e..25d85f4f146a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1578,6 +1578,7 @@ enum ImGuiNavMoveFlags_ ImGuiNavMoveFlags_Activate = 1 << 12, // Activate/select target item. ImGuiNavMoveFlags_NoSelect = 1 << 13, // Don't trigger selection by not setting g.NavJustMovedTo ImGuiNavMoveFlags_NoSetNavHighlight = 1 << 14, // Do not alter the visible state of keyboard vs mouse nav highlight + ImGuiNavMoveFlags_NoClearActiveId = 1 << 15, // (Experimental) Do not clear active id when applying move result }; enum ImGuiNavLayer From fd629d7c4873ca8bb6e7592966c7b6e2a23905e1 Mon Sep 17 00:00:00 2001 From: Nick DaCosta Date: Thu, 28 Mar 2024 13:48:18 -0400 Subject: [PATCH 215/237] Removed native child windowing (Windows Only!) --- CMakeLists.txt | 1 - backends/imgui_impl_sdl2.cpp | 138 +---------------------------------- imconfig.h | 6 +- imgui.cpp | 51 ++++--------- imgui.h | 8 +- imgui_widgets.cpp | 11 +-- 6 files changed, 26 insertions(+), 189 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bbbb130e6de..f7a5f3092388 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,6 @@ target_sources( ${CMAKE_CURRENT_SOURCE_DIR}/imgui_tables.cpp ${CMAKE_CURRENT_SOURCE_DIR}/imgui_widgets.cpp ${CMAKE_CURRENT_SOURCE_DIR}/misc/cpp/imgui_stdlib.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/microstrain/NativeChildWindow.cpp ) target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_11) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index e4aa852ca108..7ca700e05859 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -83,13 +83,6 @@ #include "imgui.h" #ifndef IMGUI_DISABLE #include "imgui_impl_sdl2.h" -#include "microstrain/NativeChildWindow.hpp" -#include -#include // Must be after mip command includes due to #define Status - -#if defined __linux__ -#include -#endif // Clang warnings with -Weverything #if defined(__clang__) @@ -855,7 +848,6 @@ struct ImGui_ImplSDL2_ViewportData Uint32 WindowID; bool WindowOwned; SDL_GLContext GLContext; - NativeChildWindow *ChildWindow = nullptr; ImGui_ImplSDL2_ViewportData() { Window = nullptr; WindowID = 0; WindowOwned = false; GLContext = nullptr; } ~ImGui_ImplSDL2_ViewportData() { IM_ASSERT(Window == nullptr && GLContext == nullptr); } }; @@ -892,83 +884,10 @@ static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport) #if SDL_HAS_ALWAYS_ON_TOP sdl_flags |= (viewport->Flags & ImGuiViewportFlags_TopMost) ? SDL_WINDOW_ALWAYS_ON_TOP : 0; #endif - - //Microstrain Custom - if(viewport->Flags & ImGuiViewportFlags_NativeChild) - { - float x_pos = viewport->Pos.x - main_viewport->Pos.x; - float y_pos = viewport->Pos.y - main_viewport->Pos.y; - - NativeChildWindow *child_window = new NativeChildWindow; - - ImGuiViewport *parent_viewport = ImGui::FindViewportByID(viewport->ParentViewportId); - - while (parent_viewport->Flags & ImGuiViewportFlags_NativeChild) - parent_viewport = ImGui::FindViewportByID(parent_viewport->ParentViewportId); - - ImGui_ImplSDL2_ViewportData *parent_viewport_data = (ImGui_ImplSDL2_ViewportData *)parent_viewport->PlatformUserData; - void *parent_ptr = nullptr; - SDL_Window *parent_window = parent_viewport_data->Window; - -#ifdef __linux__ - parent_ptr = parent_window; -#else - if (parent_window != nullptr) - { - SDL_SysWMinfo wmInfo; - SDL_VERSION(&wmInfo.version); - SDL_GetWindowWMInfo(parent_window, &wmInfo); - -#if defined _WIN32 - parent_ptr = wmInfo.info.win.window; -#endif + vd->Window = SDL_CreateWindow("No Title Yet", (int)viewport->Pos.x, (int)viewport->Pos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); -#if defined __APPLE__ - parent_ptr = wmInfo.info.cocoa.window; -#endif - } - else - { - parent_ptr = main_viewport->PlatformHandleRaw; - } - -#endif - - if(child_window->create(parent_ptr, (int)(x_pos), (int)(y_pos), (int)viewport->Size.x, (int)viewport->Size.y)) - { - void *native_child_window = child_window->get(); - -//#ifdef __linux__ - - //SDL_SysWMinfo info = SDL_SysWMinfo(); - //SDL_VERSION(&info.version); - - //vd->Window = (SDL_Window *)native_child_window; -//#else - char address[100]; - - sprintf(address, "%p", (SDL_Window*)main_viewport->PlatformHandle); - SDL_SetHint(SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT, address); - SDL_SetHint(SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL, "1"); - - vd->Window = SDL_CreateWindowFrom(native_child_window); - - child_window->enableHighDpi(); -//#endif - vd->ChildWindow = child_window; - } - else - return; - } - //Standard window creation - else - { - vd->Window = SDL_CreateWindow("No Title Yet", (int)viewport->Pos.x, (int)viewport->Pos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); - } - vd->WindowOwned = true; - if (use_opengl) { vd->GLContext = SDL_GL_CreateContext(vd->Window); @@ -978,10 +897,10 @@ static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport) SDL_GL_MakeCurrent(vd->Window, backup_context); viewport->PlatformHandle = (void*)vd->Window; - + viewport->PlatformHandleRaw = nullptr; + SDL_SysWMinfo info; SDL_VERSION(&info.version); - if (SDL_GetWindowWMInfo(vd->Window, &info)) { #if defined(SDL_VIDEO_DRIVER_WINDOWS) @@ -1000,14 +919,6 @@ static void ImGui_ImplSDL2_DestroyWindow(ImGuiViewport* viewport) SDL_GL_DeleteContext(vd->GLContext); if (vd->Window && vd->WindowOwned) SDL_DestroyWindow(vd->Window); - - if(vd->ChildWindow != nullptr) - { - NativeChildWindow *child_window = (NativeChildWindow *)vd->ChildWindow; - child_window->destroy(); - delete child_window; - } - vd->GLContext = nullptr; vd->Window = nullptr; IM_DELETE(vd); @@ -1053,38 +964,7 @@ static ImVec2 ImGui_ImplSDL2_GetWindowPos(ImGuiViewport* viewport) static void ImGui_ImplSDL2_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos) { ImGui_ImplSDL2_ViewportData* vd = (ImGui_ImplSDL2_ViewportData*)viewport->PlatformUserData; - - int pos_x = (int)pos.x, pos_y = (int)pos.y; - - ImGuiViewport *parent_viewport = ImGui::FindViewportByID(viewport->ParentViewportId); - - while (parent_viewport->Flags & ImGuiViewportFlags_NativeChild) - parent_viewport = ImGui::FindViewportByID(parent_viewport->ParentViewportId); - - //Microstrain edit (use child coordinates for child windows) -#if defined(_WIN32) - if(vd->ChildWindow != nullptr) - { - pos_x = (int)(viewport->Pos.x - parent_viewport->Pos.x); - pos_y = (int)(viewport->Pos.y - parent_viewport->Pos.y); - - SetWindowPos((HWND)vd->ChildWindow->get(), HWND_TOP, pos_x, pos_y, 0, 0, SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOSIZE); - } -#elif defined __linux__ - if(vd->ChildWindow != nullptr) - { - pos_x = viewport->Pos.x - parent_viewport->Pos.x; - pos_y = viewport->Pos.y - parent_viewport->Pos.y; - - if(vd->ChildWindow) - { - vd->ChildWindow->setSize(pos_x, pos_y, viewport->Size.x, viewport->Size.y); - } - } - -#else - SDL_SetWindowPosition(vd->Window, pos_x, pos_y); -#endif + SDL_SetWindowPosition(vd->Window, (int)pos.x, (int)pos.y); } static ImVec2 ImGui_ImplSDL2_GetWindowSize(ImGuiViewport* viewport) @@ -1098,17 +978,7 @@ static ImVec2 ImGui_ImplSDL2_GetWindowSize(ImGuiViewport* viewport) static void ImGui_ImplSDL2_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) { ImGui_ImplSDL2_ViewportData* vd = (ImGui_ImplSDL2_ViewportData*)viewport->PlatformUserData; - - //Microstrain edit (use child coordinates for child windows) -#if defined(_WIN32) - if (vd->ChildWindow != nullptr) - { - SetWindowPos((HWND)vd->ChildWindow->get(), HWND_TOP, 0, 0, size.x, size.y, SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOMOVE); - } -#else - SDL_SetWindowSize(vd->Window, (int)size.x, (int)size.y); -#endif } static void ImGui_ImplSDL2_SetWindowTitle(ImGuiViewport* viewport, const char* title) diff --git a/imconfig.h b/imconfig.h index 156bac137659..306611113816 100644 --- a/imconfig.h +++ b/imconfig.h @@ -23,7 +23,9 @@ // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. // DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. -//#define IMGUI_API __declspec( dllexport ) +#ifdef WIN32_ + #define IMGUI_API __declspec( dllexport ) +#endif //#define IMGUI_API __declspec( dllimport ) //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names. @@ -100,7 +102,7 @@ operator MyVec4() const { return MyVec4(x,y,z,w); } */ //---- ...Or use Dear ImGui's own very basic math operators. -//#define IMGUI_DEFINE_MATH_OPERATORS +#define IMGUI_DEFINE_MATH_OPERATORS //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). diff --git a/imgui.cpp b/imgui.cpp index 11daaf13ec82..528c0266c8fa 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5097,7 +5097,7 @@ static void AddWindowToDrawData(ImGuiWindow* window, int layer) static inline int GetWindowDisplayLayer(ImGuiWindow* window) { - return (window->Flags & ImGuiWindowFlags_Tooltip)? 1 : 0; + return (window->Flags & ImGuiWindowFlags_Tooltip) ? 1 : 0; } // Layer is locked for the root window, however child windows may use a different viewport (e.g. extruding menu) @@ -6082,8 +6082,7 @@ static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_cont ImVec2 size_pad = window->WindowPadding * 2.0f; ImVec2 size_desired = size_contents + size_pad + ImVec2(decoration_w_without_scrollbars, decoration_h_without_scrollbars); - //Microstrain custom! - if ((window->Flags & ImGuiWindowFlags_Tooltip) || (window->Flags & ImGuiWindowFlags_Native_Child_Window)) + if (window->Flags & ImGuiWindowFlags_Tooltip) { // Tooltip always resize return size_desired; @@ -7145,18 +7144,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->Pos = FindBestWindowPosForPopup(window); // Late create viewport if we don't fit within our current host viewport. - //Microstrain custom! if (window->ViewportAllowPlatformMonitorExtend >= 0 && !window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_IsMinimized)) - if (!window->Viewport->GetMainRect().Contains(window->Rect()) || (flags & ImGuiWindowFlags_Native_Child_Window)) + if ((window->WindowClass.ViewportFlagsOverrideSet & ImGuiViewportFlags_NoAutoMerge) || !window->Viewport->GetMainRect().Contains(window->Rect())) { - ImGuiViewportFlags viewport_flags = ImGuiViewportFlags_NoFocusOnAppearing; - - if(flags & ImGuiWindowFlags_Native_Child_Window) - viewport_flags |= ImGuiViewportFlags_NativeChild; - // This is based on the assumption that the DPI will be known ahead (same as the DPI of the selection done in UpdateSelectWindowViewport) //ImGuiViewport* old_viewport = window->Viewport; - window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, viewport_flags); + window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoFocusOnAppearing); // FIXME-DPI //IM_ASSERT(old_viewport->DpiScale == window->Viewport->DpiScale); // FIXME-DPI: Something went wrong @@ -11076,8 +11069,7 @@ bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags ext SetWindowHiddendAndSkipItemsForCurrentFrame(window); ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount); } - //Microstrain custom! - ImGuiWindowFlags flags = ImGuiWindowFlags_Native_Child_Window | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDocking; + ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDocking; Begin(window_name, NULL, flags | extra_window_flags); // 2023-03-09: Added bool return value to the API, but currently always returning true. // If this ever returns false we need to update BeginDragDropSource() accordingly. @@ -11404,9 +11396,7 @@ bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags) g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values return false; } - - //Microstrain Edit - flags |= ImGuiWindowFlags_Native_Child_Window | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings; + flags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings; ImGuiID id = g.CurrentWindow->GetID(str_id); return BeginPopupEx(id, flags); } @@ -14768,12 +14758,6 @@ static void ImGui::WindowSelectViewport(ImGuiWindow* window) ImGuiWindowFlags flags = window->Flags; window->ViewportAllowPlatformMonitorExtend = -1; - ImGuiViewportFlags viewport_flags = ImGuiViewportFlags_None; - - if(flags & ImGuiWindowFlags_Native_Child_Window) - viewport_flags |= ImGuiViewportFlags_NativeChild; - - // Restore main viewport if multi-viewport is not supported by the backend ImGuiViewportP* main_viewport = (ImGuiViewportP*)(void*)GetMainViewport(); if (!(g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)) @@ -14801,12 +14785,10 @@ static void ImGui::WindowSelectViewport(ImGuiWindow* window) { window->Viewport = (ImGuiViewportP*)FindViewportByID(window->ViewportId); if (window->Viewport == NULL && window->ViewportPos.x != FLT_MAX && window->ViewportPos.y != FLT_MAX) - window->Viewport = AddUpdateViewport(window, window->ID, window->ViewportPos, window->Size, viewport_flags); + window->Viewport = AddUpdateViewport(window, window->ID, window->ViewportPos, window->Size, ImGuiViewportFlags_None); } } - - bool lock_viewport = false; if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasViewport) { @@ -14838,12 +14820,12 @@ static void ImGui::WindowSelectViewport(ImGuiWindow* window) } else if (GetWindowAlwaysWantOwnViewport(window)) { - window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, viewport_flags); + window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None); } else if (g.MovingWindow && g.MovingWindow->RootWindowDockTree == window && IsMousePosValid()) { if (window->Viewport != NULL && window->Viewport->Window == window) - window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, viewport_flags); + window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None); } else { @@ -14858,7 +14840,7 @@ static void ImGui::WindowSelectViewport(ImGuiWindow* window) // Fallback: merge in default viewport if z-order matches, otherwise create a new viewport if (window->Viewport == NULL) if (!UpdateTryMergeWindowIntoHostViewport(window, main_viewport)) - window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, viewport_flags); + window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None); // Mark window as allowed to protrude outside of its viewport and into the current monitor if (!lock_viewport) @@ -14890,7 +14872,7 @@ static void ImGui::WindowSelectViewport(ImGuiWindow* window) else if (!UpdateTryMergeWindowIntoHostViewports(window)) // Merge? { // New viewport - window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, viewport_flags | ImGuiViewportFlags_NoFocusOnAppearing); + window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoFocusOnAppearing); } } else if (window->ViewportAllowPlatformMonitorExtend < 0 && (flags & ImGuiWindowFlags_ChildWindow) == 0) @@ -14951,10 +14933,8 @@ void ImGui::WindowSyncOwnedViewport(ImGuiWindow* window, ImGuiWindow* parent_win ImGuiViewportFlags viewport_flags = window->Viewport->Flags & ~viewport_flags_to_clear; ImGuiWindowFlags window_flags = window->Flags; const bool is_modal = (window_flags & ImGuiWindowFlags_Modal) != 0; - - //Microstrain custom! - const bool is_short_lived_floating_window = (window_flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup | ImGuiWindowFlags_Native_Child_Window)) != 0; - if ((window_flags & ImGuiWindowFlags_Tooltip) || (window_flags & ImGuiWindowFlags_Native_Child_Window)) + const bool is_short_lived_floating_window = (window_flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0; + if (window_flags & ImGuiWindowFlags_Tooltip) viewport_flags |= ImGuiViewportFlags_TopMost; if ((g.IO.ConfigViewportsNoTaskBarIcon || is_short_lived_floating_window) && !is_modal) viewport_flags |= ImGuiViewportFlags_NoTaskBarIcon; @@ -15035,11 +15015,6 @@ void ImGui::UpdatePlatformWindows() if (is_new_platform_window) { IMGUI_DEBUG_LOG_VIEWPORT("[viewport] Create Platform Window %08X '%s'\n", viewport->ID, viewport->Window ? viewport->Window->Name : "n/a"); - - //Microstrain Custom Edit - if(viewport->Window->Flags & ImGuiWindowFlags_Native_Child_Window) - viewport->Flags |= ImGuiViewportFlags_NativeChild; - g.PlatformIO.Platform_CreateWindow(viewport); if (g.PlatformIO.Renderer_CreateWindow != NULL) g.PlatformIO.Renderer_CreateWindow(viewport); diff --git a/imgui.h b/imgui.h index 7b3907376fbe..b1fe965d46b1 100644 --- a/imgui.h +++ b/imgui.h @@ -1065,11 +1065,9 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_ChildMenu = 1 << 28, // Don't use! For internal use by BeginMenu() ImGuiWindowFlags_DockNodeHost = 1 << 29, // Don't use! For internal use by Begin()/NewFrame() - // [Microstrain Custom!] - ImGuiWindowFlags_Native_Child_Window = 1 << 30, // Microstrain Custom!!! // Obsolete names #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 31, // Obsoleted in 1.90: Use ImGuiChildFlags_AlwaysUseWindowPadding in BeginChild() call. + ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 30, // Obsoleted in 1.90: Use ImGuiChildFlags_AlwaysUseWindowPadding in BeginChild() call. #endif }; @@ -3242,10 +3240,6 @@ enum ImGuiViewportFlags_ // Output status flags (from Platform) ImGuiViewportFlags_IsMinimized = 1 << 12, // Platform Window: Window is minimized, can skip render. When minimized we tend to avoid using the viewport pos/size for clipping window or testing if they are contained in the viewport. ImGuiViewportFlags_IsFocused = 1 << 13, // Platform Window: Window is focused (last call to Platform_GetWindowFocus() returned true) - - //Microstrain Custom - ImGuiViewportFlags_NativeChild = 1 << 14, // Platform Window: Create window as native child - }; // - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3a4f62268d36..0deaed69bd28 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1805,9 +1805,7 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags } // We don't use BeginPopupEx() solely because we have a custom name string, which we could make an argument to BeginPopupEx() - //Microstrain Edit - ImGuiWindowFlags window_flags = ImGuiWindowFlags_Native_Child_Window | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove; - + ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove; if (flags & ImGuiComboFlags_InputText) { PushStyleVar(ImGuiStyleVar_PopupBorderSize, 0.0f); // The child window only needs a border @@ -7664,10 +7662,9 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu) // The first menu in a hierarchy isn't so hovering doesn't get across (otherwise e.g. resizing borders with ImGuiButtonFlags_FlattenChildren would react), but top-most BeginMenu() will bypass that limitation. - // Microstrain Edit - ImGuiWindowFlags window_flags = ImGuiWindowFlags_Native_Child_Window | ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; - //if (window->Flags & ImGuiWindowFlags_ChildMenu) - // window_flags |= ImGuiWindowFlags_ChildWindow; + ImGuiWindowFlags window_flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; + if (window->Flags & ImGuiWindowFlags_ChildMenu) + window_flags |= ImGuiWindowFlags_ChildWindow; // If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin(). // We are relying on a O(N) search - so O(N log N) over the frame - which seems like the most efficient for the expected small amount of BeginMenu() calls per frame. From 25a492f3307f646a34cc4c159ab846e83003cff6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 29 Mar 2024 19:09:55 +0900 Subject: [PATCH 216/237] ProgressBar: Fixed passing fraction==NaN from leading to a crash. (#7451) --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 74a201a6a206..bc5822f99a8b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -70,6 +70,7 @@ Other changes: frames would erroneously close the window. While it is technically a popup issue it would generally manifest when fast moving the mouse bottom to top in a sub-menu. (#7325, #7287, #7063) +- ProgressBar: Fixed passing fraction==NaN from leading to a crash. (#7451) - Style: Added ImGuiStyleVar_TabBorderSize, ImGuiStyleVar_TableAngledHeadersAngle for consistency. (#7411) [@cfillion] - DrawList: Added AddConcavePolyFilled(), PathFillConcave() concave filling. (#760) [@thedmd] diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d83a080f5496..f1ffbf0f529f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1288,12 +1288,15 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over if (!ItemAdd(bb, 0)) return; - // Render + // Out of courtesy we accept a NaN fraction without crashing fraction = ImSaturate(fraction); + const float fraction_not_nan = (fraction == fraction) ? fraction : 0.0f; + + // Render RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize)); - const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y); - RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction, style.FrameRounding); + const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction_not_nan), bb.Max.y); + RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction_not_nan, style.FrameRounding); // Default displaying the fraction as percentage string, but user can override it char overlay_buf[32]; From d3c3514a59bb31406c954c2b525f330e9d167845 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 29 Mar 2024 19:39:05 +0900 Subject: [PATCH 217/237] Tables: Fixed auto-width columns when using synced-instances of same table. (#7218) --- docs/CHANGELOG.txt | 2 ++ imgui_demo.cpp | 1 + imgui_tables.cpp | 19 +++++++++++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bc5822f99a8b..4d783dc03634 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -60,6 +60,8 @@ Other changes: - Windows: BeginChild(): Resizing logic for child windows evaluates whether per-axis clamping should be applied based on parent scrollbars, not child scrollbars. (#7440, #1710) [@cfillion] Adjust those resizing limits to match window padding rather than inner clipping rectangle. +- Tables: Fixed auto-width columns when using synced-instances of same table, width of + one instance would bleed into next one instead of sharing their widths. (#7218) - Tables: Angled headers: fixed border hit box extending beyond when used within non-scrollable tables. (#7416) [@cfillion] - Tables: Angled headers: fixed borders not moving back up after TableAngleHeadersRow() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index f739dfabe92c..7297d5e7c707 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -5478,6 +5478,7 @@ static void ShowDemoWindowTables() HelpMarker("Multiple tables with the same identifier will share their settings, width, visibility, order etc."); static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoSavedSettings; + ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY); ImGui::CheckboxFlags("ImGuiTableFlags_SizingFixedFit", &flags, ImGuiTableFlags_SizingFixedFit); ImGui::CheckboxFlags("ImGuiTableFlags_HighlightHoveredColumn", &flags, ImGuiTableFlags_HighlightHoveredColumn); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 88433da28750..1fe1a721b3e7 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1068,6 +1068,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // - ClipRect.Max.x: using WorkMaxX instead of MaxX (aka including padding) makes things more consistent when resizing down, tho slightly detrimental to visibility in very-small column. // - ClipRect.Max.x: using MaxX makes it easier for header to receive hover highlight with no discontinuity and display sorting arrow. // - FIXME-TABLE: We want equal width columns to have equal (ClipRect.Max.x - WorkMinX) width, which means ClipRect.max.x cannot stray off host_clip_rect.Max.x else right-most column may appear shorter. + const float previous_instance_work_min_x = column->WorkMinX; column->WorkMinX = column->MinX + table->CellPaddingX + table->CellSpacingX1; column->WorkMaxX = column->MaxX - table->CellPaddingX - table->CellSpacingX2; // Expected max column->ItemWidth = ImTrunc(column->WidthGiven * 0.65f); @@ -1120,8 +1121,22 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // column->WorkMinX = ImLerp(column->WorkMinX, ImMax(column->StartX, column->MaxX - column->ContentWidthRowsUnfrozen), 0.5f); // Reset content width variables - column->ContentMaxXFrozen = column->ContentMaxXUnfrozen = column->WorkMinX; - column->ContentMaxXHeadersUsed = column->ContentMaxXHeadersIdeal = column->WorkMinX; + if (table->InstanceCurrent == 0) + { + column->ContentMaxXFrozen = column->WorkMinX; + column->ContentMaxXUnfrozen = column->WorkMinX; + column->ContentMaxXHeadersUsed = column->WorkMinX; + column->ContentMaxXHeadersIdeal = column->WorkMinX; + } + else + { + // As we store an absolute value to make per-cell updates faster, we need to offset values used for width computation. + const float offset_from_previous_instance = column->WorkMinX - previous_instance_work_min_x; + column->ContentMaxXFrozen += offset_from_previous_instance; + column->ContentMaxXUnfrozen += offset_from_previous_instance; + column->ContentMaxXHeadersUsed += offset_from_previous_instance; + column->ContentMaxXHeadersIdeal += offset_from_previous_instance; + } // Don't decrement auto-fit counters until container window got a chance to submit its items if (table->HostSkipItems == false) From 9a2b598ec1eeadd316650bc3081c735d0b6e15a4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Apr 2024 10:18:49 +0900 Subject: [PATCH 218/237] ListBox: Fixed text-baseline offset when using SameLine()+Text() after a labeled ListBox(). Visible in demo->basic->listbox --- docs/CHANGELOG.txt | 1 + imgui_demo.cpp | 2 ++ imgui_widgets.cpp | 1 + 3 files changed, 4 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4d783dc03634..45339c010591 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -73,6 +73,7 @@ Other changes: it would generally manifest when fast moving the mouse bottom to top in a sub-menu. (#7325, #7287, #7063) - ProgressBar: Fixed passing fraction==NaN from leading to a crash. (#7451) +- ListBox: Fixed text-baseline offset when using SameLine()+Text() after a labeled ListBox(). - Style: Added ImGuiStyleVar_TabBorderSize, ImGuiStyleVar_TableAngledHeadersAngle for consistency. (#7411) [@cfillion] - DrawList: Added AddConcavePolyFilled(), PathFillConcave() concave filling. (#760) [@thedmd] diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 7297d5e7c707..ad0be025a5f5 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1289,6 +1289,7 @@ static void ShowDemoWindowWidgets() } ImGui::EndListBox(); } + ImGui::SameLine(); HelpMarker("Here we are sharing selection state between both boxes."); // Custom size: use all width, 5 items tall ImGui::Text("Full-width:"); @@ -1823,6 +1824,7 @@ static void ShowDemoWindowWidgets() static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f }; ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr)); ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f)); + //ImGui::SameLine(); HelpMarker("Consider using ImPlot instead!"); // Fill an array of contiguous float values to plot // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f1ffbf0f529f..c8ac26625edb 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6930,6 +6930,7 @@ bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg) ImVec2 label_pos = ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y); RenderText(label_pos, label); window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, label_pos + label_size); + AlignTextToFramePadding(); } BeginChild(id, frame_bb.GetSize(), ImGuiChildFlags_FrameStyle); From 0bf134a8e2ef0b00d1070e4c8a30e552168cc74d Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Apr 2024 10:42:57 +0900 Subject: [PATCH 219/237] Refactor moving ID stack functions to their own section. --- imgui.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0b0c583c7446..1d555591667e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -77,6 +77,7 @@ CODE // [SECTION] RENDER HELPERS // [SECTION] INITIALIZATION, SHUTDOWN // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!) +// [SECTION] ID STACK // [SECTION] INPUTS // [SECTION] ERROR CHECKING // [SECTION] ITEM SUBMISSION @@ -7983,6 +7984,22 @@ ImGuiStorage* ImGui::GetStateStorage() return window->DC.StateStorage; } +bool ImGui::IsRectVisible(const ImVec2& size) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size)); +} + +bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->ClipRect.Overlaps(ImRect(rect_min, rect_max)); +} + +//----------------------------------------------------------------------------- +// [SECTION] ID STACK +//----------------------------------------------------------------------------- + void ImGui::PushID(const char* str_id) { ImGuiContext& g = *GImGui; @@ -8071,19 +8088,6 @@ ImGuiID ImGui::GetID(const void* ptr_id) return window->GetID(ptr_id); } -bool ImGui::IsRectVisible(const ImVec2& size) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size)); -} - -bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->ClipRect.Overlaps(ImRect(rect_min, rect_max)); -} - - //----------------------------------------------------------------------------- // [SECTION] INPUTS //----------------------------------------------------------------------------- From f959c417fecf49a98acbabbfacab65a651c81e7d Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Apr 2024 10:47:15 +0900 Subject: [PATCH 220/237] Refactor moving ID stack functions to their own section (part 2) --- imgui.cpp | 80 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1d555591667e..64655f15d07b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3782,45 +3782,6 @@ ImGuiWindow::~ImGuiWindow() ColumnsStorage.clear_destruct(); } -ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) -{ - ImGuiID seed = IDStack.back(); - ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed); - ImGuiContext& g = *Ctx; - if (g.DebugHookIdInfo == id) - ImGui::DebugHookIdInfo(id, ImGuiDataType_String, str, str_end); - return id; -} - -ImGuiID ImGuiWindow::GetID(const void* ptr) -{ - ImGuiID seed = IDStack.back(); - ImGuiID id = ImHashData(&ptr, sizeof(void*), seed); - ImGuiContext& g = *Ctx; - if (g.DebugHookIdInfo == id) - ImGui::DebugHookIdInfo(id, ImGuiDataType_Pointer, ptr, NULL); - return id; -} - -ImGuiID ImGuiWindow::GetID(int n) -{ - ImGuiID seed = IDStack.back(); - ImGuiID id = ImHashData(&n, sizeof(n), seed); - ImGuiContext& g = *Ctx; - if (g.DebugHookIdInfo == id) - ImGui::DebugHookIdInfo(id, ImGuiDataType_S32, (void*)(intptr_t)n, NULL); - return id; -} - -// This is only used in rare/specific situations to manufacture an ID out of nowhere. -ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs) -{ - ImGuiID seed = IDStack.back(); - ImRect r_rel = ImGui::WindowRectAbsToRel(this, r_abs); - ImGuiID id = ImHashData(&r_rel, sizeof(r_rel), seed); - return id; -} - static void SetCurrentWindow(ImGuiWindow* window) { ImGuiContext& g = *GImGui; @@ -8000,6 +7961,47 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) // [SECTION] ID STACK //----------------------------------------------------------------------------- +// 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. +ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) +{ + ImGuiID seed = IDStack.back(); + ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed); + ImGuiContext& g = *Ctx; + if (g.DebugHookIdInfo == id) + ImGui::DebugHookIdInfo(id, ImGuiDataType_String, str, str_end); + return id; +} + +ImGuiID ImGuiWindow::GetID(const void* ptr) +{ + ImGuiID seed = IDStack.back(); + ImGuiID id = ImHashData(&ptr, sizeof(void*), seed); + ImGuiContext& g = *Ctx; + if (g.DebugHookIdInfo == id) + ImGui::DebugHookIdInfo(id, ImGuiDataType_Pointer, ptr, NULL); + return id; +} + +ImGuiID ImGuiWindow::GetID(int n) +{ + ImGuiID seed = IDStack.back(); + ImGuiID id = ImHashData(&n, sizeof(n), seed); + ImGuiContext& g = *Ctx; + if (g.DebugHookIdInfo == id) + ImGui::DebugHookIdInfo(id, ImGuiDataType_S32, (void*)(intptr_t)n, NULL); + return id; +} + +// This is only used in rare/specific situations to manufacture an ID out of nowhere. +ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs) +{ + ImGuiID seed = IDStack.back(); + ImRect r_rel = ImGui::WindowRectAbsToRel(this, r_abs); + ImGuiID id = ImHashData(&r_rel, sizeof(r_rel), seed); + return id; +} + void ImGui::PushID(const char* str_id) { ImGuiContext& g = *GImGui; From e7712ff103dc8c15212f884f90d3f6a662726d1c Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Apr 2024 10:50:32 +0900 Subject: [PATCH 221/237] Out of courtesy/consistency move all the DebugHookIdInfo compares into ifndef block. --- imgui.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 64655f15d07b..e3d20a943812 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7967,9 +7967,11 @@ ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) { ImGuiID seed = IDStack.back(); ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed); +#ifndef IMGUI_DISABLE_DEBUG_TOOLS ImGuiContext& g = *Ctx; if (g.DebugHookIdInfo == id) ImGui::DebugHookIdInfo(id, ImGuiDataType_String, str, str_end); +#endif return id; } @@ -7977,9 +7979,11 @@ ImGuiID ImGuiWindow::GetID(const void* ptr) { ImGuiID seed = IDStack.back(); ImGuiID id = ImHashData(&ptr, sizeof(void*), seed); +#ifndef IMGUI_DISABLE_DEBUG_TOOLS ImGuiContext& g = *Ctx; if (g.DebugHookIdInfo == id) ImGui::DebugHookIdInfo(id, ImGuiDataType_Pointer, ptr, NULL); +#endif return id; } @@ -7987,9 +7991,11 @@ ImGuiID ImGuiWindow::GetID(int n) { ImGuiID seed = IDStack.back(); ImGuiID id = ImHashData(&n, sizeof(n), seed); +#ifndef IMGUI_DISABLE_DEBUG_TOOLS ImGuiContext& g = *Ctx; if (g.DebugHookIdInfo == id) ImGui::DebugHookIdInfo(id, ImGuiDataType_S32, (void*)(intptr_t)n, NULL); +#endif return id; } @@ -8039,8 +8045,10 @@ void ImGui::PushOverrideID(ImGuiID id) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; +#ifndef IMGUI_DISABLE_DEBUG_TOOLS if (g.DebugHookIdInfo == id) DebugHookIdInfo(id, ImGuiDataType_ID, NULL, NULL); +#endif window->IDStack.push_back(id); } @@ -8050,18 +8058,22 @@ void ImGui::PushOverrideID(ImGuiID id) ImGuiID ImGui::GetIDWithSeed(const char* str, const char* str_end, ImGuiID seed) { ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed); +#ifndef IMGUI_DISABLE_DEBUG_TOOLS ImGuiContext& g = *GImGui; if (g.DebugHookIdInfo == id) DebugHookIdInfo(id, ImGuiDataType_String, str, str_end); +#endif return id; } ImGuiID ImGui::GetIDWithSeed(int n, ImGuiID seed) { ImGuiID id = ImHashData(&n, sizeof(n), seed); +#ifndef IMGUI_DISABLE_DEBUG_TOOLS ImGuiContext& g = *GImGui; if (g.DebugHookIdInfo == id) DebugHookIdInfo(id, ImGuiDataType_S32, (void*)(intptr_t)n, NULL); +#endif return id; } From 4f9ba19e520bea478f5cb654d37ef45e6404bd52 Mon Sep 17 00:00:00 2001 From: GamingMinds-DanielC Date: Mon, 11 Mar 2024 16:35:27 +0100 Subject: [PATCH 222/237] Drags, Sliders, Inputs: Reactivated decimal point replacement for SliderScalar and DragScalar. (#7389, #6719, #2278) Amend/fix 4a242644 --- docs/CHANGELOG.txt | 2 ++ imgui_internal.h | 1 + imgui_widgets.cpp | 7 ++++--- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 45339c010591..d38b347e5bca 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -74,6 +74,8 @@ Other changes: (#7325, #7287, #7063) - ProgressBar: Fixed passing fraction==NaN from leading to a crash. (#7451) - ListBox: Fixed text-baseline offset when using SameLine()+Text() after a labeled ListBox(). +- Drags, Sliders, Inputs: Fixed io.PlatformLocaleDecimalPoint decimal point localization + feature not working regression from 1.90.1. (#7389, #6719, #2278) [@GamingMinds-DanielC] - Style: Added ImGuiStyleVar_TabBorderSize, ImGuiStyleVar_TableAngledHeadersAngle for consistency. (#7411) [@cfillion] - DrawList: Added AddConcavePolyFilled(), PathFillConcave() concave filling. (#760) [@thedmd] diff --git a/imgui_internal.h b/imgui_internal.h index 25d85f4f146a..813d6add8656 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -864,6 +864,7 @@ enum ImGuiInputTextFlagsPrivate_ ImGuiInputTextFlags_Multiline = 1 << 26, // For internal use by InputTextMultiline() ImGuiInputTextFlags_NoMarkEdited = 1 << 27, // For internal use by functions using InputText() before reformatting data ImGuiInputTextFlags_MergedItem = 1 << 28, // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match. + ImGuiInputTextFlags_LocalizeDecimalPoint= 1 << 29, // For internal use by InputScalar() and TempInputScalar() }; // Extend ImGuiButtonFlags_ diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c8ac26625edb..cf13660ba2f0 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3429,7 +3429,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format); ImStrTrimBlanks(data_buf); - ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; + ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint; bool value_changed = false; if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags)) @@ -3474,6 +3474,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format); flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string. + flags |= (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint; bool value_changed = false; if (p_step == NULL) @@ -3951,7 +3952,7 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im return false; // Generic named filters - if (apply_named_filters && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific))) + if (apply_named_filters && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint))) { // The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf to use e.g. ',' instead of '.'. // The standard mandate that programs starts in the "C" locale where the decimal point is '.'. @@ -3961,7 +3962,7 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im // Users of non-default decimal point (in particular ',') may be affected by word-selection logic (is_word_boundary_from_right/is_word_boundary_from_left) functions. ImGuiContext& g = *ctx; const unsigned c_decimal_point = (unsigned int)g.IO.PlatformLocaleDecimalPoint; - if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific)) + if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint)) if (c == '.' || c == ',') c = c_decimal_point; From 231cbee0fc4f59dbe5b8b853a11b08dc84e57c65 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 11 Apr 2024 15:45:27 +0200 Subject: [PATCH 223/237] Version 1.90.5 --- docs/CHANGELOG.txt | 8 +++++--- imgui.cpp | 4 ++-- imgui.h | 8 ++++---- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 16 insertions(+), 14 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d38b347e5bca..2c33cb2be54a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -36,9 +36,11 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 1.90.5 WIP (In Progress) + VERSION 1.90.5 (Released 2024-04-11) ----------------------------------------------------------------------- +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90.5 + Breaking changes: - More formally obsoleted GetKeyIndex() when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is set. @@ -47,7 +49,7 @@ Breaking changes: - IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) --> IsKeyPressed(ImGuiKey_XXX) - ImDrawList: Merged the radius_x/radius_y parameters in AddEllipse(), AddEllipseFilled() and PathEllipticalArcTo() into a single ImVec2 parameter. Exceptionally, because those - functions were added in 1.90, we are not adding inline redirection functions. + functions were added recently in 1.90, we are not adding inline redirection functions. The transition is easy and should affect few users. (#2743, #7417) [@cfillion] Other changes: @@ -85,7 +87,7 @@ Other changes: of interesting resources, because github doesn't allow Wiki to be crawled by search engines. - This is the main wiki: https://github.com/ocornut/imgui/wiki - This is the crawlable version: https://github-wiki-see.page/m/ocornut/imgui/wiki - Adding a link to the crawlable version, even though it is not indended for humans, + Adding a link to the crawlable version, even though it is not intended for humans, to increase its search rank. diff --git a/imgui.cpp b/imgui.cpp index e3d20a943812..daa389b1341b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.5 WIP +// dear imgui, v1.90.5 // (main code and documentation) // Help: @@ -1204,7 +1204,7 @@ ImGuiStyle::ImGuiStyle() FrameBorderSize = 0.0f; // Thickness of border around frames. Generally set to 0.0f or 1.0f. Other values not well tested. ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) - CellPadding = ImVec2(4,2); // Padding within a table cell. CellPadding.y may be altered between different rows. + CellPadding = ImVec2(4,2); // Padding within a table cell. Cellpadding.x is locked for entire table. CellPadding.y may be altered between different rows. TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1). diff --git a/imgui.h b/imgui.h index 782bf891f918..73aceb2ce480 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.5 WIP +// dear imgui, v1.90.5 // (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.5 WIP" -#define IMGUI_VERSION_NUM 19047 +#define IMGUI_VERSION "1.90.5" +#define IMGUI_VERSION_NUM 19050 #define IMGUI_HAS_TABLE /* @@ -2001,7 +2001,7 @@ struct ImGuiStyle float FrameBorderSize; // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines. ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label). - ImVec2 CellPadding; // Padding within a table cell. CellPadding.y may be altered between different rows. + ImVec2 CellPadding; // Padding within a table cell. Cellpadding.x is locked for entire table. CellPadding.y may be altered between different rows. ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). float ColumnsMinSpacing; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1). diff --git a/imgui_demo.cpp b/imgui_demo.cpp index ad0be025a5f5..356f71ae2c47 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.5 WIP +// dear imgui, v1.90.5 // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 83e29e10f50d..eded4ffad0f4 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.5 WIP +// dear imgui, v1.90.5 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 813d6add8656..55399f8d20f9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.5 WIP +// dear imgui, v1.90.5 // (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. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 1fe1a721b3e7..676c3b4e9a64 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.5 WIP +// dear imgui, v1.90.5 // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index cf13660ba2f0..aec4d51efe5e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.5 WIP +// dear imgui, v1.90.5 // (widgets code) /* From f790d516652d269989d90ef3c4ce3880f50c2a6c Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 12 Apr 2024 16:55:32 +0200 Subject: [PATCH 224/237] Silent zealous/stupid warning introduced by Clang 16 (shipping with VS2022) with -Weverything. Pointers are now illegal! --- imgui.cpp | 1 + imgui.h | 1 + imgui_demo.cpp | 1 + imgui_draw.cpp | 1 + imgui_internal.h | 2 ++ imgui_tables.cpp | 1 + imgui_widgets.cpp | 1 + 7 files changed, 8 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index daa389b1341b..953d7c2940b6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1034,6 +1034,7 @@ CODE #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 "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision +#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access #elif defined(__GNUC__) // We disable -Wpragmas because GCC doesn't provide a has_warning equivalent and some forks/patches may not follow the warning/version association. #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind diff --git a/imgui.h b/imgui.h index 73aceb2ce480..ab153e93bdad 100644 --- a/imgui.h +++ b/imgui.h @@ -130,6 +130,7 @@ Index of this file: #pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" #pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter +#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access #elif defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 356f71ae2c47..e83e7b567e97 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -131,6 +131,7 @@ Index of this file: #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 "-Wreserved-id-macro" // warning: macro name is a reserved identifier #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision +#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size diff --git a/imgui_draw.cpp b/imgui_draw.cpp index eded4ffad0f4..641aed66aebf 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -65,6 +65,7 @@ Index of this file: #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 "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter +#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used diff --git a/imgui_internal.h b/imgui_internal.h index 55399f8d20f9..940101b2d5ef 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -87,6 +87,8 @@ Index of this file: #pragma clang diagnostic ignored "-Wdouble-promotion" #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #pragma clang diagnostic ignored "-Wmissing-noreturn" // warning: function 'xxx' could be declared with attribute 'noreturn' +#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated +#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access #elif defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 676c3b4e9a64..16afee485ca8 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -228,6 +228,7 @@ Index of this file: #pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') #pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision +#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index aec4d51efe5e..964d77f32550 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -75,6 +75,7 @@ Index of this file: #pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') #pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision +#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked From 76bc1b825e6347bd01a6215b7f16e7d235a7fa2b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Apr 2024 11:24:43 +0200 Subject: [PATCH 225/237] Extracted part of NewFrame() into SetupDrawListSharedData() for documentation purpose. (#7495, #6406) Also changed g.Font->ContainerAtlas->Flags to g.IO.Fonts->Flags --- imgui.cpp | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 953d7c2940b6..fb0bd04ffc46 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4525,6 +4525,27 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags() io.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false; } +// Calling SetupDrawListSharedData() is followed by SetCurrentFont() which sets up the remaining data. +static void SetupDrawListSharedData() +{ + ImGuiContext& g = *GImGui; + ImRect virtual_space(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); + for (ImGuiViewportP* viewport : g.Viewports) + virtual_space.Add(viewport->GetMainRect()); + g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4(); + g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol; + g.DrawListSharedData.SetCircleTessellationMaxError(g.Style.CircleTessellationMaxError); + g.DrawListSharedData.InitialFlags = ImDrawListFlags_None; + if (g.Style.AntiAliasedLines) + g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines; + if (g.Style.AntiAliasedLinesUseTex && !(g.IO.Fonts->Flags & ImFontAtlasFlags_NoBakedLines)) + g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLinesUseTex; + if (g.Style.AntiAliasedFill) + g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill; + if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) + g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset; +} + void ImGui::NewFrame() { IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?"); @@ -4567,23 +4588,9 @@ void ImGui::NewFrame() // Setup current font and draw list shared data g.IO.Fonts->Locked = true; + SetupDrawListSharedData(); SetCurrentFont(GetDefaultFont()); IM_ASSERT(g.Font->IsLoaded()); - ImRect virtual_space(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); - for (ImGuiViewportP* viewport : g.Viewports) - virtual_space.Add(viewport->GetMainRect()); - g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4(); - g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol; - g.DrawListSharedData.SetCircleTessellationMaxError(g.Style.CircleTessellationMaxError); - g.DrawListSharedData.InitialFlags = ImDrawListFlags_None; - if (g.Style.AntiAliasedLines) - g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines; - if (g.Style.AntiAliasedLinesUseTex && !(g.Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedLines)) - g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLinesUseTex; - if (g.Style.AntiAliasedFill) - g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill; - if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) - g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset; // Mark rendering data as invalid to prevent user who may have a handle on it to use it. for (ImGuiViewportP* viewport : g.Viewports) From 3caa79c8a530466924ae53eb199bbe4dbe7a7a87 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Apr 2024 11:27:07 +0200 Subject: [PATCH 226/237] Version 1.90.6 WIP --- docs/CHANGELOG.txt | 9 +++++++++ imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 18 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2c33cb2be54a..2be92d3efd34 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,15 @@ HOW TO UPDATE? and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users. - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.90.6 WIP (In Progress) +----------------------------------------------------------------------- + +Breaking changes: + +Other changes: + + ----------------------------------------------------------------------- VERSION 1.90.5 (Released 2024-04-11) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index fb0bd04ffc46..668cd34fd054 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.5 +// dear imgui, v1.90.6 WIP // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index ab153e93bdad..551e687df173 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.5 +// dear imgui, v1.90.6 WIP // (headers) // Help: @@ -27,8 +27,8 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') -#define IMGUI_VERSION "1.90.5" -#define IMGUI_VERSION_NUM 19050 +#define IMGUI_VERSION "1.90.6 WIP" +#define IMGUI_VERSION_NUM 19051 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index e83e7b567e97..b4929f603aaa 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.5 +// dear imgui, v1.90.6 WIP // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 641aed66aebf..93be40cc7900 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.5 +// dear imgui, v1.90.6 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 940101b2d5ef..7c9a9924fedf 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.90.5 +// dear imgui, v1.90.6 WIP // (internal structures/api) // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 16afee485ca8..299986902aba 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.5 +// dear imgui, v1.90.6 WIP // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 964d77f32550..7dc52bb72caa 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.90.5 +// dear imgui, v1.90.6 WIP // (widgets code) /* From c1743eef48432a08438de0926a6fc657e5ce2d11 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Apr 2024 11:42:51 +0200 Subject: [PATCH 227/237] Docking: when io.ConfigDockingWithShift is enabled, fixed help tooltip erroneously reading SetNextWindowXXX() data. (#6709, #4643, #7491) --- docs/CHANGELOG.txt | 14 ++++++++++++++ imgui.cpp | 6 +++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b014d039f409..8ef1744bd24f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,20 @@ HOW TO UPDATE? and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users. - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.90.6 WIP (In Progress) +----------------------------------------------------------------------- + +Breaking changes: + +Other changes: + +Docking+Viewports Branch: + +- Docking: when io.ConfigDockingWithShift is enabled, fixed help tooltip erroneously + reading SetNextWindowXXX() data. (#6709, #4643, #7491) [@ocornut, @cfillion] + + ----------------------------------------------------------------------- VERSION 1.90.5 (Released 2024-04-11) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index d74843d7d286..1e3cce9b49da 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7445,6 +7445,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (window->AutoFitFramesY > 0) window->AutoFitFramesY--; + // Clear SetNextWindowXXX data (can aim to move this higher in the function) + g.NextWindowData.ClearFlags(); + // Apply focus (we need to call FocusWindow() AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there) // We ImGuiFocusRequestFlags_UnlessBelowModal to: // - Avoid focusing a window that is created outside of a modal. This will prevent active modal from being closed. @@ -7517,6 +7520,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Append SetCurrentViewport(window, window->Viewport); SetCurrentWindow(window); + g.NextWindowData.ClearFlags(); } if (!(flags & ImGuiWindowFlags_DockNodeHost)) @@ -7525,7 +7529,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused) window->WriteAccessed = false; window->BeginCount++; - g.NextWindowData.ClearFlags(); // Update visibility if (first_begin_of_the_frame) @@ -19143,6 +19146,7 @@ void ImGui::BeginDockableDragDropSource(ImGuiWindow* window) // When ConfigDockingWithShift is set, display a tooltip to increase UI affordance. // We cannot set for HoveredWindowUnderMovingWindow != NULL here, as it is only valid/useful when drag and drop is already active // (because of the 'is_mouse_dragging_with_an_expected_destination' logic in UpdateViewportsNewFrame() function) + IM_ASSERT(g.NextWindowData.Flags == 0); if (g.IO.ConfigDockingWithShift && g.MouseStationaryTimer >= 1.0f && g.ActiveId >= 1.0f) SetTooltip("%s", LocalizeGetMsg(ImGuiLocKey_DockingHoldShiftToDock)); return; From dad1689bf7b1cfb9cca4f0f10f3c4f4b3eaea326 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Apr 2024 12:08:07 +0200 Subject: [PATCH 228/237] Examples: SDL3: amend for removal of SDL_RENDERER_ACCELERATED. --- examples/example_sdl3_sdlrenderer3/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_sdl3_sdlrenderer3/main.cpp b/examples/example_sdl3_sdlrenderer3/main.cpp index 9740054e5173..0f2200a2576f 100644 --- a/examples/example_sdl3_sdlrenderer3/main.cpp +++ b/examples/example_sdl3_sdlrenderer3/main.cpp @@ -42,7 +42,7 @@ int main(int, char**) printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); return -1; } - SDL_Renderer* renderer = SDL_CreateRenderer(window, nullptr, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + SDL_Renderer* renderer = SDL_CreateRenderer(window, nullptr, SDL_RENDERER_PRESENTVSYNC); if (renderer == nullptr) { SDL_Log("Error: SDL_CreateRenderer(): %s\n", SDL_GetError()); From fab96a6e59302fcaba2a17ea8d5a257a4fcf0d4f Mon Sep 17 00:00:00 2001 From: Green Sky Date: Thu, 28 Mar 2024 21:05:44 +0100 Subject: [PATCH 229/237] Backends: SDL3: Re-enable calling SDL_StartTextInput()/SDL_StopTextInput(). (#7452, #6306, #6071, #1953) Amend: a7703fe --- backends/imgui_impl_sdl3.cpp | 8 +++++++- backends/imgui_impl_sdl3.h | 2 +- docs/CHANGELOG.txt | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 2669b71f7461..4bb646de598b 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -10,7 +10,7 @@ // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // Missing features: -// [x] Platform: Basic IME support. Position somehow broken in SDL3 + app needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!. +// [ ] Platform: IME SUPPORT IS BROKEN IN SDL3 BECAUSE INPUTS GETS SENT TO BOTH APP AND IME + app needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. @@ -22,6 +22,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-04-15: Inputs: Re-enable calling SDL_StartTextInput()/SDL_StopTextInput() as SDL3 no longer enables it by default and should play nicer with IME. // 2024-02-13: Inputs: Fixed gamepad support. Handle gamepad disconnection. Added ImGui_ImplSDL3_SetGamepadMode(). // 2023-11-13: Updated for recent SDL3 API changes. // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys. @@ -117,6 +118,11 @@ static void ImGui_ImplSDL3_SetPlatformImeData(ImGuiViewport*, ImGuiPlatformImeDa r.w = 1; r.h = (int)data->InputLineHeight; SDL_SetTextInputRect(&r); + SDL_StartTextInput(); + } + else + { + SDL_StopTextInput(); } } diff --git a/backends/imgui_impl_sdl3.h b/backends/imgui_impl_sdl3.h index 4898729d4a70..eafb3474943f 100644 --- a/backends/imgui_impl_sdl3.h +++ b/backends/imgui_impl_sdl3.h @@ -10,7 +10,7 @@ // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // Missing features: -// [x] Platform: Basic IME support. Position somehow broken in SDL3 + app needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!. +// [ ] Platform: IME SUPPORT IS BROKEN IN SDL3 BECAUSE INPUTS GETS SENT TO BOTH APP AND IME + app needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2be92d3efd34..408ed0f3f8ed 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,9 @@ Breaking changes: Other changes: +- Backends: SDL3: Fixed text inputs. Re-enable calling SDL_StartTextInput()/SDL_StopTextInput() + as SDL3 no longer enables it by default. (#7452, #6306, #6071, #1953) [@Green-Sky] + ----------------------------------------------------------------------- VERSION 1.90.5 (Released 2024-04-11) From daecfffefbc729f80c3380c838901b6618530fb0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Apr 2024 12:52:45 +0200 Subject: [PATCH 230/237] Text, DrawList: Improved handling of long single-line wrapped text. (#7496, #5720) --- docs/CHANGELOG.txt | 2 ++ imgui_draw.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 408ed0f3f8ed..189c9f5cc352 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,8 @@ Breaking changes: Other changes: +- Text, DrawList: Improved handling of long single-line wrapped text. Faster and + mitigitate issues with reading vertex indexing limits with 16-bit indices. - Backends: SDL3: Fixed text inputs. Re-enable calling SDL_StartTextInput()/SDL_StopTextInput() as SDL3 no longer enables it by default. (#7452, #6306, #6071, #1953) [@Green-Sky] diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 93be40cc7900..f3da38519cfe 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -4080,6 +4080,8 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im { x = start_x; y += line_height; + if (y > clip_rect.w) + break; // break out of main loop word_wrap_eol = NULL; s = CalcWordWrapNextLineStartA(s, text_end); // Wrapping skips upcoming blanks continue; From b475309fa1e9d7a91825a169e243f9c4fa085f71 Mon Sep 17 00:00:00 2001 From: GamingMinds-DanielC Date: Thu, 14 Mar 2024 14:58:32 +0100 Subject: [PATCH 231/237] Fonts: Fixed font ascent and descent calculation when a font hits exact integer values. (#7399, #7404) --- docs/CHANGELOG.txt | 5 ++++- imgui_draw.cpp | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 189c9f5cc352..e4af7859f491 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,8 +43,11 @@ Breaking changes: Other changes: +- Fonts: Fixed font ascent and descent calculation when a font hits exact integer values. + It is possible that some prior manual use of ImFontConfig::GlyphOffset may become + duplicate with this fix. (#7399, #7404) [@GamingMinds-DanielC] - Text, DrawList: Improved handling of long single-line wrapped text. Faster and - mitigitate issues with reading vertex indexing limits with 16-bit indices. + mitigitate issues with reading vertex indexing limits with 16-bit indices. (#7496, #5720) - Backends: SDL3: Fixed text inputs. Re-enable calling SDL_StartTextInput()/SDL_StopTextInput() as SDL3 no longer enables it by default. (#7452, #6306, #6071, #1953) [@Green-Sky] diff --git a/imgui_draw.cpp b/imgui_draw.cpp index f3da38519cfe..7861d4e2d9f1 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2984,8 +2984,8 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) int unscaled_ascent, unscaled_descent, unscaled_line_gap; stbtt_GetFontVMetrics(&src_tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap); - const float ascent = ImTrunc(unscaled_ascent * font_scale + ((unscaled_ascent > 0.0f) ? +1 : -1)); - const float descent = ImTrunc(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1)); + const float ascent = ImCeil(unscaled_ascent * font_scale); + const float descent = ImFloor(unscaled_descent * font_scale); ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); const float font_off_x = cfg.GlyphOffset.x; const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent); From f9df6bf66220845ed25755c5aa94adf4435b853e Mon Sep 17 00:00:00 2001 From: Elias Daler Date: Sun, 24 Mar 2024 14:18:10 +0100 Subject: [PATCH 232/237] Examples: GLFW+WebGPU: added support for WebGPU-native/Dawn (#7435, #7132) --- .gitignore | 2 + .../example_emscripten_wgpu/CMakeLists.txt | 103 ++++++++++++++++++ examples/example_emscripten_wgpu/main.cpp | 95 +++++++++++++--- .../example_emscripten_wgpu/web/index.html | 4 + 4 files changed, 188 insertions(+), 16 deletions(-) create mode 100644 examples/example_emscripten_wgpu/CMakeLists.txt diff --git a/.gitignore b/.gitignore index 211d21dda88d..9570dacea7a1 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,8 @@ examples/*.out.wasm examples/example_glfw_opengl3/web/* examples/example_sdl2_opengl3/web/* examples/example_emscripten_wgpu/web/* +## Dawn build dependencies +examples/example_emscripten_wgpu/external/* ## JetBrains IDE artifacts .idea diff --git a/examples/example_emscripten_wgpu/CMakeLists.txt b/examples/example_emscripten_wgpu/CMakeLists.txt new file mode 100644 index 000000000000..646c5b3c298b --- /dev/null +++ b/examples/example_emscripten_wgpu/CMakeLists.txt @@ -0,0 +1,103 @@ +# Building for desktop (WebGPU-native) with Dawn: +# +# git clone https://github.com/google/dawn dawn +# cmake -B build -DIMGUI_DAWN_DIR=dawn +# cmake --build build +# +# The resulting binary will be found at one of the following locations: +# * build/Debug/example_emscripten_wgpu[.exe] +# * build/example_emscripten_wgpu[.exe] + +# Building for Emscripten: +# +# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html +# 2. Install Ninja build system +# 3. emcmake cmake -G Ninja -B build +# 3. cmake --build build +# 4. emrun build/index.html + +cmake_minimum_required(VERSION 3.10.2) +project(imgui_example_emscripten_wgpu C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17 + +# Dear ImGui +set(IMGUI_DIR ../../) + +# Libraries +if(EMSCRIPTEN) + set(LIBRARIES glfw) + add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1) +else() + # Dawn wgpu desktop + set(DAWN_FETCH_DEPENDENCIES ON) + set(IMGUI_DAWN_DIR CACHE PATH "Path to Dawn repository") + if (NOT IMGUI_DAWN_DIR) + message(FATAL_ERROR "Please specify the Dawn repository by setting IMGUI_DAWN_DIR") + endif() + + option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON) + + # Dawn builds many things by default - disable things we don't need + option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF) + option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF) + option(TINT_BUILD_DOCS "Build documentation" OFF) + option(TINT_BUILD_TESTS "Build tests" OFF) + if (NOT APPLE) + option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" OFF) + endif() + if(WIN32) + option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" OFF) + option(TINT_BUILD_WGSL_READER "Build the WGSL input reader" ON) + option(TINT_BUILD_GLSL_WRITER "Build the GLSL output writer" OFF) + option(TINT_BUILD_GLSL_VALIDATOR "Build the GLSL output validator" OFF) + option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" OFF) + option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON) + endif() + + add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL) + + set(LIBRARIES webgpu_dawn webgpu_cpp webgpu_glfw glfw) +endif() + +add_executable(example_emscripten_wgpu + main.cpp + # backend files + ${IMGUI_DIR}/backends/imgui_impl_glfw.cpp + ${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp + # Dear ImGui files + ${IMGUI_DIR}/imgui.cpp + ${IMGUI_DIR}/imgui_draw.cpp + ${IMGUI_DIR}/imgui_demo.cpp + ${IMGUI_DIR}/imgui_tables.cpp + ${IMGUI_DIR}/imgui_widgets.cpp +) +target_include_directories(example_emscripten_wgpu PUBLIC + ${IMGUI_DIR} + ${IMGUI_DIR}/backends +) + +target_link_libraries(example_emscripten_wgpu PUBLIC ${LIBRARIES}) + +# Emscripten settings +if(EMSCRIPTEN) + target_link_options(example_emscripten_wgpu PRIVATE + "-sUSE_WEBGPU=1" + "-sUSE_GLFW=3" + "-sWASM=1" + "-sALLOW_MEMORY_GROWTH=1" + "-sNO_EXIT_RUNTIME=0" + "-sASSERTIONS=1" + "-sDISABLE_EXCEPTION_CATCHING=1" + "-sNO_FILESYSTEM=1" + ) + set_target_properties(example_emscripten_wgpu PROPERTIES OUTPUT_NAME "index") + # copy our custom index.html to build directory + add_custom_command(TARGET example_emscripten_wgpu POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_LIST_DIR}/web/index.html" $ + ) +endif() diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index 43e93a2ad06d..ad6c3dd1cdf9 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -1,4 +1,6 @@ -// Dear ImGui: standalone example application for Emscripten, using GLFW + WebGPU +// Dear ImGui: standalone example application for using GLFW + WebGPU +// Dawn is used as a WebGPU implementation on desktop and Emscripten is supported for +// publishing on web. // (Emscripten is a C++-to-javascript compiler, used to publish executables for the web. See https://emscripten.org/) // Learn about Dear ImGui: @@ -10,12 +12,17 @@ #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_wgpu.h" + #include + #ifdef __EMSCRIPTEN__ #include #include #include +#else +#include #endif + #include #include #include @@ -26,15 +33,16 @@ #endif // Global WebGPU required states +static WGPUInstance wgpu_instance = nullptr; static WGPUDevice wgpu_device = nullptr; static WGPUSurface wgpu_surface = nullptr; static WGPUTextureFormat wgpu_preferred_fmt = WGPUTextureFormat_RGBA8Unorm; static WGPUSwapChain wgpu_swap_chain = nullptr; -static int wgpu_swap_chain_width = 0; -static int wgpu_swap_chain_height = 0; +static int wgpu_swap_chain_width = 1280; +static int wgpu_swap_chain_height = 720; // Forward declarations -static bool InitWGPU(); +static bool InitWGPU(GLFWwindow* window); static void CreateSwapChain(int width, int height); static void glfw_error_callback(int error, const char* description) @@ -56,6 +64,33 @@ static void wgpu_error_callback(WGPUErrorType error_type, const char* message, v printf("%s error: %s\n", error_type_lbl, message); } +static WGPUAdapter requestAdapter(WGPUInstance instance) { + auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, char const* message, void* pUserData) { + if (status == WGPURequestAdapterStatus_Success) { + *static_cast(pUserData) = adapter; + } else { + printf("Could not get WebGPU adapter: %s\n", message); + } + }; + WGPUAdapter adapter; + wgpuInstanceRequestAdapter(instance, nullptr, onAdapterRequestEnded, (void*)&adapter); + return adapter; +} + +static WGPUDevice requestDevice(WGPUAdapter& adapter) { + auto onDeviceRequestEnded = [](WGPURequestDeviceStatus status, WGPUDevice device, char const* message, void* pUserData) { + if (status == WGPURequestDeviceStatus_Success) { + *static_cast(pUserData) = device; + } else { + printf("Could not get WebGPU device: %s\n", message); + } + }; + + WGPUDevice device; + wgpuAdapterRequestDevice(adapter, nullptr, onDeviceRequestEnded, (void*)&device); + return device; +} + // Main code int main(int, char**) { @@ -66,18 +101,19 @@ int main(int, char**) // Make sure GLFW does not initialize any graphics context. // This needs to be done explicitly later. glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr); + GLFWwindow* window = glfwCreateWindow(wgpu_swap_chain_width, wgpu_swap_chain_height, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr); if (window == nullptr) return 1; // Initialize the WebGPU environment - if (!InitWGPU()) + if (!InitWGPU(window)) { if (window) glfwDestroyWindow(window); glfwTerminate(); return 1; } + CreateSwapChain(wgpu_swap_chain_width, wgpu_swap_chain_height); glfwShowWindow(window); // Setup Dear ImGui context @@ -115,7 +151,7 @@ int main(int, char**) //io.Fonts->AddFontDefault(); #ifndef IMGUI_DISABLE_FILE_FUNCTIONS //io.Fonts->AddFontFromFileTTF("fonts/segoeui.ttf", 18.0f); - io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf", 16.0f); + // io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf", 10.0f); @@ -200,6 +236,11 @@ int main(int, char**) // Rendering ImGui::Render(); +#ifndef __EMSCRIPTEN__ + // Tick needs to be called in Dawn to display validation errors + wgpuDeviceTick(wgpu_device); +#endif + WGPURenderPassColorAttachment color_attachments = {}; color_attachments.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED; color_attachments.loadOp = WGPULoadOp_Clear; @@ -223,6 +264,15 @@ int main(int, char**) WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc); WGPUQueue queue = wgpuDeviceGetQueue(wgpu_device); wgpuQueueSubmit(queue, 1, &cmd_buffer); + +#ifndef __EMSCRIPTEN__ + wgpuSwapChainPresent(wgpu_swap_chain); +#endif + + wgpuTextureViewRelease(color_attachments.view); + wgpuRenderPassEncoderRelease(pass); + wgpuCommandEncoderRelease(encoder); + wgpuCommandBufferRelease(cmd_buffer); } #ifdef __EMSCRIPTEN__ EMSCRIPTEN_MAINLOOP_END; @@ -239,29 +289,42 @@ int main(int, char**) return 0; } -static bool InitWGPU() +static bool InitWGPU(GLFWwindow* window) { + wgpu::Instance instance = wgpuCreateInstance(nullptr); + +#ifdef __EMSCRIPTEN__ wgpu_device = emscripten_webgpu_get_device(); if (!wgpu_device) return false; +#else + WGPUAdapter adapter = requestAdapter(instance.Get()); + if (!adapter) + return false; + wgpu_device = requestDevice(adapter); +#endif - wgpuDeviceSetUncapturedErrorCallback(wgpu_device, wgpu_error_callback, nullptr); - - // Use C++ wrapper due to misbehavior in Emscripten. - // Some offset computation for wgpuInstanceCreateSurface in JavaScript - // seem to be inline with struct alignments in the C++ structure +#ifdef __EMSCRIPTEN__ wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {}; html_surface_desc.selector = "#canvas"; - wgpu::SurfaceDescriptor surface_desc = {}; surface_desc.nextInChain = &html_surface_desc; - - wgpu::Instance instance = wgpuCreateInstance(nullptr); wgpu::Surface surface = instance.CreateSurface(&surface_desc); + wgpu::Adapter adapter = {}; wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter); +#else + wgpu::Surface surface = wgpu::glfw::CreateSurfaceForWindow(instance, window); + if (!surface) + return false; + wgpu_preferred_fmt = WGPUTextureFormat_BGRA8Unorm; +#endif + + wgpu_instance = instance.MoveToCHandle(); wgpu_surface = surface.MoveToCHandle(); + wgpuDeviceSetUncapturedErrorCallback(wgpu_device, wgpu_error_callback, nullptr); + return true; } diff --git a/examples/example_emscripten_wgpu/web/index.html b/examples/example_emscripten_wgpu/web/index.html index 82b1c422151f..6fad6b2a76c8 100644 --- a/examples/example_emscripten_wgpu/web/index.html +++ b/examples/example_emscripten_wgpu/web/index.html @@ -63,6 +63,10 @@ // Initialize the graphics adapter { + if (!navigator.gpu) { + throw Error("WebGPU not supported."); + } + const adapter = await navigator.gpu.requestAdapter(); const device = await adapter.requestDevice(); Module.preinitializedWebGPUDevice = device; From 80a5fdb1089512c4993be6db1a42eb670f332024 Mon Sep 17 00:00:00 2001 From: Jules Fouchy Date: Fri, 5 Apr 2024 19:07:39 +0200 Subject: [PATCH 233/237] Examples: GLFW+WebGPU: Fixed condition for when to recreate swapchain. (#7435, #7132) --- examples/example_emscripten_wgpu/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index ad6c3dd1cdf9..d6ed58f034f1 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -184,7 +184,7 @@ int main(int, char**) // React to changes in screen size int width, height; glfwGetFramebufferSize((GLFWwindow*)window, &width, &height); - if (width != wgpu_swap_chain_width && height != wgpu_swap_chain_height) + if (width != wgpu_swap_chain_width || height != wgpu_swap_chain_height) { ImGui_ImplWGPU_InvalidateDeviceObjects(); CreateSwapChain(width, height); From 648278cd62fbbf1556f5f2942c7487db58de43cd Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 16 Apr 2024 12:08:45 +0200 Subject: [PATCH 234/237] Examples: GLFW+WebGPU: Amends. (#7435, #7132) --- docs/CHANGELOG.txt | 1 + .../example_emscripten_wgpu/CMakeLists.txt | 17 ++--- examples/example_emscripten_wgpu/main.cpp | 69 ++++++++++--------- 3 files changed, 43 insertions(+), 44 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e4af7859f491..cda9dd6d30da 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,6 +50,7 @@ Other changes: mitigitate issues with reading vertex indexing limits with 16-bit indices. (#7496, #5720) - Backends: SDL3: Fixed text inputs. Re-enable calling SDL_StartTextInput()/SDL_StopTextInput() as SDL3 no longer enables it by default. (#7452, #6306, #6071, #1953) [@Green-Sky] +- Examples: GLFW+WebGPU: Added support for WebGPU-native/Dawn (#7435, #7132) [@eliasdaler, @Zelif] ----------------------------------------------------------------------- diff --git a/examples/example_emscripten_wgpu/CMakeLists.txt b/examples/example_emscripten_wgpu/CMakeLists.txt index 646c5b3c298b..b08e36ede28a 100644 --- a/examples/example_emscripten_wgpu/CMakeLists.txt +++ b/examples/example_emscripten_wgpu/CMakeLists.txt @@ -1,15 +1,12 @@ # Building for desktop (WebGPU-native) with Dawn: -# -# git clone https://github.com/google/dawn dawn -# cmake -B build -DIMGUI_DAWN_DIR=dawn -# cmake --build build -# +# 1. git clone https://github.com/google/dawn dawn +# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn +# 3. cmake --build build # The resulting binary will be found at one of the following locations: # * build/Debug/example_emscripten_wgpu[.exe] # * build/example_emscripten_wgpu[.exe] # Building for Emscripten: -# # 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html # 2. Install Ninja build system # 3. emcmake cmake -G Ninja -B build @@ -39,9 +36,9 @@ else() if (NOT IMGUI_DAWN_DIR) message(FATAL_ERROR "Please specify the Dawn repository by setting IMGUI_DAWN_DIR") endif() - + option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON) - + # Dawn builds many things by default - disable things we don't need option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF) option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF) @@ -58,9 +55,9 @@ else() option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" OFF) option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON) endif() - + add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL) - + set(LIBRARIES webgpu_dawn webgpu_cpp webgpu_glfw glfw) endif() diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index d6ed58f034f1..4e47b8323bd6 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -1,7 +1,6 @@ // Dear ImGui: standalone example application for using GLFW + WebGPU -// Dawn is used as a WebGPU implementation on desktop and Emscripten is supported for -// publishing on web. -// (Emscripten is a C++-to-javascript compiler, used to publish executables for the web. See https://emscripten.org/) +// - Emscripten is supported for publishing on web. See https://emscripten.org. +// - Dawn is used as a WebGPU implementation on desktop. // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq @@ -12,7 +11,6 @@ #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_wgpu.h" - #include #ifdef __EMSCRIPTEN__ @@ -64,33 +62,6 @@ static void wgpu_error_callback(WGPUErrorType error_type, const char* message, v printf("%s error: %s\n", error_type_lbl, message); } -static WGPUAdapter requestAdapter(WGPUInstance instance) { - auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, char const* message, void* pUserData) { - if (status == WGPURequestAdapterStatus_Success) { - *static_cast(pUserData) = adapter; - } else { - printf("Could not get WebGPU adapter: %s\n", message); - } - }; - WGPUAdapter adapter; - wgpuInstanceRequestAdapter(instance, nullptr, onAdapterRequestEnded, (void*)&adapter); - return adapter; -} - -static WGPUDevice requestDevice(WGPUAdapter& adapter) { - auto onDeviceRequestEnded = [](WGPURequestDeviceStatus status, WGPUDevice device, char const* message, void* pUserData) { - if (status == WGPURequestDeviceStatus_Success) { - *static_cast(pUserData) = device; - } else { - printf("Could not get WebGPU device: %s\n", message); - } - }; - - WGPUDevice device; - wgpuAdapterRequestDevice(adapter, nullptr, onDeviceRequestEnded, (void*)&device); - return device; -} - // Main code int main(int, char**) { @@ -151,7 +122,7 @@ int main(int, char**) //io.Fonts->AddFontDefault(); #ifndef IMGUI_DISABLE_FILE_FUNCTIONS //io.Fonts->AddFontFromFileTTF("fonts/segoeui.ttf", 18.0f); - // io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf", 10.0f); @@ -289,6 +260,36 @@ int main(int, char**) return 0; } +#ifndef __EMSCRIPTEN__ +static WGPUAdapter RequestAdapter(WGPUInstance instance) +{ + auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, const char* message, void* pUserData) + { + if (status == WGPURequestAdapterStatus_Success) + *(WGPUAdapter*)(pUserData) = adapter; + else + printf("Could not get WebGPU adapter: %s\n", message); +}; + WGPUAdapter adapter; + wgpuInstanceRequestAdapter(instance, nullptr, onAdapterRequestEnded, (void*)&adapter); + return adapter; +} + +static WGPUDevice RequestDevice(WGPUAdapter& adapter) +{ + auto onDeviceRequestEnded = [](WGPURequestDeviceStatus status, WGPUDevice device, const char* message, void* pUserData) + { + if (status == WGPURequestDeviceStatus_Success) + *(WGPUDevice*)(pUserData) = device; + else + printf("Could not get WebGPU device: %s\n", message); + }; + WGPUDevice device; + wgpuAdapterRequestDevice(adapter, nullptr, onDeviceRequestEnded, (void*)&device); + return device; +} +#endif + static bool InitWGPU(GLFWwindow* window) { wgpu::Instance instance = wgpuCreateInstance(nullptr); @@ -298,10 +299,10 @@ static bool InitWGPU(GLFWwindow* window) if (!wgpu_device) return false; #else - WGPUAdapter adapter = requestAdapter(instance.Get()); + WGPUAdapter adapter = RequestAdapter(instance.Get()); if (!adapter) return false; - wgpu_device = requestDevice(adapter); + wgpu_device = RequestDevice(adapter); #endif #ifdef __EMSCRIPTEN__ From 7b8107e7c8485efebf1b1d42e1497119be9ea85a Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 16 Apr 2024 13:51:03 +0200 Subject: [PATCH 235/237] Examples: GLFW+WebGPU: Rename example_emscripten_wgpu/ to example_glfw_wgpu/ (#7435, #7132) --- .github/workflows/build.yml | 4 ++-- .gitignore | 5 ++--- backends/imgui_impl_wgpu.cpp | 2 +- docs/BACKENDS.md | 4 ++-- docs/CHANGELOG.txt | 1 + docs/EXAMPLES.md | 4 ++-- .../CMakeLists.txt | 20 +++++++++---------- .../Makefile.emscripten | 0 .../README.md | 4 ++-- .../main.cpp | 0 .../web/index.html | 2 +- 11 files changed, 23 insertions(+), 23 deletions(-) rename examples/{example_emscripten_wgpu => example_glfw_wgpu}/CMakeLists.txt (83%) rename examples/{example_emscripten_wgpu => example_glfw_wgpu}/Makefile.emscripten (100%) rename examples/{example_emscripten_wgpu => example_glfw_wgpu}/README.md (90%) rename examples/{example_emscripten_wgpu => example_glfw_wgpu}/main.cpp (100%) rename examples/{example_emscripten_wgpu => example_glfw_wgpu}/web/index.html (97%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d332903ed0d9..48082d056392 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -489,12 +489,12 @@ jobs: popd make -C examples/example_sdl2_opengl3 -f Makefile.emscripten - - name: Build example_emscripten_wgpu + - name: Build example_glfw_wgpu run: | pushd emsdk-master source ./emsdk_env.sh popd - make -C examples/example_emscripten_wgpu -f Makefile.emscripten + make -C examples/example_glfw_wgpu -f Makefile.emscripten Android: runs-on: ubuntu-22.04 diff --git a/.gitignore b/.gitignore index 9570dacea7a1..64b5e1221c04 100644 --- a/.gitignore +++ b/.gitignore @@ -40,10 +40,9 @@ examples/*.o.tmp examples/*.out.js examples/*.out.wasm examples/example_glfw_opengl3/web/* +examples/example_glfw_wgpu/web/* +examples/example_glfw_wgpu/external/* examples/example_sdl2_opengl3/web/* -examples/example_emscripten_wgpu/web/* -## Dawn build dependencies -examples/example_emscripten_wgpu/external/* ## JetBrains IDE artifacts .idea diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 618dbb4ccb84..7c6bc3b995b6 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -751,7 +751,7 @@ bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info) // Create buffers with a default size (they will later be grown as needed) bd->pFrameResources = new FrameResources[bd->numFramesInFlight]; - for (int i = 0; i < bd->numFramesInFlight; i++) + for (unsigned int i = 0; i < bd->numFramesInFlight; i++) { FrameResources* fr = &bd->pFrameResources[i]; fr->IndexBuffer = nullptr; diff --git a/docs/BACKENDS.md b/docs/BACKENDS.md index e5aa79be1638..88a96a6bd9df 100644 --- a/docs/BACKENDS.md +++ b/docs/BACKENDS.md @@ -79,14 +79,14 @@ List of Renderer Backends: imgui_impl_sdlrenderer2.cpp ; SDL_Renderer (optional component of SDL2 available from SDL 2.0.18+) imgui_impl_sdlrenderer3.cpp ; SDL_Renderer (optional component of SDL3 available from SDL 3.0.0+) imgui_impl_vulkan.cpp ; Vulkan - imgui_impl_wgpu.cpp ; WebGPU + imgui_impl_wgpu.cpp ; WebGPU (web and desktop) List of high-level Frameworks Backends (combining Platform + Renderer): imgui_impl_allegro5.cpp Emscripten is also supported! -The SDL+GL, GLFW+GL and SDL+WebGPU examples are all ready to build and run with Emscripten. +The SDL+GL, GLFW+GL and GLFW+WebGPU examples are all ready to build and run with Emscripten. ### Backends for third-party frameworks, graphics API or other languages diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index cda9dd6d30da..fdf2919939eb 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,6 +51,7 @@ Other changes: - Backends: SDL3: Fixed text inputs. Re-enable calling SDL_StartTextInput()/SDL_StopTextInput() as SDL3 no longer enables it by default. (#7452, #6306, #6071, #1953) [@Green-Sky] - Examples: GLFW+WebGPU: Added support for WebGPU-native/Dawn (#7435, #7132) [@eliasdaler, @Zelif] +- Examples: GLFW+WebGPU: Renamed example_emscripten_wgpu/ to example_glfw_wgpu/. (#7435, #7132) ----------------------------------------------------------------------- diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md index edaddb0554f3..e813489666ea 100644 --- a/docs/EXAMPLES.md +++ b/docs/EXAMPLES.md @@ -104,8 +104,8 @@ OSX + OpenGL2 example.
(NB: imgui_impl_osx.mm is currently not as feature complete as other platforms backends. You may prefer to use the GLFW Or SDL backends, which will also support Windows and Linux.) -[example_emscripten_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_emscripten_wgpu/)
-Emcripten + GLFW + WebGPU example.
+[example_glfw_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_wgpu/)
+GLFW + WebGPU example. Supports Emscripten (web) or Dawn (desktop)
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_wgpu.cpp Note that the 'example_glfw_opengl3' and 'example_sdl2_opengl3' examples also supports Emscripten! diff --git a/examples/example_emscripten_wgpu/CMakeLists.txt b/examples/example_glfw_wgpu/CMakeLists.txt similarity index 83% rename from examples/example_emscripten_wgpu/CMakeLists.txt rename to examples/example_glfw_wgpu/CMakeLists.txt index b08e36ede28a..e682836ddb58 100644 --- a/examples/example_emscripten_wgpu/CMakeLists.txt +++ b/examples/example_glfw_wgpu/CMakeLists.txt @@ -3,8 +3,8 @@ # 2. cmake -B build -DIMGUI_DAWN_DIR=dawn # 3. cmake --build build # The resulting binary will be found at one of the following locations: -# * build/Debug/example_emscripten_wgpu[.exe] -# * build/example_emscripten_wgpu[.exe] +# * build/Debug/example_glfw_wgpu[.exe] +# * build/example_glfw_wgpu[.exe] # Building for Emscripten: # 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html @@ -14,7 +14,7 @@ # 4. emrun build/index.html cmake_minimum_required(VERSION 3.10.2) -project(imgui_example_emscripten_wgpu C CXX) +project(imgui_example_glfw_wgpu C CXX) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) @@ -61,7 +61,7 @@ else() set(LIBRARIES webgpu_dawn webgpu_cpp webgpu_glfw glfw) endif() -add_executable(example_emscripten_wgpu +add_executable(example_glfw_wgpu main.cpp # backend files ${IMGUI_DIR}/backends/imgui_impl_glfw.cpp @@ -73,16 +73,16 @@ add_executable(example_emscripten_wgpu ${IMGUI_DIR}/imgui_tables.cpp ${IMGUI_DIR}/imgui_widgets.cpp ) -target_include_directories(example_emscripten_wgpu PUBLIC +target_include_directories(example_glfw_wgpu PUBLIC ${IMGUI_DIR} ${IMGUI_DIR}/backends ) -target_link_libraries(example_emscripten_wgpu PUBLIC ${LIBRARIES}) +target_link_libraries(example_glfw_wgpu PUBLIC ${LIBRARIES}) # Emscripten settings if(EMSCRIPTEN) - target_link_options(example_emscripten_wgpu PRIVATE + target_link_options(example_glfw_wgpu PRIVATE "-sUSE_WEBGPU=1" "-sUSE_GLFW=3" "-sWASM=1" @@ -92,9 +92,9 @@ if(EMSCRIPTEN) "-sDISABLE_EXCEPTION_CATCHING=1" "-sNO_FILESYSTEM=1" ) - set_target_properties(example_emscripten_wgpu PROPERTIES OUTPUT_NAME "index") + set_target_properties(example_glfw_wgpu PROPERTIES OUTPUT_NAME "index") # copy our custom index.html to build directory - add_custom_command(TARGET example_emscripten_wgpu POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_LIST_DIR}/web/index.html" $ + add_custom_command(TARGET example_glfw_wgpu POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_LIST_DIR}/web/index.html" $ ) endif() diff --git a/examples/example_emscripten_wgpu/Makefile.emscripten b/examples/example_glfw_wgpu/Makefile.emscripten similarity index 100% rename from examples/example_emscripten_wgpu/Makefile.emscripten rename to examples/example_glfw_wgpu/Makefile.emscripten diff --git a/examples/example_emscripten_wgpu/README.md b/examples/example_glfw_wgpu/README.md similarity index 90% rename from examples/example_emscripten_wgpu/README.md rename to examples/example_glfw_wgpu/README.md index e60025da2602..399d431ffaa1 100644 --- a/examples/example_emscripten_wgpu/README.md +++ b/examples/example_glfw_wgpu/README.md @@ -6,7 +6,7 @@ - You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup. -- Then build using `make -f Makefile.emscripten` while in the `example_emscripten_wgpu/` directory. +- Then build using `make -f Makefile.emscripten` while in the `example_glfw_wgpu/` directory. - Requires recent Emscripten as WGPU is still a work-in-progress API. @@ -18,7 +18,7 @@ To run on a local machine: - Otherwise, generally you will need a local webserver: - Quoting [https://emscripten.org/docs/getting_started](https://emscripten.org/docs/getting_started/Tutorial.html#generating-html):
_"Unfortunately several browsers (including Chrome, Safari, and Internet Explorer) do not support file:// [XHR](https://emscripten.org/docs/site/glossary.html#term-xhr) requests, and can’t load extra files needed by the HTML (like a .wasm file, or packaged file data as mentioned lower down). For these browsers you’ll need to serve the files using a [local webserver](https://emscripten.org/docs/getting_started/FAQ.html#faq-local-webserver) and then open http://localhost:8000/hello.html."_ - - Emscripten SDK has a handy `emrun` command: `emrun web/example_emscripten_opengl3.html --browser firefox` which will spawn a temporary local webserver (in Firefox). See https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html for details. + - Emscripten SDK has a handy `emrun` command: `emrun web/example_glfw_wgpu.html --browser firefox` which will spawn a temporary local webserver (in Firefox). See https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html for details. - You may use Python 3 builtin webserver: `python -m http.server -d web` (this is what `make serve` uses). - You may use Python 2 builtin webserver: `cd web && python -m SimpleHTTPServer`. - If you are accessing the files over a network, certain browsers, such as Firefox, will restrict Gamepad API access to secure contexts only (e.g. https only). diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_glfw_wgpu/main.cpp similarity index 100% rename from examples/example_emscripten_wgpu/main.cpp rename to examples/example_glfw_wgpu/main.cpp diff --git a/examples/example_emscripten_wgpu/web/index.html b/examples/example_glfw_wgpu/web/index.html similarity index 97% rename from examples/example_emscripten_wgpu/web/index.html rename to examples/example_glfw_wgpu/web/index.html index 6fad6b2a76c8..a2a91c4a75f8 100644 --- a/examples/example_emscripten_wgpu/web/index.html +++ b/examples/example_glfw_wgpu/web/index.html @@ -3,7 +3,7 @@ - Dear ImGui Emscripten+WebGPU example + Dear ImGui Emscripten+GLFW+WebGPU example