mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-30 20:51:06 +01:00 
			
		
		
		
	Tables: sharing transient buffers between tables, reducing memory footprints. (#3740)
This commit is contained in:
		| @@ -4204,7 +4204,9 @@ void ImGui::Shutdown(ImGuiContext* context) | |||||||
|     g.ShrinkWidthBuffer.clear(); |     g.ShrinkWidthBuffer.clear(); | ||||||
|  |  | ||||||
|     g.Tables.Clear(); |     g.Tables.Clear(); | ||||||
|     g.CurrentTableStack.clear(); |     for (int i = 0; i < g.TablesTempDataStack.Size; i++) | ||||||
|  |         g.TablesTempDataStack[i].~ImGuiTableTempData(); | ||||||
|  |     g.TablesTempDataStack.clear(); | ||||||
|     g.DrawChannelsTempMergeBuffer.clear(); |     g.DrawChannelsTempMergeBuffer.clear(); | ||||||
|  |  | ||||||
|     g.ClipboardHandlerData.clear(); |     g.ClipboardHandlerData.clear(); | ||||||
|   | |||||||
| @@ -130,10 +130,11 @@ struct ImGuiTabBar;                 // Storage for a tab bar | |||||||
| struct ImGuiTabItem;                // Storage for a tab item (within a tab bar) | struct ImGuiTabItem;                // Storage for a tab item (within a tab bar) | ||||||
| struct ImGuiTable;                  // Storage for a table | struct ImGuiTable;                  // Storage for a table | ||||||
| struct ImGuiTableColumn;            // Storage for one column of a table | struct ImGuiTableColumn;            // Storage for one column of a table | ||||||
|  | struct ImGuiTableTempData;          // Temporary storage for one table (one per table in the stack), shared between tables. | ||||||
| struct ImGuiTableSettings;          // Storage for a table .ini settings | struct ImGuiTableSettings;          // Storage for a table .ini settings | ||||||
| struct ImGuiTableColumnsSettings;   // Storage for a column .ini settings | struct ImGuiTableColumnsSettings;   // Storage for a column .ini settings | ||||||
| struct ImGuiWindow;                 // Storage for one window | struct ImGuiWindow;                 // Storage for one window | ||||||
| struct ImGuiWindowTempData;         // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame) | struct ImGuiWindowTempData;         // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame, in practice we currently keep it for each window) | ||||||
| struct ImGuiWindowSettings;         // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session) | struct ImGuiWindowSettings;         // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session) | ||||||
|  |  | ||||||
| // Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists. | // Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists. | ||||||
| @@ -1516,8 +1517,9 @@ struct ImGuiContext | |||||||
|  |  | ||||||
|     // Table |     // Table | ||||||
|     ImGuiTable*                     CurrentTable; |     ImGuiTable*                     CurrentTable; | ||||||
|  |     int                             CurrentTableStackIdx; | ||||||
|     ImPool<ImGuiTable>              Tables; |     ImPool<ImGuiTable>              Tables; | ||||||
|     ImVector<ImGuiPtrOrIndex>       CurrentTableStack; |     ImVector<ImGuiTableTempData>    TablesTempDataStack; | ||||||
|     ImVector<float>                 TablesLastTimeActive;       // Last used timestamp of each tables (SOA, for efficient GC) |     ImVector<float>                 TablesLastTimeActive;       // Last used timestamp of each tables (SOA, for efficient GC) | ||||||
|     ImVector<ImDrawChannel>         DrawChannelsTempMergeBuffer; |     ImVector<ImDrawChannel>         DrawChannelsTempMergeBuffer; | ||||||
|  |  | ||||||
| @@ -1694,6 +1696,7 @@ struct ImGuiContext | |||||||
|         memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal)); |         memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal)); | ||||||
|  |  | ||||||
|         CurrentTable = NULL; |         CurrentTable = NULL; | ||||||
|  |         CurrentTableStackIdx = -1; | ||||||
|         CurrentTabBar = NULL; |         CurrentTabBar = NULL; | ||||||
|  |  | ||||||
|         LastValidMousePos = ImVec2(0.0f, 0.0f); |         LastValidMousePos = ImVec2(0.0f, 0.0f); | ||||||
| @@ -2089,12 +2092,13 @@ struct ImGuiTableCellData | |||||||
|     ImGuiTableColumnIdx         Column;     // Column number |     ImGuiTableColumnIdx         Column;     // Column number | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // FIXME-TABLE: transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData | // FIXME-TABLE: more transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData | ||||||
| struct ImGuiTable | struct ImGuiTable | ||||||
| { | { | ||||||
|     ImGuiID                     ID; |     ImGuiID                     ID; | ||||||
|     ImGuiTableFlags             Flags; |     ImGuiTableFlags             Flags; | ||||||
|     void*                       RawData;                    // Single allocation to hold Columns[], DisplayOrderToIndex[] and RowCellData[] |     void*                       RawData;                    // Single allocation to hold Columns[], DisplayOrderToIndex[] and RowCellData[] | ||||||
|  |     ImGuiTableTempData*         TempData;                   // Transient data while table is active. Point within g.CurrentTableStack[] | ||||||
|     ImSpan<ImGuiTableColumn>    Columns;                    // Point within RawData[] |     ImSpan<ImGuiTableColumn>    Columns;                    // Point within RawData[] | ||||||
|     ImSpan<ImGuiTableColumnIdx> DisplayOrderToIndex;        // Point within RawData[]. Store display order of columns (when not reordered, the values are 0...Count-1) |     ImSpan<ImGuiTableColumnIdx> DisplayOrderToIndex;        // Point within RawData[]. Store display order of columns (when not reordered, the values are 0...Count-1) | ||||||
|     ImSpan<ImGuiTableCellData>  RowCellData;                // Point within RawData[]. Store cells background requests for current row. |     ImSpan<ImGuiTableCellData>  RowCellData;                // Point within RawData[]. Store cells background requests for current row. | ||||||
| @@ -2146,22 +2150,13 @@ struct ImGuiTable | |||||||
|     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                      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                      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                      HostBackupParentWorkRect;   // Backup of InnerWindow->ParentWorkRect at the end of BeginTable() |  | ||||||
|     ImRect                      HostBackupInnerClipRect;    // Backup of InnerWindow->ClipRect during PushTableBackground()/PopTableBackground() |     ImRect                      HostBackupInnerClipRect;    // Backup of InnerWindow->ClipRect during PushTableBackground()/PopTableBackground() | ||||||
|     ImVec2                      HostBackupPrevLineSize;     // Backup of InnerWindow->DC.PrevLineSize at the end of BeginTable() |  | ||||||
|     ImVec2                      HostBackupCurrLineSize;     // Backup of InnerWindow->DC.CurrLineSize at the end of BeginTable() |  | ||||||
|     ImVec2                      HostBackupCursorMaxPos;     // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable() |  | ||||||
|     ImVec2                      UserOuterSize;              // outer_size.x passed to BeginTable() |  | ||||||
|     ImVec1                      HostBackupColumnsOffset;    // Backup of OuterWindow->DC.ColumnsOffset at the end of BeginTable() |  | ||||||
|     float                       HostBackupItemWidth;        // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable() |  | ||||||
|     int                         HostBackupItemWidthStackSize;// Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable() |  | ||||||
|     ImGuiWindow*                OuterWindow;                // Parent window for the table |     ImGuiWindow*                OuterWindow;                // Parent window for the table | ||||||
|     ImGuiWindow*                InnerWindow;                // Window holding the table data (== OuterWindow or a child window) |     ImGuiWindow*                InnerWindow;                // Window holding the table data (== OuterWindow or a child window) | ||||||
|     ImGuiTextBuffer             ColumnsNames;               // Contiguous buffer holding columns names |     ImGuiTextBuffer             ColumnsNames;               // Contiguous buffer holding columns names | ||||||
|     ImDrawListSplitter          DrawSplitter;               // We carry our own ImDrawList splitter to allow recursion (FIXME: could be stored outside, worst case we need 1 splitter per recursing table) |     ImDrawListSplitter          DrawSplitter;               // We carry our own ImDrawList splitter to allow recursion (should move to ImGuiTableTempDataB) | ||||||
|     ImGuiTableColumnSortSpecs   SortSpecsSingle; |     ImGuiTableColumnSortSpecs   SortSpecsSingle; | ||||||
|     ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti;     // FIXME-OPT: Using a small-vector pattern would work be good. |     ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti;     // FIXME-OPT: Using a small-vector pattern would be good. | ||||||
|     ImGuiTableSortSpecs         SortSpecs;                  // Public facing sorts specs, this is what we return in TableGetSortSpecs() |     ImGuiTableSortSpecs         SortSpecs;                  // Public facing sorts specs, this is what we return in TableGetSortSpecs() | ||||||
|     ImGuiTableColumnIdx         SortSpecsCount; |     ImGuiTableColumnIdx         SortSpecsCount; | ||||||
|     ImGuiTableColumnIdx         ColumnsEnabledCount;        // Number of enabled columns (<= ColumnsCount) |     ImGuiTableColumnIdx         ColumnsEnabledCount;        // Number of enabled columns (<= ColumnsCount) | ||||||
| @@ -2208,6 +2203,26 @@ struct ImGuiTable | |||||||
|     IMGUI_API ~ImGuiTable()     { IM_FREE(RawData); } |     IMGUI_API ~ImGuiTable()     { IM_FREE(RawData); } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | // Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared. | ||||||
|  | // Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure. | ||||||
|  | // FIXME-TABLE: more transient data could be stored here: DrawSplitter (!), SortSpecs? incoming RowData? | ||||||
|  | struct ImGuiTableTempData | ||||||
|  | { | ||||||
|  |     int                         TableIndex;                 // Index in g.Tables.Buf[] pool | ||||||
|  |     ImVec2                      UserOuterSize;              // outer_size.x passed to BeginTable() | ||||||
|  |  | ||||||
|  |     ImRect                      HostBackupWorkRect;         // Backup of InnerWindow->WorkRect at the end of BeginTable() | ||||||
|  |     ImRect                      HostBackupParentWorkRect;   // Backup of InnerWindow->ParentWorkRect at the end of BeginTable() | ||||||
|  |     ImVec2                      HostBackupPrevLineSize;     // Backup of InnerWindow->DC.PrevLineSize at the end of BeginTable() | ||||||
|  |     ImVec2                      HostBackupCurrLineSize;     // Backup of InnerWindow->DC.CurrLineSize at the end of BeginTable() | ||||||
|  |     ImVec2                      HostBackupCursorMaxPos;     // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable() | ||||||
|  |     ImVec1                      HostBackupColumnsOffset;    // Backup of OuterWindow->DC.ColumnsOffset at the end of BeginTable() | ||||||
|  |     float                       HostBackupItemWidth;        // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable() | ||||||
|  |     int                         HostBackupItemWidthStackSize;//Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable() | ||||||
|  |  | ||||||
|  |     IMGUI_API ImGuiTableTempData() { memset(this, 0, sizeof(*this)); LastTimeActive = -1.0f; } | ||||||
|  | }; | ||||||
|  |  | ||||||
| // sizeof() ~ 12 | // sizeof() ~ 12 | ||||||
| struct ImGuiTableColumnSettings | struct ImGuiTableColumnSettings | ||||||
| { | { | ||||||
|   | |||||||
| @@ -343,6 +343,14 @@ bool    ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG | |||||||
|     if (instance_no > 0) |     if (instance_no > 0) | ||||||
|         IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID"); |         IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID"); | ||||||
|  |  | ||||||
|  |     // Acquire temporary buffers | ||||||
|  |     const int table_idx = g.Tables.GetIndex(table); | ||||||
|  |     g.CurrentTableStackIdx++; | ||||||
|  |     if (g.CurrentTableStackIdx + 1 > g.TablesTempDataStack.Size) | ||||||
|  |         g.TablesTempDataStack.resize(g.CurrentTableStackIdx + 1, ImGuiTableTempData()); | ||||||
|  |     ImGuiTableTempData* temp_data = table->TempData = &g.TablesTempDataStack[g.CurrentTableStackIdx]; | ||||||
|  |     temp_data->TableIndex = table_idx; | ||||||
|  |  | ||||||
|     // Fix flags |     // Fix flags | ||||||
|     table->IsDefaultSizingPolicy = (flags & ImGuiTableFlags_SizingMask_) == 0; |     table->IsDefaultSizingPolicy = (flags & ImGuiTableFlags_SizingMask_) == 0; | ||||||
|     flags = TableFixFlags(flags, outer_window); |     flags = TableFixFlags(flags, outer_window); | ||||||
| @@ -356,7 +364,7 @@ bool    ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG | |||||||
|     table->ColumnsCount = columns_count; |     table->ColumnsCount = columns_count; | ||||||
|     table->IsLayoutLocked = false; |     table->IsLayoutLocked = false; | ||||||
|     table->InnerWidth = inner_width; |     table->InnerWidth = inner_width; | ||||||
|     table->UserOuterSize = outer_size; |     temp_data->UserOuterSize = outer_size; | ||||||
|  |  | ||||||
|     // When not using a child window, WorkRect.Max will grow as we append contents. |     // When not using a child window, WorkRect.Max will grow as we append contents. | ||||||
|     if (use_child_window) |     if (use_child_window) | ||||||
| @@ -405,14 +413,14 @@ bool    ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG | |||||||
|     table->HostIndentX = inner_window->DC.Indent.x; |     table->HostIndentX = inner_window->DC.Indent.x; | ||||||
|     table->HostClipRect = inner_window->ClipRect; |     table->HostClipRect = inner_window->ClipRect; | ||||||
|     table->HostSkipItems = inner_window->SkipItems; |     table->HostSkipItems = inner_window->SkipItems; | ||||||
|     table->HostBackupWorkRect = inner_window->WorkRect; |     temp_data->HostBackupWorkRect = inner_window->WorkRect; | ||||||
|     table->HostBackupParentWorkRect = inner_window->ParentWorkRect; |     temp_data->HostBackupParentWorkRect = inner_window->ParentWorkRect; | ||||||
|     table->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset; |     temp_data->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset; | ||||||
|     table->HostBackupPrevLineSize = inner_window->DC.PrevLineSize; |     temp_data->HostBackupPrevLineSize = inner_window->DC.PrevLineSize; | ||||||
|     table->HostBackupCurrLineSize = inner_window->DC.CurrLineSize; |     temp_data->HostBackupCurrLineSize = inner_window->DC.CurrLineSize; | ||||||
|     table->HostBackupCursorMaxPos = inner_window->DC.CursorMaxPos; |     temp_data->HostBackupCursorMaxPos = inner_window->DC.CursorMaxPos; | ||||||
|     table->HostBackupItemWidth = outer_window->DC.ItemWidth; |     temp_data->HostBackupItemWidth = outer_window->DC.ItemWidth; | ||||||
|     table->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size; |     temp_data->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size; | ||||||
|     inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); |     inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); | ||||||
|  |  | ||||||
|     // Padding and Spacing |     // Padding and Spacing | ||||||
| @@ -455,8 +463,6 @@ bool    ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG | |||||||
|     table->BorderColorLight = GetColorU32(ImGuiCol_TableBorderLight); |     table->BorderColorLight = GetColorU32(ImGuiCol_TableBorderLight); | ||||||
|  |  | ||||||
|     // Make table current |     // Make table current | ||||||
|     const int table_idx = g.Tables.GetIndex(table); |  | ||||||
|     g.CurrentTableStack.push_back(ImGuiPtrOrIndex(table_idx)); |  | ||||||
|     g.CurrentTable = table; |     g.CurrentTable = table; | ||||||
|     outer_window->DC.CurrentTableIdx = table_idx; |     outer_window->DC.CurrentTableIdx = table_idx; | ||||||
|     if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly. |     if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly. | ||||||
| @@ -1205,6 +1211,7 @@ void    ImGui::EndTable() | |||||||
|     const ImGuiTableFlags flags = table->Flags; |     const ImGuiTableFlags flags = table->Flags; | ||||||
|     ImGuiWindow* inner_window = table->InnerWindow; |     ImGuiWindow* inner_window = table->InnerWindow; | ||||||
|     ImGuiWindow* outer_window = table->OuterWindow; |     ImGuiWindow* outer_window = table->OuterWindow; | ||||||
|  |     ImGuiTableTempData* temp_data = table->TempData; | ||||||
|     IM_ASSERT(inner_window == g.CurrentWindow); |     IM_ASSERT(inner_window == g.CurrentWindow); | ||||||
|     IM_ASSERT(outer_window == inner_window || outer_window == inner_window->ParentWindow); |     IM_ASSERT(outer_window == inner_window || outer_window == inner_window->ParentWindow); | ||||||
|  |  | ||||||
| @@ -1217,9 +1224,9 @@ void    ImGui::EndTable() | |||||||
|             TableOpenContextMenu((int)table->HoveredColumnBody); |             TableOpenContextMenu((int)table->HoveredColumnBody); | ||||||
|  |  | ||||||
|     // Finalize table height |     // Finalize table height | ||||||
|     inner_window->DC.PrevLineSize = table->HostBackupPrevLineSize; |     inner_window->DC.PrevLineSize = temp_data->HostBackupPrevLineSize; | ||||||
|     inner_window->DC.CurrLineSize = table->HostBackupCurrLineSize; |     inner_window->DC.CurrLineSize = temp_data->HostBackupCurrLineSize; | ||||||
|     inner_window->DC.CursorMaxPos = table->HostBackupCursorMaxPos; |     inner_window->DC.CursorMaxPos = temp_data->HostBackupCursorMaxPos; | ||||||
|     const float inner_content_max_y = table->RowPosY2; |     const float inner_content_max_y = table->RowPosY2; | ||||||
|     IM_ASSERT(table->RowPosY2 == inner_window->DC.CursorPos.y); |     IM_ASSERT(table->RowPosY2 == inner_window->DC.CursorPos.y); | ||||||
|     if (inner_window != outer_window) |     if (inner_window != outer_window) | ||||||
| @@ -1266,10 +1273,11 @@ void    ImGui::EndTable() | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
|     // Flatten channels and merge draw calls |     // Flatten channels and merge draw calls | ||||||
|     table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, 0); |     ImDrawListSplitter* splitter = &table->DrawSplitter; | ||||||
|  |     splitter->SetCurrentChannel(inner_window->DrawList, 0); | ||||||
|     if ((table->Flags & ImGuiTableFlags_NoClip) == 0) |     if ((table->Flags & ImGuiTableFlags_NoClip) == 0) | ||||||
|         TableMergeDrawChannels(table); |         TableMergeDrawChannels(table); | ||||||
|     table->DrawSplitter.Merge(inner_window->DrawList); |     splitter->Merge(inner_window->DrawList); | ||||||
|  |  | ||||||
|     // Update ColumnsAutoFitWidth to get us ahead for host using our size to auto-resize without waiting for next BeginTable() |     // Update ColumnsAutoFitWidth to get us ahead for host using our size to auto-resize without waiting for next BeginTable() | ||||||
|     const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1); |     const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1); | ||||||
| @@ -1311,18 +1319,18 @@ void    ImGui::EndTable() | |||||||
|  |  | ||||||
|     // Pop from id stack |     // Pop from id stack | ||||||
|     IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table->ID + table->InstanceCurrent, "Mismatching PushID/PopID!"); |     IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table->ID + table->InstanceCurrent, "Mismatching PushID/PopID!"); | ||||||
|     IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= table->HostBackupItemWidthStackSize, "Too many PopItemWidth!"); |     IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= temp_data->HostBackupItemWidthStackSize, "Too many PopItemWidth!"); | ||||||
|     PopID(); |     PopID(); | ||||||
|  |  | ||||||
|     // Restore window data that we modified |     // Restore window data that we modified | ||||||
|     const ImVec2 backup_outer_max_pos = outer_window->DC.CursorMaxPos; |     const ImVec2 backup_outer_max_pos = outer_window->DC.CursorMaxPos; | ||||||
|     inner_window->WorkRect = table->HostBackupWorkRect; |     inner_window->WorkRect = temp_data->HostBackupWorkRect; | ||||||
|     inner_window->ParentWorkRect = table->HostBackupParentWorkRect; |     inner_window->ParentWorkRect = temp_data->HostBackupParentWorkRect; | ||||||
|     inner_window->SkipItems = table->HostSkipItems; |     inner_window->SkipItems = table->HostSkipItems; | ||||||
|     outer_window->DC.CursorPos = table->OuterRect.Min; |     outer_window->DC.CursorPos = table->OuterRect.Min; | ||||||
|     outer_window->DC.ItemWidth = table->HostBackupItemWidth; |     outer_window->DC.ItemWidth = temp_data->HostBackupItemWidth; | ||||||
|     outer_window->DC.ItemWidthStack.Size = table->HostBackupItemWidthStackSize; |     outer_window->DC.ItemWidthStack.Size = temp_data->HostBackupItemWidthStackSize; | ||||||
|     outer_window->DC.ColumnsOffset = table->HostBackupColumnsOffset; |     outer_window->DC.ColumnsOffset = temp_data->HostBackupColumnsOffset; | ||||||
|  |  | ||||||
|     // Layout in outer window |     // Layout in outer window | ||||||
|     // (FIXME: To allow auto-fit and allow desirable effect of SameLine() we dissociate 'used' vs 'ideal' size by overriding |     // (FIXME: To allow auto-fit and allow desirable effect of SameLine() we dissociate 'used' vs 'ideal' size by overriding | ||||||
| @@ -1345,20 +1353,20 @@ void    ImGui::EndTable() | |||||||
|         IM_ASSERT((table->Flags & ImGuiTableFlags_ScrollX) == 0); |         IM_ASSERT((table->Flags & ImGuiTableFlags_ScrollX) == 0); | ||||||
|         outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth); |         outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth); | ||||||
|     } |     } | ||||||
|     else if (table->UserOuterSize.x <= 0.0f) |     else if (temp_data->UserOuterSize.x <= 0.0f) | ||||||
|     { |     { | ||||||
|         const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f; |         const float decoration_size = (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 - table->UserOuterSize.x); |         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)); |         outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth)); | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Max.x); |         outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Max.x); | ||||||
|     } |     } | ||||||
|     if (table->UserOuterSize.y <= 0.0f) |     if (temp_data->UserOuterSize.y <= 0.0f) | ||||||
|     { |     { | ||||||
|         const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.y : 0.0f; |         const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.y : 0.0f; | ||||||
|         outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - table->UserOuterSize.y); |         outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - temp_data->UserOuterSize.y); | ||||||
|         outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y)); |         outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y)); | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
| @@ -1374,8 +1382,12 @@ void    ImGui::EndTable() | |||||||
|  |  | ||||||
|     // Clear or restore current table, if any |     // Clear or restore current table, if any | ||||||
|     IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table); |     IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table); | ||||||
|     g.CurrentTableStack.pop_back(); |     IM_ASSERT(g.CurrentTableStackIdx >= 0); | ||||||
|     g.CurrentTable = g.CurrentTableStack.Size ? g.Tables.GetByIndex(g.CurrentTableStack.back().Index) : NULL; |     g.CurrentTableStackIdx--; | ||||||
|  |     temp_data = g.CurrentTableStackIdx >= 0 ? &g.TablesTempDataStack[g.CurrentTableStackIdx] : NULL; | ||||||
|  |     g.CurrentTable = temp_data ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL; | ||||||
|  |     if (g.CurrentTable) | ||||||
|  |         g.CurrentTable->TempData = temp_data; | ||||||
|     outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1; |     outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user