181 lines
4.9 KiB
Plaintext
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;
|
||
|
}
|
||
|
}
|
||
|
}
|