using UnityEngine; using UnityEditor; //using System.Windows.Markup; //using UnityScript.Steps; using Unity.Collections; [ExecuteAlways]//脚本在任意情况下均会运行 public class SCGridLayoutGroup : SCBaseLayoutGroup { /// /// 组的布局类型 /// [SerializeField] private LayoutTypes layoutType = LayoutTypes.Horizontal; public LayoutTypes LayoutType { get { return layoutType; } set { layoutType = value; } } /// /// 不满一行时的子物体对齐方式 /// [SerializeField] private GroupHorizontalAlignment groupHorizontalAlign = GroupHorizontalAlignment.Left; public GroupHorizontalAlignment GroupHorizontalAlign { get { return groupHorizontalAlign; } set { groupHorizontalAlign = value; } } /// /// 不满一列时的子物体对齐方式 /// [SerializeField] private GroupVerticalAlignment groupVerticalAlign = GroupVerticalAlignment.Top; public GroupVerticalAlignment GroupVerticalAlign { get { return groupVerticalAlign; } set { groupVerticalAlign = value; } } /// /// 子物体的队形类型 /// [SerializeField] private GroupArrayTypes groupArrayType = GroupArrayTypes.Plane; public GroupArrayTypes GroupArrayType { get { return groupArrayType; } set { groupArrayType = value; } } /// /// 组锚点相对于基类的位置 /// [SerializeField] private AnchorRelativeBase anchorLayout = AnchorRelativeBase.MiddleCenter; public AnchorRelativeBase AnchorLayout { get { return anchorLayout; } set { anchorLayout = value; } } /// /// 各子物体的面向 /// [SerializeField] private ObjFacingTypes facingType = ObjFacingTypes.None; public ObjFacingTypes FacingType { get { return facingType; } set { facingType = value; } } /// /// 列数 /// [SerializeField] private int columns = 2; public int Columns { get { return columns; } set { if (LayoutType == LayoutTypes.Horizontal) { return; } columns = value; } } /// /// 行数 /// [SerializeField] private int rows = 2; public int Rows { get { return rows; } set { if (LayoutType == LayoutTypes.Vertical) { return; } rows = value; } } /// /// 横向间距 /// [SerializeField] private float spaceX = 2f; public float SpaceX { get { return spaceX; } set { spaceX = value; } } /// /// 纵向间距 /// [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; } } /// /// 子物体Z轴相较于基类的位置 /// [SerializeField] [Range(-100f, 100f)] private float childOffsetZ = 0f; public float ChildOffsetZ { get { return childOffsetZ; } set { childOffsetZ = value; } } /// /// 半径 /// [SerializeField] [Range(0.05f,200)] private float radius = 2f; public float Radius { get { return radius; } set { radius = value; } } /// /// 辐射角度 /// [SerializeField] [Range(5f, 360f)] private float radialRange = 180f; public float RadialRange { get { return radialRange; } set { radialRange = value; } } /// /// 锚点是否用轴对齐 /// [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()//初始化值 { 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()//子物体的位置 { 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()//赋予子物体位置 { 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)//子物体的面向 { 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);//返回一个向量在指定轴上的投影 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);//返回一个向量在指定轴上的投影 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(); } }