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;
}
}
}