diff --git a/Scripts/UI/Layout/FlowLayoutGroup.cs b/Scripts/UI/Layout/FlowLayoutGroup.cs index 6f1b5be..b85b1f1 100644 --- a/Scripts/UI/Layout/FlowLayoutGroup.cs +++ b/Scripts/UI/Layout/FlowLayoutGroup.cs @@ -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; } } - + /// /// Holds the rects that will make up the current row being processed /// private readonly IList _rowList = new List(); - + /// /// Main layout method /// @@ -96,103 +97,96 @@ protected bool IsLowerAlign /// If true, sets the layout input for the axis. If false, sets child position for axis 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) { @@ -201,56 +195,47 @@ private float CalculateRowVerticalOffset(float groupHeight, float yOffset, float h = yOffset; } return h; - } - + protected void LayoutRow(IList 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) @@ -258,37 +243,34 @@ protected void LayoutRow(IList contents, float rowWidth, float ro 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