using System; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace BF { [ExecuteInEditMode] public class BFGridLayout : BFLayoutBase { public enum Corner { /// /// Upper Left corner. /// UpperLeft = 0, /// /// Upper Right corner. /// UpperRight = 1, /// /// Lower Left corner. /// LowerLeft = 2, /// /// Lower Right corner. /// LowerRight = 3 } public enum Constraint { /// /// Don't constrain the number of rows or columns. /// Flexible = 0, /// /// Constrain the number of columns to a specified number. /// FixedColumnCount = 1, /// /// Constraint the number of rows to a specified number. /// FixedRowCount = 2 } [SerializeField] protected Vector2 spacing = Vector2.zero; public Vector2 Spaceing { get { return spacing; } set { SetProperty(ref spacing, value); } } [SerializeField] protected Vector2 cellSize = Vector2.zero; public Vector2 CellSize { get { return cellSize; } set { SetProperty(ref cellSize, value); } } [SerializeField] protected Corner startCorner = Corner.UpperLeft; public Corner StartCorner { get { return startCorner; } set { SetProperty(ref startCorner, value); } } [SerializeField] protected Constraint constraintType = Constraint.Flexible; public Constraint ConstraintType { get { return constraintType; } set { SetProperty(ref constraintType, value); } } [SerializeField] protected int constraintCount = 1; public int ConstraintCount { get { return constraintCount; } set { if (value <= 0) { SetProperty(ref constraintCount, 1); } else { SetProperty(ref constraintCount, value); } } } private int row = 0; private int column = 0; private float verticalSize = 0f; private float horizontalSize = 0f; private Vector2 curStartPos = Vector2.zero; //左上角开始位置 private void Update() { if (!isDirty) { return; } RefreshLayout(); } public void RefreshLayout() { CalculateLayoutInput(); CalculateRowAndColumn(); CaculateCorners(); SetChildPos(); isDirty = false; } protected void CalculateLayoutInput() { RectChildren.Clear(); var toIgnoreList = new List(); for (var i = 0; i < RectTransform.childCount; i++) { var rect = (RectTransform) RectTransform.GetChild(i); if (rect == null || !rect.gameObject.activeSelf) { continue; } // rect.GetComponents(typeof(ILayoutIgnorer), toIgnoreList); // for (int j = 0; j < toIgnoreList.Count; j++) // { // var ignorer = (ILayoutIgnorer)toIgnoreList[j]; // if (!ignorer.ignoreLayout) // { // m_RectChildren.Add(rect); // break; // } // } RectChildren.Add(rect); } toIgnoreList = null; } /// /// 计算行列数 Fixable 以行填满为标准 /// protected void CalculateRowAndColumn() { var rectSize = RectTransform.sizeDelta; var childCount = RectChildren.Count; if (ConstraintType == Constraint.Flexible) { column = (int) Math.Floor((rectSize.x + Spaceing.x) / (CellSize.x + Spaceing.x)); column = Math.Max(1, Math.Min(column, childCount)); if (childCount % column == 0) { row = childCount / column; } else { row = childCount / column + 1; } } else if (ConstraintType == Constraint.FixedRowCount) { row = constraintCount; if (childCount % row == 0) { column = childCount / row; } else { column = childCount / row + 1; } } else if (ConstraintType == Constraint.FixedColumnCount) { column = constraintCount; if (childCount % column == 0) { row = childCount / column; } else { row = childCount / column + 1; } } horizontalSize = column * (CellSize.x + Spaceing.x) - Spaceing.x; verticalSize = row * (CellSize.y + Spaceing.y) - Spaceing.y; } protected void CaculateCorners() { var rectSize = RectTransform.sizeDelta; //align参数 var horizontalAlign = (int) ChildAlignment % 3; var verticalAlign = (int) ChildAlignment / 3; var left = 0f; var right = 0f; var top = 0f; var bottom = 0f; if (horizontalAlign == 0) //left { left = Left; right = left + (column - 1) * (cellSize.x + Spaceing.x); } else if (horizontalAlign == 1) //center { var middle = rectSize.x / 2; left = middle - horizontalSize / 2; right = left + (column - 1) * (cellSize.x + Spaceing.x); } else if (horizontalAlign == 2) //right { right = rectSize.x - Right - cellSize.x; left = right - (column - 1) * (cellSize.x + Spaceing.x); } if (verticalAlign == 0) //upper { top = Top; } else if (verticalAlign == 1) //middle { var middle = rectSize.y / 2; top = middle - verticalSize / 2; } else if (verticalAlign == 2) //lower { bottom = rectSize.y - Bottom - cellSize.y; top = bottom - (row - 1) * (cellSize.y + Spaceing.y); } curStartPos = new Vector2(left, top); } protected void SetChildPos() { var startPos = curStartPos; var countDown = 0; var tmpPos = Vector2.zero; if (startCorner == Corner.LowerLeft) { for (var i = row - 1; i >= 0; i--) { tmpPos.y = i * (cellSize.y + Spaceing.y); for (var j = 0; j < column; ++j) { if (countDown >= RectChildren.Count) { break; } tmpPos.x = j * (cellSize.x + Spaceing.x); SetChildAlongAxis(RectChildren[countDown], 0, startPos.x + tmpPos.x, cellSize.x); SetChildAlongAxis(RectChildren[countDown], 1, startPos.y + tmpPos.y, cellSize.y); countDown++; } } } else if (startCorner == Corner.LowerRight) { for (var i = row - 1; i >= 0; i--) { tmpPos.y = i * (cellSize.y + Spaceing.y); for (var j = column - 1; j >= 0; j--) { if (countDown >= RectChildren.Count) { break; } tmpPos.x = j * (cellSize.x + Spaceing.x); SetChildAlongAxis(RectChildren[countDown], 0, startPos.x + tmpPos.x, cellSize.x); SetChildAlongAxis(RectChildren[countDown], 1, startPos.y + tmpPos.y, cellSize.y); countDown++; } } } else if (startCorner == Corner.UpperLeft) { for (var i = 0; i < row; ++i) { tmpPos.y = i * (cellSize.y + Spaceing.y); for (var j = 0; j < column; ++j) { if (countDown >= RectChildren.Count) { break; } tmpPos.x = j * (cellSize.x + Spaceing.x); SetChildAlongAxis(RectChildren[countDown], 0, startPos.x + tmpPos.x, cellSize.x); SetChildAlongAxis(RectChildren[countDown], 1, startPos.y + tmpPos.y, cellSize.y); countDown++; } } } else if (startCorner == Corner.UpperRight) { for (var i = 0; i < row; ++i) { tmpPos.y = i * (cellSize.y + Spaceing.y); for (var j = column - 1; j >= 0; j--) { if (countDown >= RectChildren.Count) { break; } tmpPos.x = j * (cellSize.x + Spaceing.x); SetChildAlongAxis(RectChildren[countDown], 0, startPos.x + tmpPos.x, cellSize.x); SetChildAlongAxis(RectChildren[countDown], 1, startPos.y + tmpPos.y, cellSize.y); countDown++; } } } } public float GetVerticalSize() { return verticalSize + Top + Bottom; } public float GetHorizontalSize() { return horizontalSize + Left + Right; } } }