Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 91 additions & 109 deletions Scripts/UI/Layout/FlowLayoutGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,81 +13,82 @@ namespace SRF.UI.Layout
[AddComponentMenu(ComponentMenuPaths.FlowLayoutGroup)]
public class FlowLayoutGroup : LayoutGroup
{

public float Spacing = 0f;

public float SpacingX = 0f;
public float SpacingY = 0f;
public bool ExpandHorizontalSpacing = false;

public bool ChildForceExpandWidth = false;
public bool ChildForceExpandHeight = false;

private float _layoutHeight;

public override void CalculateLayoutInputHorizontal()
{

base.CalculateLayoutInputHorizontal();

var minWidth = GetGreatestMinimumChildWidth() + padding.left + padding.right;

SetLayoutInputForAxis(minWidth, -1, -1, 0);

}

public override void SetLayoutHorizontal()
{
SetLayout(rectTransform.rect.width, 0, false);
}

public override void SetLayoutVertical()
{
SetLayout(rectTransform.rect.width, 1, false);
}

public override void CalculateLayoutInputVertical()
{
_layoutHeight = SetLayout(rectTransform.rect.width, 1, true);
}

protected bool IsCenterAlign
{
get
{
return childAlignment == TextAnchor.LowerCenter || childAlignment == TextAnchor.MiddleCenter ||
childAlignment == TextAnchor.UpperCenter;
childAlignment == TextAnchor.UpperCenter;
}
}

protected bool IsRightAlign
{
get
{
return childAlignment == TextAnchor.LowerRight || childAlignment == TextAnchor.MiddleRight ||
childAlignment == TextAnchor.UpperRight;
childAlignment == TextAnchor.UpperRight;
}
}

protected bool IsMiddleAlign
{
get
{
return childAlignment == TextAnchor.MiddleLeft || childAlignment == TextAnchor.MiddleRight ||
childAlignment == TextAnchor.MiddleCenter;
childAlignment == TextAnchor.MiddleCenter;
}
}

protected bool IsLowerAlign
{
get
{
return childAlignment == TextAnchor.LowerLeft || childAlignment == TextAnchor.LowerRight ||
childAlignment == TextAnchor.LowerCenter;
childAlignment == TextAnchor.LowerCenter;
}
}

/// <summary>
/// Holds the rects that will make up the current row being processed
/// </summary>
private readonly IList<RectTransform> _rowList = new List<RectTransform>();

/// <summary>
/// Main layout method
/// </summary>
Expand All @@ -96,103 +97,96 @@ protected bool IsLowerAlign
/// <param name="layoutInput">If true, sets the layout input for the axis. If false, sets child position for axis</param>
public float SetLayout(float width, int axis, bool layoutInput)
{

var groupHeight = rectTransform.rect.height;

// Width that is available after padding is subtracted
var workingWidth = rectTransform.rect.width - padding.left - padding.right;

// Accumulates the total height of the rows, including spacing and padding.
var yOffset = IsLowerAlign ? padding.bottom : (float)padding.top;

var yOffset = IsLowerAlign ? (float)padding.bottom : (float)padding.top;
var currentRowWidth = 0f;
var currentRowHeight = 0f;

for (var i = 0; i < rectChildren.Count; i++) {

// LowerAlign works from back to front
var index = IsLowerAlign ? rectChildren.Count - 1 - i : i;

var child = rectChildren[index];

var childWidth = LayoutUtility.GetPreferredSize(child, 0);
var childHeight = LayoutUtility.GetPreferredSize(child, 1);

// Max child width is layout group with - padding
// Max child width is layout group width - padding
childWidth = Mathf.Min(childWidth, workingWidth);

// Apply spacing if not the first element in a row
if(_rowList.Count > 0)
currentRowWidth += Spacing;


// If adding this element would exceed the bounds of the row,
// go to a new line after processing the current row
if (currentRowWidth + childWidth > workingWidth) {

// Undo spacing addition if we're moving to a new line (Spacing is not applied on edges)
currentRowWidth -= Spacing;


currentRowWidth -= SpacingX;

// Process current row elements positioning
if (!layoutInput) {

var h = CalculateRowVerticalOffset(groupHeight, yOffset, currentRowHeight);
LayoutRow(_rowList, currentRowWidth, currentRowHeight, workingWidth, padding.left, h, axis);

}

// Clear existing row
_rowList.Clear();

// Add the current row height to total height accumulator, and reset to 0 for the next row
yOffset += currentRowHeight;
yOffset += Spacing;

yOffset += SpacingY;
currentRowHeight = 0;
currentRowWidth = 0;

}

currentRowWidth += childWidth;
_rowList.Add(child);

// We need the largest element height to determine the starting position of the next line
if (childHeight > currentRowHeight) {
currentRowHeight = childHeight;
}

// Don't do this for the last one
if (i < rectChildren.Count - 1 )
currentRowWidth += SpacingX;
}

if (!layoutInput) {

var h = CalculateRowVerticalOffset(groupHeight, yOffset, currentRowHeight);

// Layout the final row
LayoutRow(_rowList, currentRowWidth, currentRowHeight, workingWidth, padding.left, h, axis);

}

_rowList.Clear();

// Add the last rows height to the height accumulator
yOffset += currentRowHeight;
yOffset += IsLowerAlign ? padding.top : padding.bottom;

if (layoutInput) {

if(axis == 1)
SetLayoutInputForAxis(yOffset, yOffset, -1, axis);

}

return yOffset;

}

private float CalculateRowVerticalOffset(float groupHeight, float yOffset, float currentRowHeight)
{

float h;

if (IsLowerAlign) {
h = groupHeight - yOffset - currentRowHeight;
} else if (IsMiddleAlign) {
Expand All @@ -201,94 +195,82 @@ private float CalculateRowVerticalOffset(float groupHeight, float yOffset, float
h = yOffset;
}
return h;

}

protected void LayoutRow(IList<RectTransform> contents, float rowWidth, float rowHeight, float maxWidth, float xOffset, float yOffset, int axis)
{

var xPos = xOffset;

if (!ChildForceExpandWidth && IsCenterAlign)
xPos += (maxWidth - rowWidth) * 0.5f;
else if (!ChildForceExpandWidth && IsRightAlign)
xPos += (maxWidth - rowWidth);

var extraWidth = 0f;
var extraSpacing = 0f;

if (ChildForceExpandWidth) {

var flexibleChildCount = 0;

for (var i = 0; i < _rowList.Count; i++) {

if (LayoutUtility.GetFlexibleWidth(_rowList[i]) > 0f)
flexibleChildCount ++;

extraWidth = (maxWidth - rowWidth)/_rowList.Count;
}
else if (ExpandHorizontalSpacing) {
extraSpacing = (maxWidth - rowWidth)/(_rowList.Count - 1);
if (_rowList.Count > 1) {
if (IsCenterAlign)
xPos -= extraSpacing * 0.5f * (_rowList.Count - 1);
else if (IsRightAlign)
xPos -= extraSpacing * (_rowList.Count - 1);
}

if(flexibleChildCount > 0)
extraWidth = (maxWidth - rowWidth)/flexibleChildCount;

}



for (var j = 0; j < _rowList.Count; j++) {

var index = IsLowerAlign ? _rowList.Count - 1 - j : j;

var rowChild = _rowList[index];

var rowChildWidth = LayoutUtility.GetPreferredSize(rowChild, 0);

if (LayoutUtility.GetFlexibleWidth(rowChild) > 0f)
rowChildWidth += extraWidth;


var rowChildWidth = LayoutUtility.GetPreferredSize(rowChild, 0) + extraWidth;
var rowChildHeight = LayoutUtility.GetPreferredSize(rowChild, 1);

if (ChildForceExpandHeight)
rowChildHeight = rowHeight;

rowChildWidth = Mathf.Min(rowChildWidth, maxWidth);

var yPos = yOffset;

if (IsMiddleAlign)
yPos += (rowHeight - rowChildHeight) * 0.5f;
else if (IsLowerAlign)
yPos += (rowHeight - rowChildHeight);

//
if (ExpandHorizontalSpacing && j > 0)
xPos += extraSpacing;

if (axis == 0)
SetChildAlongAxis(rowChild, 0, xPos, rowChildWidth);
else
SetChildAlongAxis(rowChild, 1, yPos, rowChildHeight);

xPos += rowChildWidth + Spacing;

// Don't do horizontal spacing for the last one
if (j < _rowList.Count - 1 )
xPos += rowChildWidth + SpacingX;
}

}

public float GetGreatestMinimumChildWidth()
{

var max = 0f;

for (var i = 0; i < rectChildren.Count; i++) {

var w = LayoutUtility.GetMinWidth(rectChildren[i]);

max = Mathf.Max(w, max);

}

return max;

}

}


}

#endif