You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1207 lines
29 KiB
1207 lines
29 KiB
using UnityEngine; |
|
using UnityEngine.UI; |
|
using UnityEngine.Events; |
|
using UnityEngine.EventSystems; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System; |
|
|
|
namespace EasyLayout { |
|
/// <summary> |
|
/// Grid constraints. |
|
/// Flexible - Don't constrain the number of rows or columns. |
|
/// FixedColumnCount - Constraint the number of columns to a specified number. |
|
/// FixedRowCount - Constraint the number of rows to a specified number. |
|
/// </summary> |
|
public enum GridConstraints |
|
{ |
|
Flexible = 0, |
|
FixedColumnCount = 1, |
|
FixedRowCount = 2, |
|
} |
|
|
|
/// <summary> |
|
/// Padding. |
|
/// </summary> |
|
[Serializable] |
|
public struct Padding |
|
{ |
|
/// <summary> |
|
/// The left padding. |
|
/// </summary> |
|
[SerializeField] |
|
public float Left; |
|
|
|
/// <summary> |
|
/// The right padding. |
|
/// </summary> |
|
[SerializeField] |
|
public float Right; |
|
|
|
/// <summary> |
|
/// The top padding. |
|
/// </summary> |
|
[SerializeField] |
|
public float Top; |
|
|
|
/// <summary> |
|
/// The bottom padding. |
|
/// </summary> |
|
[SerializeField] |
|
public float Bottom; |
|
|
|
/// <summary> |
|
/// Initializes a new instance of the struct. |
|
/// </summary> |
|
/// <param name="left">Left.</param> |
|
/// <param name="right">Right.</param> |
|
/// <param name="top">Top.</param> |
|
/// <param name="bottom">Bottom.</param> |
|
public Padding(float left, float right, float top, float bottom) |
|
{ |
|
Left = left; |
|
Right = right; |
|
Top = top; |
|
Bottom = bottom; |
|
} |
|
|
|
/// <summary> |
|
/// Returns a string that represents the current object. |
|
/// </summary> |
|
/// <returns>A string that represents the current object.</returns> |
|
public override string ToString() |
|
{ |
|
return String.Format("Padding(left: {0}, right: {1}, top: {2}, bottom: {3})", |
|
Left, |
|
Right, |
|
Top, |
|
Bottom |
|
); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Children size. |
|
/// DoNothing - Don't change size of children. |
|
/// SetPreferred - Set size of children to preferred. |
|
/// SetMaxFromPreferred - Set size of children to maximum size of children preferred. |
|
/// FitContainer - Stretch size of children to fit container. |
|
/// </summary> |
|
[Flags] |
|
public enum ChildrenSize { |
|
DoNothing = 0, |
|
SetPreferred = 1, |
|
SetMaxFromPreferred = 2, |
|
FitContainer = 3, |
|
} |
|
|
|
/// <summary> |
|
/// Anchors. |
|
/// UpperLeft - UpperLeft. |
|
/// UpperCenter - UpperCenter. |
|
/// UpperRight - UpperRight. |
|
/// MiddleLeft - MiddleLeft. |
|
/// MiddleCenter - MiddleCenter. |
|
/// MiddleRight - MiddleRight. |
|
/// LowerLeft - LowerLeft. |
|
/// LowerCenter - LowerCenter. |
|
/// LowerRight - LowerRight. |
|
/// </summary> |
|
[Flags] |
|
public enum Anchors { |
|
UpperLeft = 0, |
|
UpperCenter = 1, |
|
UpperRight = 2, |
|
|
|
MiddleLeft = 3, |
|
MiddleCenter = 4, |
|
MiddleRight = 5, |
|
|
|
LowerLeft = 6, |
|
LowerCenter = 7, |
|
LowerRight = 8, |
|
} |
|
|
|
/// <summary> |
|
/// Stackings. |
|
/// Horizontal - Horizontal. |
|
/// Vertical - Vertical. |
|
/// </summary> |
|
[Flags] |
|
public enum Stackings { |
|
Horizontal = 0, |
|
Vertical = 1, |
|
} |
|
|
|
/// <summary> |
|
/// Horizontal aligns. |
|
/// Left - Left. |
|
/// Center - Center. |
|
/// Right - Right. |
|
/// </summary> |
|
[Flags] |
|
public enum HorizontalAligns { |
|
Left = 0, |
|
Center = 1, |
|
Right = 2, |
|
} |
|
|
|
/// <summary> |
|
/// Inner aligns. |
|
/// Top - Top. |
|
/// Middle - Middle. |
|
/// Bottom - Bottom. |
|
/// </summary> |
|
[Flags] |
|
public enum InnerAligns { |
|
Top = 0, |
|
Middle = 1, |
|
Bottom = 2, |
|
} |
|
|
|
/// <summary> |
|
/// Layout type to use. |
|
/// Compact - Compact. |
|
/// Grid - Grid. |
|
/// </summary> |
|
[Flags] |
|
public enum LayoutTypes { |
|
Compact = 0, |
|
Grid = 1, |
|
} |
|
|
|
/// <summary> |
|
/// EasyLayout. |
|
/// Warning: using RectTransform relative size with positive size delta (like 100% + 10) with ContentSizeFitter can lead to infinite increased size. |
|
/// </summary> |
|
[ExecuteInEditMode] |
|
[RequireComponent(typeof(RectTransform))] |
|
[AddComponentMenu("UI/UIWidgets/EasyLayout")] |
|
public class EasyLayout : UnityEngine.UI.LayoutGroup { |
|
/// <summary> |
|
/// The group position. |
|
/// </summary> |
|
[SerializeField] |
|
public Anchors GroupPosition = Anchors.UpperLeft; |
|
|
|
/// <summary> |
|
/// The stacking type. |
|
/// </summary> |
|
[SerializeField] |
|
public Stackings Stacking = Stackings.Horizontal; |
|
|
|
/// <summary> |
|
/// The type of the layout. |
|
/// </summary> |
|
[SerializeField] |
|
public LayoutTypes LayoutType = LayoutTypes.Compact; |
|
|
|
/// <summary> |
|
/// Which constraint to use for the Grid layout. |
|
/// </summary> |
|
[SerializeField] |
|
public GridConstraints GridConstraint = GridConstraints.Flexible; |
|
|
|
/// <summary> |
|
/// How many cells there should be along the constrained axis. |
|
/// </summary> |
|
[SerializeField] |
|
public int GridConstraintCount = 1; |
|
|
|
/// <summary> |
|
/// The row align. |
|
/// </summary> |
|
[SerializeField] |
|
public HorizontalAligns RowAlign = HorizontalAligns.Left; |
|
|
|
/// <summary> |
|
/// The inner align. |
|
/// </summary> |
|
[SerializeField] |
|
public InnerAligns InnerAlign = InnerAligns.Top; |
|
|
|
/// <summary> |
|
/// The cell align. |
|
/// </summary> |
|
[SerializeField] |
|
public Anchors CellAlign = Anchors.UpperLeft; |
|
|
|
/// <summary> |
|
/// The spacing. |
|
/// </summary> |
|
[SerializeField] |
|
public Vector2 Spacing = new Vector2(5, 5); |
|
|
|
/// <summary> |
|
/// Symmetric margin. |
|
/// </summary> |
|
[SerializeField] |
|
public bool Symmetric = true; |
|
|
|
/// <summary> |
|
/// The margin. |
|
/// </summary> |
|
[SerializeField] |
|
public Vector2 Margin = new Vector2(5, 5); |
|
|
|
/// <summary> |
|
/// The padding. |
|
/// </summary> |
|
[SerializeField] |
|
public Padding PaddingInner = new Padding(); |
|
|
|
/// <summary> |
|
/// The margin top. |
|
/// </summary> |
|
[SerializeField] |
|
public float MarginTop = 5f; |
|
|
|
/// <summary> |
|
/// The margin bottom. |
|
/// </summary> |
|
[SerializeField] |
|
public float MarginBottom = 5f; |
|
|
|
/// <summary> |
|
/// The margin left. |
|
/// </summary> |
|
[SerializeField] |
|
public float MarginLeft = 5f; |
|
|
|
/// <summary> |
|
/// The margin right. |
|
/// </summary> |
|
[SerializeField] |
|
public float MarginRight = 5f; |
|
|
|
/// <summary> |
|
/// The right to left stacking. |
|
/// </summary> |
|
[SerializeField] |
|
public bool RightToLeft = false; |
|
|
|
/// <summary> |
|
/// The top to bottom stacking. |
|
/// </summary> |
|
[SerializeField] |
|
public bool TopToBottom = true; |
|
|
|
/// <summary> |
|
/// The skip inactive. |
|
/// </summary> |
|
[SerializeField] |
|
public bool SkipInactive = true; |
|
|
|
/// <summary> |
|
/// The filter. |
|
/// </summary> |
|
public Func<IEnumerable<GameObject>,IEnumerable<GameObject>> Filter = null; |
|
|
|
/// <summary> |
|
/// How to control width of the children. |
|
/// </summary> |
|
public ChildrenSize ChildrenWidth; |
|
|
|
/// <summary> |
|
/// How to control height of the children. |
|
/// </summary> |
|
public ChildrenSize ChildrenHeight; |
|
|
|
/// <summary> |
|
/// Control width of children. |
|
/// </summary> |
|
[SerializeField] |
|
[Obsolete("Use ChildrenWidth with ChildrenSize.SetPreferred instead.")] |
|
public bool ControlWidth; |
|
|
|
/// <summary> |
|
/// Control height of children. |
|
/// </summary> |
|
[SerializeField] |
|
[Obsolete("Use ChildrenHeight with ChildrenSize.SetPreferred instead.")] |
|
public bool ControlHeight; |
|
|
|
/// <summary> |
|
/// Sets width of the chidren to maximum width from them. |
|
/// </summary> |
|
[SerializeField] |
|
[Obsolete("Use ChildrenWidth with ChildrenSize.SetMaxFromPreferred instead.")] |
|
public bool MaxWidth; |
|
|
|
/// <summary> |
|
/// Sets height of the chidren to maximum height from them. |
|
/// </summary> |
|
[SerializeField] |
|
[Obsolete("Use ChildrenHeight with ChildrenSize.SetMaxFromPreferred instead.")] |
|
public bool MaxHeight; |
|
|
|
Vector2 _blockSize; |
|
|
|
/// <summary> |
|
/// Gets or sets the size of the inner block. |
|
/// </summary> |
|
/// <value>The size of the inner block.</value> |
|
public Vector2 BlockSize { |
|
get { |
|
return _blockSize; |
|
} |
|
protected set { |
|
_blockSize = value; |
|
} |
|
} |
|
|
|
Vector2 _uiSize; |
|
/// <summary> |
|
/// Gets or sets the UI size. |
|
/// </summary> |
|
/// <value>The UI size.</value> |
|
public Vector2 UISize { |
|
get { |
|
return _uiSize; |
|
} |
|
protected set { |
|
_uiSize = value; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Gets the minimum height. |
|
/// </summary> |
|
/// <value>The minimum height.</value> |
|
public override float minHeight |
|
{ |
|
get |
|
{ |
|
//CalculateLayoutSize(); |
|
return BlockSize[1]; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Gets the minimum width. |
|
/// </summary> |
|
/// <value>The minimum width.</value> |
|
public override float minWidth |
|
{ |
|
get |
|
{ |
|
//CalculateLayoutSize(); |
|
return BlockSize[0]; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Gets the preferred height. |
|
/// </summary> |
|
/// <value>The preferred height.</value> |
|
public override float preferredHeight |
|
{ |
|
get |
|
{ |
|
//CalculateLayoutSize(); |
|
return BlockSize[1]; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Gets the preferred width. |
|
/// </summary> |
|
/// <value>The preferred width.</value> |
|
public override float preferredWidth |
|
{ |
|
get |
|
{ |
|
//CalculateLayoutSize(); |
|
return BlockSize[0]; |
|
} |
|
} |
|
|
|
static readonly List<Vector2> groupPositions = new List<Vector2>{ |
|
new Vector2(0.0f, 1.0f),//Anchors.UpperLeft |
|
new Vector2(0.5f, 1.0f),//Anchors.UpperCenter |
|
new Vector2(1.0f, 1.0f),//Anchors.UpperRight |
|
|
|
new Vector2(0.0f, 0.5f),//Anchors.MiddleLeft |
|
new Vector2(0.5f, 0.5f),//Anchors.MiddleCenter |
|
new Vector2(1.0f, 0.5f),//Anchors.MiddleRight |
|
|
|
new Vector2(0.0f, 0.0f),//Anchors.LowerLeft |
|
new Vector2(0.5f, 0.0f),//Anchors.LowerCenter |
|
new Vector2(1.0f, 0.0f),//Anchors.LowerRight |
|
}; |
|
|
|
static readonly List<float> rowAligns = new List<float>{ |
|
0.0f,//HorizontalAligns.Left |
|
0.5f,//HorizontalAligns.Center |
|
1.0f,//HorizontalAligns.Right |
|
}; |
|
static readonly List<float> innerAligns = new List<float>{ |
|
0.0f,//InnerAligns.Top |
|
0.5f,//InnerAligns.Middle |
|
1.0f,//InnerAligns.Bottom |
|
}; |
|
|
|
/// <summary> |
|
/// Raises the disable event. |
|
/// </summary> |
|
protected override void OnDisable() |
|
{ |
|
propertiesTracker.Clear(); |
|
base.OnDisable(); |
|
} |
|
|
|
/// <summary> |
|
/// Raises the rect transform removed event. |
|
/// </summary> |
|
void OnRectTransformRemoved() |
|
{ |
|
SetDirty(); |
|
} |
|
|
|
/// <summary> |
|
/// Sets the layout horizontal. |
|
/// </summary> |
|
public override void SetLayoutHorizontal() |
|
{ |
|
RepositionUIElements(); |
|
} |
|
|
|
/// <summary> |
|
/// Sets the layout vertical. |
|
/// </summary> |
|
public override void SetLayoutVertical() |
|
{ |
|
RepositionUIElements(); |
|
} |
|
|
|
/// <summary> |
|
/// Calculates the layout input horizontal. |
|
/// </summary> |
|
public override void CalculateLayoutInputHorizontal() |
|
{ |
|
base.CalculateLayoutInputHorizontal(); |
|
CalculateLayoutSize(); |
|
} |
|
|
|
/// <summary> |
|
/// Calculates the layout input vertical. |
|
/// </summary> |
|
public override void CalculateLayoutInputVertical() |
|
{ |
|
CalculateLayoutSize(); |
|
} |
|
|
|
/// <summary> |
|
/// Gets the length. |
|
/// </summary> |
|
/// <returns>The length.</returns> |
|
/// <param name="ui">User interface.</param> |
|
/// <param name="scaled">If set to <c>true</c> scaled.</param> |
|
public float GetLength(RectTransform ui, bool scaled=true) |
|
{ |
|
if (scaled) |
|
{ |
|
return Stacking==Stackings.Horizontal ? EasyLayoutUtilites.ScaledWidth(ui) : EasyLayoutUtilites.ScaledHeight(ui); |
|
} |
|
return Stacking==Stackings.Horizontal ? ui.rect.width : ui.rect.height; |
|
} |
|
|
|
/// <summary> |
|
/// Calculates the size of the group. |
|
/// </summary> |
|
/// <returns>The group size.</returns> |
|
/// <param name="group">Group.</param> |
|
Vector2 CalculateGroupSize(List<List<RectTransform>> group) |
|
{ |
|
float width = 0f; |
|
if (LayoutType==LayoutTypes.Compact) |
|
{ |
|
for (int i = 0; i < group.Count; i++) |
|
{ |
|
float row_width = Spacing.x * (group[i].Count - 1); |
|
for (int j = 0; j < group[i].Count; j++) |
|
{ |
|
row_width += EasyLayoutUtilites.ScaledWidth(group[i][j]); |
|
} |
|
width = Mathf.Max(width, row_width); |
|
} |
|
} |
|
else |
|
{ |
|
GetMaxColumnsWidths(group, MaxColumnsWidths); |
|
for (int i = 0; i < MaxColumnsWidths.Count; i++) |
|
{ |
|
width += MaxColumnsWidths[i]; |
|
} |
|
width += MaxColumnsWidths.Count * Spacing.x - Spacing.x; |
|
} |
|
|
|
float height = Spacing.y * (group.Count - 1); |
|
for (int i = 0; i < group.Count; i++) |
|
{ |
|
float row_height = 0f; |
|
for (int j = 0; j < group[i].Count; j++) |
|
{ |
|
row_height = Mathf.Max(row_height, EasyLayoutUtilites.ScaledHeight(group[i][j])); |
|
} |
|
height += row_height; |
|
} |
|
|
|
width += PaddingInner.Left + PaddingInner.Right; |
|
height += PaddingInner.Top + PaddingInner.Bottom; |
|
|
|
return new Vector2(width, height); |
|
} |
|
|
|
/// <summary> |
|
/// Marks layout to update. |
|
/// </summary> |
|
public void NeedUpdateLayout() |
|
{ |
|
UpdateLayout(); |
|
} |
|
|
|
/// <summary> |
|
/// Updates the size of the block. |
|
/// </summary> |
|
void UpdateBlockSize() |
|
{ |
|
if (Symmetric) |
|
{ |
|
BlockSize = new Vector2(UISize.x + Margin.x * 2, UISize.y + Margin.y * 2); |
|
} |
|
else |
|
{ |
|
BlockSize = new Vector2(UISize.x + MarginLeft + MarginRight, UISize.y + MarginTop + MarginBottom); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Calculates the size of the layout. |
|
/// </summary> |
|
public void CalculateLayoutSize() |
|
{ |
|
var group = GroupUIElements(); |
|
if (group.Count==0) |
|
{ |
|
UISize = new Vector2(0, 0); |
|
UpdateBlockSize(); |
|
|
|
return ; |
|
} |
|
|
|
UISize = CalculateGroupSize(group); |
|
UpdateBlockSize(); |
|
} |
|
|
|
/// <summary> |
|
/// Repositions the user interface elements. |
|
/// </summary> |
|
void RepositionUIElements() |
|
{ |
|
var group = GroupUIElements(); |
|
if (group.Count==0) |
|
{ |
|
UISize = new Vector2(0, 0); |
|
UpdateBlockSize(); |
|
|
|
//LayoutRebuilder.MarkLayoutForRebuild(rectTransform); |
|
return ; |
|
} |
|
|
|
UISize = CalculateGroupSize(group); |
|
UpdateBlockSize(); |
|
|
|
var anchor_position = groupPositions[(int)GroupPosition]; |
|
var start_position = new Vector2( |
|
rectTransform.rect.width * (anchor_position.x - rectTransform.pivot.x), |
|
rectTransform.rect.height * (anchor_position.y - rectTransform.pivot.y) |
|
); |
|
|
|
start_position.x -= anchor_position.x * UISize.x; |
|
start_position.y += (1 - anchor_position.y) * UISize.y; |
|
|
|
start_position.x += GetMarginLeft() * ((1 - anchor_position.x) * 2 - 1); |
|
start_position.y += GetMarginTop() * ((1 - anchor_position.y) * 2 - 1); |
|
|
|
start_position.x += PaddingInner.Left; |
|
start_position.y -= PaddingInner.Top; |
|
|
|
SetPositions(group, start_position, UISize); |
|
|
|
//LayoutRebuilder.MarkLayoutForRebuild(rectTransform); |
|
} |
|
|
|
/// <summary> |
|
/// Updates the layout. |
|
/// </summary> |
|
public void UpdateLayout() |
|
{ |
|
CalculateLayoutInputHorizontal(); |
|
|
|
RepositionUIElements(); |
|
} |
|
|
|
/// <summary> |
|
/// Gets the user interface element position. |
|
/// </summary> |
|
/// <returns>The user interface position.</returns> |
|
/// <param name="ui">User interface.</param> |
|
/// <param name="position">Position.</param> |
|
/// <param name="align">Align.</param> |
|
Vector2 GetUIPosition(RectTransform ui, Vector2 position, Vector2 align) |
|
{ |
|
var pivot_fix_x = EasyLayoutUtilites.ScaledWidth(ui) * ui.pivot.x; |
|
var pivox_fix_y = EasyLayoutUtilites.ScaledHeight(ui) * ui.pivot.y; |
|
var new_x = position.x + pivot_fix_x + align.x; |
|
var new_y = position.y - EasyLayoutUtilites.ScaledHeight(ui) + pivox_fix_y - align.y; |
|
|
|
return new Vector2(new_x, new_y); |
|
} |
|
|
|
void GetRowsWidths(List<List<RectTransform>> group, List<float> widths) |
|
{ |
|
widths.Clear(); |
|
|
|
for (int i = 0; i < group.Count; i++) |
|
{ |
|
float width = 0f; |
|
for (int j = 0; j < group[i].Count; j++) |
|
{ |
|
width += EasyLayoutUtilites.ScaledWidth(group[i][j]); |
|
} |
|
widths.Add(width + (group[i].Count - 1) * Spacing.x); |
|
} |
|
} |
|
|
|
void GetMaxColumnsWidths(List<List<RectTransform>> group, List<float> maxColumnsWidths) |
|
{ |
|
maxColumnsWidths.Clear(); |
|
|
|
for (var i = 0; i < group.Count; i++) |
|
{ |
|
for (var j = 0; j < group[i].Count; j++) |
|
{ |
|
if (maxColumnsWidths.Count <= j) |
|
{ |
|
maxColumnsWidths.Add(0); |
|
} |
|
maxColumnsWidths[j] = Mathf.Max(maxColumnsWidths[j], EasyLayoutUtilites.ScaledWidth(group[i][j])); |
|
} |
|
} |
|
} |
|
|
|
void GetColumnsHeights(List<List<RectTransform>> group, List<float> heights) |
|
{ |
|
heights.Clear(); |
|
|
|
for (int i = 0; i < group.Count; i++) |
|
{ |
|
float height = 0; |
|
for (int j = 0; j < group[i].Count; j++) |
|
{ |
|
height += EasyLayoutUtilites.ScaledHeight(group[i][j]); |
|
} |
|
heights.Add(height + (group[i].Count - 1) * Spacing.y); |
|
} |
|
} |
|
|
|
float GetMaxRowHeight(List<RectTransform> row) |
|
{ |
|
float height = 0; |
|
for (int i = 0; i < row.Count; i++) |
|
{ |
|
height = Mathf.Max(height, EasyLayoutUtilites.ScaledHeight(row[i])); |
|
} |
|
return height; |
|
} |
|
|
|
void GetMaxRowsHeights(List<List<RectTransform>> group, List<float> heights) |
|
{ |
|
heights.Clear(); |
|
var transposed_group = EasyLayoutUtilites.Transpose(group); |
|
|
|
for (int i = 0; i < transposed_group.Count; i++) |
|
{ |
|
heights.Add(GetMaxRowHeight(transposed_group[i])); |
|
} |
|
} |
|
|
|
Vector2 GetMaxCellSize(List<List<RectTransform>> group) |
|
{ |
|
float x = 0f; |
|
float y = 0f; |
|
for (int i = 0; i < group.Count; i++) |
|
{ |
|
for (int j = 0; j < group[i].Count; j++) |
|
{ |
|
x = Mathf.Max(x, EasyLayoutUtilites.ScaledWidth(group[i][j])); |
|
y = Mathf.Max(y, EasyLayoutUtilites.ScaledHeight(group[i][j])); |
|
} |
|
} |
|
|
|
return new Vector2(x, y); |
|
} |
|
|
|
Vector2 GetMaxCellSize(List<RectTransform> row) |
|
{ |
|
float x = 0f; |
|
float y = 0f; |
|
for (int i = 0; i < row.Count; i++) |
|
{ |
|
x = Mathf.Max(x, EasyLayoutUtilites.ScaledWidth(row[i])); |
|
y = Mathf.Max(y, EasyLayoutUtilites.ScaledHeight(row[i])); |
|
} |
|
|
|
return new Vector2(x, y); |
|
} |
|
|
|
Vector2 GetAlignByWidth(RectTransform ui, float maxWidth, Vector2 cellMaxSize, float emptyWidth) |
|
{ |
|
if (LayoutType==LayoutTypes.Compact) |
|
{ |
|
return new Vector2( |
|
emptyWidth * rowAligns[(int)RowAlign], |
|
(cellMaxSize.y - EasyLayoutUtilites.ScaledHeight(ui)) * innerAligns[(int)InnerAlign] |
|
); |
|
} |
|
else |
|
{ |
|
var cell_align = groupPositions[(int)CellAlign]; |
|
|
|
return new Vector2( |
|
(maxWidth - EasyLayoutUtilites.ScaledWidth(ui)) * cell_align.x, |
|
(cellMaxSize.y - EasyLayoutUtilites.ScaledHeight(ui)) * (1 - cell_align.y) |
|
); |
|
} |
|
} |
|
|
|
Vector2 GetAlignByHeight(RectTransform ui, float maxHeight, Vector2 cellMaxSize, float emptyHeight) |
|
{ |
|
if (LayoutType==LayoutTypes.Compact) |
|
{ |
|
return new Vector2( |
|
(cellMaxSize.x - EasyLayoutUtilites.ScaledWidth(ui)) * innerAligns[(int)InnerAlign], |
|
emptyHeight * rowAligns[(int)RowAlign] |
|
); |
|
} |
|
else |
|
{ |
|
var cell_align = groupPositions[(int)CellAlign]; |
|
|
|
return new Vector2( |
|
(cellMaxSize.x - EasyLayoutUtilites.ScaledWidth(ui)) * (1 - cell_align.x), |
|
(maxHeight - EasyLayoutUtilites.ScaledHeight(ui)) * cell_align.y |
|
); |
|
} |
|
} |
|
|
|
List<float> RowsWidths = new List<float>(); |
|
List<float> MaxColumnsWidths = new List<float>(); |
|
|
|
List<float> ColumnsHeights = new List<float>(); |
|
List<float> MaxRowsHeights = new List<float>(); |
|
|
|
RectTransform currentUIElement; |
|
|
|
void SetPositions(List<List<RectTransform>> group, Vector2 startPosition, Vector2 groupSize) |
|
{ |
|
if (Stacking==Stackings.Horizontal) |
|
{ |
|
SetPositionsHorizontal(group, startPosition, groupSize); |
|
} |
|
else |
|
{ |
|
SetPositionsVertical(group, startPosition, groupSize); |
|
} |
|
} |
|
|
|
void SetPositionsHorizontal(List<List<RectTransform>> group, Vector2 startPosition, Vector2 groupSize) |
|
{ |
|
var position = startPosition; |
|
|
|
GetRowsWidths(group, RowsWidths); |
|
GetMaxColumnsWidths(group, MaxColumnsWidths); |
|
|
|
var align = new Vector2(0, 0); |
|
|
|
for (int coord_x = 0; coord_x < group.Count; coord_x++) |
|
{ |
|
var row_cell_max_size = GetMaxCellSize(group[coord_x]); |
|
|
|
for (int coord_y = 0; coord_y < group[coord_x].Count; coord_y++) |
|
{ |
|
currentUIElement = group[coord_x][coord_y]; |
|
align = GetAlignByWidth(currentUIElement, MaxColumnsWidths[coord_y], row_cell_max_size, groupSize.x - RowsWidths[coord_x]); |
|
|
|
var new_position = GetUIPosition(currentUIElement, position, align); |
|
if (currentUIElement.localPosition.x != new_position.x || currentUIElement.localPosition.y != new_position.y) |
|
{ |
|
currentUIElement.localPosition = new_position; |
|
} |
|
|
|
position.x += ((LayoutType==LayoutTypes.Compact) |
|
? EasyLayoutUtilites.ScaledWidth(currentUIElement) |
|
: MaxColumnsWidths[coord_y]) + Spacing.x; |
|
} |
|
position.x = startPosition.x; |
|
position.y -= row_cell_max_size.y + Spacing.y; |
|
} |
|
} |
|
|
|
void SetPositionsVertical(List<List<RectTransform>> group, Vector2 startPosition, Vector2 groupSize) |
|
{ |
|
var position = startPosition; |
|
|
|
group = EasyLayoutUtilites.Transpose(group); |
|
GetColumnsHeights(group, ColumnsHeights); |
|
GetMaxRowsHeights(group, MaxRowsHeights); |
|
|
|
var align = new Vector2(0, 0); |
|
|
|
for (int coord_y = 0; coord_y < group.Count; coord_y++) |
|
{ |
|
var column_cell_max_size = GetMaxCellSize(group[coord_y]); |
|
|
|
for (int coord_x = 0; coord_x < group[coord_y].Count; coord_x++) |
|
{ |
|
currentUIElement = group[coord_y][coord_x]; |
|
|
|
align = GetAlignByHeight(currentUIElement, MaxRowsHeights[coord_x], column_cell_max_size, groupSize.y - ColumnsHeights[coord_y]); |
|
|
|
var new_position = GetUIPosition(currentUIElement, position, align); |
|
if (currentUIElement.localPosition.x != new_position.x || currentUIElement.localPosition.y != new_position.y) |
|
{ |
|
currentUIElement.localPosition = new_position; |
|
} |
|
|
|
position.y -= ((LayoutType==LayoutTypes.Compact) |
|
? EasyLayoutUtilites.ScaledHeight(currentUIElement) |
|
: MaxRowsHeights[coord_x]) + Spacing.y; |
|
} |
|
position.y = startPosition.y; |
|
position.x += column_cell_max_size.x + Spacing.x; |
|
} |
|
} |
|
|
|
float max_width = -1; |
|
float max_height = -1; |
|
void ResizeElements(List<RectTransform> elements) |
|
{ |
|
propertiesTracker.Clear(); |
|
|
|
if (ChildrenWidth==ChildrenSize.DoNothing && ChildrenHeight==ChildrenSize.DoNothing) |
|
{ |
|
return ; |
|
} |
|
if (elements==null) |
|
{ |
|
return ; |
|
} |
|
if (elements.Count==0) |
|
{ |
|
return ; |
|
} |
|
if (LayoutType==LayoutTypes.Grid && GridConstraint!=GridConstraints.Flexible) |
|
{ |
|
//elements.ForEach(Add2Tracker); |
|
//return ; |
|
} |
|
|
|
max_width = (ChildrenWidth==ChildrenSize.SetMaxFromPreferred) ? elements.Select<RectTransform,float>(EasyLayoutUtilites.GetPreferredWidth).Max() : -1f; |
|
max_height = (ChildrenHeight==ChildrenSize.SetMaxFromPreferred) ? elements.Select<RectTransform,float>(EasyLayoutUtilites.GetPreferredHeight).Max() : -1f; |
|
|
|
elements.ForEach(ResizeChild); |
|
} |
|
|
|
DrivenRectTransformTracker propertiesTracker; |
|
|
|
void Add2Tracker(RectTransform child) |
|
{ |
|
DrivenTransformProperties driven_properties = DrivenTransformProperties.None; |
|
|
|
if (ChildrenWidth!=ChildrenSize.DoNothing) |
|
{ |
|
driven_properties |= DrivenTransformProperties.SizeDeltaX; |
|
} |
|
if (ChildrenHeight!=ChildrenSize.DoNothing) |
|
{ |
|
driven_properties |= DrivenTransformProperties.SizeDeltaY; |
|
} |
|
|
|
propertiesTracker.Add(this, child, driven_properties); |
|
} |
|
|
|
void ResizeChild(RectTransform child) |
|
{ |
|
DrivenTransformProperties driven_properties = DrivenTransformProperties.None; |
|
|
|
if (ChildrenWidth!=ChildrenSize.DoNothing) |
|
{ |
|
driven_properties |= DrivenTransformProperties.SizeDeltaX; |
|
var width = (max_width!=-1) ? max_width : EasyLayoutUtilites.GetPreferredWidth(child); |
|
child.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, width); |
|
} |
|
if (ChildrenHeight!=ChildrenSize.DoNothing) |
|
{ |
|
driven_properties |= DrivenTransformProperties.SizeDeltaY; |
|
var height = (max_height!=-1) ? max_height : EasyLayoutUtilites.GetPreferredHeight(child); |
|
child.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height); |
|
} |
|
|
|
propertiesTracker.Add(this, child, driven_properties); |
|
} |
|
|
|
bool IsIgnoreLayout(Transform rect) |
|
{ |
|
#if UNITY_4_6 || UNITY_4_7 |
|
var ignorer = rect.GetComponent(typeof(ILayoutIgnorer)) as ILayoutIgnorer; |
|
#else |
|
var ignorer = rect.GetComponent<ILayoutIgnorer>(); |
|
#endif |
|
return (ignorer!=null) && ignorer.ignoreLayout; |
|
} |
|
|
|
List<RectTransform> GetUIElements() |
|
{ |
|
var elements = rectChildren; |
|
|
|
if (!SkipInactive) |
|
{ |
|
elements = new List<RectTransform>(); |
|
foreach (Transform child in transform) |
|
{ |
|
if (!IsIgnoreLayout(child)) |
|
{ |
|
elements.Add(child as RectTransform); |
|
} |
|
} |
|
} |
|
|
|
if (Filter!=null) |
|
{ |
|
var temp = Filter(elements.Convert<RectTransform,GameObject>(GetGameObject)); |
|
var result = temp.Select<GameObject,RectTransform>(GetRectTransform).ToList(); |
|
|
|
ResizeElements(result); |
|
|
|
return result; |
|
} |
|
|
|
ResizeElements(elements); |
|
|
|
return elements; |
|
} |
|
|
|
GameObject GetGameObject(RectTransform element) |
|
{ |
|
return element.gameObject; |
|
} |
|
|
|
RectTransform GetRectTransform(GameObject go) |
|
{ |
|
return go.transform as RectTransform; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the margin top. |
|
/// </summary> |
|
public float GetMarginTop() |
|
{ |
|
return Symmetric ? Margin.y : MarginTop; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the margin bottom. |
|
/// </summary> |
|
public float GetMarginBottom() |
|
{ |
|
return Symmetric ? Margin.y : MarginBottom; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the margin left. |
|
/// </summary> |
|
public float GetMarginLeft() |
|
{ |
|
return Symmetric ? Margin.x : MarginLeft; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the margin right. |
|
/// </summary> |
|
public float GetMarginRight() |
|
{ |
|
return Symmetric ? Margin.y : MarginRight; |
|
} |
|
|
|
void ReverseList(List<RectTransform> list) |
|
{ |
|
list.Reverse(); |
|
} |
|
|
|
void ClearUIElementsGroup() |
|
{ |
|
for (int i = 0; i < uiElementsGroup.Count; i++) |
|
{ |
|
uiElementsGroup[i].Clear(); |
|
ListCache.Push(uiElementsGroup[i]); |
|
} |
|
uiElementsGroup.Clear(); |
|
} |
|
|
|
static Stack<List<RectTransform>> ListCache = new Stack<List<RectTransform>>(); |
|
|
|
/// <summary> |
|
/// Gets the List<RectTransform>. |
|
/// </summary> |
|
/// <returns>The rect transform list.</returns> |
|
public List<RectTransform> GetRectTransformList() |
|
{ |
|
if (ListCache.Count > 0) |
|
{ |
|
return ListCache.Pop(); |
|
} |
|
else |
|
{ |
|
return new List<RectTransform>(); |
|
} |
|
} |
|
|
|
List<List<RectTransform>> uiElementsGroup = new List<List<RectTransform>>(); |
|
List<List<RectTransform>> GroupUIElements() |
|
{ |
|
var base_length = GetLength(rectTransform, false); |
|
base_length -= (Stacking==Stackings.Horizontal) ? (GetMarginLeft() + GetMarginRight()) : (GetMarginTop() + GetMarginBottom()); |
|
|
|
var ui_elements = GetUIElements(); |
|
|
|
ClearUIElementsGroup(); |
|
if (LayoutType==LayoutTypes.Compact) |
|
{ |
|
EasyLayoutCompact.Group(ui_elements, base_length, this, uiElementsGroup); |
|
|
|
if (Stacking==Stackings.Vertical) |
|
{ |
|
uiElementsGroup = EasyLayoutUtilites.Transpose(uiElementsGroup); |
|
} |
|
} |
|
else |
|
{ |
|
GridConstraintCount = Mathf.Max(1, GridConstraintCount); |
|
if (GridConstraint==GridConstraints.Flexible) |
|
{ |
|
EasyLayoutGrid.GroupFlexible(ui_elements, base_length, this, uiElementsGroup); |
|
} |
|
else if (GridConstraint==GridConstraints.FixedRowCount) |
|
{ |
|
if (Stacking==Stackings.Vertical) |
|
{ |
|
EasyLayoutGrid.GroupByRowsVertical(ui_elements, this, GridConstraintCount, uiElementsGroup); |
|
} |
|
else |
|
{ |
|
EasyLayoutGrid.GroupByRowsHorizontal(ui_elements, this, GridConstraintCount, uiElementsGroup); |
|
} |
|
} |
|
else if (GridConstraint==GridConstraints.FixedColumnCount) |
|
{ |
|
if (Stacking==Stackings.Vertical) |
|
{ |
|
EasyLayoutGrid.GroupByColumnsVertical(ui_elements, this, GridConstraintCount, uiElementsGroup); |
|
} |
|
else |
|
{ |
|
EasyLayoutGrid.GroupByColumnsHorizontal(ui_elements, this, GridConstraintCount, uiElementsGroup); |
|
} |
|
} |
|
} |
|
|
|
if (!TopToBottom) |
|
{ |
|
uiElementsGroup.Reverse(); |
|
} |
|
|
|
if (RightToLeft) |
|
{ |
|
uiElementsGroup.ForEach(ReverseList); |
|
} |
|
|
|
var width = rectTransform.rect.width - (GetMarginLeft() + GetMarginRight()); |
|
var height = rectTransform.rect.height - (GetMarginTop() + GetMarginBottom()); |
|
if (LayoutType==LayoutTypes.Grid) |
|
{ |
|
if (ChildrenWidth==ChildrenSize.FitContainer) |
|
{ |
|
EasyLayoutUtilites.ResizeColumnWidthToFit(width, uiElementsGroup, Spacing.x, PaddingInner.Left + PaddingInner.Right); |
|
} |
|
if (ChildrenHeight==ChildrenSize.FitContainer) |
|
{ |
|
EasyLayoutUtilites.ResizeRowHeightToFit(height, uiElementsGroup, Spacing.y, PaddingInner.Top + PaddingInner.Bottom); |
|
} |
|
} |
|
else |
|
{ |
|
if (Stacking==Stackings.Horizontal) |
|
{ |
|
if (ChildrenWidth==ChildrenSize.FitContainer) |
|
{ |
|
EasyLayoutUtilites.ResizeWidthToFit(width, uiElementsGroup, Spacing.x); |
|
} |
|
if (ChildrenHeight==ChildrenSize.FitContainer) |
|
{ |
|
EasyLayoutUtilites.ResizeRowHeightToFit(height, uiElementsGroup, Spacing.y, PaddingInner.Top + PaddingInner.Bottom); |
|
} |
|
} |
|
else |
|
{ |
|
if (ChildrenHeight==ChildrenSize.FitContainer) |
|
{ |
|
EasyLayoutUtilites.ResizeHeightToFit(height, uiElementsGroup, Spacing.y); |
|
} |
|
if (ChildrenWidth==ChildrenSize.FitContainer) |
|
{ |
|
EasyLayoutUtilites.ResizeColumnWidthToFit(width, uiElementsGroup, Spacing.x, PaddingInner.Left + PaddingInner.Right); |
|
} |
|
} |
|
} |
|
|
|
return uiElementsGroup; |
|
} |
|
|
|
/// <summary> |
|
/// Awake this instance. |
|
/// </summary> |
|
protected override void Awake() |
|
{ |
|
base.Awake(); |
|
Upgrade(); |
|
} |
|
|
|
[SerializeField] |
|
int version = 0; |
|
|
|
#pragma warning disable 0618 |
|
/// <summary> |
|
/// Upgrade to keep compatibility between versions. |
|
/// </summary> |
|
public virtual void Upgrade() |
|
{ |
|
//upgrade to 1.6 |
|
if (version==0) |
|
{ |
|
if (ControlWidth) |
|
{ |
|
ChildrenWidth = (MaxWidth) ? ChildrenSize.SetMaxFromPreferred : ChildrenSize.SetPreferred; |
|
} |
|
if (ControlHeight) |
|
{ |
|
ChildrenHeight = (MaxHeight) ? ChildrenSize.SetMaxFromPreferred : ChildrenSize.SetPreferred; |
|
} |
|
} |
|
version = 1; |
|
} |
|
#pragma warning restore 0618 |
|
} |
|
|
|
} |