2023-05-22 15:59:35 +08:00

359 lines
11 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BF
{
[ExecuteInEditMode]
public class BFGridLayout : BFLayoutBase
{
public enum Corner
{
/// <summary>
/// Upper Left corner.
/// </summary>
UpperLeft = 0,
/// <summary>
/// Upper Right corner.
/// </summary>
UpperRight = 1,
/// <summary>
/// Lower Left corner.
/// </summary>
LowerLeft = 2,
/// <summary>
/// Lower Right corner.
/// </summary>
LowerRight = 3
}
public enum Constraint
{
/// <summary>
/// Don't constrain the number of rows or columns.
/// </summary>
Flexible = 0,
/// <summary>
/// Constrain the number of columns to a specified number.
/// </summary>
FixedColumnCount = 1,
/// <summary>
/// Constraint the number of rows to a specified number.
/// </summary>
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<Component>();
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;
}
/// <summary>
/// 计算行列数 Fixable 以行填满为标准
/// </summary>
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;
}
}
}