mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-26 13:37:00 +00:00
Tables: clarify assumption that rendering of bg/borders in bg0/bg1 are cpu-clipped allowing frozen/unfrozen to share drawcmd + remove offset on outer borders of scrolling tables.
This commit is contained in:
parent
30468829c2
commit
22ace4438c
@ -2019,7 +2019,8 @@ struct ImGuiTable
|
|||||||
ImRect WorkRect;
|
ImRect WorkRect;
|
||||||
ImRect InnerClipRect;
|
ImRect InnerClipRect;
|
||||||
ImRect BgClipRect; // We use this to cpu-clip cell background color fill
|
ImRect BgClipRect; // We use this to cpu-clip cell background color fill
|
||||||
ImRect BgClipRectForDrawCmd;
|
ImRect Bg0ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG0/1 channel. This tends to be == OuterWindow->ClipRect at BeginTable() because output in BG0/BG1 is cpu-clipped
|
||||||
|
ImRect Bg2ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG2 channel. This tends to be a correct, tight-fit, because output to BG2 are done by widgets relying on regular ClipRect.
|
||||||
ImRect HostClipRect; // This is used to check if we can eventually merge our columns draw calls into the current draw call of the current window.
|
ImRect HostClipRect; // This is used to check if we can eventually merge our columns draw calls into the current draw call of the current window.
|
||||||
ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable()
|
ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable()
|
||||||
ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()
|
ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()
|
||||||
|
@ -1601,7 +1601,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
|||||||
// In theory we could call SetWindowClipRectBeforeSetChannel() but since we know TableEndRow() is
|
// In theory we could call SetWindowClipRectBeforeSetChannel() but since we know TableEndRow() is
|
||||||
// always followed by a change of clipping rectangle we perform the smallest overwrite possible here.
|
// always followed by a change of clipping rectangle we perform the smallest overwrite possible here.
|
||||||
if ((table->Flags & ImGuiTableFlags_NoClip) == 0)
|
if ((table->Flags & ImGuiTableFlags_NoClip) == 0)
|
||||||
window->DrawList->_CmdHeader.ClipRect = table->BgClipRectForDrawCmd.ToVec4();
|
window->DrawList->_CmdHeader.ClipRect = table->Bg0ClipRectForDrawCmd.ToVec4();
|
||||||
table->DrawSplitter.SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_BG0);
|
table->DrawSplitter.SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_BG0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1657,10 +1657,10 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
|||||||
|
|
||||||
// BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect
|
// BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect
|
||||||
float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y);
|
float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y);
|
||||||
table->BgClipRect.Min.y = table->BgClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y);
|
table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y);
|
||||||
table->BgClipRect.Max.y = table->BgClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y;
|
table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y;
|
||||||
table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen;
|
table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen;
|
||||||
IM_ASSERT(table->BgClipRectForDrawCmd.Min.y <= table->BgClipRectForDrawCmd.Max.y);
|
IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.Max.y);
|
||||||
|
|
||||||
float row_height = table->RowPosY2 - table->RowPosY1;
|
float row_height = table->RowPosY2 - table->RowPosY1;
|
||||||
table->RowPosY2 = window->DC.CursorPos.y = table->WorkRect.Min.y + table->RowPosY2 - table->OuterRect.Min.y;
|
table->RowPosY2 = window->DC.CursorPos.y = table->WorkRect.Min.y + table->RowPosY2 - table->OuterRect.Min.y;
|
||||||
@ -1669,7 +1669,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
|||||||
{
|
{
|
||||||
ImGuiTableColumn* column = &table->Columns[column_n];
|
ImGuiTableColumn* column = &table->Columns[column_n];
|
||||||
column->DrawChannelCurrent = column->DrawChannelUnfrozen;
|
column->DrawChannelCurrent = column->DrawChannelUnfrozen;
|
||||||
column->ClipRect.Min.y = table->BgClipRectForDrawCmd.Min.y;
|
column->ClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y
|
// Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y
|
||||||
@ -2019,7 +2019,7 @@ void ImGui::TablePushBackgroundChannel()
|
|||||||
|
|
||||||
// Optimization: avoid SetCurrentChannel() + PushClipRect()
|
// Optimization: avoid SetCurrentChannel() + PushClipRect()
|
||||||
table->HostBackupInnerClipRect = window->ClipRect;
|
table->HostBackupInnerClipRect = window->ClipRect;
|
||||||
SetWindowClipRectBeforeSetChannel(window, table->BgClipRectForDrawCmd);
|
SetWindowClipRectBeforeSetChannel(window, table->Bg2ClipRectForDrawCmd);
|
||||||
table->DrawSplitter.SetCurrentChannel(window->DrawList, table->Bg2DrawChannelCurrent);
|
table->DrawSplitter.SetCurrentChannel(window->DrawList, table->Bg2DrawChannelCurrent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2046,7 +2046,7 @@ void ImGui::TablePopBackgroundChannel()
|
|||||||
// - We allocate 1 or 2 background draw channels. This is because we know TablePushBackgroundChannel() is only used for
|
// - We allocate 1 or 2 background draw channels. This is because we know TablePushBackgroundChannel() is only used for
|
||||||
// horizontal spanning. If we allowed vertical spanning we'd need one background draw channel per merge group (1-4).
|
// horizontal spanning. If we allowed vertical spanning we'd need one background draw channel per merge group (1-4).
|
||||||
// Draw channel allocation (before merging):
|
// Draw channel allocation (before merging):
|
||||||
// - NoClip --> 2+D+1 channels: bg0/1 + bg2 + foreground (same clip rect == 1 draw call) (FIXME-TABLE: could merge bg2 and foreground?)
|
// - NoClip --> 2+D+1 channels: bg0/1 + bg2 + foreground (same clip rect == always 1 draw call)
|
||||||
// - Clip --> 2+D+N channels
|
// - Clip --> 2+D+N channels
|
||||||
// - FreezeRows --> 2+D+N*2 (unless scrolling value is zero)
|
// - FreezeRows --> 2+D+N*2 (unless scrolling value is zero)
|
||||||
// - FreezeRows || FreezeColunns --> 3+D+N*2 (unless scrolling value is zero)
|
// - FreezeRows || FreezeColunns --> 3+D+N*2 (unless scrolling value is zero)
|
||||||
@ -2085,7 +2085,8 @@ void ImGui::TableSetupDrawChannels(ImGuiTable* table)
|
|||||||
// All our cell highlight are manually clipped with BgClipRect. When unfreezing it will be made smaller to fit scrolling rect.
|
// All our cell highlight are manually clipped with BgClipRect. When unfreezing it will be made smaller to fit scrolling rect.
|
||||||
// (This technically isn't part of setting up draw channels, but is reasonably related to be done here)
|
// (This technically isn't part of setting up draw channels, but is reasonably related to be done here)
|
||||||
table->BgClipRect = table->InnerClipRect;
|
table->BgClipRect = table->InnerClipRect;
|
||||||
table->BgClipRectForDrawCmd = table->HostClipRect;
|
table->Bg0ClipRectForDrawCmd = table->OuterWindow->ClipRect;
|
||||||
|
table->Bg2ClipRectForDrawCmd = table->HostClipRect;
|
||||||
IM_ASSERT(table->BgClipRect.Min.y <= table->BgClipRect.Max.y);
|
IM_ASSERT(table->BgClipRect.Min.y <= table->BgClipRect.Max.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2288,19 +2289,17 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
|
|||||||
void ImGui::TableDrawBorders(ImGuiTable* table)
|
void ImGui::TableDrawBorders(ImGuiTable* table)
|
||||||
{
|
{
|
||||||
ImGuiWindow* inner_window = table->InnerWindow;
|
ImGuiWindow* inner_window = table->InnerWindow;
|
||||||
ImGuiWindow* outer_window = table->OuterWindow;
|
|
||||||
table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_BG0);
|
table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_BG0);
|
||||||
if (inner_window->Hidden || !table->HostClipRect.Overlaps(table->InnerClipRect))
|
if (inner_window->Hidden || !table->HostClipRect.Overlaps(table->InnerClipRect))
|
||||||
return;
|
return;
|
||||||
ImDrawList* inner_drawlist = inner_window->DrawList;
|
ImDrawList* inner_drawlist = inner_window->DrawList;
|
||||||
ImDrawList* outer_drawlist = outer_window->DrawList;
|
inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false);
|
||||||
|
|
||||||
// Draw inner border and resizing feedback
|
// Draw inner border and resizing feedback
|
||||||
const float border_size = TABLE_BORDER_SIZE;
|
const float border_size = TABLE_BORDER_SIZE;
|
||||||
const float draw_y1 = table->InnerRect.Min.y;
|
const float draw_y1 = table->InnerRect.Min.y;
|
||||||
const float draw_y2_body = table->InnerRect.Max.y;
|
const float draw_y2_body = table->InnerRect.Max.y;
|
||||||
const float draw_y2_head = table->IsUsingHeaders ? ((table->FreezeRowsCount >= 1 ? table->OuterRect.Min.y : table->WorkRect.Min.y) + table->LastFirstRowHeight) : draw_y1;
|
const float draw_y2_head = table->IsUsingHeaders ? ((table->FreezeRowsCount >= 1 ? table->OuterRect.Min.y : table->WorkRect.Min.y) + table->LastFirstRowHeight) : draw_y1;
|
||||||
|
|
||||||
if (table->Flags & ImGuiTableFlags_BordersInnerV)
|
if (table->Flags & ImGuiTableFlags_BordersInnerV)
|
||||||
{
|
{
|
||||||
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
|
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
|
||||||
@ -2351,23 +2350,21 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
|
|||||||
// parent. In inner_window, it won't reach out over scrollbars. Another weird solution would be to display part
|
// parent. In inner_window, it won't reach out over scrollbars. Another weird solution would be to display part
|
||||||
// of it in inner window, and the part that's over scrollbars in the outer window..)
|
// of it in inner window, and the part that's over scrollbars in the outer window..)
|
||||||
// Either solution currently won't allow us to use a larger border size: the border would clipped.
|
// Either solution currently won't allow us to use a larger border size: the border would clipped.
|
||||||
ImRect outer_border = table->OuterRect;
|
const ImRect outer_border = table->OuterRect;
|
||||||
const ImU32 outer_col = table->BorderColorStrong;
|
const ImU32 outer_col = table->BorderColorStrong;
|
||||||
if (inner_window != outer_window) // FIXME-TABLE
|
|
||||||
outer_border.Expand(1.0f);
|
|
||||||
if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter)
|
if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter)
|
||||||
{
|
{
|
||||||
outer_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, ~0, border_size);
|
inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, ~0, border_size);
|
||||||
}
|
}
|
||||||
else if (table->Flags & ImGuiTableFlags_BordersOuterV)
|
else if (table->Flags & ImGuiTableFlags_BordersOuterV)
|
||||||
{
|
{
|
||||||
outer_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Min.x, outer_border.Max.y), outer_col, border_size);
|
inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Min.x, outer_border.Max.y), outer_col, border_size);
|
||||||
outer_drawlist->AddLine(ImVec2(outer_border.Max.x, outer_border.Min.y), outer_border.Max, outer_col, border_size);
|
inner_drawlist->AddLine(ImVec2(outer_border.Max.x, outer_border.Min.y), outer_border.Max, outer_col, border_size);
|
||||||
}
|
}
|
||||||
else if (table->Flags & ImGuiTableFlags_BordersOuterH)
|
else if (table->Flags & ImGuiTableFlags_BordersOuterH)
|
||||||
{
|
{
|
||||||
outer_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Max.x, outer_border.Min.y), outer_col, border_size);
|
inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Max.x, outer_border.Min.y), outer_col, border_size);
|
||||||
outer_drawlist->AddLine(ImVec2(outer_border.Min.x, outer_border.Max.y), outer_border.Max, outer_col, border_size);
|
inner_drawlist->AddLine(ImVec2(outer_border.Min.x, outer_border.Max.y), outer_border.Max, outer_col, border_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((table->Flags & ImGuiTableFlags_BordersInnerH) && table->RowPosY2 < table->OuterRect.Max.y)
|
if ((table->Flags & ImGuiTableFlags_BordersInnerH) && table->RowPosY2 < table->OuterRect.Max.y)
|
||||||
@ -2377,6 +2374,8 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
|
|||||||
if (border_y >= table->BgClipRect.Min.y && border_y < table->BgClipRect.Max.y)
|
if (border_y >= table->BgClipRect.Min.y && border_y < table->BgClipRect.Max.y)
|
||||||
inner_drawlist->AddLine(ImVec2(table->BorderX1, border_y), ImVec2(table->BorderX2, border_y), table->BorderColorLight, border_size);
|
inner_drawlist->AddLine(ImVec2(table->BorderX1, border_y), ImVec2(table->BorderX2, border_y), table->BorderColorLight, border_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inner_drawlist->PopClipRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
@ -2638,7 +2637,6 @@ void ImGui::TableHeadersRow()
|
|||||||
// Emit a column header (text + optional sort order)
|
// Emit a column header (text + optional sort order)
|
||||||
// We cpu-clip text here so that all columns headers can be merged into a same draw call.
|
// We cpu-clip text here so that all columns headers can be merged into a same draw call.
|
||||||
// Note that because of how we cpu-clip and display sorting indicators, you _cannot_ use SameLine() after a TableHeader()
|
// Note that because of how we cpu-clip and display sorting indicators, you _cannot_ use SameLine() after a TableHeader()
|
||||||
// FIXME-TABLE: Style confusion between CellPadding.y and FramePadding.y
|
|
||||||
void ImGui::TableHeader(const char* label)
|
void ImGui::TableHeader(const char* label)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
@ -2660,7 +2658,7 @@ void ImGui::TableHeader(const char* label)
|
|||||||
ImVec2 label_pos = window->DC.CursorPos;
|
ImVec2 label_pos = window->DC.CursorPos;
|
||||||
|
|
||||||
// If we already got a row height, there's use that.
|
// If we already got a row height, there's use that.
|
||||||
// FIXME-TABLE-PADDING: Problem if the correct outer-padding CellBgRect strays off our ClipRect
|
// FIXME-TABLE: Padding problem if the correct outer-padding CellBgRect strays off our ClipRect?
|
||||||
ImRect cell_r = TableGetCellBgRect(table, column_n);
|
ImRect cell_r = TableGetCellBgRect(table, column_n);
|
||||||
float label_height = ImMax(label_size.y, table->RowMinHeight - table->CellPaddingY * 2.0f);
|
float label_height = ImMax(label_size.y, table->RowMinHeight - table->CellPaddingY * 2.0f);
|
||||||
|
|
||||||
@ -2671,7 +2669,7 @@ void ImGui::TableHeader(const char* label)
|
|||||||
const float ARROW_SCALE = 0.65f;
|
const float ARROW_SCALE = 0.65f;
|
||||||
if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort))
|
if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort))
|
||||||
{
|
{
|
||||||
w_arrow = ImFloor(g.FontSize * ARROW_SCALE + g.Style.FramePadding.x);// table->CellPadding.x);
|
w_arrow = ImFloor(g.FontSize * ARROW_SCALE + g.Style.FramePadding.x);
|
||||||
if (column->SortOrder > 0)
|
if (column->SortOrder > 0)
|
||||||
{
|
{
|
||||||
ImFormatString(sort_order_suf, IM_ARRAYSIZE(sort_order_suf), "%d", column->SortOrder + 1);
|
ImFormatString(sort_order_suf, IM_ARRAYSIZE(sort_order_suf), "%d", column->SortOrder + 1);
|
||||||
|
Loading…
Reference in New Issue
Block a user