Allow more than 64 columns in Dear ImGUI (patched)

Improves Channel window displays, with System info.
This commit is contained in:
cam900 2022-05-27 13:38:45 +09:00
parent 905aa1b1a1
commit 67a7f39d9a
4 changed files with 135 additions and 59 deletions

View file

@ -315,7 +315,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
return false;
// Sanity checks
IM_ASSERT(columns_count > 0 && columns_count <= IMGUI_TABLE_MAX_COLUMNS && "Only 1..64 columns allowed!");
IM_ASSERT(columns_count > 0 && "Only 1..64 columns allowed!");
if (flags & ImGuiTableFlags_ScrollX)
IM_ASSERT(inner_width >= 0.0f);
@ -358,6 +358,16 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->LastFrameActive = g.FrameCount;
table->OuterWindow = table->InnerWindow = outer_window;
table->ColumnsCount = columns_count;
if (table->EnabledMaskByDisplayOrder.BitCount < columns_count ||
table->EnabledMaskByIndex.BitCount < columns_count ||
table->VisibleMaskByIndex.BitCount < columns_count ||
table->RequestOutputMaskByIndex.BitCount < columns_count)
{
table->EnabledMaskByDisplayOrder.Create(columns_count);
table->EnabledMaskByIndex.Create(columns_count);
table->VisibleMaskByIndex.Create(columns_count);
table->RequestOutputMaskByIndex.Create(columns_count);
}
table->IsLayoutLocked = false;
table->InnerWidth = inner_width;
temp_data->UserOuterSize = outer_size;
@ -721,8 +731,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
const ImGuiTableFlags table_sizing_policy = (table->Flags & ImGuiTableFlags_SizingMask_);
table->IsDefaultDisplayOrder = true;
table->ColumnsEnabledCount = 0;
table->EnabledMaskByIndex = 0x00;
table->EnabledMaskByDisplayOrder = 0x00;
table->EnabledMaskByIndex.ClearAllBits();
table->EnabledMaskByDisplayOrder.ClearAllBits();
table->LeftMostEnabledColumn = -1;
table->MinColumnWidth = ImMax(1.0f, g.Style.FramePadding.x * 1.0f); // g.Style.ColumnsMinSpacing; // FIXME-TABLE
@ -787,8 +797,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
else
table->LeftMostEnabledColumn = (ImGuiTableColumnIdx)column_n;
column->IndexWithinEnabledSet = table->ColumnsEnabledCount++;
table->EnabledMaskByIndex |= (ImU64)1 << column_n;
table->EnabledMaskByDisplayOrder |= (ImU64)1 << column->DisplayOrder;
table->EnabledMaskByIndex |= column_n;
table->EnabledMaskByDisplayOrder |= column->DisplayOrder;
prev_visible_column_idx = column_n;
IM_ASSERT(column->IndexWithinEnabledSet <= column->DisplayOrder);
@ -836,7 +846,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
table->LeftMostStretchedColumn = table->RightMostStretchedColumn = -1;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{
if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n)))
if (!(table->EnabledMaskByIndex & column_n))
continue;
ImGuiTableColumn* column = &table->Columns[column_n];
@ -852,7 +862,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!)
if (column->AutoFitQueue != 0x00)
column->WidthRequest = width_auto;
else if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !column_is_resizable && (table->RequestOutputMaskByIndex & ((ImU64)1 << column_n)))
else if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !column_is_resizable && (table->RequestOutputMaskByIndex & column_n))
column->WidthRequest = width_auto;
// FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets
@ -899,7 +909,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
table->ColumnsGivenWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{
if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n)))
if (!(table->EnabledMaskByIndex & column_n))
continue;
ImGuiTableColumn* column = &table->Columns[column_n];
@ -926,7 +936,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
if (width_remaining_for_stretched_columns >= 1.0f && !(table->Flags & ImGuiTableFlags_PreciseWidths))
for (int order_n = table->ColumnsCount - 1; stretch_sum_weights > 0.0f && width_remaining_for_stretched_columns >= 1.0f && order_n >= 0; order_n--)
{
if (!(table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n)))
if (!(table->EnabledMaskByDisplayOrder & order_n))
continue;
ImGuiTableColumn* column = &table->Columns[table->DisplayOrderToIndex[order_n]];
if (!(column->Flags & ImGuiTableColumnFlags_WidthStretch))
@ -949,8 +959,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
float offset_x = ((table->FreezeColumnsCount > 0) ? table->OuterRect.Min.x : work_rect.Min.x) + table->OuterPaddingX - table->CellSpacingX1;
ImRect host_clip_rect = table->InnerClipRect;
//host_clip_rect.Max.x += table->CellPaddingX + table->CellSpacingX2;
table->VisibleMaskByIndex = 0x00;
table->RequestOutputMaskByIndex = 0x00;
table->VisibleMaskByIndex.ClearAllBits();
table->RequestOutputMaskByIndex.ClearAllBits();
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
{
const int column_n = table->DisplayOrderToIndex[order_n];
@ -967,7 +977,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// Clear status flags
column->Flags &= ~ImGuiTableColumnFlags_StatusMask_;
if ((table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n)) == 0)
if ((table->EnabledMaskByDisplayOrder & order_n) == 0)
{
// Hidden column: clear a few fields and we are done with it for the remainder of the function.
// We set a zero-width clip rect but set Min.y/Max.y properly to not interfere with the clipper.
@ -1020,12 +1030,12 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
column->IsVisibleY = true; // (column->ClipRect.Max.y > column->ClipRect.Min.y);
const bool is_visible = column->IsVisibleX; //&& column->IsVisibleY;
if (is_visible)
table->VisibleMaskByIndex |= ((ImU64)1 << column_n);
table->VisibleMaskByIndex |= column_n;
// Mark column as requesting output from user. Note that fixed + non-resizable sets are auto-fitting at all times and therefore always request output.
column->IsRequestOutput = is_visible || column->AutoFitQueue != 0 || column->CannotSkipItemsQueue != 0;
if (column->IsRequestOutput)
table->RequestOutputMaskByIndex |= ((ImU64)1 << column_n);
table->RequestOutputMaskByIndex |= column_n;
// Mark column as SkipItems (ignoring all items/layout)
column->IsSkipItems = !column->IsEnabled || table->HostSkipItems;
@ -1153,7 +1163,7 @@ void ImGui::TableUpdateBorders(ImGuiTable* table)
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
{
if (!(table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n)))
if (!(table->EnabledMaskByDisplayOrder & order_n))
continue;
const int column_n = table->DisplayOrderToIndex[order_n];
@ -1289,7 +1299,7 @@ void ImGui::EndTable()
float auto_fit_width_for_stretched = 0.0f;
float auto_fit_width_for_stretched_min = 0.0f;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
if (table->EnabledMaskByIndex & ((ImU64)1 << column_n))
if (table->EnabledMaskByIndex & column_n)
{
ImGuiTableColumn* column = &table->Columns[column_n];
float column_width_request = ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !(column->Flags & ImGuiTableColumnFlags_NoResize)) ? column->WidthRequest : TableGetColumnWidthAuto(table, column);
@ -1480,7 +1490,7 @@ void ImGui::TableSetupScrollFreeze(int columns, int rows)
ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!");
IM_ASSERT(table->IsLayoutLocked == false && "Need to call TableSetupColumn() before first row!");
IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS);
IM_ASSERT(columns >= 0);
IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit
table->FreezeColumnsRequest = (table->Flags & ImGuiTableFlags_ScrollX) ? (ImGuiTableColumnIdx)ImMin(columns, table->ColumnsCount) : 0;
@ -1635,7 +1645,7 @@ void ImGui::TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n
return;
if (column_n == -1)
column_n = table->CurrentColumn;
if ((table->VisibleMaskByIndex & ((ImU64)1 << column_n)) == 0)
if ((table->VisibleMaskByIndex & column_n) == 0)
return;
if (table->RowCellDataCurrent < 0 || table->RowCellData[table->RowCellDataCurrent].Column != column_n)
table->RowCellDataCurrent++;
@ -1910,7 +1920,7 @@ bool ImGui::TableSetColumnIndex(int column_n)
// Return whether the column is visible. User may choose to skip submitting items based on this return value,
// however they shouldn't skip submitting for columns that may have the tallest contribution to row height.
return (table->RequestOutputMaskByIndex & ((ImU64)1 << column_n)) != 0;
return (table->RequestOutputMaskByIndex & column_n) != 0;
}
// [Public] Append into the next column, wrap and create a new row when already on last column
@ -1936,7 +1946,7 @@ bool ImGui::TableNextColumn()
// Return whether the column is visible. User may choose to skip submitting items based on this return value,
// however they shouldn't skip submitting for columns that may have the tallest contribution to row height.
int column_n = table->CurrentColumn;
return (table->RequestOutputMaskByIndex & ((ImU64)1 << column_n)) != 0;
return (table->RequestOutputMaskByIndex & column_n) != 0;
}
@ -2349,17 +2359,23 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
{
ImRect ClipRect;
int ChannelsCount;
ImBitArray<IMGUI_TABLE_MAX_DRAW_CHANNELS> ChannelsMask;
ImBitVector ChannelsMask;
MergeGroup() { ChannelsCount = 0; }
MergeGroup(int sz) : ChannelsMask(sz) { ChannelsCount = 0; }
};
int merge_group_mask = 0x00;
MergeGroup merge_groups[4];
int merge_group_bitlen = IMGUI_TABLE_DRAW_CHANNELS(table->ColumnsCount);
MergeGroup merge_groups[4]{
merge_group_bitlen,
merge_group_bitlen,
merge_group_bitlen,
merge_group_bitlen
};
// 1. Scan channels and take note of those which can be merged
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{
if ((table->VisibleMaskByIndex & ((ImU64)1 << column_n)) == 0)
if ((table->VisibleMaskByIndex & column_n) == 0)
continue;
ImGuiTableColumn* column = &table->Columns[column_n];
@ -2391,7 +2407,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
}
const int merge_group_n = (has_freeze_h && column_n < table->FreezeColumnsCount ? 0 : 1) + (has_freeze_v && merge_group_sub_n == 0 ? 0 : 2);
IM_ASSERT(channel_no < IMGUI_TABLE_MAX_DRAW_CHANNELS);
IM_ASSERT(channel_no < merge_group_bitlen);
MergeGroup* merge_group = &merge_groups[merge_group_n];
if (merge_group->ChannelsCount == 0)
merge_group->ClipRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
@ -2431,7 +2447,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
const int LEADING_DRAW_CHANNELS = 2;
g.DrawChannelsTempMergeBuffer.resize(splitter->_Count - LEADING_DRAW_CHANNELS); // Use shared temporary storage so the allocation gets amortized
ImDrawChannel* dst_tmp = g.DrawChannelsTempMergeBuffer.Data;
ImBitArray<IMGUI_TABLE_MAX_DRAW_CHANNELS> remaining_mask; // We need 132-bit of storage
ImBitVector remaining_mask(merge_group_bitlen); // We need 132-bit of storage
remaining_mask.SetBitRange(LEADING_DRAW_CHANNELS, splitter->_Count);
remaining_mask.ClearBit(table->Bg2DrawChannelUnfrozen);
IM_ASSERT(has_freeze_v == false || table->Bg2DrawChannelUnfrozen != TABLE_DRAW_CHANNEL_BG2_FROZEN);
@ -2466,7 +2482,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
GetOverlayDrawList()->AddLine(merge_group->ClipRect.Max, merge_clip_rect.Max, IM_COL32(255, 100, 0, 200));
#endif
remaining_count -= merge_group->ChannelsCount;
for (int n = 0; n < IM_ARRAYSIZE(remaining_mask.Storage); n++)
for (int n = 0; n < remaining_mask.Storage.size(); n++)
remaining_mask.Storage[n] &= ~merge_group->ChannelsMask.Storage[n];
for (int n = 0; n < splitter->_Count && merge_channels_count != 0; n++)
{
@ -2523,7 +2539,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
{
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
{
if (!(table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n)))
if (!(table->EnabledMaskByDisplayOrder & order_n))
continue;
const int column_n = table->DisplayOrderToIndex[order_n];