359 lines
11 KiB
C#
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;
|
|
}
|
|
}
|
|
|
|
}
|
|
|