From b350b270f733db5029e75bc4567d7eca2956989d Mon Sep 17 00:00:00 2001 From: Rahul Raman Date: Tue, 27 Dec 2016 19:51:46 +0000 Subject: [PATCH 01/11] Added TableLayout component that child objects into a non-uniform grid, with fixed, user-defined column widths and flexible row heights --HG-- branch : develop_5.3 --- Scripts/Layout/TableLayout.cs | 271 ++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 Scripts/Layout/TableLayout.cs diff --git a/Scripts/Layout/TableLayout.cs b/Scripts/Layout/TableLayout.cs new file mode 100644 index 0000000..4ee3be7 --- /dev/null +++ b/Scripts/Layout/TableLayout.cs @@ -0,0 +1,271 @@ +/// Credit RahulOfTheRamanEffect +/// Sourced from - https://forum.unity3d.com/members/rahuloftheramaneffect.773241/ + +namespace UnityEngine.UI.Extensions +{ + /// + /// Arranges child objects into a non-uniform grid, with fixed column widths and flexible row heights + /// + public class TableLayout : LayoutGroup + { + public enum Corner + { + UpperLeft = 0, + UpperRight = 1, + LowerLeft = 2, + LowerRight = 3 + } + + [SerializeField] + protected Corner startCorner = Corner.UpperLeft; + /// + /// The corner starting from which the cells should be arranged + /// + public Corner StartCorner + { + get { return startCorner; } + set + { + SetProperty(ref startCorner, value); + } + } + + [SerializeField] + protected float[] columnWidths = new float[0]; + /// + /// The widths of all the columns in the table + /// + public float[] ColumnWidths + { + get { return columnWidths; } + set + { + SetProperty(ref columnWidths, value); + } + } + + [SerializeField] + protected float minimumRowHeight = 32f; + /// + /// The minimum height for any row in the table + /// + public float MinimumRowHeight + { + get { return minimumRowHeight; } + set + { + SetProperty(ref minimumRowHeight, value); + } + } + + [SerializeField] + protected float cellSpacing = 0f; + /// + /// The horizontal spacing between each cell in the table + /// + public float CellSpacing + { + get { return cellSpacing; } + set + { + SetProperty(ref cellSpacing, value); + } + } + + [SerializeField] + protected float rowSpacing = 0; + /// + /// The vertical spacing between each row in the table + /// + public float RowSpacing + { + get { return rowSpacing; } + set + { + SetProperty(ref rowSpacing, value); + } + } + + public override void CalculateLayoutInputHorizontal() + { + base.CalculateLayoutInputHorizontal(); + + float horizontalSize = padding.horizontal; + + if (columnWidths.Length > 1) + horizontalSize += ((columnWidths.Length - 1) * cellSpacing); + + // We calculate the actual cell count for cases where the number of children is lesser than the number of columns + int actualCellCount = Mathf.Min(rectChildren.Count, columnWidths.Length); + + for (int i = 0; i < actualCellCount; i++) + horizontalSize += columnWidths[i]; + + SetLayoutInputForAxis(horizontalSize, horizontalSize, 0, 0); + } + + public override void CalculateLayoutInputVertical() + { + int rowCount = Mathf.CeilToInt(rectChildren.Count / (float)columnWidths.Length); + + float totalMinHeight = padding.vertical; + float totalPreferredHeight = padding.vertical; + + if (rowCount > 1) + { + float heightFromSpacing = ((rowCount - 1) * rowSpacing); + totalMinHeight += heightFromSpacing; + totalPreferredHeight += heightFromSpacing; + } + + // Find the max value for minimum and preferred heights in each row + for (int i = 0; i < rowCount; i++) + { + float maxMinimumHeightInRow = 0; + float maxPreferredHeightInRow = 0; + + for (int j = 0; j < columnWidths.Length; j++) + { + int childIndex = (i * columnWidths.Length) + j; + + if (childIndex >= rectChildren.Count) + break; + + maxPreferredHeightInRow = Mathf.Max(LayoutUtility.GetPreferredHeight(rectChildren[childIndex]), maxPreferredHeightInRow); + maxMinimumHeightInRow = Mathf.Max(LayoutUtility.GetMinHeight(rectChildren[childIndex]), maxMinimumHeightInRow); + } + + maxMinimumHeightInRow = Mathf.Max(minimumRowHeight, maxMinimumHeightInRow); + totalMinHeight += maxMinimumHeightInRow; + + maxPreferredHeightInRow = Mathf.Max(minimumRowHeight, maxPreferredHeightInRow); + totalPreferredHeight += maxPreferredHeightInRow; + } + + + totalPreferredHeight = Mathf.Max(totalMinHeight, totalPreferredHeight); + SetLayoutInputForAxis(totalMinHeight, totalPreferredHeight, 1, 1); + } + + public override void SetLayoutHorizontal() + { + int columnCount = columnWidths.Length; + + for (int i = 0; i < rectChildren.Count; i++) + { + RectTransform child = rectChildren[i]; + m_Tracker.Add(this, child, + DrivenTransformProperties.Anchors | + DrivenTransformProperties.AnchoredPosition | + DrivenTransformProperties.SizeDelta); + child.anchorMin = Vector2.up; + child.anchorMax = Vector2.up; + Vector2 childSizeDelta = child.sizeDelta; + childSizeDelta.x = columnWidths[i % columnCount]; + child.sizeDelta = childSizeDelta; + } + } + + public override void SetLayoutVertical() + { + float tableLayoutHeight = rectTransform.rect.height; + + int columnCount = columnWidths.Length; + int rowCount = Mathf.CeilToInt(rectChildren.Count / (float)columnCount); + + int cornerX = (int)startCorner % 2; + int cornerY = (int)startCorner / 2; + + Vector2 startOffset = new Vector2(); + + float requiredWidthWithoutPadding = 0; + for (int i = 0; i < columnWidths.Length; i++) + { + requiredWidthWithoutPadding += columnWidths[i]; + requiredWidthWithoutPadding += cellSpacing; + } + requiredWidthWithoutPadding -= cellSpacing; + + startOffset.x = GetStartOffset(0, requiredWidthWithoutPadding); + + float requiredHeightWithoutPadding = 0; + + for (int i = 0; i < rowCount; i++) + { + float maxPreferredHeightInRow = 0; + + for (int j = 0; j < columnCount; j++) + { + int childIndex = (i * columnCount) + j; + + if (childIndex >= rectChildren.Count) + break; + + maxPreferredHeightInRow = Mathf.Max(LayoutUtility.GetPreferredHeight(rectChildren[childIndex]), maxPreferredHeightInRow); + } + + maxPreferredHeightInRow = Mathf.Max(minimumRowHeight, maxPreferredHeightInRow); + requiredHeightWithoutPadding += maxPreferredHeightInRow; + requiredHeightWithoutPadding += rowSpacing; + } + + requiredHeightWithoutPadding -= rowSpacing; + + startOffset.y = GetStartOffset(1, requiredHeightWithoutPadding); + + if (cornerX == 1) + startOffset.x += requiredWidthWithoutPadding; + + if (cornerY == 1) + startOffset.y += requiredHeightWithoutPadding; + + float positionY = startOffset.y; + + for (int i = 0; i < rowCount; i++) + { + float positionX = startOffset.x; + + float maxPreferredHeightInRow = 0; + + for (int j = 0; j < columnCount; j++) + { + int childIndex = (i * columnCount) + j; + + if (childIndex >= rectChildren.Count) + break; + + float sizeXOfRect = columnWidths[j] + cellSpacing; + + if (cornerX == 1) + positionX -= sizeXOfRect; + + SetChildAlongAxis(rectChildren[childIndex], 0, positionX, columnWidths[j]); + + if (cornerX != 1) + positionX += sizeXOfRect; + + maxPreferredHeightInRow = Mathf.Max(LayoutUtility.GetPreferredHeight(rectChildren[childIndex]), maxPreferredHeightInRow); + } + + maxPreferredHeightInRow = Mathf.Max(minimumRowHeight, maxPreferredHeightInRow); + float sizeYOfRect = maxPreferredHeightInRow + rowSpacing; + + if (cornerY == 1) + positionY -= sizeYOfRect; + + for (int j = 0; j < columnCount; j++) + { + int childIndex = (i * columnCount) + j; + + if (childIndex >= rectChildren.Count) + break; + + SetChildAlongAxis(rectChildren[childIndex], 1, positionY, maxPreferredHeightInRow); + } + + if (cornerY != 1) + positionY += sizeYOfRect; + } + } + } +} \ No newline at end of file From bbd5102246ba280074e7edd74093268c3164cbff Mon Sep 17 00:00:00 2001 From: Rahul Raman Date: Tue, 27 Dec 2016 20:14:03 +0000 Subject: [PATCH 02/11] Renaming "TableLayout.cs" to "TableLayoutGroup.cs" to be consistent with Unity component naming --HG-- branch : develop_5.3 --- Scripts/Layout/{TableLayout.cs => TableLayoutGroup.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Scripts/Layout/{TableLayout.cs => TableLayoutGroup.cs} (100%) diff --git a/Scripts/Layout/TableLayout.cs b/Scripts/Layout/TableLayoutGroup.cs similarity index 100% rename from Scripts/Layout/TableLayout.cs rename to Scripts/Layout/TableLayoutGroup.cs From 81dd26b5ef292fb9450009d7e80c51e9f352ae22 Mon Sep 17 00:00:00 2001 From: Rahul Raman Date: Tue, 27 Dec 2016 20:16:50 +0000 Subject: [PATCH 03/11] Edited SetLayoutVertical() to avoid unnecessary recomputation of maxPreferredHeightInRow --HG-- branch : develop_5.3 --- Scripts/Layout/TableLayoutGroup.cs | 31 ++++++++++-------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/Scripts/Layout/TableLayoutGroup.cs b/Scripts/Layout/TableLayoutGroup.cs index 4ee3be7..b48d6b4 100644 --- a/Scripts/Layout/TableLayoutGroup.cs +++ b/Scripts/Layout/TableLayoutGroup.cs @@ -6,7 +6,7 @@ namespace UnityEngine.UI.Extensions /// /// Arranges child objects into a non-uniform grid, with fixed column widths and flexible row heights /// - public class TableLayout : LayoutGroup + public class TableLayoutGroup : LayoutGroup { public enum Corner { @@ -190,6 +190,8 @@ namespace UnityEngine.UI.Extensions float requiredHeightWithoutPadding = 0; + float[] maxPreferredHeightInRows = new float[rowCount]; + for (int i = 0; i < rowCount; i++) { float maxPreferredHeightInRow = 0; @@ -205,6 +207,7 @@ namespace UnityEngine.UI.Extensions } maxPreferredHeightInRow = Mathf.Max(minimumRowHeight, maxPreferredHeightInRow); + maxPreferredHeightInRows[i] = maxPreferredHeightInRow; requiredHeightWithoutPadding += maxPreferredHeightInRow; requiredHeightWithoutPadding += rowSpacing; } @@ -225,7 +228,10 @@ namespace UnityEngine.UI.Extensions { float positionX = startOffset.x; - float maxPreferredHeightInRow = 0; + float sizeYOfRect = maxPreferredHeightInRows[i] + rowSpacing; + + if (cornerY == 1) + positionY -= sizeYOfRect; for (int j = 0; j < columnCount; j++) { @@ -240,29 +246,12 @@ namespace UnityEngine.UI.Extensions positionX -= sizeXOfRect; SetChildAlongAxis(rectChildren[childIndex], 0, positionX, columnWidths[j]); + SetChildAlongAxis(rectChildren[childIndex], 1, positionY, maxPreferredHeightInRows[i]); if (cornerX != 1) positionX += sizeXOfRect; - - maxPreferredHeightInRow = Mathf.Max(LayoutUtility.GetPreferredHeight(rectChildren[childIndex]), maxPreferredHeightInRow); } - - maxPreferredHeightInRow = Mathf.Max(minimumRowHeight, maxPreferredHeightInRow); - float sizeYOfRect = maxPreferredHeightInRow + rowSpacing; - - if (cornerY == 1) - positionY -= sizeYOfRect; - - for (int j = 0; j < columnCount; j++) - { - int childIndex = (i * columnCount) + j; - - if (childIndex >= rectChildren.Count) - break; - - SetChildAlongAxis(rectChildren[childIndex], 1, positionY, maxPreferredHeightInRow); - } - + if (cornerY != 1) positionY += sizeYOfRect; } From ff95c38ee2c8b2c9361c715790a76326227de19b Mon Sep 17 00:00:00 2001 From: Rahul Raman Date: Tue, 27 Dec 2016 20:28:12 +0000 Subject: [PATCH 04/11] Fixed computation of cell positions for all start corners --HG-- branch : develop_5.3 --- Scripts/Layout/TableLayoutGroup.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Scripts/Layout/TableLayoutGroup.cs b/Scripts/Layout/TableLayoutGroup.cs index b48d6b4..487ffc6 100644 --- a/Scripts/Layout/TableLayoutGroup.cs +++ b/Scripts/Layout/TableLayoutGroup.cs @@ -231,7 +231,7 @@ namespace UnityEngine.UI.Extensions float sizeYOfRect = maxPreferredHeightInRows[i] + rowSpacing; if (cornerY == 1) - positionY -= sizeYOfRect; + positionY -= maxPreferredHeightInRows[i]; for (int j = 0; j < columnCount; j++) { @@ -243,16 +243,20 @@ namespace UnityEngine.UI.Extensions float sizeXOfRect = columnWidths[j] + cellSpacing; if (cornerX == 1) - positionX -= sizeXOfRect; + positionX -= columnWidths[j]; SetChildAlongAxis(rectChildren[childIndex], 0, positionX, columnWidths[j]); SetChildAlongAxis(rectChildren[childIndex], 1, positionY, maxPreferredHeightInRows[i]); - if (cornerX != 1) + if (cornerX == 1) + positionX -= cellSpacing; + else positionX += sizeXOfRect; } - - if (cornerY != 1) + + if (cornerY == 1) + positionY -= rowSpacing; + else positionY += sizeYOfRect; } } From da480b1f8bba0e769a3f282f4601c41c4b56984b Mon Sep 17 00:00:00 2001 From: Rahul Raman Date: Tue, 27 Dec 2016 20:46:57 +0000 Subject: [PATCH 05/11] Clean up: Removed duplicate calculations and unnecessary intermediate variables. --HG-- branch : develop_5.3 --- Scripts/Layout/TableLayoutGroup.cs | 64 +++++++++++------------------- 1 file changed, 23 insertions(+), 41 deletions(-) diff --git a/Scripts/Layout/TableLayoutGroup.cs b/Scripts/Layout/TableLayoutGroup.cs index 487ffc6..76ce0a9 100644 --- a/Scripts/Layout/TableLayoutGroup.cs +++ b/Scripts/Layout/TableLayoutGroup.cs @@ -86,6 +86,8 @@ namespace UnityEngine.UI.Extensions } } + private float[] maxPreferredHeightInRows; + public override void CalculateLayoutInputHorizontal() { base.CalculateLayoutInputHorizontal(); @@ -108,6 +110,8 @@ namespace UnityEngine.UI.Extensions { int rowCount = Mathf.CeilToInt(rectChildren.Count / (float)columnWidths.Length); + maxPreferredHeightInRows = new float[rowCount]; + float totalMinHeight = padding.vertical; float totalPreferredHeight = padding.vertical; @@ -139,10 +143,10 @@ namespace UnityEngine.UI.Extensions totalMinHeight += maxMinimumHeightInRow; maxPreferredHeightInRow = Mathf.Max(minimumRowHeight, maxPreferredHeightInRow); + maxPreferredHeightInRows[i] = maxPreferredHeightInRow; totalPreferredHeight += maxPreferredHeightInRow; } - totalPreferredHeight = Mathf.Max(totalMinHeight, totalPreferredHeight); SetLayoutInputForAxis(totalMinHeight, totalPreferredHeight, 1, 1); } @@ -177,59 +181,39 @@ namespace UnityEngine.UI.Extensions int cornerY = (int)startCorner / 2; Vector2 startOffset = new Vector2(); - - float requiredWidthWithoutPadding = 0; - for (int i = 0; i < columnWidths.Length; i++) + Vector2 requiredSizeWithoutPadding = new Vector2(); + + for (int i = 0; i < columnCount; i++) { - requiredWidthWithoutPadding += columnWidths[i]; - requiredWidthWithoutPadding += cellSpacing; + requiredSizeWithoutPadding.x += columnWidths[i]; + requiredSizeWithoutPadding.x += cellSpacing; } - requiredWidthWithoutPadding -= cellSpacing; - - startOffset.x = GetStartOffset(0, requiredWidthWithoutPadding); - - float requiredHeightWithoutPadding = 0; - - float[] maxPreferredHeightInRows = new float[rowCount]; + requiredSizeWithoutPadding.x -= cellSpacing; + startOffset.x = GetStartOffset(0, requiredSizeWithoutPadding.x); + for (int i = 0; i < rowCount; i++) { - float maxPreferredHeightInRow = 0; - - for (int j = 0; j < columnCount; j++) - { - int childIndex = (i * columnCount) + j; - - if (childIndex >= rectChildren.Count) - break; - - maxPreferredHeightInRow = Mathf.Max(LayoutUtility.GetPreferredHeight(rectChildren[childIndex]), maxPreferredHeightInRow); - } - - maxPreferredHeightInRow = Mathf.Max(minimumRowHeight, maxPreferredHeightInRow); - maxPreferredHeightInRows[i] = maxPreferredHeightInRow; - requiredHeightWithoutPadding += maxPreferredHeightInRow; - requiredHeightWithoutPadding += rowSpacing; + requiredSizeWithoutPadding.y += maxPreferredHeightInRows[i]; + requiredSizeWithoutPadding.y += rowSpacing; } - requiredHeightWithoutPadding -= rowSpacing; + requiredSizeWithoutPadding.y -= rowSpacing; - startOffset.y = GetStartOffset(1, requiredHeightWithoutPadding); + startOffset.y = GetStartOffset(1, requiredSizeWithoutPadding.y); if (cornerX == 1) - startOffset.x += requiredWidthWithoutPadding; + startOffset.x += requiredSizeWithoutPadding.x; if (cornerY == 1) - startOffset.y += requiredHeightWithoutPadding; + startOffset.y += requiredSizeWithoutPadding.y; float positionY = startOffset.y; for (int i = 0; i < rowCount; i++) { float positionX = startOffset.x; - - float sizeYOfRect = maxPreferredHeightInRows[i] + rowSpacing; - + if (cornerY == 1) positionY -= maxPreferredHeightInRows[i]; @@ -239,9 +223,7 @@ namespace UnityEngine.UI.Extensions if (childIndex >= rectChildren.Count) break; - - float sizeXOfRect = columnWidths[j] + cellSpacing; - + if (cornerX == 1) positionX -= columnWidths[j]; @@ -251,13 +233,13 @@ namespace UnityEngine.UI.Extensions if (cornerX == 1) positionX -= cellSpacing; else - positionX += sizeXOfRect; + positionX += columnWidths[j] + cellSpacing; } if (cornerY == 1) positionY -= rowSpacing; else - positionY += sizeYOfRect; + positionY += maxPreferredHeightInRows[i] + rowSpacing; } } } From 9cf482d6eddae16a91137ef6385f8da919dc7738 Mon Sep 17 00:00:00 2001 From: Rahul Raman Date: Tue, 27 Dec 2016 21:34:16 +0000 Subject: [PATCH 06/11] Allowed flexible row expansion as a choice, instead of a compulsion --HG-- branch : develop_5.3 --- Scripts/Layout/TableLayoutGroup.cs | 77 ++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/Scripts/Layout/TableLayoutGroup.cs b/Scripts/Layout/TableLayoutGroup.cs index 76ce0a9..160b52a 100644 --- a/Scripts/Layout/TableLayoutGroup.cs +++ b/Scripts/Layout/TableLayoutGroup.cs @@ -15,7 +15,7 @@ namespace UnityEngine.UI.Extensions LowerLeft = 2, LowerRight = 3 } - + [SerializeField] protected Corner startCorner = Corner.UpperLeft; /// @@ -58,6 +58,20 @@ namespace UnityEngine.UI.Extensions } } + [SerializeField] + protected bool flexibleRowHeight = true; + /// + /// Expand rows to fit the cell with the highest preferred height? + /// + public bool FlexibleRowHeight + { + get { return flexibleRowHeight; } + set + { + SetProperty(ref flexibleRowHeight, value); + } + } + [SerializeField] protected float cellSpacing = 0f; /// @@ -71,7 +85,7 @@ namespace UnityEngine.UI.Extensions SetProperty(ref cellSpacing, value); } } - + [SerializeField] protected float rowSpacing = 0; /// @@ -121,32 +135,45 @@ namespace UnityEngine.UI.Extensions totalMinHeight += heightFromSpacing; totalPreferredHeight += heightFromSpacing; } - - // Find the max value for minimum and preferred heights in each row - for (int i = 0; i < rowCount; i++) + + if (flexibleRowHeight) { - float maxMinimumHeightInRow = 0; - float maxPreferredHeightInRow = 0; - - for (int j = 0; j < columnWidths.Length; j++) + // Find the max value for minimum and preferred heights in each row + for (int i = 0; i < rowCount; i++) { - int childIndex = (i * columnWidths.Length) + j; + float maxMinimumHeightInRow = 0; + float maxPreferredHeightInRow = 0; - if (childIndex >= rectChildren.Count) - break; + for (int j = 0; j < columnWidths.Length; j++) + { + int childIndex = (i * columnWidths.Length) + j; - maxPreferredHeightInRow = Mathf.Max(LayoutUtility.GetPreferredHeight(rectChildren[childIndex]), maxPreferredHeightInRow); - maxMinimumHeightInRow = Mathf.Max(LayoutUtility.GetMinHeight(rectChildren[childIndex]), maxMinimumHeightInRow); + if (childIndex >= rectChildren.Count) + break; + + maxPreferredHeightInRow = Mathf.Max(LayoutUtility.GetPreferredHeight(rectChildren[childIndex]), maxPreferredHeightInRow); + maxMinimumHeightInRow = Mathf.Max(LayoutUtility.GetMinHeight(rectChildren[childIndex]), maxMinimumHeightInRow); + } + + maxMinimumHeightInRow = Mathf.Max(minimumRowHeight, maxMinimumHeightInRow); + totalMinHeight += maxMinimumHeightInRow; + + maxPreferredHeightInRow = Mathf.Max(minimumRowHeight, maxPreferredHeightInRow); + maxPreferredHeightInRows[i] = maxPreferredHeightInRow; + totalPreferredHeight += maxPreferredHeightInRow; + } + } + else + { + for (int i = 0; i < rowCount; i++) + { + maxPreferredHeightInRows[i] = minimumRowHeight; } - maxMinimumHeightInRow = Mathf.Max(minimumRowHeight, maxMinimumHeightInRow); - totalMinHeight += maxMinimumHeightInRow; - - maxPreferredHeightInRow = Mathf.Max(minimumRowHeight, maxPreferredHeightInRow); - maxPreferredHeightInRows[i] = maxPreferredHeightInRow; - totalPreferredHeight += maxPreferredHeightInRow; + totalMinHeight += rowCount * minimumRowHeight; + totalPreferredHeight = totalMinHeight; } - + totalPreferredHeight = Mathf.Max(totalMinHeight, totalPreferredHeight); SetLayoutInputForAxis(totalMinHeight, totalPreferredHeight, 1, 1); } @@ -182,7 +209,7 @@ namespace UnityEngine.UI.Extensions Vector2 startOffset = new Vector2(); Vector2 requiredSizeWithoutPadding = new Vector2(); - + for (int i = 0; i < columnCount; i++) { requiredSizeWithoutPadding.x += columnWidths[i]; @@ -191,7 +218,7 @@ namespace UnityEngine.UI.Extensions requiredSizeWithoutPadding.x -= cellSpacing; startOffset.x = GetStartOffset(0, requiredSizeWithoutPadding.x); - + for (int i = 0; i < rowCount; i++) { requiredSizeWithoutPadding.y += maxPreferredHeightInRows[i]; @@ -213,7 +240,7 @@ namespace UnityEngine.UI.Extensions for (int i = 0; i < rowCount; i++) { float positionX = startOffset.x; - + if (cornerY == 1) positionY -= maxPreferredHeightInRows[i]; @@ -223,7 +250,7 @@ namespace UnityEngine.UI.Extensions if (childIndex >= rectChildren.Count) break; - + if (cornerX == 1) positionX -= columnWidths[j]; From b8bd3712329f9951409eb6b00a52744b35991757 Mon Sep 17 00:00:00 2001 From: Rahul Raman Date: Tue, 27 Dec 2016 21:54:32 +0000 Subject: [PATCH 07/11] Cleanup: Added sensible defaults. Removed all initialization errors. --HG-- branch : develop_5.3 --- Scripts/Layout/TableLayoutGroup.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Scripts/Layout/TableLayoutGroup.cs b/Scripts/Layout/TableLayoutGroup.cs index 160b52a..0d68bd3 100644 --- a/Scripts/Layout/TableLayoutGroup.cs +++ b/Scripts/Layout/TableLayoutGroup.cs @@ -31,7 +31,7 @@ namespace UnityEngine.UI.Extensions } [SerializeField] - protected float[] columnWidths = new float[0]; + protected float[] columnWidths = new float[1] { 96f }; /// /// The widths of all the columns in the table /// @@ -122,6 +122,9 @@ namespace UnityEngine.UI.Extensions public override void CalculateLayoutInputVertical() { + if (columnWidths.Length == 0) + return; + int rowCount = Mathf.CeilToInt(rectChildren.Count / (float)columnWidths.Length); maxPreferredHeightInRows = new float[rowCount]; @@ -182,6 +185,9 @@ namespace UnityEngine.UI.Extensions { int columnCount = columnWidths.Length; + if (columnCount == 0) + return; + for (int i = 0; i < rectChildren.Count; i++) { RectTransform child = rectChildren[i]; @@ -199,11 +205,14 @@ namespace UnityEngine.UI.Extensions public override void SetLayoutVertical() { - float tableLayoutHeight = rectTransform.rect.height; - int columnCount = columnWidths.Length; + if (columnCount == 0) + return; + int rowCount = Mathf.CeilToInt(rectChildren.Count / (float)columnCount); + float tableLayoutHeight = rectTransform.rect.height; + int cornerX = (int)startCorner % 2; int cornerY = (int)startCorner / 2; From 2e8682a49139c41574b262087f0bd28f09d3d469 Mon Sep 17 00:00:00 2001 From: Rahul Raman Date: Tue, 27 Dec 2016 21:59:20 +0000 Subject: [PATCH 08/11] Cleanup: Renamed "Cell Spacing" as "Column Spacing" --HG-- branch : develop_5.3 --- Scripts/Layout/TableLayoutGroup.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Scripts/Layout/TableLayoutGroup.cs b/Scripts/Layout/TableLayoutGroup.cs index 0d68bd3..f6363f4 100644 --- a/Scripts/Layout/TableLayoutGroup.cs +++ b/Scripts/Layout/TableLayoutGroup.cs @@ -73,16 +73,16 @@ namespace UnityEngine.UI.Extensions } [SerializeField] - protected float cellSpacing = 0f; + protected float columnSpacing = 0f; /// /// The horizontal spacing between each cell in the table /// - public float CellSpacing + public float ColumnSpacing { - get { return cellSpacing; } + get { return columnSpacing; } set { - SetProperty(ref cellSpacing, value); + SetProperty(ref columnSpacing, value); } } @@ -109,7 +109,7 @@ namespace UnityEngine.UI.Extensions float horizontalSize = padding.horizontal; if (columnWidths.Length > 1) - horizontalSize += ((columnWidths.Length - 1) * cellSpacing); + horizontalSize += ((columnWidths.Length - 1) * columnSpacing); // We calculate the actual cell count for cases where the number of children is lesser than the number of columns int actualCellCount = Mathf.Min(rectChildren.Count, columnWidths.Length); @@ -222,9 +222,9 @@ namespace UnityEngine.UI.Extensions for (int i = 0; i < columnCount; i++) { requiredSizeWithoutPadding.x += columnWidths[i]; - requiredSizeWithoutPadding.x += cellSpacing; + requiredSizeWithoutPadding.x += columnSpacing; } - requiredSizeWithoutPadding.x -= cellSpacing; + requiredSizeWithoutPadding.x -= columnSpacing; startOffset.x = GetStartOffset(0, requiredSizeWithoutPadding.x); @@ -267,9 +267,9 @@ namespace UnityEngine.UI.Extensions SetChildAlongAxis(rectChildren[childIndex], 1, positionY, maxPreferredHeightInRows[i]); if (cornerX == 1) - positionX -= cellSpacing; + positionX -= columnSpacing; else - positionX += columnWidths[j] + cellSpacing; + positionX += columnWidths[j] + columnSpacing; } if (cornerY == 1) From 5a64abfa80d9500a8420add4efd8546129a8071d Mon Sep 17 00:00:00 2001 From: Rahul Raman Date: Wed, 28 Dec 2016 06:46:38 +0000 Subject: [PATCH 09/11] Fixed behaviour when no column width is provided --HG-- branch : develop_5.3 --- Scripts/Layout/TableLayoutGroup.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Scripts/Layout/TableLayoutGroup.cs b/Scripts/Layout/TableLayoutGroup.cs index f6363f4..e1d91ea 100644 --- a/Scripts/Layout/TableLayoutGroup.cs +++ b/Scripts/Layout/TableLayoutGroup.cs @@ -122,9 +122,6 @@ namespace UnityEngine.UI.Extensions public override void CalculateLayoutInputVertical() { - if (columnWidths.Length == 0) - return; - int rowCount = Mathf.CeilToInt(rectChildren.Count / (float)columnWidths.Length); maxPreferredHeightInRows = new float[rowCount]; @@ -183,10 +180,10 @@ namespace UnityEngine.UI.Extensions public override void SetLayoutHorizontal() { - int columnCount = columnWidths.Length; + if (columnWidths.Length == 0) + columnWidths = new float[1] { 0f }; - if (columnCount == 0) - return; + int columnCount = columnWidths.Length; for (int i = 0; i < rectChildren.Count; i++) { @@ -206,8 +203,6 @@ namespace UnityEngine.UI.Extensions public override void SetLayoutVertical() { int columnCount = columnWidths.Length; - if (columnCount == 0) - return; int rowCount = Mathf.CeilToInt(rectChildren.Count / (float)columnCount); From 1d251301eb7aa55fc3a48174f3fce72df2137358 Mon Sep 17 00:00:00 2001 From: Rahul Raman Date: Wed, 28 Dec 2016 16:15:52 +0000 Subject: [PATCH 10/11] Improved calculation of SetLayoutHorizontal and SetLayoutVertical; Renamed certain variables, removed certain others and refactored code to be more sensible; Fixed behaviour for a specific configuration of TableLayoutGroup and ContentSizeFitter --HG-- branch : develop_5.3 --- Scripts/Layout/TableLayoutGroup.cs | 147 ++++++++++++++--------------- 1 file changed, 73 insertions(+), 74 deletions(-) diff --git a/Scripts/Layout/TableLayoutGroup.cs b/Scripts/Layout/TableLayoutGroup.cs index e1d91ea..9263344 100644 --- a/Scripts/Layout/TableLayoutGroup.cs +++ b/Scripts/Layout/TableLayoutGroup.cs @@ -100,31 +100,34 @@ namespace UnityEngine.UI.Extensions } } - private float[] maxPreferredHeightInRows; + private float[] preferredRowHeights; public override void CalculateLayoutInputHorizontal() { base.CalculateLayoutInputHorizontal(); float horizontalSize = padding.horizontal; - - if (columnWidths.Length > 1) - horizontalSize += ((columnWidths.Length - 1) * columnSpacing); - + // We calculate the actual cell count for cases where the number of children is lesser than the number of columns int actualCellCount = Mathf.Min(rectChildren.Count, columnWidths.Length); for (int i = 0; i < actualCellCount; i++) + { horizontalSize += columnWidths[i]; + horizontalSize += columnSpacing; + } + + horizontalSize -= columnSpacing; SetLayoutInputForAxis(horizontalSize, horizontalSize, 0, 0); } public override void CalculateLayoutInputVertical() { - int rowCount = Mathf.CeilToInt(rectChildren.Count / (float)columnWidths.Length); + int columnCount = columnWidths.Length; + int rowCount = Mathf.CeilToInt(rectChildren.Count / (float)columnCount); - maxPreferredHeightInRows = new float[rowCount]; + preferredRowHeights = new float[rowCount]; float totalMinHeight = padding.vertical; float totalPreferredHeight = padding.vertical; @@ -144,9 +147,9 @@ namespace UnityEngine.UI.Extensions float maxMinimumHeightInRow = 0; float maxPreferredHeightInRow = 0; - for (int j = 0; j < columnWidths.Length; j++) + for (int j = 0; j < columnCount; j++) { - int childIndex = (i * columnWidths.Length) + j; + int childIndex = (i * columnCount) + j; if (childIndex >= rectChildren.Count) break; @@ -159,7 +162,7 @@ namespace UnityEngine.UI.Extensions totalMinHeight += maxMinimumHeightInRow; maxPreferredHeightInRow = Mathf.Max(minimumRowHeight, maxPreferredHeightInRow); - maxPreferredHeightInRows[i] = maxPreferredHeightInRow; + preferredRowHeights[i] = maxPreferredHeightInRow; totalPreferredHeight += maxPreferredHeightInRow; } } @@ -167,7 +170,7 @@ namespace UnityEngine.UI.Extensions { for (int i = 0; i < rowCount; i++) { - maxPreferredHeightInRows[i] = minimumRowHeight; + preferredRowHeights[i] = minimumRowHeight; } totalMinHeight += rowCount * minimumRowHeight; @@ -184,93 +187,89 @@ namespace UnityEngine.UI.Extensions columnWidths = new float[1] { 0f }; int columnCount = columnWidths.Length; + int cornerX = (int)startCorner % 2; + + float startOffset = 0; + float requiredSizeWithoutPadding = 0; + int actualCellCount = Mathf.Min(rectChildren.Count, columnWidths.Length); + + for (int i = 0; i < actualCellCount; i++) + { + requiredSizeWithoutPadding += columnWidths[i]; + requiredSizeWithoutPadding += columnSpacing; + } + + requiredSizeWithoutPadding -= columnSpacing; + + startOffset = GetStartOffset(0, requiredSizeWithoutPadding); + + if (cornerX == 1) + startOffset += requiredSizeWithoutPadding; + + float positionX = startOffset; for (int i = 0; i < rectChildren.Count; i++) { - RectTransform child = rectChildren[i]; - m_Tracker.Add(this, child, - DrivenTransformProperties.Anchors | - DrivenTransformProperties.AnchoredPosition | - DrivenTransformProperties.SizeDelta); - child.anchorMin = Vector2.up; - child.anchorMax = Vector2.up; - Vector2 childSizeDelta = child.sizeDelta; - childSizeDelta.x = columnWidths[i % columnCount]; - child.sizeDelta = childSizeDelta; + int currentRowIndex = i / columnCount; + int currentColumnIndex = i % columnCount; + + if (currentColumnIndex == 0) + positionX = startOffset; + + if (cornerX == 1) + positionX -= columnWidths[currentColumnIndex]; + + SetChildAlongAxis(rectChildren[i], 0, positionX, columnWidths[currentColumnIndex]); + + if (cornerX == 1) + positionX -= columnSpacing; + else + positionX += columnWidths[currentColumnIndex] + columnSpacing; } } public override void SetLayoutVertical() { int columnCount = columnWidths.Length; - - int rowCount = Mathf.CeilToInt(rectChildren.Count / (float)columnCount); - - float tableLayoutHeight = rectTransform.rect.height; - - int cornerX = (int)startCorner % 2; + int rowCount = preferredRowHeights.Length; + int cornerY = (int)startCorner / 2; - Vector2 startOffset = new Vector2(); - Vector2 requiredSizeWithoutPadding = new Vector2(); - - for (int i = 0; i < columnCount; i++) - { - requiredSizeWithoutPadding.x += columnWidths[i]; - requiredSizeWithoutPadding.x += columnSpacing; - } - requiredSizeWithoutPadding.x -= columnSpacing; - - startOffset.x = GetStartOffset(0, requiredSizeWithoutPadding.x); - + float startOffset = 0; + float requiredSizeWithoutPadding = 0; + for (int i = 0; i < rowCount; i++) { - requiredSizeWithoutPadding.y += maxPreferredHeightInRows[i]; - requiredSizeWithoutPadding.y += rowSpacing; + requiredSizeWithoutPadding += preferredRowHeights[i]; + requiredSizeWithoutPadding += rowSpacing; } - requiredSizeWithoutPadding.y -= rowSpacing; - - startOffset.y = GetStartOffset(1, requiredSizeWithoutPadding.y); - - if (cornerX == 1) - startOffset.x += requiredSizeWithoutPadding.x; + requiredSizeWithoutPadding -= rowSpacing; + startOffset = GetStartOffset(1, requiredSizeWithoutPadding); + if (cornerY == 1) - startOffset.y += requiredSizeWithoutPadding.y; + startOffset += requiredSizeWithoutPadding; - float positionY = startOffset.y; + float positionY = startOffset; - for (int i = 0; i < rowCount; i++) + for (int i = 0; i < rectChildren.Count; i++) { - float positionX = startOffset.x; + int currentRowIndex = i / columnCount; + int currentColumnIndex = i % columnCount; - if (cornerY == 1) - positionY -= maxPreferredHeightInRows[i]; - - for (int j = 0; j < columnCount; j++) + if (currentColumnIndex == 0 && cornerY == 1) + positionY -= preferredRowHeights[currentRowIndex]; + + SetChildAlongAxis(rectChildren[i], 1, positionY, preferredRowHeights[currentRowIndex]); + + if (currentColumnIndex == columnCount - 1) { - int childIndex = (i * columnCount) + j; - - if (childIndex >= rectChildren.Count) - break; - - if (cornerX == 1) - positionX -= columnWidths[j]; - - SetChildAlongAxis(rectChildren[childIndex], 0, positionX, columnWidths[j]); - SetChildAlongAxis(rectChildren[childIndex], 1, positionY, maxPreferredHeightInRows[i]); - - if (cornerX == 1) - positionX -= columnSpacing; + if (cornerY == 1) + positionY -= rowSpacing; else - positionX += columnWidths[j] + columnSpacing; + positionY += preferredRowHeights[currentRowIndex] + rowSpacing; } - - if (cornerY == 1) - positionY -= rowSpacing; - else - positionY += maxPreferredHeightInRows[i] + rowSpacing; } } } From 6888cb500da6d4202f2c15b8d5800899ff6e2c0e Mon Sep 17 00:00:00 2001 From: Rahul Raman Date: Wed, 28 Dec 2016 20:37:03 +0000 Subject: [PATCH 11/11] Refactored CalculateLayoutInputVertical; Released memory used by temporary array for reclaiming by the GC; Added comments to help understand the script better --HG-- branch : develop_5.3 --- Scripts/Layout/TableLayoutGroup.cs | 58 ++++++++++++++++++------------ 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/Scripts/Layout/TableLayoutGroup.cs b/Scripts/Layout/TableLayoutGroup.cs index 9263344..6c44751 100644 --- a/Scripts/Layout/TableLayoutGroup.cs +++ b/Scripts/Layout/TableLayoutGroup.cs @@ -99,7 +99,8 @@ namespace UnityEngine.UI.Extensions SetProperty(ref rowSpacing, value); } } - + + // Temporarily stores data generated during the execution CalculateLayoutInputVertical for use in SetLayoutVertical private float[] preferredRowHeights; public override void CalculateLayoutInputHorizontal() @@ -141,37 +142,42 @@ namespace UnityEngine.UI.Extensions if (flexibleRowHeight) { - // Find the max value for minimum and preferred heights in each row - for (int i = 0; i < rowCount; i++) + // If flexibleRowHeight is enabled, find the max value for minimum and preferred heights in each row + + float maxMinimumHeightInRow = 0; + float maxPreferredHeightInRow = 0; + + for (int i = 0; i < rectChildren.Count; i++) { - float maxMinimumHeightInRow = 0; - float maxPreferredHeightInRow = 0; + int currentRowIndex = i / columnCount; + int currentColumnIndex = i % columnCount; - for (int j = 0; j < columnCount; j++) + // If it's the first cell in the row, reset heights for the row + if (currentColumnIndex == 0) { - int childIndex = (i * columnCount) + j; - - if (childIndex >= rectChildren.Count) - break; - - maxPreferredHeightInRow = Mathf.Max(LayoutUtility.GetPreferredHeight(rectChildren[childIndex]), maxPreferredHeightInRow); - maxMinimumHeightInRow = Mathf.Max(LayoutUtility.GetMinHeight(rectChildren[childIndex]), maxMinimumHeightInRow); + maxMinimumHeightInRow = minimumRowHeight; + maxPreferredHeightInRow = minimumRowHeight; } - maxMinimumHeightInRow = Mathf.Max(minimumRowHeight, maxMinimumHeightInRow); - totalMinHeight += maxMinimumHeightInRow; + maxPreferredHeightInRow = Mathf.Max(LayoutUtility.GetPreferredHeight(rectChildren[i]), maxPreferredHeightInRow); + maxMinimumHeightInRow = Mathf.Max(LayoutUtility.GetMinHeight(rectChildren[i]), maxMinimumHeightInRow); - maxPreferredHeightInRow = Mathf.Max(minimumRowHeight, maxPreferredHeightInRow); - preferredRowHeights[i] = maxPreferredHeightInRow; - totalPreferredHeight += maxPreferredHeightInRow; + // If it's the last cell in the row, or if it's the last cell and the row is incomplete, set calculated heights + if (currentColumnIndex == columnCount - 1 || (i == rectChildren.Count - 1 && currentRowIndex == rowCount - 1)) + { + totalMinHeight += maxMinimumHeightInRow; + totalPreferredHeight += maxPreferredHeightInRow; + + // Add calculated row height to a commonly accessible array for reuse in SetLayoutVertical() + preferredRowHeights[currentRowIndex] = maxPreferredHeightInRow; + } } } else { + // If flexibleRowHeight is disabled, then use the minimumRowHeight to calculate vertical layout information for (int i = 0; i < rowCount; i++) - { preferredRowHeights[i] = minimumRowHeight; - } totalMinHeight += rowCount * minimumRowHeight; totalPreferredHeight = totalMinHeight; @@ -183,6 +189,7 @@ namespace UnityEngine.UI.Extensions public override void SetLayoutHorizontal() { + // If no column width is defined, then assign a reasonable default if (columnWidths.Length == 0) columnWidths = new float[1] { 0f }; @@ -191,6 +198,8 @@ namespace UnityEngine.UI.Extensions float startOffset = 0; float requiredSizeWithoutPadding = 0; + + // We calculate the actual cell count for cases where the number of children is lesser than the number of columns int actualCellCount = Mathf.Min(rectChildren.Count, columnWidths.Length); for (int i = 0; i < actualCellCount; i++) @@ -210,9 +219,9 @@ namespace UnityEngine.UI.Extensions for (int i = 0; i < rectChildren.Count; i++) { - int currentRowIndex = i / columnCount; int currentColumnIndex = i % columnCount; + // If it's the first cell in the row, reset positionX if (currentColumnIndex == 0) positionX = startOffset; @@ -258,11 +267,13 @@ namespace UnityEngine.UI.Extensions int currentRowIndex = i / columnCount; int currentColumnIndex = i % columnCount; + // If it's the first cell in the row and start corner is one of the bottom corners, then modify positionY appropriately if (currentColumnIndex == 0 && cornerY == 1) positionY -= preferredRowHeights[currentRowIndex]; SetChildAlongAxis(rectChildren[i], 1, positionY, preferredRowHeights[currentRowIndex]); - + + // If it's the first last cell in the row, then modify positionY appropriately if (currentColumnIndex == columnCount - 1) { if (cornerY == 1) @@ -271,6 +282,9 @@ namespace UnityEngine.UI.Extensions positionY += preferredRowHeights[currentRowIndex] + rowSpacing; } } + + // Set preferredRowHeights to null to free memory + preferredRowHeights = null; } } } \ No newline at end of file