WXMC/.svn/pristine/04/042288d9d4d5ed562f6f8307add264ee17692089.svn-base
2024-12-04 16:18:46 +08:00

181 lines
4.9 KiB
Plaintext

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GridLayout3D : MonoBehaviour
{
#region Define
private const int MAX_CHILD_COUNT = 100;
public enum ParentPositionAsTypes { TopLeft, CenterLeft, BottomLeft, CenterTop, Center, CenterBottom, TopRight, CenterRight, BottomRight };
#endregion
[SerializeField]
private Vector2 m_interval;
[SerializeField]
private ParentPositionAsTypes m_parentPositionType = ParentPositionAsTypes.Center;
[SerializeField]
private bool m_fixRowCount;
[SerializeField]
private int m_fixedRowCount;
[SerializeField]
private bool m_fixColumnCount;
[SerializeField]
private int m_fixedColumnCount;
private Transform[] m_childTransformCache = new Transform[MAX_CHILD_COUNT];
// Update is called once per frame
void Update()
{
UpdateLayout();
}
private void OnValidate()
{
UpdateLayout();
}
private Vector3 GetTopLeft(Vector2 boundingBoxSize)
{
Vector3 topLeft = transform.position;
switch (m_parentPositionType)
{
case ParentPositionAsTypes.TopLeft:
break;
case ParentPositionAsTypes.CenterLeft:
topLeft.y = topLeft.y + boundingBoxSize.y / 2.0f;
break;
case ParentPositionAsTypes.BottomLeft:
topLeft.y = topLeft.y + boundingBoxSize.y;
break;
case ParentPositionAsTypes.CenterTop:
topLeft.x = topLeft.x - boundingBoxSize.x / 2.0f;
break;
case ParentPositionAsTypes.Center:
topLeft.x = topLeft.x - boundingBoxSize.x / 2.0f;
topLeft.y = topLeft.y + boundingBoxSize.y / 2.0f;
break;
case ParentPositionAsTypes.CenterBottom:
topLeft.x = topLeft.x - boundingBoxSize.x / 2.0f;
topLeft.y = topLeft.y + boundingBoxSize.y;
break;
case ParentPositionAsTypes.TopRight:
topLeft.x = topLeft.x - boundingBoxSize.x;
break;
case ParentPositionAsTypes.CenterRight:
topLeft.x = topLeft.x - boundingBoxSize.x;
topLeft.y = topLeft.y + boundingBoxSize.y / 2.0f;
break;
case ParentPositionAsTypes.BottomRight:
topLeft.x = topLeft.x - boundingBoxSize.x;
topLeft.y = topLeft.y + boundingBoxSize.y;
break;
default:
break;
}
return topLeft;
}
private void UpdateLayout()
{
int childCount = transform.childCount;
if (childCount == 0)
{
return;
}
if (childCount > MAX_CHILD_COUNT)
{
childCount = MAX_CHILD_COUNT;
}
for (int i = 0; i < childCount; i++)
{
m_childTransformCache[i] = transform.GetChild(i);
}
int rowCount;
int columnCount;
if (m_fixColumnCount && m_fixRowCount)
{
rowCount = m_fixedRowCount;
columnCount = m_fixedColumnCount;
}
else if (m_fixColumnCount)
{
columnCount = m_fixedColumnCount;
rowCount = Mathf.CeilToInt((float)childCount / (float)columnCount);
}
else if (m_fixRowCount)
{
rowCount = m_fixedRowCount;
columnCount = Mathf.CeilToInt((float)childCount / (float)rowCount);
}
else
{
rowCount = Mathf.CeilToInt(Mathf.Sqrt(childCount));
columnCount = rowCount;
}
if (rowCount * columnCount < childCount)
{
rowCount = Mathf.CeilToInt(Mathf.Sqrt(childCount));
columnCount = rowCount;
}
Vector2 boundingBoxSize = new Vector2(
(columnCount - 1) * m_interval.x,
(rowCount - 1) * m_interval.y);
Vector3 topLeft = GetTopLeft(boundingBoxSize);
int count = 0;
bool breakAllTheWay = false;
for (int col = 0; col < columnCount; col++)
{
for (int row = 0; row < rowCount; row++)
{
if (m_childTransformCache[count] == null)
{
breakAllTheWay = true;
break;
}
Vector3 destPos = topLeft;
destPos.x = destPos.x + col * m_interval.x;
destPos.y = destPos.y - row * m_interval.y;
m_childTransformCache[count].transform.position = destPos;
count++;
}
if (breakAllTheWay)
{
break;
}
}
// Clear cache
for (int i = 0; i < MAX_CHILD_COUNT; i++)
{
if (m_childTransformCache[i] == null)
{
break;
}
m_childTransformCache[i] = null;
}
}
}