using UnityEngine; using UnityEditor; using Unity.Collections; namespace SC.XR.Unity { [ExecuteAlways]//Script will run in any circumstance public class SCGridLayoutGroup : SCBaseLayoutGroup { /// /// The layout of the set of type /// [SerializeField] private LayoutTypes layoutType = LayoutTypes.Horizontal; public LayoutTypes LayoutType { get { return layoutType; } set { layoutType = value; } } /// /// Less than a row when the child object alignment /// [SerializeField] private GroupHorizontalAlignment groupHorizontalAlign = GroupHorizontalAlignment.Left; public GroupHorizontalAlignment GroupHorizontalAlign { get { return groupHorizontalAlign; } set { groupHorizontalAlign = value; } } /// /// Less than a column when the child object alignment /// [SerializeField] private GroupVerticalAlignment groupVerticalAlign = GroupVerticalAlignment.Top; public GroupVerticalAlignment GroupVerticalAlign { get { return groupVerticalAlign; } set { groupVerticalAlign = value; } } /// /// The child object types of formation /// [SerializeField] private GroupArrayTypes groupArrayType = GroupArrayTypes.Plane; public GroupArrayTypes GroupArrayType { get { return groupArrayType; } set { groupArrayType = value; } } /// /// The position of the group anchor point relative to the base class /// [SerializeField] private AnchorRelativeBase anchorLayout = AnchorRelativeBase.MiddleCenter; public AnchorRelativeBase AnchorLayout { get { return anchorLayout; } set { anchorLayout = value; } } /// /// The child object oriented /// [SerializeField] private ObjFacingTypes facingType = ObjFacingTypes.None; public ObjFacingTypes FacingType { get { return facingType; } set { facingType = value; } } /// /// The number of columns /// [SerializeField] private int columns = 2; public int Columns { get { return columns; } set { if (LayoutType == LayoutTypes.Vertical) { return; } columns = value; } } /// /// The number of rows /// [SerializeField] private int rows = 2; public int Rows { get { return rows; } set { if (LayoutType == LayoutTypes.Horizontal) { return; } rows = value; } } /// /// Horizontal spacing /// [SerializeField] private float spaceX = 2f; public float SpaceX { get { return spaceX; } set { spaceX = value; } } /// /// The vertical spacing /// [SerializeField] private float spaceY = 2f; public float SpaceY { get { return spaceY; } set { spaceY = value; } } [SerializeField] [Range(-100f, 100f)] private float childOffsetX = 0f; public float ChildOffsetX { get { return childOffsetX; } set { childOffsetX = value; } } [SerializeField] [Range(-100f, 100f)] private float childOffsetY = 0f; public float ChildOffsetY { get { return childOffsetY; } set { childOffsetY = value; } } /// /// The location of the child object Z axis relative to the base class /// [SerializeField] [Range(-100f, 100f)] private float childOffsetZ = 0f; public float ChildOffsetZ { get { return childOffsetZ; } set { childOffsetZ = value; } } /// /// The radius /// [SerializeField] [Range(0.05f, 200)] private float radius = 2f; public float Radius { get { return radius; } set { radius = value; } } /// /// Radiation Angle /// [SerializeField] [Range(5f, 360f)] private float radialRange = 180f; public float RadialRange { get { return radialRange; } set { radialRange = value; } } /// /// If the anchor point with the shaft alignment /// [SerializeField] private bool isAnchorWithAxis = false; public bool IsAnchorWithAxis { get { return isAnchorWithAxis; } set { isAnchorWithAxis = value; } } private GroupObj tempobj; private Vector3[] childPos; private Vector3 newPos; private int objCount; private int rowMax; private int colMax; private float acnhoroffsetX; private float anchoroffsetY; private float shortOffsetX; private float shortOffsetY; private void Init()//The initialization value { childPos = new Vector3[ObjList.Count]; newPos = Vector3.zero; objCount = 0; rowMax = 0; colMax = 0; acnhoroffsetX = 0; anchoroffsetY = 0; shortOffsetX = 0; shortOffsetY = 0; } protected override void LayoutChildren() { Init(); SetObjPos(); ArrayType(); } private void Update() { } private void SetObjPos()//The location of the object { switch (LayoutType) { case LayoutTypes.Horizontal: colMax = Columns; rowMax = Mathf.CeilToInt((float)ObjList.Count / Columns); break; case LayoutTypes.Vertical: rowMax = Rows; colMax = Mathf.CeilToInt((float)ObjList.Count / Rows); break; } acnhoroffsetX = (colMax * 0.5f * SpaceX); if (AnchorLayout == AnchorRelativeBase.LowerLeft || AnchorLayout == AnchorRelativeBase.UpperLeft || AnchorLayout == AnchorRelativeBase.MiddleLeft) { acnhoroffsetX = IsAnchorWithAxis ? 0.5f * SpaceX : 0; } else if (AnchorLayout == AnchorRelativeBase.LowerRight || AnchorLayout == AnchorRelativeBase.UpperRight || AnchorLayout == AnchorRelativeBase.MiddleRight) { acnhoroffsetX = IsAnchorWithAxis ? (colMax - 0.5f) * SpaceX : colMax * SpaceX; } anchoroffsetY = (rowMax * 0.5f * SpaceY); if (AnchorLayout == AnchorRelativeBase.UpperLeft || AnchorLayout == AnchorRelativeBase.UpperCenter || AnchorLayout == AnchorRelativeBase.UpperRight) { anchoroffsetY = IsAnchorWithAxis ? 0.5f * SpaceY : 0; } else if (AnchorLayout == AnchorRelativeBase.LowerLeft || AnchorLayout == AnchorRelativeBase.LowerCenter || AnchorLayout == AnchorRelativeBase.LowerRight) { anchoroffsetY = IsAnchorWithAxis ? (rowMax - 0.5f) * SpaceY : rowMax * SpaceY; } if (LayoutType == LayoutTypes.Horizontal) { for (int i = 0; i < rowMax; i++) { for (int j = 0; j < colMax; j++) { if (i == rowMax - 1) { if (GroupHorizontalAlign == GroupHorizontalAlignment.Left) { shortOffsetX = 0; } else if (GroupHorizontalAlign == GroupHorizontalAlignment.Center) { shortOffsetX = SpaceX * ((colMax - (ObjList.Count % colMax)) % colMax) * 0.5f; } else if (GroupHorizontalAlign == GroupHorizontalAlignment.Right) { shortOffsetX = SpaceX * ((colMax - (ObjList.Count % colMax)) % colMax); } } if (objCount < ObjList.Count) { childPos[objCount].Set(0.5f * SpaceX * (1 + 2 * j) - acnhoroffsetX + shortOffsetX + ChildOffsetX, (0.5f * SpaceY * (-1 - 2 * i)) + anchoroffsetY + shortOffsetY + ChildOffsetY, 0.0f); } objCount++; } } } else { for (int i = 0; i < colMax; i++) { for (int j = 0; j < rowMax; j++) { if (i == colMax - 1) { if (GroupVerticalAlign == GroupVerticalAlignment.Top) { shortOffsetY = 0; } else if (GroupVerticalAlign == GroupVerticalAlignment.Middle) { shortOffsetY = -SpaceY * ((rowMax - (ObjList.Count % rowMax)) % rowMax) * 0.5f; } else if (GroupVerticalAlign == GroupVerticalAlignment.Bottom) { shortOffsetY = -SpaceY * ((rowMax - (ObjList.Count % rowMax)) % rowMax); } } if (objCount < ObjList.Count) { childPos[objCount].Set(0.5f * SpaceX * (1 + 2 * i) - acnhoroffsetX + shortOffsetX + ChildOffsetX, (0.5f * SpaceY * (-1 - 2 * j)) + anchoroffsetY + shortOffsetY + childOffsetY, 0.0f); } objCount++; } } } } private void ArrayType()//Give the child object position { switch (GroupArrayType) { case GroupArrayTypes.Plane: for (int i = 0; i < ObjList.Count; i++) { tempobj = ObjList[i]; newPos = childPos[i]; newPos.z = ChildOffsetZ; tempobj.Transform.localPosition = newPos; ObjFacing(tempobj); ObjList[i] = tempobj; } break; case GroupArrayTypes.Cylinder: for (int i = 0; i < ObjList.Count; i++) { tempobj = ObjList[i]; newPos = CylinderArray(childPos[i], radius); tempobj.Transform.localPosition = newPos; ObjFacing(tempobj); ObjList[i] = tempobj; } break; case GroupArrayTypes.Radial: int tempColumn = 0; int tempRow = 1; for (int i = 0; i < ObjList.Count; i++) { tempobj = ObjList[i]; newPos = RadialArray(childPos[i], radius, radialRange, tempRow, rowMax, tempColumn, colMax); if (tempColumn == columns - 1) { tempColumn = 0; tempRow++; } else { tempColumn++; } tempobj.Transform.localPosition = newPos; ObjFacing(tempobj); ObjList[i] = tempobj; } break; case GroupArrayTypes.Sphere: for (int i = 0; i < ObjList.Count; i++) { tempobj = ObjList[i]; newPos = SphereArray(childPos[i], radius); tempobj.Transform.localPosition = newPos; ObjFacing(tempobj); ObjList[i] = tempobj; } break; case GroupArrayTypes.Round: for (int i = 0; i < ObjList.Count; i++) { tempobj = ObjList[i]; newPos = RoundArray(childPos[i], radius, i + 1, ObjList.Count); newPos.Set(newPos.x + ChildOffsetX, newPos.y + ChildOffsetY, newPos.z + ChildOffsetZ); tempobj.Transform.localPosition = newPos; ObjFacing(tempobj); ObjList[i] = tempobj; } break; } } private Vector3 CylinderArray(Vector3 objPos, float radius) { float circ = 2.0f * Mathf.PI * radius; float xAngle = (objPos.x / circ) * 360f; objPos.Set(0.0f, objPos.y, radius); Quaternion rot = Quaternion.Euler(0.0f, xAngle, 0.0f); objPos = rot * objPos; return objPos; } private Vector3 SphereArray(Vector3 objPos, float radius) { float circ = 2.0f * Mathf.PI * radius; float XAngle = (objPos.x / circ) * 360f; float YAngle = -(objPos.y / circ) * 360f; objPos.Set(0.0f, 0.0f, radius); Quaternion rot = Quaternion.Euler(YAngle, XAngle, 0.0f); objPos = rot * objPos; return objPos; } private Vector3 RadialArray(Vector3 objPos, float radius, float radialRange, int row, int rowMax, int column, int colMax) { float radialSpaceAngle = radialRange / colMax; objPos.Set(0.0f, 0.0f, (radius / rowMax) * row); float YAngle = radialSpaceAngle * (column - (colMax * 0.5f)) + (radialSpaceAngle * .5f); Quaternion rot = Quaternion.Euler(0.0f, YAngle, 0.0f); objPos = rot * objPos; return objPos; } private Vector3 RoundArray(Vector3 objPos, float radius, int i, int totalCount) { float angle = (360f * i) / totalCount; float x = radius * Mathf.Cos(angle * Mathf.PI / 180f); float y = radius * Mathf.Sin(angle * Mathf.PI / 180f); objPos.Set(x, 0, y); return objPos; } private void ObjFacing(GroupObj obj)//The child object toward { Vector3 centerPos; Vector3 FacingNode; switch (FacingType) { case ObjFacingTypes.None: obj.Transform.transform.localEulerAngles = Vector3.zero; break; case ObjFacingTypes.FaceOrigin: obj.Transform.rotation = Quaternion.LookRotation(obj.Transform.position - transform.position, transform.up); break; case ObjFacingTypes.FaceOriginReversed: obj.Transform.rotation = Quaternion.LookRotation(transform.position - obj.Transform.position, transform.up); break; case ObjFacingTypes.FaceCenterAxis: centerPos = Vector3.Project(obj.Transform.position - transform.position, transform.up);//Returns a vector projection on the specified axis FacingNode = transform.position + centerPos; obj.Transform.rotation = Quaternion.LookRotation(obj.Transform.position - FacingNode, transform.up); break; case ObjFacingTypes.FaceCenterAxisReversed: centerPos = Vector3.Project(obj.Transform.position - transform.position, transform.up);//Returns a vector projection on the specified axis FacingNode = transform.position + centerPos; obj.Transform.rotation = Quaternion.LookRotation(FacingNode - obj.Transform.position, transform.up); break; case ObjFacingTypes.FaceParentDown: obj.Transform.forward = transform.rotation * Vector3.down; break; case ObjFacingTypes.FaceParentUp: obj.Transform.forward = transform.rotation * Vector3.up; break; case ObjFacingTypes.FaceParentFoward: obj.Transform.forward = transform.rotation * Vector3.forward; break; case ObjFacingTypes.FaceParentBack: obj.Transform.forward = transform.rotation * Vector3.back; break; } } private void setNull() { tempobj = null; childPos = null; } private void OnDestroy() { setNull(); } } }