using UnityEngine; using UnityEngine.UI; using System.Collections.Generic; using System.Linq; using System; namespace EasyLayout { /// /// EasyLayout utilites. /// public static class EasyLayoutUtilites { struct Sizes { public float Min; public float Preferred; public float Flexible; } struct SizesInfo { public float TotalMin; public float TotalPreferred; public float TotalFlexible; public Sizes[] Sizes; } static SizesInfo GetSizesInfo(Sizes[] sizes) { var result = new SizesInfo(){Sizes = sizes}; for (int i = 0; i < sizes.Length; i++) { result.TotalMin += sizes[i].Min; result.TotalPreferred += sizes[i].Preferred; result.TotalFlexible += sizes[i].Flexible; } if (result.TotalFlexible==0f) { for (int i = 0; i < sizes.Length; i++) { sizes[i].Flexible = 1f; } result.TotalFlexible += sizes.Length; } return result; } static SizesInfo GetWidths(List elems) { var sizes = new Sizes[elems.Count]; for (int i = 0; i < elems.Count; i++) { sizes[i] = new Sizes(){ Min = GetMinWidth(elems[i]), Preferred = GetPreferredWidth(elems[i]), Flexible = GetFlexibleWidth(elems[i]), }; } return GetSizesInfo(sizes); } static SizesInfo GetHeights(List elems) { var sizes = new Sizes[elems.Count]; for (int i = 0; i < elems.Count; i++) { sizes[i] = new Sizes(){ Min = GetMinHeight(elems[i]), Preferred = GetPreferredHeight(elems[i]), Flexible = GetFlexibleHeight(elems[i]), }; } return GetSizesInfo(sizes); } static SizesInfo GetWidths(List> elems) { var sizes = new Sizes[elems.Count]; for (int i = 0; i < elems.Count; i++) { sizes[i] = new Sizes(){ Min = GetMaxMinWidth(elems[i]), Preferred = GetMaxPreferredWidth(elems[i]), Flexible = GetMaxFlexibleWidth(elems[i]), }; } return GetSizesInfo(sizes); } static SizesInfo GetHeights(List> elems) { var sizes = new Sizes[elems.Count]; for (int i = 0; i < elems.Count; i++) { sizes[i] = new Sizes(){ Min = GetMaxMinHeight(elems[i]), Preferred = GetMaxPreferredHeight(elems[i]), Flexible = GetMaxFlexibleHeight(elems[i]), }; } return GetSizesInfo(sizes); } static void ResizeToFit(float size, List elems, float spacing, RectTransform.Axis axis) { var sizes = axis==RectTransform.Axis.Horizontal ? GetWidths(elems) : GetHeights(elems); float free_space = size - sizes.TotalPreferred - ((elems.Count - 1) * spacing); var per_flexible = free_space / sizes.TotalFlexible; var minPrefLerp = 0f; if (sizes.TotalMin!=sizes.TotalPreferred) { minPrefLerp = Mathf.Clamp01((size - sizes.TotalMin) / (sizes.TotalPreferred - sizes.TotalMin)); } for (int i = 0; i < elems.Count; i++) { var element_size = Mathf.Lerp(sizes.Sizes[i].Min, sizes.Sizes[i].Preferred, minPrefLerp) + (per_flexible * sizes.Sizes[i].Flexible); elems[i].SetSizeWithCurrentAnchors(axis, element_size); } } static void ResizeToFit(float size, List> elems, float spacing, RectTransform.Axis axis) { var sizes = axis==RectTransform.Axis.Horizontal ? GetWidths(elems) : GetHeights(elems); float free_space = size - sizes.TotalPreferred - ((elems.Count - 1) * spacing); var per_flexible = Mathf.Max(0f, free_space / sizes.TotalFlexible); var minPrefLerp = 0f; if (sizes.TotalMin != sizes.TotalPreferred) { minPrefLerp = Mathf.Clamp01((size - sizes.TotalMin) / (sizes.TotalPreferred - sizes.TotalMin)); } for (int i = 0; i < elems.Count; i++) { var element_size = Mathf.Lerp(sizes.Sizes[i].Min, sizes.Sizes[i].Preferred, minPrefLerp) + (per_flexible * sizes.Sizes[i].Flexible); for (int j = 0; j < elems[i].Count; j++) { elems[i][j].SetSizeWithCurrentAnchors(axis, element_size); } } } /// /// Resizes the width to fit container. /// /// Width. /// Group. /// Spacing. static public void ResizeWidthToFit(float width, List> group, float spacing) { for (int i = 0; i < group.Count; i++) { ResizeToFit(width, group[i], spacing, RectTransform.Axis.Horizontal); } } /// /// Resizes the height to fit container. /// /// Height. /// Group. /// Spacing. static public void ResizeHeightToFit(float height, List> group, float spacing) { var transposed_group = Transpose(group); for (int i = 0; i < transposed_group.Count; i++) { ResizeToFit(height, transposed_group[i], spacing, RectTransform.Axis.Vertical); } } /// /// Resizes the column width to fit container. /// /// Width. /// Group. /// Spacing. /// Padding. static public void ResizeColumnWidthToFit(float width, List> group, float spacing, float padding) { var transposed_group = Transpose(group); ResizeToFit(width - padding, transposed_group, spacing, RectTransform.Axis.Horizontal); } /// /// Resizes the row height to fit container. /// /// Height. /// Group. /// Spacing. /// Padding. static public void ResizeRowHeightToFit(float height, List> group, float spacing, float padding) { ResizeToFit(height - padding, group, spacing, RectTransform.Axis.Vertical); } /// /// Gets the maximum PreferredHeight. /// /// The max preferred height. /// Column. public static float GetMaxPreferredHeight(List column) { return column.Max(GetPreferredHeight); } /// /// Gets the maximum MinHeight. /// /// The max minimum height. /// Column. public static float GetMaxMinHeight(List column) { return column.Max(GetMinHeight); } /// /// Gets the maximum FlexibleHeight. /// /// The max flexible height. /// Column. public static float GetMaxFlexibleHeight(List column) { return column.Max(GetFlexibleHeight); } /// /// Gets the maximum PreferredWidth. /// /// The max preferred width. /// Row. public static float GetMaxPreferredWidth(List row) { return row.Max(GetPreferredWidth); } /// /// Gets the maximum MinWidth. /// /// The max minimum width. /// Row. public static float GetMaxMinWidth(List row) { return row.Max(GetMinWidth); } /// /// Gets the maximum FlexibleWidth. /// /// The max flexible width. /// Row. public static float GetMaxFlexibleWidth(List row) { return row.Max(GetFlexibleWidth); } /// /// Transpose the specified group. /// /// Group. /// The 1st type parameter. public static List> Transpose(List> group) { var result = new List>(); for (int i = 0; i < group.Count; i++) { for (int j = 0; j < group[i].Count; j++) { if (result.Count<=j) { result.Add(new List()); } result[j].Add(group[i][j]); } } return result; } static void Log(IEnumerable values) { Debug.Log("[" + string.Join("; ", values.Select(x => x.ToString()).ToArray()) + "]"); } /// /// Gets the preferred width of the RectTransform. /// /// The preferred width. /// Rect. public static float GetPreferredWidth(RectTransform rect) { #if UNITY_4_6 || UNITY_4_7 return Mathf.Max(0f, LayoutUtility.GetPreferredWidth(rect)); #else if (rect==null) { return 0f; } if (rect.gameObject.activeInHierarchy) { return Mathf.Max(0f, LayoutUtility.GetPreferredWidth(rect)); } else { float result = 0f; var elements = rect.GetComponents(); var max_priority = elements.Max(x => x.layoutPriority); foreach (var elem in elements) { if (elem.layoutPriority==max_priority) { result = Mathf.Max(result, Mathf.Max(elem.preferredWidth, elem.minWidth)); } } return result; } #endif } /// /// Gets the min width of the RectTransform. /// /// The preferred width. /// Rect. public static float GetMinWidth(RectTransform rect) { #if UNITY_4_6 || UNITY_4_7 return Mathf.Max(0f, LayoutUtility.GetMinWidth(rect)); #else if (rect==null) { return 0f; } if (rect.gameObject.activeInHierarchy) { return Mathf.Max(0f, LayoutUtility.GetMinWidth(rect)); } else { float result = 0f; var elements = rect.GetComponents(); var max_priority = elements.Max(x => x.layoutPriority); foreach (var elem in elements) { if (elem.layoutPriority==max_priority) { result = Mathf.Max(result, elem.minWidth); } } return result; } #endif } /// /// Gets the preferred height of the RectTransform. /// /// The preferred height. /// Rect. public static float GetPreferredHeight(RectTransform rect) { #if UNITY_4_6 || UNITY_4_7 return Mathf.Max(0f, LayoutUtility.GetPreferredHeight(rect)); #else if (rect==null) { return 0f; } if (rect.gameObject.activeInHierarchy) { return Mathf.Max(0f, LayoutUtility.GetPreferredHeight(rect)); } else { float result = 0f; var elements = rect.GetComponents(); var max_priority = elements.Max(x => x.layoutPriority); foreach (var elem in elements) { if (elem.layoutPriority==max_priority) { result = Mathf.Max(result, Mathf.Max(elem.preferredHeight, elem.minHeight)); } } return result; } #endif } /// /// Gets the min height of the RectTransform. /// /// The min height. /// Rect. public static float GetMinHeight(RectTransform rect) { #if UNITY_4_6 || UNITY_4_7 return Mathf.Max(0f, LayoutUtility.GetMinHeight(rect)); #else if (rect==null) { return 0f; } if (rect.gameObject.activeInHierarchy) { return Mathf.Max(0f, LayoutUtility.GetMinHeight(rect)); } else { float result = 0f; var elements = rect.GetComponents(); var max_priority = elements.Max(x => x.layoutPriority); foreach (var elem in elements) { if (elem.layoutPriority==max_priority) { result = Mathf.Max(result, elem.minHeight); } } return result; } #endif } /// /// Gets the flexible width of the RectTransform. /// /// The flexible width. /// Rect. public static float GetFlexibleWidth(RectTransform rect) { #if UNITY_4_6 || UNITY_4_7 return Mathf.Max(0f, LayoutUtility.GetFlexibleWidth(rect)); #else if (rect==null) { return 0f; } if (rect.gameObject.activeInHierarchy) { return Mathf.Max(0f, LayoutUtility.GetFlexibleWidth(rect)); } else { float result = 0f; var elements = rect.GetComponents(); var max_priority = elements.Max(x => x.layoutPriority); foreach (var elem in elements) { if (elem.layoutPriority==max_priority) { result = Mathf.Max(result, elem.flexibleWidth); } } return result; } #endif } /// /// Gets the flexible height of the RectTransform. /// /// The flexible height. /// Rect. public static float GetFlexibleHeight(RectTransform rect) { #if UNITY_4_6 || UNITY_4_7 return Mathf.Max(0f, LayoutUtility.GetFlexibleHeight(rect)); #else if (rect==null) { return 0f; } if (rect.gameObject.activeInHierarchy) { return Mathf.Max(0f, LayoutUtility.GetFlexibleHeight(rect)); } else { float result = 0f; var elements = rect.GetComponents(); var max_priority = elements.Max(x => x.layoutPriority); foreach (var elem in elements) { if (elem.layoutPriority==max_priority) { result = Mathf.Max(result, elem.flexibleHeight); } } return result; } #endif } /// /// Get scaled width. /// /// The width. /// User interface. public static float ScaledWidth(RectTransform ui) { return ui.rect.width * ui.localScale.x; } /// /// Get scaled height. /// /// The height. /// User interface. public static float ScaledHeight(RectTransform ui) { return ui.rect.height * ui.localScale.y; } } }