Updated Table Layout Group component for release and added docs
--HG-- branch : develop_5.3release
parent
473c0f3757
commit
909589e544
|
@ -1,290 +1,291 @@
|
||||||
/// Credit RahulOfTheRamanEffect
|
/// Credit RahulOfTheRamanEffect
|
||||||
/// Sourced from - https://forum.unity3d.com/members/rahuloftheramaneffect.773241/
|
/// Sourced from - https://forum.unity3d.com/members/rahuloftheramaneffect.773241/
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Arranges child objects into a non-uniform grid, with fixed column widths and flexible row heights
|
/// Arranges child objects into a non-uniform grid, with fixed column widths and flexible row heights
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TableLayoutGroup : LayoutGroup
|
[AddComponentMenu("Layout/Extensions/Table Layout Group")]
|
||||||
{
|
public class TableLayoutGroup : LayoutGroup
|
||||||
public enum Corner
|
{
|
||||||
{
|
public enum Corner
|
||||||
UpperLeft = 0,
|
{
|
||||||
UpperRight = 1,
|
UpperLeft = 0,
|
||||||
LowerLeft = 2,
|
UpperRight = 1,
|
||||||
LowerRight = 3
|
LowerLeft = 2,
|
||||||
}
|
LowerRight = 3
|
||||||
|
}
|
||||||
[SerializeField]
|
|
||||||
protected Corner startCorner = Corner.UpperLeft;
|
[SerializeField]
|
||||||
/// <summary>
|
protected Corner startCorner = Corner.UpperLeft;
|
||||||
/// The corner starting from which the cells should be arranged
|
/// <summary>
|
||||||
/// </summary>
|
/// The corner starting from which the cells should be arranged
|
||||||
public Corner StartCorner
|
/// </summary>
|
||||||
{
|
public Corner StartCorner
|
||||||
get { return startCorner; }
|
{
|
||||||
set
|
get { return startCorner; }
|
||||||
{
|
set
|
||||||
SetProperty(ref startCorner, value);
|
{
|
||||||
}
|
SetProperty(ref startCorner, value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
[SerializeField]
|
|
||||||
protected float[] columnWidths = new float[1] { 96f };
|
[SerializeField]
|
||||||
/// <summary>
|
protected float[] columnWidths = new float[1] { 96f };
|
||||||
/// The widths of all the columns in the table
|
/// <summary>
|
||||||
/// </summary>
|
/// The widths of all the columns in the table
|
||||||
public float[] ColumnWidths
|
/// </summary>
|
||||||
{
|
public float[] ColumnWidths
|
||||||
get { return columnWidths; }
|
{
|
||||||
set
|
get { return columnWidths; }
|
||||||
{
|
set
|
||||||
SetProperty(ref columnWidths, value);
|
{
|
||||||
}
|
SetProperty(ref columnWidths, value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
[SerializeField]
|
|
||||||
protected float minimumRowHeight = 32f;
|
[SerializeField]
|
||||||
/// <summary>
|
protected float minimumRowHeight = 32f;
|
||||||
/// The minimum height for any row in the table
|
/// <summary>
|
||||||
/// </summary>
|
/// The minimum height for any row in the table
|
||||||
public float MinimumRowHeight
|
/// </summary>
|
||||||
{
|
public float MinimumRowHeight
|
||||||
get { return minimumRowHeight; }
|
{
|
||||||
set
|
get { return minimumRowHeight; }
|
||||||
{
|
set
|
||||||
SetProperty(ref minimumRowHeight, value);
|
{
|
||||||
}
|
SetProperty(ref minimumRowHeight, value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
[SerializeField]
|
|
||||||
protected bool flexibleRowHeight = true;
|
[SerializeField]
|
||||||
/// <summary>
|
protected bool flexibleRowHeight = true;
|
||||||
/// Expand rows to fit the cell with the highest preferred height?
|
/// <summary>
|
||||||
/// </summary>
|
/// Expand rows to fit the cell with the highest preferred height?
|
||||||
public bool FlexibleRowHeight
|
/// </summary>
|
||||||
{
|
public bool FlexibleRowHeight
|
||||||
get { return flexibleRowHeight; }
|
{
|
||||||
set
|
get { return flexibleRowHeight; }
|
||||||
{
|
set
|
||||||
SetProperty(ref flexibleRowHeight, value);
|
{
|
||||||
}
|
SetProperty(ref flexibleRowHeight, value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
[SerializeField]
|
|
||||||
protected float columnSpacing = 0f;
|
[SerializeField]
|
||||||
/// <summary>
|
protected float columnSpacing = 0f;
|
||||||
/// The horizontal spacing between each cell in the table
|
/// <summary>
|
||||||
/// </summary>
|
/// The horizontal spacing between each cell in the table
|
||||||
public float ColumnSpacing
|
/// </summary>
|
||||||
{
|
public float ColumnSpacing
|
||||||
get { return columnSpacing; }
|
{
|
||||||
set
|
get { return columnSpacing; }
|
||||||
{
|
set
|
||||||
SetProperty(ref columnSpacing, value);
|
{
|
||||||
}
|
SetProperty(ref columnSpacing, value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
[SerializeField]
|
|
||||||
protected float rowSpacing = 0;
|
[SerializeField]
|
||||||
/// <summary>
|
protected float rowSpacing = 0;
|
||||||
/// The vertical spacing between each row in the table
|
/// <summary>
|
||||||
/// </summary>
|
/// The vertical spacing between each row in the table
|
||||||
public float RowSpacing
|
/// </summary>
|
||||||
{
|
public float RowSpacing
|
||||||
get { return rowSpacing; }
|
{
|
||||||
set
|
get { return rowSpacing; }
|
||||||
{
|
set
|
||||||
SetProperty(ref rowSpacing, value);
|
{
|
||||||
}
|
SetProperty(ref rowSpacing, value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Temporarily stores data generated during the execution CalculateLayoutInputVertical for use in SetLayoutVertical
|
|
||||||
private float[] preferredRowHeights;
|
// Temporarily stores data generated during the execution CalculateLayoutInputVertical for use in SetLayoutVertical
|
||||||
|
private float[] preferredRowHeights;
|
||||||
public override void CalculateLayoutInputHorizontal()
|
|
||||||
{
|
public override void CalculateLayoutInputHorizontal()
|
||||||
base.CalculateLayoutInputHorizontal();
|
{
|
||||||
|
base.CalculateLayoutInputHorizontal();
|
||||||
float horizontalSize = padding.horizontal;
|
|
||||||
|
float horizontalSize = padding.horizontal;
|
||||||
// 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);
|
// 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++)
|
|
||||||
{
|
for (int i = 0; i < actualCellCount; i++)
|
||||||
horizontalSize += columnWidths[i];
|
{
|
||||||
horizontalSize += columnSpacing;
|
horizontalSize += columnWidths[i];
|
||||||
}
|
horizontalSize += columnSpacing;
|
||||||
|
}
|
||||||
horizontalSize -= columnSpacing;
|
|
||||||
|
horizontalSize -= columnSpacing;
|
||||||
SetLayoutInputForAxis(horizontalSize, horizontalSize, 0, 0);
|
|
||||||
}
|
SetLayoutInputForAxis(horizontalSize, horizontalSize, 0, 0);
|
||||||
|
}
|
||||||
public override void CalculateLayoutInputVertical()
|
|
||||||
{
|
public override void CalculateLayoutInputVertical()
|
||||||
int columnCount = columnWidths.Length;
|
{
|
||||||
int rowCount = Mathf.CeilToInt(rectChildren.Count / (float)columnCount);
|
int columnCount = columnWidths.Length;
|
||||||
|
int rowCount = Mathf.CeilToInt(rectChildren.Count / (float)columnCount);
|
||||||
preferredRowHeights = new float[rowCount];
|
|
||||||
|
preferredRowHeights = new float[rowCount];
|
||||||
float totalMinHeight = padding.vertical;
|
|
||||||
float totalPreferredHeight = padding.vertical;
|
float totalMinHeight = padding.vertical;
|
||||||
|
float totalPreferredHeight = padding.vertical;
|
||||||
if (rowCount > 1)
|
|
||||||
{
|
if (rowCount > 1)
|
||||||
float heightFromSpacing = ((rowCount - 1) * rowSpacing);
|
{
|
||||||
totalMinHeight += heightFromSpacing;
|
float heightFromSpacing = ((rowCount - 1) * rowSpacing);
|
||||||
totalPreferredHeight += heightFromSpacing;
|
totalMinHeight += heightFromSpacing;
|
||||||
}
|
totalPreferredHeight += heightFromSpacing;
|
||||||
|
}
|
||||||
if (flexibleRowHeight)
|
|
||||||
{
|
if (flexibleRowHeight)
|
||||||
// If flexibleRowHeight is enabled, find the max value for minimum and preferred heights in each row
|
{
|
||||||
|
// If flexibleRowHeight is enabled, find the max value for minimum and preferred heights in each row
|
||||||
float maxMinimumHeightInRow = 0;
|
|
||||||
float maxPreferredHeightInRow = 0;
|
float maxMinimumHeightInRow = 0;
|
||||||
|
float maxPreferredHeightInRow = 0;
|
||||||
for (int i = 0; i < rectChildren.Count; i++)
|
|
||||||
{
|
for (int i = 0; i < rectChildren.Count; i++)
|
||||||
int currentRowIndex = i / columnCount;
|
{
|
||||||
int currentColumnIndex = i % columnCount;
|
int currentRowIndex = i / columnCount;
|
||||||
|
int currentColumnIndex = i % columnCount;
|
||||||
// If it's the first cell in the row, reset heights for the row
|
|
||||||
if (currentColumnIndex == 0)
|
// If it's the first cell in the row, reset heights for the row
|
||||||
{
|
if (currentColumnIndex == 0)
|
||||||
maxMinimumHeightInRow = minimumRowHeight;
|
{
|
||||||
maxPreferredHeightInRow = minimumRowHeight;
|
maxMinimumHeightInRow = minimumRowHeight;
|
||||||
}
|
maxPreferredHeightInRow = minimumRowHeight;
|
||||||
|
}
|
||||||
maxPreferredHeightInRow = Mathf.Max(LayoutUtility.GetPreferredHeight(rectChildren[i]), maxPreferredHeightInRow);
|
|
||||||
maxMinimumHeightInRow = Mathf.Max(LayoutUtility.GetMinHeight(rectChildren[i]), maxMinimumHeightInRow);
|
maxPreferredHeightInRow = Mathf.Max(LayoutUtility.GetPreferredHeight(rectChildren[i]), maxPreferredHeightInRow);
|
||||||
|
maxMinimumHeightInRow = Mathf.Max(LayoutUtility.GetMinHeight(rectChildren[i]), maxMinimumHeightInRow);
|
||||||
// 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))
|
// 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;
|
totalMinHeight += maxMinimumHeightInRow;
|
||||||
|
totalPreferredHeight += maxPreferredHeightInRow;
|
||||||
// Add calculated row height to a commonly accessible array for reuse in SetLayoutVertical()
|
|
||||||
preferredRowHeights[currentRowIndex] = maxPreferredHeightInRow;
|
// Add calculated row height to a commonly accessible array for reuse in SetLayoutVertical()
|
||||||
}
|
preferredRowHeights[currentRowIndex] = maxPreferredHeightInRow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
// If flexibleRowHeight is disabled, then use the minimumRowHeight to calculate vertical layout information
|
{
|
||||||
for (int i = 0; i < rowCount; i++)
|
// If flexibleRowHeight is disabled, then use the minimumRowHeight to calculate vertical layout information
|
||||||
preferredRowHeights[i] = minimumRowHeight;
|
for (int i = 0; i < rowCount; i++)
|
||||||
|
preferredRowHeights[i] = minimumRowHeight;
|
||||||
totalMinHeight += rowCount * minimumRowHeight;
|
|
||||||
totalPreferredHeight = totalMinHeight;
|
totalMinHeight += rowCount * minimumRowHeight;
|
||||||
}
|
totalPreferredHeight = totalMinHeight;
|
||||||
|
}
|
||||||
totalPreferredHeight = Mathf.Max(totalMinHeight, totalPreferredHeight);
|
|
||||||
SetLayoutInputForAxis(totalMinHeight, totalPreferredHeight, 1, 1);
|
totalPreferredHeight = Mathf.Max(totalMinHeight, totalPreferredHeight);
|
||||||
}
|
SetLayoutInputForAxis(totalMinHeight, totalPreferredHeight, 1, 1);
|
||||||
|
}
|
||||||
public override void SetLayoutHorizontal()
|
|
||||||
{
|
public override void SetLayoutHorizontal()
|
||||||
// If no column width is defined, then assign a reasonable default
|
{
|
||||||
if (columnWidths.Length == 0)
|
// If no column width is defined, then assign a reasonable default
|
||||||
columnWidths = new float[1] { 0f };
|
if (columnWidths.Length == 0)
|
||||||
|
columnWidths = new float[1] { 0f };
|
||||||
int columnCount = columnWidths.Length;
|
|
||||||
int cornerX = (int)startCorner % 2;
|
int columnCount = columnWidths.Length;
|
||||||
|
int cornerX = (int)startCorner % 2;
|
||||||
float startOffset = 0;
|
|
||||||
float requiredSizeWithoutPadding = 0;
|
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);
|
// 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++)
|
|
||||||
{
|
for (int i = 0; i < actualCellCount; i++)
|
||||||
requiredSizeWithoutPadding += columnWidths[i];
|
{
|
||||||
requiredSizeWithoutPadding += columnSpacing;
|
requiredSizeWithoutPadding += columnWidths[i];
|
||||||
}
|
requiredSizeWithoutPadding += columnSpacing;
|
||||||
|
}
|
||||||
requiredSizeWithoutPadding -= columnSpacing;
|
|
||||||
|
requiredSizeWithoutPadding -= columnSpacing;
|
||||||
startOffset = GetStartOffset(0, requiredSizeWithoutPadding);
|
|
||||||
|
startOffset = GetStartOffset(0, requiredSizeWithoutPadding);
|
||||||
if (cornerX == 1)
|
|
||||||
startOffset += requiredSizeWithoutPadding;
|
if (cornerX == 1)
|
||||||
|
startOffset += requiredSizeWithoutPadding;
|
||||||
float positionX = startOffset;
|
|
||||||
|
float positionX = startOffset;
|
||||||
for (int i = 0; i < rectChildren.Count; i++)
|
|
||||||
{
|
for (int i = 0; i < rectChildren.Count; i++)
|
||||||
int currentColumnIndex = i % columnCount;
|
{
|
||||||
|
int currentColumnIndex = i % columnCount;
|
||||||
// If it's the first cell in the row, reset positionX
|
|
||||||
if (currentColumnIndex == 0)
|
// If it's the first cell in the row, reset positionX
|
||||||
positionX = startOffset;
|
if (currentColumnIndex == 0)
|
||||||
|
positionX = startOffset;
|
||||||
if (cornerX == 1)
|
|
||||||
positionX -= columnWidths[currentColumnIndex];
|
if (cornerX == 1)
|
||||||
|
positionX -= columnWidths[currentColumnIndex];
|
||||||
SetChildAlongAxis(rectChildren[i], 0, positionX, columnWidths[currentColumnIndex]);
|
|
||||||
|
SetChildAlongAxis(rectChildren[i], 0, positionX, columnWidths[currentColumnIndex]);
|
||||||
if (cornerX == 1)
|
|
||||||
positionX -= columnSpacing;
|
if (cornerX == 1)
|
||||||
else
|
positionX -= columnSpacing;
|
||||||
positionX += columnWidths[currentColumnIndex] + columnSpacing;
|
else
|
||||||
}
|
positionX += columnWidths[currentColumnIndex] + columnSpacing;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public override void SetLayoutVertical()
|
|
||||||
{
|
public override void SetLayoutVertical()
|
||||||
int columnCount = columnWidths.Length;
|
{
|
||||||
int rowCount = preferredRowHeights.Length;
|
int columnCount = columnWidths.Length;
|
||||||
|
int rowCount = preferredRowHeights.Length;
|
||||||
int cornerY = (int)startCorner / 2;
|
|
||||||
|
int cornerY = (int)startCorner / 2;
|
||||||
float startOffset = 0;
|
|
||||||
float requiredSizeWithoutPadding = 0;
|
float startOffset = 0;
|
||||||
|
float requiredSizeWithoutPadding = 0;
|
||||||
for (int i = 0; i < rowCount; i++)
|
|
||||||
{
|
for (int i = 0; i < rowCount; i++)
|
||||||
requiredSizeWithoutPadding += preferredRowHeights[i];
|
{
|
||||||
requiredSizeWithoutPadding += rowSpacing;
|
requiredSizeWithoutPadding += preferredRowHeights[i];
|
||||||
}
|
requiredSizeWithoutPadding += rowSpacing;
|
||||||
|
}
|
||||||
requiredSizeWithoutPadding -= rowSpacing;
|
|
||||||
|
requiredSizeWithoutPadding -= rowSpacing;
|
||||||
startOffset = GetStartOffset(1, requiredSizeWithoutPadding);
|
|
||||||
|
startOffset = GetStartOffset(1, requiredSizeWithoutPadding);
|
||||||
if (cornerY == 1)
|
|
||||||
startOffset += requiredSizeWithoutPadding;
|
if (cornerY == 1)
|
||||||
|
startOffset += requiredSizeWithoutPadding;
|
||||||
float positionY = startOffset;
|
|
||||||
|
float positionY = startOffset;
|
||||||
for (int i = 0; i < rectChildren.Count; i++)
|
|
||||||
{
|
for (int i = 0; i < rectChildren.Count; i++)
|
||||||
int currentRowIndex = i / columnCount;
|
{
|
||||||
int currentColumnIndex = i % columnCount;
|
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)
|
// If it's the first cell in the row and start corner is one of the bottom corners, then modify positionY appropriately
|
||||||
positionY -= preferredRowHeights[currentRowIndex];
|
if (currentColumnIndex == 0 && cornerY == 1)
|
||||||
|
positionY -= preferredRowHeights[currentRowIndex];
|
||||||
SetChildAlongAxis(rectChildren[i], 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 it's the first last cell in the row, then modify positionY appropriately
|
||||||
{
|
if (currentColumnIndex == columnCount - 1)
|
||||||
if (cornerY == 1)
|
{
|
||||||
positionY -= rowSpacing;
|
if (cornerY == 1)
|
||||||
else
|
positionY -= rowSpacing;
|
||||||
positionY += preferredRowHeights[currentRowIndex] + rowSpacing;
|
else
|
||||||
}
|
positionY += preferredRowHeights[currentRowIndex] + rowSpacing;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Set preferredRowHeights to null to free memory
|
|
||||||
preferredRowHeights = null;
|
// Set preferredRowHeights to null to free memory
|
||||||
}
|
preferredRowHeights = null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6cee1f3bb43ca9c4c9e00b54a998d9ce
|
||||||
|
timeCreated: 1483117134
|
||||||
|
licenseType: Pro
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Loading…
Reference in New Issue