AlignDistributeWindow.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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 class AlignDistributeWindow : EditorWindow
  9. {
  10. private static ActiveWindow activeWindow = ActiveWindow.Align;
  11. private static AlignTo alignTo = AlignTo.SelectionBounds;
  12. internal static DistributeTo distributeTo = DistributeTo.SelectionBounds;
  13. private static DistanceOption distanceOption = DistanceOption.Space;
  14. private static SortOrder sortOrder;
  15. internal static AnchorMode anchorMode = AnchorMode.FollowObject;
  16. private static readonly string[] alignToOptions = System.Enum.GetNames(typeof(AlignTo));
  17. private static readonly string[] distanceOptions = System.Enum.GetNames(typeof(DistanceOption));
  18. private static readonly string[] anchorModeOptions = System.Enum.GetNames(typeof(AnchorMode));
  19. private static bool showPadding = true;
  20. private static float paddingLeftBottomPixels = 0f;
  21. private static float paddingRightTopPixels = 0f;
  22. private Texture2D alignLeft, alignCenter, alignRight, alignBottom, alignMiddle, alignTop;
  23. private Texture2D distributeHorizontal, distributeVertical;
  24. [MenuItem("Tools/Better UI/Align and Distribute", false, 62)]
  25. public static void ShowWindow()
  26. {
  27. EditorWindow window = GetWindow(typeof(AlignDistributeWindow), false, "Align/Distribute");
  28. window.minSize = new Vector2(270, 350);
  29. }
  30. private void OnEnable()
  31. {
  32. alignLeft = Resources.Load<Texture2D>("allign_left");
  33. alignCenter = Resources.Load<Texture2D>("allign_center");
  34. alignRight = Resources.Load<Texture2D>("allign_right");
  35. alignBottom = Resources.Load<Texture2D>("allign_bottom");
  36. alignMiddle = Resources.Load<Texture2D>("allign_middle");
  37. alignTop = Resources.Load<Texture2D>("allign_top");
  38. distributeHorizontal = Resources.Load<Texture2D>("distribute_horizontally");
  39. distributeVertical = Resources.Load<Texture2D>("distribute_vertically");
  40. }
  41. private void OnSelectionChange()
  42. {
  43. Repaint();
  44. }
  45. private void OnGUI()
  46. {
  47. EditorGUIUtility.labelWidth = 2f;
  48. EditorGUILayout.Space();
  49. DrawModeSelection();
  50. EditorGUILayout.Space();
  51. DrawSelectionInfo();
  52. switch (activeWindow)
  53. {
  54. case ActiveWindow.Align:
  55. DrawAlignButtons();
  56. EditorGUILayout.Space();
  57. DrawAlignTo();
  58. break;
  59. case ActiveWindow.Distribute:
  60. DrawDistributeButtons();
  61. EditorGUILayout.Space();
  62. DrawPadding();
  63. EditorGUILayout.Space();
  64. DrawOrderOptions();
  65. EditorGUILayout.Space();
  66. DrawDistributeTo();
  67. EditorGUILayout.Space();
  68. DrawDistanceOptions();
  69. break;
  70. }
  71. EditorGUILayout.Space();
  72. DrawAnchorMode();
  73. EditorGUIUtility.labelWidth = 0f;
  74. }
  75. private void DrawModeSelection()
  76. {
  77. EditorGUILayout.BeginHorizontal();
  78. if (GUILayout.Toggle((activeWindow == ActiveWindow.Align), "Align", EditorStyles.miniButtonLeft))
  79. {
  80. activeWindow = ActiveWindow.Align;
  81. }
  82. if (GUILayout.Toggle((activeWindow == ActiveWindow.Distribute), "Distribute", EditorStyles.miniButtonRight))
  83. {
  84. activeWindow = ActiveWindow.Distribute;
  85. }
  86. EditorGUILayout.EndHorizontal();
  87. }
  88. private void DrawSelectionInfo()
  89. {
  90. SelectionStatus selectionStatus = Utility.IsSelectionValid();
  91. if (selectionStatus != SelectionStatus.Valid)
  92. {
  93. DrawInvalidSelectionInfo(selectionStatus);
  94. }
  95. else
  96. {
  97. Transform[] selection = Selection.transforms;
  98. string label = (selection.Length == 1) ? selection[0].name : string.Format("{0} UI Elements", selection.Length);
  99. EditorGUILayout.LabelField(label, EditorStyles.centeredGreyMiniLabel);
  100. }
  101. EditorGUILayout.Space();
  102. }
  103. private void DrawInvalidSelectionInfo(SelectionStatus selectionStatus)
  104. {
  105. GUIStyle warn = GUI.skin.GetStyle("WarningOverlay");
  106. EditorGUI.BeginDisabledGroup(true);
  107. string message;
  108. switch (selectionStatus)
  109. {
  110. case SelectionStatus.NothingSelected:
  111. message = "Nothing selected";
  112. break;
  113. case SelectionStatus.ParentIsNull:
  114. case SelectionStatus.ParentIsNoRectTransform:
  115. message = "Objects must be inside a Canvas.";
  116. break;
  117. case SelectionStatus.ContainsNoRectTransform:
  118. message = "All objects must have a RectTransform.";
  119. break;
  120. case SelectionStatus.UnequalParents:
  121. message = "Objects must have the same parent.";
  122. break;
  123. case SelectionStatus.Valid:
  124. // Function should never be called when selection is valid.
  125. message = "Unknown problem discovered.";
  126. break;
  127. default:
  128. Debug.LogError("Invalid SelectionStatus: " + selectionStatus);
  129. throw new ArgumentOutOfRangeException();
  130. }
  131. EditorGUILayout.BeginHorizontal();
  132. GUILayout.Space(5);
  133. GUILayout.TextArea(message, warn);
  134. GUILayout.Space(5);
  135. EditorGUILayout.EndHorizontal();
  136. }
  137. private void DrawAlignButtons()
  138. {
  139. EditorGUILayout.BeginHorizontal();
  140. GUILayout.FlexibleSpace();
  141. if (GUILayout.Button(new GUIContent(alignLeft, "Align to the left"), GUILayout.Width(60f), GUILayout.Height(60f)))
  142. {
  143. Align.AlignSelection(AlignMode.Left, alignTo);
  144. }
  145. if (GUILayout.Button(new GUIContent(alignCenter, "Align to the center"), GUILayout.Width(60f), GUILayout.Height(60f)))
  146. {
  147. Align.AlignSelection(AlignMode.Vertical, alignTo);
  148. }
  149. if (GUILayout.Button(new GUIContent(alignRight, "Align to the right"), GUILayout.Width(60f), GUILayout.Height(60f)))
  150. {
  151. Align.AlignSelection(AlignMode.Right, alignTo);
  152. }
  153. GUILayout.FlexibleSpace();
  154. EditorGUILayout.EndHorizontal();
  155. EditorGUILayout.BeginHorizontal();
  156. GUILayout.FlexibleSpace();
  157. if (GUILayout.Button(new GUIContent(alignTop, "Align to the top"), GUILayout.Width(60f), GUILayout.Height(60f)))
  158. {
  159. Align.AlignSelection(AlignMode.Top, alignTo);
  160. }
  161. if (GUILayout.Button(new GUIContent(alignMiddle, "Align to the middle"), GUILayout.Width(60f), GUILayout.Height(60f)))
  162. {
  163. Align.AlignSelection(AlignMode.Horizontal, alignTo);
  164. }
  165. if (GUILayout.Button(new GUIContent(alignBottom, "Align to the bottom"), GUILayout.Width(60f), GUILayout.Height(60f)))
  166. {
  167. Align.AlignSelection(AlignMode.Bottom, alignTo);
  168. }
  169. GUILayout.FlexibleSpace();
  170. EditorGUILayout.EndHorizontal();
  171. }
  172. private void DrawDistributeButtons()
  173. {
  174. EditorGUILayout.BeginHorizontal();
  175. GUILayout.FlexibleSpace();
  176. if (GUILayout.Button(new GUIContent(distributeHorizontal, "Distribute horizontally"), GUILayout.Width(60f), GUILayout.Height(60f)))
  177. {
  178. if (Selection.GetTransforms(SelectionMode.Unfiltered).Length > 1)
  179. {
  180. Distribute.DistributeSelection(AlignMode.Horizontal, distanceOption, sortOrder,
  181. paddingLeftBottomPixels, paddingRightTopPixels);
  182. }
  183. else
  184. {
  185. Align.AlignSelection(AlignMode.Horizontal, AlignTo.Parent);
  186. }
  187. }
  188. if (GUILayout.Button(new GUIContent(distributeVertical, "Distribute vertically"), GUILayout.Width(60f), GUILayout.Height(60f)))
  189. {
  190. if (Selection.GetTransforms(SelectionMode.Unfiltered).Length > 1)
  191. {
  192. Distribute.DistributeSelection(AlignMode.Vertical, distanceOption, sortOrder,
  193. paddingLeftBottomPixels, paddingRightTopPixels);
  194. }
  195. else
  196. {
  197. Align.AlignSelection(AlignMode.Vertical, AlignTo.Parent);
  198. }
  199. }
  200. GUILayout.FlexibleSpace();
  201. EditorGUILayout.EndHorizontal();
  202. }
  203. private void DrawDistanceOptions()
  204. {
  205. EditorGUILayout.BeginHorizontal();
  206. EditorGUILayout.LabelField("Align by", GUILayout.ExpandWidth(false));
  207. distanceOption = (DistanceOption) EditorGUILayout.Popup((int)distanceOption, distanceOptions);
  208. EditorGUILayout.EndHorizontal();
  209. }
  210. private void DrawPadding()
  211. {
  212. EditorGUILayout.BeginHorizontal();
  213. {
  214. EditorGUILayout.BeginVertical();
  215. EditorGUILayout.LabelField("Padding");
  216. if (showPadding)
  217. {
  218. EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(false));
  219. GUILayout.Space(25);
  220. EditorGUILayout.LabelField("Left / Bottom", GUILayout.Width(80));
  221. paddingLeftBottomPixels = EditorGUILayout.FloatField(paddingLeftBottomPixels);
  222. EditorGUILayout.EndHorizontal();
  223. EditorGUILayout.BeginHorizontal();
  224. GUILayout.Space(25);
  225. EditorGUILayout.LabelField("Right / Top", GUILayout.Width(80));
  226. paddingRightTopPixels = EditorGUILayout.FloatField(paddingRightTopPixels);
  227. EditorGUILayout.EndHorizontal();
  228. }
  229. EditorGUILayout.EndVertical();
  230. }
  231. EditorGUILayout.EndHorizontal();
  232. }
  233. private void DrawOrderOptions()
  234. {
  235. EditorGUILayout.BeginHorizontal();
  236. EditorGUILayout.LabelField("Sorting Order", GUILayout.Width(100f));
  237. EditorGUILayout.BeginVertical();
  238. {
  239. if (GUILayout.Toggle((sortOrder == SortOrder.Positional), "Positional", "Radio"))
  240. {
  241. sortOrder = SortOrder.Positional;
  242. }
  243. if (GUILayout.Toggle((sortOrder == SortOrder.Hierarchical), "Hierarchical", "Radio"))
  244. {
  245. sortOrder = SortOrder.Hierarchical;
  246. }
  247. }
  248. EditorGUILayout.EndVertical();
  249. EditorGUILayout.EndHorizontal();
  250. }
  251. private void DrawDistributeTo()
  252. {
  253. EditorGUILayout.BeginHorizontal();
  254. EditorGUILayout.LabelField("Distribute along", GUILayout.Width(100f));
  255. EditorGUILayout.BeginVertical();
  256. {
  257. if (GUILayout.Toggle(distributeTo == DistributeTo.SelectionBounds, "Selection Bounds", "Radio"))
  258. {
  259. distributeTo = DistributeTo.SelectionBounds;
  260. }
  261. if (GUILayout.Toggle(distributeTo == DistributeTo.Parent, "Parent", "Radio"))
  262. {
  263. distributeTo = DistributeTo.Parent;
  264. }
  265. }
  266. EditorGUILayout.EndVertical();
  267. EditorGUILayout.EndHorizontal();
  268. }
  269. private void DrawAlignTo()
  270. {
  271. EditorGUILayout.BeginHorizontal();
  272. EditorGUILayout.LabelField("Align to", GUILayout.ExpandWidth(false));
  273. alignTo = (AlignTo)EditorGUILayout.Popup((int)alignTo, alignToOptions);
  274. EditorGUILayout.EndHorizontal();
  275. }
  276. private void DrawAnchorMode()
  277. {
  278. EditorGUILayout.BeginHorizontal();
  279. EditorGUILayout.LabelField("Anchors", GUILayout.ExpandWidth(false));
  280. anchorMode = (AnchorMode)EditorGUILayout.Popup((int)anchorMode, anchorModeOptions);
  281. EditorGUILayout.EndHorizontal();
  282. }
  283. }
  284. }