343 lines
7.8 KiB
C#
343 lines
7.8 KiB
C#
//----------------------------------------------
|
|
// NGUI: Next-Gen UI kit
|
|
// Copyright © 2011-2015 Tasharen Entertainment
|
|
//----------------------------------------------
|
|
|
|
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
|
|
/// <summary>
|
|
/// 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).
|
|
/// </summary>
|
|
|
|
[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,
|
|
}
|
|
|
|
/// <summary>
|
|
/// How many columns there will be before a new line is started. 0 means unlimited.
|
|
/// </summary>
|
|
|
|
public int columns = 0;
|
|
|
|
/// <summary>
|
|
/// Which way the new lines will be added.
|
|
/// </summary>
|
|
|
|
public Direction direction = Direction.Down;
|
|
|
|
/// <summary>
|
|
/// How to sort the grid's elements.
|
|
/// </summary>
|
|
|
|
public Sorting sorting = Sorting.None;
|
|
|
|
/// <summary>
|
|
/// Final pivot point for the table itself.
|
|
/// </summary>
|
|
|
|
public UIWidget.Pivot pivot = UIWidget.Pivot.TopLeft;
|
|
|
|
/// <summary>
|
|
/// Final pivot point for the table's content.
|
|
/// </summary>
|
|
|
|
public UIWidget.Pivot cellAlignment = UIWidget.Pivot.TopLeft;
|
|
|
|
/// <summary>
|
|
/// Whether inactive children will be discarded from the table's calculations.
|
|
/// </summary>
|
|
|
|
public bool hideInactive = true;
|
|
|
|
/// <summary>
|
|
/// Whether the parent container will be notified of the table's changes.
|
|
/// </summary>
|
|
|
|
public bool keepWithinPanel = false;
|
|
|
|
/// <summary>
|
|
/// Padding around each entry, in pixels.
|
|
/// </summary>
|
|
|
|
public Vector2 padding = Vector2.zero;
|
|
|
|
/// <summary>
|
|
/// Delegate function that will be called when the table repositions its content.
|
|
/// </summary>
|
|
|
|
public OnReposition onReposition;
|
|
|
|
/// <summary>
|
|
/// Custom sort delegate, used when the sorting method is set to 'custom'.
|
|
/// </summary>
|
|
|
|
public System.Comparison<Transform> onCustomSort;
|
|
|
|
protected UIPanel mPanel;
|
|
protected bool mInitDone = false;
|
|
protected bool mReposition = false;
|
|
|
|
//调整位置需要等待的帧数,默认不等待当前帧进行处理
|
|
public int repositionWaitFrameCount = 0;
|
|
|
|
/// <summary>
|
|
/// Reposition the children on the next Update().
|
|
/// </summary>
|
|
|
|
public bool repositionNow { set { if (value) { mReposition = true; enabled = true; } } }
|
|
|
|
/// <summary>
|
|
/// Get the current list of the grid's children.
|
|
/// </summary>
|
|
|
|
public List<Transform> GetChildList ()
|
|
{
|
|
Transform myTrans = transform;
|
|
List<Transform> list = new List<Transform>();
|
|
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Want your own custom sorting logic? Override this function.
|
|
/// </summary>
|
|
|
|
protected virtual void Sort (List<Transform> list) { list.Sort(UIGrid.SortByName); }
|
|
|
|
/// <summary>
|
|
/// Position the grid's contents when the script starts.
|
|
/// </summary>
|
|
|
|
protected virtual void Start ()
|
|
{
|
|
Init();
|
|
Reposition();
|
|
enabled = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Find the necessary components.
|
|
/// </summary>
|
|
|
|
protected virtual void Init ()
|
|
{
|
|
mInitDone = true;
|
|
mPanel = NGUITools.FindInParents<UIPanel>(gameObject);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Is it time to reposition? Do so now.
|
|
/// </summary>
|
|
|
|
protected virtual void LateUpdate ()
|
|
{
|
|
if (repositionWaitFrameCount > 0)
|
|
{
|
|
repositionWaitFrameCount--;
|
|
if (repositionWaitFrameCount == 0)
|
|
{
|
|
Reposition();
|
|
}
|
|
return;
|
|
}
|
|
if (mReposition) Reposition();
|
|
enabled = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reposition the content on inspector validation.
|
|
/// </summary>
|
|
|
|
void OnValidate () { if (!Application.isPlaying && NGUITools.GetActive(this)) Reposition(); }
|
|
|
|
/// <summary>
|
|
/// Positions the grid items, taking their own size into consideration.
|
|
/// </summary>
|
|
|
|
protected void RepositionVariableSize (List<Transform> 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<SpringPosition>();
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recalculate the position of all elements within the table, sorting them alphabetically if necessary.
|
|
/// </summary>
|
|
|
|
[ContextMenu("Execute")]
|
|
public virtual void Reposition ()
|
|
{
|
|
if (Application.isPlaying && !mInitDone && NGUITools.GetActive(this)) Init();
|
|
|
|
mReposition = false;
|
|
Transform myTrans = transform;
|
|
List<Transform> ch = GetChildList();
|
|
if (ch.Count > 0) RepositionVariableSize(ch);
|
|
|
|
if (keepWithinPanel && mPanel != null)
|
|
{
|
|
mPanel.ConstrainTargetToBounds(myTrans, true);
|
|
UIScrollView sv = mPanel.GetComponent<UIScrollView>();
|
|
if (sv != null) sv.UpdateScrollbars(true);
|
|
}
|
|
|
|
if (onReposition != null)
|
|
onReposition();
|
|
}
|
|
}
|