//---------------------------------------------- // NGUI: Next-Gen UI kit // Copyright © 2011-2015 Tasharen Entertainment //---------------------------------------------- using UnityEngine; using System.Collections.Generic; /// /// All children added to the game object with this script will be arranged into a table /// with rows and columns automatically adjusting their size to fit their content /// (think "table" tag in HTML). /// [AddComponentMenu("NGUI/Interaction/Table")] public class UITable : UIWidgetContainer { public delegate void OnReposition (); public enum Direction { Down, Up, } public enum Sorting { None, Alphabetic, Horizontal, Vertical, Custom, } /// /// How many columns there will be before a new line is started. 0 means unlimited. /// public int columns = 0; /// /// Which way the new lines will be added. /// public Direction direction = Direction.Down; /// /// How to sort the grid's elements. /// public Sorting sorting = Sorting.None; /// /// Final pivot point for the table itself. /// public UIWidget.Pivot pivot = UIWidget.Pivot.TopLeft; /// /// Final pivot point for the table's content. /// public UIWidget.Pivot cellAlignment = UIWidget.Pivot.TopLeft; /// /// Whether inactive children will be discarded from the table's calculations. /// public bool hideInactive = true; /// /// Whether the parent container will be notified of the table's changes. /// public bool keepWithinPanel = false; /// /// Padding around each entry, in pixels. /// public Vector2 padding = Vector2.zero; /// /// Delegate function that will be called when the table repositions its content. /// public OnReposition onReposition; /// /// Custom sort delegate, used when the sorting method is set to 'custom'. /// public System.Comparison onCustomSort; protected UIPanel mPanel; protected bool mInitDone = false; protected bool mReposition = false; //调整位置需要等待的帧数,默认不等待当前帧进行处理 public int repositionWaitFrameCount = 0; /// /// Reposition the children on the next Update(). /// public bool repositionNow { set { if (value) { mReposition = true; enabled = true; } } } /// /// Get the current list of the grid's children. /// public List GetChildList () { Transform myTrans = transform; List list = new List(); for (int i = 0; i < myTrans.childCount; ++i) { Transform t = myTrans.GetChild(i); if (!hideInactive || (t && NGUITools.GetActive(t.gameObject))) list.Add(t); } // Sort the list using the desired sorting logic if (sorting != Sorting.None) { if (sorting == Sorting.Alphabetic) list.Sort(UIGrid.SortByName); else if (sorting == Sorting.Horizontal) list.Sort(UIGrid.SortHorizontal); else if (sorting == Sorting.Vertical) list.Sort(UIGrid.SortVertical); else if (onCustomSort != null) list.Sort(onCustomSort); else Sort(list); } return list; } /// /// Want your own custom sorting logic? Override this function. /// protected virtual void Sort (List list) { list.Sort(UIGrid.SortByName); } /// /// Position the grid's contents when the script starts. /// protected virtual void Start () { Init(); Reposition(); enabled = false; } /// /// Find the necessary components. /// protected virtual void Init () { mInitDone = true; mPanel = NGUITools.FindInParents(gameObject); } /// /// Is it time to reposition? Do so now. /// protected virtual void LateUpdate () { if (repositionWaitFrameCount > 0) { repositionWaitFrameCount--; if (repositionWaitFrameCount == 0) { Reposition(); } return; } if (mReposition) Reposition(); enabled = false; } /// /// Reposition the content on inspector validation. /// void OnValidate () { if (!Application.isPlaying && NGUITools.GetActive(this)) Reposition(); } /// /// Positions the grid items, taking their own size into consideration. /// protected void RepositionVariableSize (List children) { float xOffset = 0; float yOffset = 0; int cols = columns > 0 ? children.Count / columns + 1 : 1; int rows = columns > 0 ? columns : children.Count; Bounds[,] bounds = new Bounds[cols, rows]; Bounds[] boundsRows = new Bounds[rows]; Bounds[] boundsCols = new Bounds[cols]; int x = 0; int y = 0; for (int i = 0, imax = children.Count; i < imax; ++i) { Transform t = children[i]; Bounds b = NGUIMath.CalculateRelativeWidgetBounds(t, !hideInactive); Vector3 scale = t.localScale; b.min = Vector3.Scale(b.min, scale); b.max = Vector3.Scale(b.max, scale); bounds[y, x] = b; if (boundsRows[x].size == Vector3.zero) { boundsRows[x] = b; } else { boundsRows[x].Encapsulate(b); } if (boundsCols[y].size == Vector3.zero) { boundsCols[y] = b; } else { boundsCols[y].Encapsulate(b); } if (++x >= columns && columns > 0) { x = 0; ++y; } } x = 0; y = 0; Vector2 po = NGUIMath.GetPivotOffset(cellAlignment); for (int i = 0, imax = children.Count; i < imax; ++i) { Transform t = children[i]; Bounds b = bounds[y, x]; Bounds br = boundsRows[x]; Bounds bc = boundsCols[y]; Vector3 pos = t.localPosition; pos.x = xOffset + b.extents.x - b.center.x; pos.x -= Mathf.Lerp(0f, b.max.x - b.min.x - br.max.x + br.min.x, po.x) - padding.x; if (direction == Direction.Down) { pos.y = -yOffset - b.extents.y - b.center.y; pos.y += Mathf.Lerp(b.max.y - b.min.y - bc.max.y + bc.min.y, 0f, po.y) - padding.y; } else { pos.y = yOffset + b.extents.y - b.center.y; pos.y -= Mathf.Lerp(0f, b.max.y - b.min.y - bc.max.y + bc.min.y, po.y) - padding.y; } xOffset += br.size.x + padding.x * 2f; t.localPosition = pos; if (++x >= columns && columns > 0) { x = 0; ++y; xOffset = 0f; yOffset += bc.size.y + padding.y * 2f; } } // Apply the origin offset if (pivot != UIWidget.Pivot.TopLeft) { po = NGUIMath.GetPivotOffset(pivot); float fx, fy; Bounds b = NGUIMath.CalculateRelativeWidgetBounds(transform); fx = Mathf.Lerp(0f, b.size.x, po.x); fy = Mathf.Lerp(-b.size.y, 0f, po.y); Transform myTrans = transform; for (int i = 0; i < myTrans.childCount; ++i) { Transform t = myTrans.GetChild(i); SpringPosition sp = t.GetComponent(); if (sp != null) { sp.target.x -= fx; sp.target.y -= fy; } else { Vector3 pos = t.localPosition; pos.x -= fx; pos.y -= fy; t.localPosition = pos; } } } } /// /// Recalculate the position of all elements within the table, sorting them alphabetically if necessary. /// [ContextMenu("Execute")] public virtual void Reposition () { if (Application.isPlaying && !mInitDone && NGUITools.GetActive(this)) Init(); mReposition = false; Transform myTrans = transform; List ch = GetChildList(); if (ch.Count > 0) RepositionVariableSize(ch); if (keepWithinPanel && mPanel != null) { mPanel.ConstrainTargetToBounds(myTrans, true); UIScrollView sv = mPanel.GetComponent(); if (sv != null) sv.UpdateScrollbars(true); } if (onReposition != null) onReposition(); } }