GridLayoutGroup.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. using static EZXR.Glass.UI.HorizontalLayoutGroup;
  6. namespace EZXR.Glass.UI
  7. {
  8. [ExecuteInEditMode]
  9. public class GridLayoutGroup : LayoutGroup
  10. {
  11. public List<SpatialUIElement> children = new List<SpatialUIElement>();
  12. float prevChildCount;
  13. Vector3 prevSize;
  14. [Tooltip("单位是m")]
  15. public float horizontalSpace = 0.001f;
  16. float prevHorizontalSpace;
  17. [Tooltip("单位是m")]
  18. public float verticalSpace = 0.001f;
  19. float prevVerticalSpace;
  20. Vector3 anchor;
  21. public enum HoriAlignment
  22. {
  23. Left,
  24. Middle,
  25. Right
  26. }
  27. public HoriAlignment horiAlignment;
  28. HoriAlignment prevHoriAlignment;
  29. public enum VertAlignment
  30. {
  31. Top,
  32. Middle,
  33. Bottom
  34. }
  35. public VertAlignment vertAlignment;
  36. VertAlignment prevVertAlignment;
  37. public override void OnValidate()
  38. {
  39. if (!Application.isPlaying)
  40. {
  41. base.OnValidate();
  42. GetSpatialUIElement();
  43. if (horizontalSpace != prevHorizontalSpace || verticalSpace != prevVerticalSpace || spatialUIElement.size != prevSize || children.Count != prevChildCount)
  44. {
  45. prevHorizontalSpace = horizontalSpace;
  46. prevVerticalSpace = verticalSpace;
  47. prevSize = spatialUIElement.size;
  48. prevChildCount = children.Count;
  49. needReLayout = true;
  50. }
  51. }
  52. }
  53. public void AddChild(SpatialUIElement child)
  54. {
  55. if (!children.Contains(child))
  56. {
  57. children.Add(child);
  58. needReLayout = true;
  59. }
  60. }
  61. // Update is called once per frame
  62. void Update()
  63. {
  64. if (startLayout)
  65. {
  66. if (needReLayout)
  67. {
  68. needReLayout = false;
  69. if (transform.childCount > 0)
  70. {
  71. children = new List<SpatialUIElement>();
  72. for (int i = 0; i < transform.childCount; i++)
  73. {
  74. SpatialUIElement temp = transform.GetChild(i).GetComponent<SpatialUIElement>();
  75. if (temp != null && temp.gameObject.activeInHierarchy)
  76. {
  77. children.Add(temp);
  78. }
  79. }
  80. int numPerRow = Mathf.FloorToInt((spatialUIElement.size.x + horizontalSpace) / (children[0].size.x + horizontalSpace));
  81. int numPerCol = Mathf.FloorToInt((spatialUIElement.size.y + verticalSpace) / (children[0].size.y + verticalSpace));
  82. float horiOffset = 0.0f;
  83. float vertOffset = 0.0f;
  84. switch (horiAlignment)
  85. {
  86. case HoriAlignment.Left:
  87. horiOffset = 0;
  88. break;
  89. case HoriAlignment.Middle:
  90. horiOffset = (spatialUIElement.size.x - (children[0].size.x * numPerRow + horizontalSpace * (numPerRow - 1))) / 2.0f;
  91. break;
  92. case HoriAlignment.Right:
  93. horiOffset = 0;
  94. break;
  95. }
  96. switch (vertAlignment)
  97. {
  98. case VertAlignment.Top:
  99. vertOffset = 0.0f;
  100. break;
  101. case VertAlignment.Middle:
  102. vertOffset = (spatialUIElement.size.y - (children[0].size.y * numPerCol + verticalSpace * (numPerCol - 1))) / 2.0f;
  103. break;
  104. case VertAlignment.Bottom:
  105. break;
  106. }
  107. anchor = spatialUIElement.size / 2.0f - new Vector3(horiOffset, vertOffset, 0);
  108. Vector3 curPos = Vector3.zero;
  109. for (int i = 0; i < children.Count; i++)
  110. {
  111. if (children[i] != null)
  112. {
  113. //下面的0.0000001f是为了解决float判定相等的bug
  114. if ((curPos.x + children[i].size.x <= spatialUIElement.size.x + 0.0000001f) && (curPos.y + children[i].size.y <= spatialUIElement.size.y + 0.0000001f))
  115. {
  116. children[i].transform.localPosition = new Vector3(anchor.x - curPos.x - children[i].size.x / 2.0f, anchor.y - curPos.y - children[i].size.y / 2.0f, 0);
  117. curPos = new Vector3(curPos.x + children[i].size.x + horizontalSpace, curPos.y, curPos.z);
  118. }
  119. else if (curPos.x + children[i].size.x > spatialUIElement.size.x && curPos.y + 2.0 * children[i].size.y + verticalSpace <= spatialUIElement.size.y + 0.0000001f)
  120. {
  121. children[i].transform.localPosition = new Vector3(anchor.x - children[i].size.x / 2.0f, anchor.y - (curPos.y + children[i - 1].size.y + verticalSpace) - children[i].size.y / 2.0f, 0);
  122. curPos = new Vector3(0 + children[i].size.x + horizontalSpace, curPos.y + children[i - 1].size.y + verticalSpace, curPos.z);
  123. }
  124. else
  125. {
  126. Debug.LogError($"GridLayoutGroup: No enough space for {children[i].name}");
  127. }
  128. }
  129. }
  130. }
  131. }
  132. }
  133. }
  134. }
  135. }