public class MultiColumnWrap : MonoBehaviour
{
[Header("Prefabs")]
public GameObject CellPrefab;
[Header("NGUI Scrolling")]
public UIPanel _UIPanel;
public UIScrollView _scrollView;
public UITable _table;
public UIScrollBar _scrollBar;
private List<CellScript> _cellList;
private GameObject _lastCell
private int _numCellsInPanel; //This is how many cells the panel can fit
private Vector2 _cellSize;
private float _svStartingPosY;
void Start()
{
//Instantiate enough Prefabs to fill our Panel and then some. This will be our cycling pool of Cells
_cellList
= new List
<CellScript
>();
//Get Bounds of the prefabs that will populate this view
GameObject template = NGUITools.AddChild(_table.gameObject, CellPrefab);
Bounds b = NGUIMath.CalculateRelativeWidgetBounds(template.transform, true);
GameObject.Destroy(template);
//Calculate the maximum number of cells a user could see within the panel
_cellSize.x = b.size.x;
_cellSize.y = b.size.y;
//Calculate how many cells we can fit in the panels clip region
_numCellsInPanel = Mathf.CeilToInt(_UIPanel.baseClipRegion.w / (_cellSize.y + _table.padding.y)) * _table.columns;
//Add one more row to cover scrolling
_numCellsInPanel += Mathf.FloorToInt(_UIPanel.baseClipRegion.z / (_cellSize.x + _table.padding.x));
//Instantiate cells and make them inactive
for(int i = 0; i < _numCellsInPanel; i++)
{
GameObject cellGO = NGUITools.AddChild(_table.gameObject, CellPrefab);
CellScript cellScript = cellGO.GetComponent<CellScript>();
if(cellScript != null)
{
_cellList.Add(cellScript);
}
cellGO.SetActive(false);
}
//Set the Cells with our Data
for(int i = TopCellIndex, j = 0; i < data.Length && j < _numCellsInPanel; i++, j++)
{
CellScript cellScript = _cellList[j].GetComponent<CellScript>();
if(cellScript != null)
{
_lastCell = cellScript[i];
cellScript.gameObject.SetActive(true);
cellScript.SetData(data[i]);
}
}
_table.repositionNow = true;
_scrollView.ResetPosition();
//Start our update loop
StartCoroutine(UpdateCR());
}
IEnumerator UpdateCR()
{
yield return null; //Wait for NGUI to Reposition
_svStartingPosY = _scrollView.transform.localPosition.y;
//let's spin our main loop
while(true)
{
//Make sure we aren't already showing the bottom cell
if(_lastCell != data[data.Length - 1])
{
//Check if we moved a row off screen - Down
if(_scrollView.transform.localPosition.y > (_svStartingPosY + _cellSize.y))
{
MoveScrollView(true);
}
}
else
{
_scrollView.RestrictWithinBounds(true);
}
//Make sure we aren't already showing the top cell
if(TopCellIndex > 0)
{
//Check if we moved a row off screen - Up
if(_scrollView.transform.localPosition.y < _svStartingPosY)
{
MoveScrollView(false);
}
}
else
{
_scrollView.RestrictWithinBounds(true);
}
UpdateScrollbar();
yield return null;//tick
}
}
void MoveScrollView(bool moveDown)
{
if(moveDown == true)
{
TopCellIndex += _table.columns;
}
else
{
TopCellIndex -= _table.columns;
}
Mathf.Clamp(TopCellIndex, 0, data.Length);
for(int i = 0; i < _cellList.Count; i++)
{
CellScript currCell = _cellList[i];
if(TopCellIndex + i >= data.Length)
{
//We've run out of players on the data side
currCell.gameObject.SetActive(false);
}
else
{
//Set the data, and update
currCell.gameObject.SetActive(true);
_lastCell = data[TopCellIndex + i];
currCell.SetData(_lastCell);
}
}
float distance = _cellSize.y;
_scrollView
.MoveRelative(new Vector3
(0
.0f, moveDown
? -distance
: distance, 0
.0f
)); }
void UpdateScrollbar()
{
if(data.Length < _numCellsInPanel)
{
_scrollBar.gameObject.SetActive(false);
}
else if(data.Length > 0)
{
_scrollBar.gameObject.SetActive(true);
float pct = TopCellIndex / (float)(data.Length - _numCellsInPanel);
_scrollBar.value = Mathf.Lerp(_scrollBar.value, pct, 0.1f);
_scrollBar.barSize = _numCellsInPanel / (float)data.Length;
}
}
}