Utility.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEditor;
  5. using UnityEngine;
  6. namespace TheraBytes.BetterUi.Editor.AlignDistribute
  7. {
  8. public static class Utility
  9. {
  10. internal static GameObject helperObject;
  11. internal static void CleanUp()
  12. {
  13. if (helperObject != null)
  14. {
  15. GameObject.DestroyImmediate(helperObject);
  16. }
  17. }
  18. // Sort from smallest to largest
  19. private class AreaComparer : IComparer<Transform>
  20. {
  21. public int Compare(Transform a, Transform b)
  22. {
  23. return GetTransformArea(a).CompareTo(GetTransformArea(b));
  24. }
  25. private float GetTransformArea(Transform transform)
  26. {
  27. Vector2 size = GetTransformSize(transform);
  28. return size.x * size.y;
  29. }
  30. }
  31. private class WidthComparer : IComparer<Transform>
  32. {
  33. public int Compare(Transform a, Transform b)
  34. {
  35. Vector2 sizeA = GetTransformSize(a);
  36. Vector2 sizeB = GetTransformSize(b);
  37. return sizeA.x.CompareTo(sizeB.x);
  38. }
  39. }
  40. private class HeightComparer : IComparer<Transform>
  41. {
  42. public int Compare(Transform a, Transform b)
  43. {
  44. Vector2 sizeA = GetTransformSize(a);
  45. Vector2 sizeB = GetTransformSize(b);
  46. return sizeA.y.CompareTo(sizeB.y);
  47. }
  48. }
  49. private class PositionComparerX : IComparer<Transform>
  50. {
  51. public int Compare(Transform a, Transform b)
  52. {
  53. return a.position.x.CompareTo(b.position.x);
  54. }
  55. }
  56. private class PositionComparerY : IComparer<Transform>
  57. {
  58. public int Compare(Transform a, Transform b)
  59. {
  60. return a.position.y.CompareTo(b.position.y);
  61. }
  62. }
  63. public static Transform[] SortHierarchically(Transform[] input)
  64. {
  65. Transform parent = input[0].parent;
  66. Transform[] result = new Transform[input.Length];
  67. int currentIndex = 0;
  68. for (int i = 0; i < parent.childCount && currentIndex < input.Length; i++)
  69. {
  70. foreach (Transform transform in input)
  71. {
  72. if (parent.GetChild(i) != transform)
  73. {
  74. continue;
  75. }
  76. result[currentIndex] = transform;
  77. currentIndex++;
  78. break;
  79. }
  80. }
  81. return result;
  82. }
  83. public static Transform[] SortByArea(Transform[] input)
  84. {
  85. Array.Sort(input, new AreaComparer());
  86. return input;
  87. }
  88. public static Transform[] SortByWidth(Transform[] input)
  89. {
  90. Array.Sort(input, new WidthComparer());
  91. return input;
  92. }
  93. public static Transform[] SortByHeight(Transform[] input)
  94. {
  95. Array.Sort(input, new HeightComparer());
  96. return input;
  97. }
  98. public static Transform[] SortByPositionX(Transform[] input)
  99. {
  100. Array.Sort(input, new PositionComparerX());
  101. return input;
  102. }
  103. public static Transform[] SortByPositionY(Transform[] input)
  104. {
  105. Array.Sort(input, new PositionComparerY());
  106. return input;
  107. }
  108. public static Vector2 GetTransformSize(Transform rectTransform)
  109. {
  110. return GetTransformSize(rectTransform as RectTransform);
  111. }
  112. public static Vector2 GetTransformSize(RectTransform rectTransform)
  113. {
  114. Vector2 result = new Vector2();
  115. result.x = Mathf.Abs(rectTransform.rect.width * rectTransform.lossyScale.x);
  116. result.y = Mathf.Abs(rectTransform.rect.height * rectTransform.lossyScale.y);
  117. return result;
  118. }
  119. public static Vector2 GetLocalPivotPosition(RectTransform rectTransform)
  120. {
  121. Vector2 result = GetTransformSize(rectTransform);
  122. result.x *= rectTransform.pivot.x;
  123. result.y *= rectTransform.pivot.y;
  124. return result;
  125. }
  126. public static Vector2 GetPivotAndCenterLocalDistance(RectTransform rectTransform)
  127. {
  128. Vector2 size = GetTransformSize(rectTransform);
  129. float y = size.y * (rectTransform.pivot.y - 0.5f);
  130. float x = size.x * (rectTransform.pivot.x - 0.5f);
  131. return new Vector2(x, y);
  132. }
  133. public static SelectionStatus IsSelectionValid()
  134. {
  135. Transform[] transforms = Selection.GetTransforms(SelectionMode.Unfiltered);
  136. if (transforms == null || transforms.Length < 1)
  137. {
  138. return SelectionStatus.NothingSelected;
  139. }
  140. Transform sharedParent = transforms[0].parent;
  141. if (sharedParent == null)
  142. {
  143. return SelectionStatus.ParentIsNull;
  144. }
  145. if (sharedParent.GetComponent(typeof(RectTransform)) == null)
  146. {
  147. return SelectionStatus.ParentIsNoRectTransform;
  148. }
  149. for (int i = 1; i < transforms.Length; i++)
  150. {
  151. if (transforms[i].GetComponent(typeof(RectTransform)) == null)
  152. {
  153. return SelectionStatus.ContainsNoRectTransform;
  154. }
  155. if (sharedParent != transforms[i].parent)
  156. {
  157. return SelectionStatus.UnequalParents;
  158. }
  159. }
  160. return SelectionStatus.Valid;
  161. }
  162. public static void AdjustAnchors(RectTransform rectTransform, Vector2 oldPosition)
  163. {
  164. switch (AlignDistributeWindow.anchorMode)
  165. {
  166. case AnchorMode.StayAtCurrentPosition:
  167. return;
  168. case AnchorMode.SnapToBorder:
  169. SnapAnchorsWindow.SnapBorder(rectTransform, true, true, true, true);
  170. return;
  171. case AnchorMode.FollowObject:
  172. FollowAnchor(rectTransform, oldPosition);
  173. return;
  174. default:
  175. Debug.LogError("Unknown AnchorMode: " + AlignDistributeWindow.anchorMode);
  176. throw new ArgumentOutOfRangeException();
  177. }
  178. }
  179. private static void FollowAnchor(RectTransform rectTransform, Vector2 oldPosition)
  180. {
  181. Vector3 currentPosition = rectTransform.position;
  182. Vector2 halfSize = GetTransformSize(rectTransform) * 0.5f;
  183. Vector2 parentSize = GetTransformSize(rectTransform.parent);
  184. Vector2 pivotAndCenterDistance = GetPivotAndCenterLocalDistance(rectTransform);
  185. Vector2 max = (Vector2)rectTransform.position + halfSize - pivotAndCenterDistance;
  186. Vector2 min = (Vector2)rectTransform.position - halfSize - pivotAndCenterDistance;
  187. Vector2 oldMax = oldPosition + halfSize - pivotAndCenterDistance;
  188. Vector2 oldMin = oldPosition - halfSize - pivotAndCenterDistance;
  189. Vector2 diffMax = oldMax - max;
  190. Vector2 diffMin = oldMin - min;
  191. // Normalize
  192. diffMin.x /= parentSize.x;
  193. diffMin.y /= parentSize.y;
  194. diffMax.x /= parentSize.x;
  195. diffMax.y /= parentSize.y;
  196. // Apply Values
  197. rectTransform.anchorMax = rectTransform.anchorMax - diffMax;
  198. rectTransform.anchorMin = rectTransform.anchorMin - diffMin;
  199. rectTransform.position = currentPosition;
  200. }
  201. public static RectTransform GetBoundingBoxRectTransform(Transform[] selection)
  202. {
  203. // Instantiating a RectTransform doesn't work, therefore we need a temporal GameObject...
  204. helperObject = new GameObject("Bounding Box Rect", typeof(RectTransform));
  205. helperObject.transform.SetParent(selection[0].parent);
  206. RectTransform result = helperObject.GetComponent<RectTransform>();
  207. Vector2 min = new Vector2(Mathf.Infinity, Mathf.Infinity);
  208. Vector2 max = new Vector2(Mathf.NegativeInfinity, Mathf.NegativeInfinity);
  209. foreach (Transform transform in selection)
  210. {
  211. RectTransform rectTransform = transform as RectTransform;
  212. Vector2 size = Utility.GetTransformSize(rectTransform);
  213. Vector2 upperRight = (Vector2)rectTransform.position + size * 0.5f - Utility.GetPivotAndCenterLocalDistance(rectTransform);
  214. Vector2 lowerLeft = (Vector2)rectTransform.position - size * 0.5f - Utility.GetPivotAndCenterLocalDistance(rectTransform);
  215. min.x = Mathf.Min(min.x, lowerLeft.x);
  216. min.y = Mathf.Min(min.y, lowerLeft.y);
  217. max.x = Mathf.Max(max.x, upperRight.x);
  218. max.y = Mathf.Max(max.y, upperRight.y);
  219. }
  220. result.position = new Vector3(min.x + max.x, min.y + max.y) * 0.5f;
  221. result.sizeDelta = new Vector2(Mathf.Abs(max.x - min.x), Mathf.Abs(max.y - min.y));
  222. return result;
  223. }
  224. }
  225. }