|
using System; |
|
using System.Collections; |
|
using System.Collections.Generic; |
|
using UnityEngine; |
|
|
|
namespace AT.InfiniteScrollView |
|
{ |
|
[System.Serializable] |
|
public class InfiniteItem |
|
{ |
|
public int index; |
|
public GameObject gameObject; |
|
} |
|
|
|
[System.Serializable] |
|
public class InfiniteScrollView |
|
{ |
|
public enum TABLE_NEXT_DIRECTION_TYPE |
|
{ ZIGZAG, ONE_DIRECTION, } |
|
|
|
public enum TABLE_POSITION_SORT_TYPE |
|
{ DYNAMIC, FLAT, } |
|
|
|
[Header("Scroll View")] |
|
public GameObject scrollView; |
|
public TABLE_NEXT_DIRECTION_TYPE tableDirectionType = TABLE_NEXT_DIRECTION_TYPE.ZIGZAG; |
|
public TABLE_POSITION_SORT_TYPE tableSortType = TABLE_POSITION_SORT_TYPE.DYNAMIC; |
|
|
|
[Header("ScrollView DragNotification")] |
|
public UIScrollView.OnDragNotification onDragStarted; |
|
public UIScrollView.OnDragNotification onStoppedMoving; |
|
public UIScrollView.OnDragNotification onDragFinished; |
|
|
|
[Header("Item")] |
|
public GameObject itemPrefab; |
|
public int prepareSize = 2; |
|
public Vector2 padding = Vector2.zero; |
|
|
|
[Header("Scrollbar")] |
|
public UIProgressBar scrollbar; |
|
public UIScrollView.ShowCondition showCondition = UIScrollView.ShowCondition.OnlyIfNeeded; |
|
public float sliderValue; |
|
public TweenAlpha tweenAlpha; |
|
|
|
[Header("Action")] |
|
public System.Action<int, GameObject> OnUpdateItem = null; |
|
public System.Func<int> OnGetItemCount = null; |
|
|
|
|
|
[Header("(AUTO) Infinite Setting")] |
|
[SerializeField] protected UIPanel panel; |
|
[SerializeField] protected UIScrollView view; |
|
[SerializeField] protected LinkedList<InfiniteItem> itemList = new LinkedList<InfiniteItem>(); |
|
[SerializeField] protected bool isHorizontal = false; |
|
[SerializeField] protected int rowCount; |
|
[SerializeField] protected int columnCount; |
|
[SerializeField] protected int maxItemCountInView; |
|
[SerializeField] protected int maxItemCount; |
|
|
|
[Header("(AUTO) List View Init Size")] |
|
[SerializeField] protected Vector2 bufferStart; // buffer1 |
|
[SerializeField] protected Vector2 bufferEnd; // buffer2 |
|
[SerializeField] protected Vector2 initPosition; // Initialize Position |
|
[SerializeField] protected float initBound; // Initialize Bound |
|
|
|
public void Init() |
|
{ |
|
view = scrollView.GetComponent<UIScrollView>(); |
|
panel = view.GetComponent<UIPanel>(); |
|
panel.onClipMove += OnMove; |
|
|
|
Vector4 clip = panel.baseClipRegion; |
|
Vector2 viewSize = new Vector2(clip.z, clip.w); |
|
|
|
Bounds bound = NGUIMath.CalculateRelativeWidgetBounds(itemPrefab.transform, true); |
|
Vector2 itemSize = new Vector2(bound.size.x, bound.size.y); |
|
|
|
Vector3 totalItemSize = itemSize + padding; |
|
|
|
columnCount = Mathf.RoundToInt(viewSize.x / totalItemSize.x); |
|
rowCount = Mathf.RoundToInt(viewSize.y / totalItemSize.y); |
|
maxItemCountInView = columnCount * rowCount; |
|
|
|
if (view.movement == UIScrollView.Movement.Horizontal) |
|
{ |
|
isHorizontal = true; |
|
columnCount = columnCount + prepareSize; |
|
|
|
initPosition.x = -(viewSize.x * 0.5f) + (totalItemSize.x / 2.0f); |
|
initPosition.y = totalItemSize.y * (rowCount - 1) / 2.0f; |
|
initBound = -(viewSize.x - padding.x) * 0.5f; |
|
} |
|
else if (view.movement == UIScrollView.Movement.Vertical) |
|
{ |
|
isHorizontal = false; |
|
rowCount = rowCount + prepareSize; |
|
|
|
initPosition.x = -totalItemSize.x * (columnCount - 1) / 2.0f; |
|
initPosition.y = (viewSize.y / 2.0f) - (totalItemSize.y / 2.0f); |
|
initBound = (viewSize.y - padding.y) * 0.5f; |
|
} |
|
maxItemCount = columnCount * rowCount; |
|
|
|
bufferEnd.x = totalItemSize.x * columnCount; |
|
bufferEnd.y = totalItemSize.y * rowCount; |
|
bufferStart.x = bufferEnd.x * 0.5f; |
|
bufferStart.y = bufferEnd.y * 0.5f; |
|
|
|
// Prefab GameObject InActive |
|
itemPrefab.gameObject.SetActive(false); |
|
|
|
// Clear Pool |
|
itemList.Clear(); |
|
|
|
// Item Add To Pool |
|
InfiniteItem item = null; |
|
for (int i = 0; i < maxItemCount; i++) |
|
{ |
|
item = new InfiniteItem |
|
{ |
|
index = i, |
|
gameObject = NGUITools.AddChild(scrollView.gameObject, itemPrefab) |
|
}; |
|
item.gameObject.transform.name = item.index.ToString(); |
|
itemList.AddLast(item); |
|
} |
|
|
|
// Calculate Reset Item Position & ScrollView Reset |
|
ResetScroll(); |
|
|
|
// Scrollbar Tween Alpha |
|
if (scrollbar) |
|
{ |
|
tweenAlpha = scrollbar.GetComponent<TweenAlpha>(); |
|
if (tweenAlpha == null) |
|
tweenAlpha = scrollbar.gameObject.AddComponent<TweenAlpha>(); |
|
|
|
tweenAlpha.from = 1; |
|
tweenAlpha.to = 0; |
|
tweenAlpha.duration = 1.0f; |
|
tweenAlpha.SetStartToCurrentValue(); |
|
if (showCondition != UIScrollView.ShowCondition.Always) |
|
tweenAlpha.PlayForward(); |
|
} |
|
|
|
// Remove Drag Notification |
|
view.onDragStarted -= OnDragStarted; |
|
view.onStoppedMoving -= OnStoppedMoving; |
|
view.onDragFinished -= OnDragFinished; |
|
|
|
// Add Drag Notification |
|
view.onDragStarted += OnDragStarted; |
|
view.onStoppedMoving += OnStoppedMoving; |
|
view.onDragFinished += OnDragFinished; |
|
} |
|
|
|
void OnDragStarted() |
|
{ |
|
ShowScrollbars(true); |
|
if (onDragStarted != null) onDragStarted(); |
|
} |
|
|
|
void OnStoppedMoving() |
|
{ |
|
ShowScrollbars(false); |
|
if (onStoppedMoving != null) onStoppedMoving(); |
|
} |
|
|
|
void OnDragFinished() |
|
{ |
|
if (onDragFinished != null) onDragFinished(); |
|
} |
|
|
|
///<summary> Update - Clipping Event When Panel OnMove </summary> |
|
protected void OnMove(UIPanel panel) |
|
{ |
|
// Clipping Item Update |
|
UpdateScrollViewItems(); |
|
|
|
// Scrollbar Update |
|
if (scrollbar) |
|
UpdateScrollBars(); |
|
} |
|
|
|
/// <summary> Visible Item Count In View </summary> |
|
public int GetVisibleItemCount() |
|
{ |
|
int result = 0; |
|
UIWidget widget = null; |
|
foreach (InfiniteItem item in itemList) |
|
{ |
|
widget = item.gameObject.GetComponentInChildren<UIWidget>(); |
|
if (widget != null) |
|
if (panel.IsVisible(widget)) result++; |
|
} |
|
|
|
return result; |
|
} |
|
|
|
/// <summary> ScrollBar Update </summary> |
|
public void UpdateScrollBars() |
|
{ |
|
if (OnGetItemCount == null) return; |
|
if (scrollbar == null) return; |
|
|
|
int endIndex = 0; |
|
UIWidget widget = null; |
|
foreach (var item in itemList) |
|
{ |
|
widget = item.gameObject.GetComponentInChildren<UIWidget>(); |
|
if (widget && panel.IsVisible(widget)) |
|
endIndex = endIndex < item.index ? item.index : endIndex; |
|
} |
|
|
|
// Do - Calculate ScrollBar Value & Size |
|
UpdateScrollBars(scrollbar, endIndex, GetVisibleItemCount(), OnGetItemCount()); |
|
} |
|
|
|
/// <summary> Calculate ScrollBar Value & Size</summary> |
|
private void UpdateScrollBars(UIProgressBar slider, float lastVisibleIndex, float visibleItemCount, float totalItemCount) |
|
{ |
|
// Slider Value For Scroll Position |
|
if (lastVisibleIndex < maxItemCountInView) lastVisibleIndex = 0; |
|
slider.value = Mathf.Clamp01(lastVisibleIndex / (totalItemCount - 1)); |
|
|
|
// Slider Bar Size as Current Visible Item Count |
|
UIScrollBar sb = slider as UIScrollBar; |
|
if (sb != null) sb.barSize = Mathf.Clamp01((visibleItemCount / totalItemCount)); |
|
} |
|
|
|
void ShowScrollbars(bool isShow) |
|
{ |
|
if (null == scrollbar) return; |
|
switch (showCondition) |
|
{ |
|
case UIScrollView.ShowCondition.Always: |
|
tweenAlpha.enabled = false; |
|
scrollbar.alpha = 1.0f; |
|
break; |
|
case UIScrollView.ShowCondition.OnlyIfNeeded: |
|
case UIScrollView.ShowCondition.WhenDragging: |
|
if (isShow == false) tweenAlpha.PlayForward(); |
|
else tweenAlpha.PlayReverse(); |
|
break; |
|
} |
|
} |
|
|
|
/// <summary> Update ScrollView Items - Clipped Item Check </summary> |
|
protected void UpdateScrollViewItems() |
|
{ |
|
int realIndex = 0; |
|
bool flag = true; |
|
float distance = 0.0f; |
|
Vector3 pos; |
|
Vector3 size; |
|
Vector4 clip = panel.finalClipRegion; |
|
Transform trans = null; |
|
InfiniteItem item = null; |
|
|
|
// Horizontal ScrollView Update |
|
if (isHorizontal) |
|
{ |
|
// To do... |
|
} |
|
else // Vertical ScrollView Update |
|
{ |
|
// Top Item Clipping Check - When Vertical |
|
while (flag) |
|
{ |
|
for (int i = 0; i < columnCount; i++) |
|
{ |
|
item = itemList.First.Value; |
|
trans = item.gameObject.transform; |
|
pos = trans.localPosition; |
|
distance = pos.y - clip.y; |
|
size = GetItemSize(trans, false); |
|
|
|
if (distance > bufferStart.y + size.y) |
|
{ |
|
Transform targetTrans; |
|
Vector3 targetItemSize; |
|
|
|
realIndex = item.index + maxItemCount; |
|
item.index = realIndex; |
|
trans.name = realIndex.ToString(); |
|
|
|
if (realIndex < OnGetItemCount()) |
|
{ |
|
OnUpdateItem(realIndex, item.gameObject); |
|
|
|
UIWidget[] widgets = item.gameObject.GetComponentsInChildren<UIWidget>(); |
|
foreach (var widget in widgets) widget.ResetAndUpdateAnchors(); |
|
|
|
item.gameObject.SetActive(true); |
|
} |
|
else |
|
{ |
|
item.gameObject.SetActive(false); |
|
} |
|
|
|
LinkedListNode<InfiniteItem> targetNode = itemList.Last; |
|
int index = targetNode.Value.index; |
|
int column = index % columnCount; |
|
while (column != realIndex % columnCount) |
|
{ |
|
targetNode = targetNode.Previous; |
|
index = targetNode.Value.index; |
|
column = index % columnCount; |
|
} |
|
|
|
targetTrans = targetNode.Value.gameObject.transform; |
|
targetItemSize = GetItemSize(targetTrans, false); |
|
|
|
pos.x = targetTrans.localPosition.x; |
|
pos.y = targetTrans.localPosition.y - (targetItemSize.y + padding.y); |
|
trans.localPosition = pos; |
|
|
|
itemList.RemoveFirst(); |
|
itemList.AddLast(item); |
|
view.InvalidateBounds(); |
|
} |
|
} |
|
break; |
|
} |
|
|
|
// Bottom Item Cliping Check - When Vertical |
|
flag = true; |
|
while (flag) |
|
{ |
|
for (int i = 0; i < columnCount; i++) |
|
{ |
|
item = itemList.Last.Value; |
|
trans = itemList.Last.Value.gameObject.transform; |
|
pos = trans.localPosition; |
|
distance = pos.y - clip.y; |
|
|
|
if (distance < -(bufferStart.y)) |
|
{ |
|
Transform targetTrans; |
|
Vector3 targetItemSize; |
|
Vector3 differSize; |
|
Vector3 itemSize; |
|
|
|
realIndex = int.Parse(trans.name) - maxItemCount; |
|
if (realIndex >= 0 && realIndex < OnGetItemCount()) |
|
{ |
|
item.index = realIndex; |
|
trans.name = realIndex.ToString(); |
|
|
|
OnUpdateItem(realIndex, item.gameObject); |
|
|
|
UIWidget[] widgets = item.gameObject.GetComponentsInChildren<UIWidget>(); |
|
foreach (var widget in widgets) widget.ResetAndUpdateAnchors(); |
|
|
|
item.gameObject.SetActive(true); |
|
itemSize = GetItemSize(item.gameObject.transform, false); |
|
|
|
LinkedListNode<InfiniteItem> targetNode = itemList.First; |
|
int index = targetNode.Value.index; |
|
int column = index % columnCount; |
|
while (column != realIndex % columnCount) |
|
{ |
|
targetNode = targetNode.Next; |
|
index = targetNode.Value.index; |
|
column = index % columnCount; |
|
} |
|
|
|
targetTrans = targetNode.Value.gameObject.transform; |
|
targetItemSize = GetItemSize(targetTrans, false); |
|
differSize = itemSize - targetItemSize; |
|
|
|
pos.x = targetTrans.localPosition.x; |
|
pos.y = targetTrans.localPosition.y + (targetItemSize.y + padding.y) + differSize.y; |
|
trans.localPosition = pos; |
|
|
|
itemList.RemoveLast(); |
|
itemList.AddFirst(item); |
|
view.InvalidateBounds(); |
|
} |
|
} |
|
} |
|
break; |
|
} |
|
} |
|
} |
|
|
|
/// <summary> Refresh Infinite ScrollView - Pivot: Current Top Item, Update Item </summary> |
|
[ContextMenu("Refresh")] |
|
public void Refresh() |
|
{ |
|
if (OnGetItemCount == null) return; |
|
|
|
int sortingTopIndex = OnGetItemCount(); |
|
InfiniteItem topItem = null; |
|
|
|
foreach (InfiniteItem item in itemList) |
|
{ |
|
if (item.index >= 0 && item.index < OnGetItemCount()) |
|
{ |
|
OnUpdateItem(item.index, item.gameObject); |
|
|
|
UIWidget[] widgets = item.gameObject.GetComponentsInChildren<UIWidget>(); |
|
foreach (var widget in widgets) widget.ResetAndUpdateAnchors(); |
|
|
|
item.gameObject.SetActive(true); |
|
|
|
if (item.index <= sortingTopIndex) |
|
{ |
|
sortingTopIndex = item.index; |
|
topItem = item; |
|
} |
|
} |
|
else |
|
{ |
|
item.gameObject.SetActive(false); |
|
} |
|
} |
|
|
|
// Reposition Items |
|
int index = 0; |
|
int row = 0, column = 0; |
|
int curRowOrColumn = -1; |
|
int firstRowOrColumn = isHorizontal ? itemList.First.Value.index / rowCount : itemList.First.Value.index % columnCount; |
|
|
|
Vector3 itemSize = Vector3.zero; |
|
Vector3 position = Vector3.zero; |
|
|
|
Vector3[] biggerItemSizeInRowsOrColumns = new Vector3[isHorizontal ? columnCount : rowCount]; |
|
Vector3[] biggerItemPosInRowsOrColumns = new Vector3[isHorizontal ? columnCount : rowCount]; |
|
Vector3[] beforeItemsSize = new Vector3[isHorizontal ? rowCount : columnCount]; |
|
Vector2[] beforeItemsPos = new Vector2[isHorizontal ? rowCount : columnCount]; |
|
|
|
foreach (InfiniteItem item in itemList) |
|
{ |
|
itemSize = GetItemSize(item.gameObject.transform, false); |
|
|
|
if (isHorizontal) |
|
{ |
|
row = index % rowCount; |
|
column = index / rowCount; |
|
} |
|
else |
|
{ |
|
row = index / columnCount; |
|
column = index % columnCount; |
|
} |
|
|
|
// Horizontal |
|
if (isHorizontal) |
|
{ |
|
// To do... |
|
} |
|
else // Vertical |
|
{ |
|
if (tableDirectionType == TABLE_NEXT_DIRECTION_TYPE.ZIGZAG) |
|
{ |
|
if (tableSortType == TABLE_POSITION_SORT_TYPE.DYNAMIC) |
|
{ |
|
// Current Item's Row == First Item's Row ? |
|
if (row == firstRowOrColumn) |
|
{ |
|
position.x = item.gameObject.transform.localPosition.x; |
|
position.y = item.gameObject.transform.localPosition.y; |
|
curRowOrColumn = row; |
|
} |
|
else |
|
{ |
|
if (curRowOrColumn == row) // Same Line - Next Item |
|
{ |
|
position.x = beforeItemsPos[column - 1].x + (beforeItemsSize[column - 1].x + padding.x); |
|
position.y = (row > 0) ? beforeItemsPos[column].y - (beforeItemsSize[column].y + padding.y) : initPosition.y; |
|
} |
|
else |
|
{ |
|
position.x = initPosition.x + ((itemSize.x / 2.0f) * (columnCount - 1)) + padding.x; |
|
position.y = (row > 0) ? beforeItemsPos[column].y - (beforeItemsSize[column].y + padding.y) : initPosition.y; |
|
curRowOrColumn++; |
|
} |
|
} |
|
} |
|
else if (tableSortType == TABLE_POSITION_SORT_TYPE.FLAT) |
|
{ |
|
|
|
|
|
if (curRowOrColumn == row) // Same Line - Next Item |
|
{ |
|
position.x = beforeItemsPos[column - 1].x + (beforeItemsSize[column - 1].x + padding.x); |
|
position.y = (row > 0) ? beforeItemsPos[column - 1].y : initPosition.y; |
|
} |
|
else // New Line - First Item |
|
{ |
|
position.x = initPosition.x + ((itemSize.x / 2.0f) * (columnCount - 1)) + padding.x; |
|
|
|
position.y = (row > 0) ? biggerItemPosInRowsOrColumns[row - 1].y - (biggerItemSizeInRowsOrColumns[row - 1].y + padding.y) : initPosition.y; |
|
curRowOrColumn++; |
|
} |
|
|
|
if (biggerItemSizeInRowsOrColumns[row].y < itemSize.y) |
|
{ |
|
biggerItemSizeInRowsOrColumns[row] = itemSize; |
|
biggerItemPosInRowsOrColumns[row].y = position.y; |
|
} |
|
} |
|
} |
|
} |
|
|
|
item.gameObject.transform.localPosition = position; |
|
beforeItemsPos[column] = position; |
|
beforeItemsSize[column] = itemSize; |
|
index++; |
|
} |
|
|
|
if(scrollbar) |
|
UpdateScrollBars(); |
|
} |
|
|
|
/// <summary> Reset Infinite ScrollView - Reset Item Position, ScrollView Clipping </summary> |
|
[ContextMenu("Reset")] |
|
public void ResetScroll() |
|
{ |
|
if (OnGetItemCount == null) return; |
|
int index = 0; |
|
foreach (InfiniteItem item in itemList) |
|
{ |
|
item.index = index; |
|
item.gameObject.name = index.ToString(); |
|
if (index < OnGetItemCount()) |
|
{ |
|
OnUpdateItem(index, item.gameObject); |
|
item.gameObject.SetActive(true); |
|
|
|
UIWidget[] widgets = item.gameObject.GetComponentsInChildren<UIWidget>(); |
|
foreach (var widget in widgets) widget.ResetAndUpdateAnchors(); |
|
} |
|
else |
|
{ |
|
item.gameObject.SetActive(false); |
|
} |
|
++index; |
|
} |
|
|
|
CalculateResetPosition(); |
|
|
|
if (scrollbar) |
|
UpdateScrollBars(); |
|
} |
|
|
|
/// <summary> Coroutine(Wait for 1 frame) - Calculate Reset Position </summary> |
|
IEnumerator CoCalculateResetPosition() |
|
{ |
|
// Wait 1 Frame For Update Each Widget Anchors |
|
yield return new WaitForEndOfFrame(); |
|
|
|
// Calculate Item in ScrollView |
|
CalculateResetPosition(); |
|
} |
|
|
|
/// <summary> Calculate Reset Item Position </summary> |
|
private void CalculateResetPosition() |
|
{ |
|
Vector3 itemSize = Vector3.zero; |
|
Vector3 position = Vector3.zero; |
|
|
|
Vector3[] biggerItemSizeInRowsOrColumns = new Vector3[isHorizontal ? columnCount : rowCount]; |
|
Vector3[] biggerItemPosInRowsOrColumns = new Vector3[isHorizontal ? columnCount : rowCount]; |
|
Vector3[] beforeItemsSize = new Vector3[isHorizontal ? rowCount : columnCount]; |
|
Vector2[] beforeItemsPos = new Vector2[isHorizontal ? rowCount : columnCount]; |
|
|
|
// Reposition Items |
|
int index = 0; |
|
int row = 0, column = 0; |
|
int curRowOrColumn = -1; |
|
|
|
foreach (InfiniteItem item in itemList) |
|
{ |
|
itemSize = GetItemSize(item.gameObject.transform); |
|
|
|
if (isHorizontal) |
|
{ |
|
row = index % rowCount; |
|
column = index / rowCount; |
|
} |
|
else |
|
{ |
|
row = index / columnCount; |
|
column = index % columnCount; |
|
} |
|
|
|
// Horizontal |
|
if (isHorizontal) |
|
{ |
|
// To do... |
|
} |
|
else // Vertical |
|
{ |
|
if (tableDirectionType == TABLE_NEXT_DIRECTION_TYPE.ZIGZAG) |
|
{ |
|
if (tableSortType == TABLE_POSITION_SORT_TYPE.DYNAMIC) |
|
{ |
|
if (curRowOrColumn == row) // Same Line - Next Item |
|
{ |
|
position.x = beforeItemsPos[column - 1].x + (beforeItemsSize[column - 1].x + padding.x); |
|
position.y = (row > 0) ? beforeItemsPos[column].y - (beforeItemsSize[column].y + padding.y) : initPosition.y; |
|
} |
|
else // New Line - First Item |
|
{ |
|
position.x = initPosition.x + ((itemSize.x / 2.0f) * (columnCount - 1)) + padding.x; |
|
position.y = (row > 0) ? beforeItemsPos[column].y - (beforeItemsSize[column].y + padding.y) : initPosition.y; |
|
curRowOrColumn++; |
|
} |
|
} |
|
else if (tableSortType == TABLE_POSITION_SORT_TYPE.FLAT) |
|
{ |
|
if (curRowOrColumn == row) // Same Line - Next Item |
|
{ |
|
position.x = beforeItemsPos[column - 1].x + (beforeItemsSize[column - 1].x + padding.x); |
|
position.y = (row > 0) ? beforeItemsPos[column - 1].y : initPosition.y; |
|
} |
|
else // New Line - First Item |
|
{ |
|
position.x = initPosition.x + ((itemSize.x / 2.0f) * (columnCount - 1)) + padding.x; |
|
|
|
position.y = (row > 0) ? biggerItemPosInRowsOrColumns[row - 1].y - (biggerItemSizeInRowsOrColumns[row - 1].y + padding.y) : initPosition.y; |
|
curRowOrColumn++; |
|
} |
|
|
|
if (biggerItemSizeInRowsOrColumns[row].y < itemSize.y) |
|
{ |
|
biggerItemSizeInRowsOrColumns[row] = itemSize; |
|
biggerItemPosInRowsOrColumns[row].y = position.y; |
|
} |
|
} |
|
} |
|
else if (tableDirectionType == TABLE_NEXT_DIRECTION_TYPE.ONE_DIRECTION) |
|
{ |
|
// To do... |
|
} |
|
} |
|
|
|
item.gameObject.transform.localPosition = position; |
|
beforeItemsPos[column] = position; |
|
beforeItemsSize[column] = itemSize; |
|
index++; |
|
} |
|
|
|
ResetScrollView(); |
|
} |
|
|
|
/// <summary> Reset ScrollView Clip, DragAmount </summary> |
|
public void ResetScrollView() |
|
{ |
|
if (panel == null) return; |
|
Vector4 clip = panel.finalClipRegion; |
|
if (isHorizontal) |
|
{ |
|
if (GetContentsSize() < clip.z) |
|
{ |
|
view.ResetPosition(); |
|
view.SetDragAmount(padding.x / clip.z, 0.0f, false); |
|
} |
|
else |
|
{ |
|
view.ResetPosition(); |
|
} |
|
} |
|
else |
|
{ |
|
if (GetContentsSize() < clip.w) |
|
{ |
|
view.ResetPosition(); |
|
view.SetDragAmount(0.0f, padding.y / clip.w, false); |
|
} |
|
else |
|
{ |
|
view.ResetPosition(); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> Get Item's Relative Widget Size in the GameObject </summary> |
|
public Vector3 GetItemSize(Transform tr, bool isConsiderInactive = true) |
|
{ |
|
if (tr == null) |
|
return Vector3.zero; |
|
|
|
Bounds bound = NGUIMath.CalculateRelativeWidgetBounds(tr, isConsiderInactive); |
|
return bound.size; |
|
} |
|
|
|
/// <summary> Total Contents Size - It's not Accurately </summary> |
|
public float GetContentsSize(int targetRowOrColumn = 0) |
|
{ |
|
if (OnGetItemCount == null) |
|
return 0; |
|
|
|
float result = 0; |
|
// Horizontal |
|
if (isHorizontal) |
|
{ |
|
// Each Column Item Size X |
|
foreach (var item in itemList) |
|
{ |
|
// Target Row == Item Row ? |
|
if (targetRowOrColumn == (item.index % rowCount)) |
|
result += GetItemSize(item.gameObject.transform).x; |
|
} |
|
} |
|
else // Vertical |
|
{ |
|
// Vertical << Column Item Size X |
|
foreach (var item in itemList) |
|
{ |
|
// Target Column == Item Column ? |
|
if (targetRowOrColumn == (item.index % columnCount)) |
|
result += GetItemSize(item.gameObject.transform).y; |
|
} |
|
} |
|
|
|
int totalItemCount = OnGetItemCount(); |
|
result = result * (totalItemCount / maxItemCountInView); |
|
|
|
return result; |
|
} |
|
|
|
/// <summary> SetFocus Method Work Only When (1 Row(When Horizontal) || 1 Column(Vertical)) |
|
/// <para> Warning! Do not use Immediately after Init, This Method Need a Frame later Init </para> |
|
/// </summary> |
|
public void SetFocus(int index) |
|
{ |
|
if (OnGetItemCount == null) return; |
|
if ((isHorizontal && rowCount > 1) || (!isHorizontal && columnCount > 1)) return; |
|
if (index >= OnGetItemCount()) return; |
|
|
|
index = Math.Max(index, 0); |
|
LinkedListNode<InfiniteItem> item = itemList.Last; |
|
while (item != null) |
|
{ |
|
item.Value.index = index; |
|
item.Value.gameObject.name = index.ToString(); |
|
|
|
if (index >= 0 && index < OnGetItemCount()) |
|
{ |
|
OnUpdateItem(index, item.Value.gameObject); |
|
item.Value.gameObject.SetActive(true); |
|
|
|
UIWidget[] widgets = item.Value.gameObject.GetComponentsInChildren<UIWidget>(); |
|
foreach (var widget in widgets) widget.ResetAndUpdateAnchors(); |
|
} |
|
else |
|
{ |
|
item.Value.gameObject.SetActive(false); |
|
} |
|
|
|
item = item.Previous; |
|
index--; |
|
} |
|
|
|
Vector4 clip = panel.baseClipRegion; |
|
Vector2 viewSize = new Vector2(clip.z, clip.w); |
|
|
|
int calIndex = 0; |
|
Vector3 position = Vector3.zero; |
|
Vector3 itemSize = Vector3.zero; |
|
|
|
Vector3 afterItemSize = Vector3.zero; |
|
Vector3 afterItemPosition = Vector3.zero; |
|
|
|
// View Init Position Right & Bottom |
|
afterItemPosition.x = isHorizontal ? -(viewSize.x / 2.0f) : 0; |
|
afterItemPosition.y = !isHorizontal ? -(viewSize.y / 2.0f) : 0; |
|
|
|
// Add Current clip Offset + Center |
|
afterItemPosition.x += panel.clipOffset.x + (isHorizontal ? clip.x : 0); |
|
afterItemPosition.y += panel.clipOffset.y + (!isHorizontal ? clip.y : 0); |
|
|
|
item = itemList.Last; |
|
|
|
while (item != null) |
|
{ |
|
itemSize = GetItemSize(item.Value.gameObject.transform); |
|
|
|
position.x = afterItemPosition.x - ((calIndex == 0 ? 0 : itemSize.x) + padding.x) * (isHorizontal ? 1 : 0) + (calIndex == 0 && isHorizontal ? (itemSize.x) / 2.0f : 0); |
|
position.y = afterItemPosition.y + ((calIndex == 0 ? 0 : itemSize.y) + padding.y) * (!isHorizontal ? 1 : 0) + (calIndex == 0 && !isHorizontal ? (itemSize.y) / 2.0f : 0); |
|
|
|
item.Value.gameObject.transform.localPosition = position; |
|
|
|
afterItemSize = itemSize; |
|
afterItemPosition.x = position.x; |
|
afterItemPosition.y = position.y; |
|
|
|
calIndex++; |
|
item = item.Previous; |
|
} |
|
|
|
view.InvalidateBounds(); |
|
} |
|
|
|
public void RefreshToLastItem() |
|
{ |
|
if (OnGetItemCount == null) return; |
|
|
|
} |
|
|
|
public void RefreshToFirstItem() |
|
{ |
|
if (OnGetItemCount == null) return; |
|
ResetScroll(); |
|
} |
|
|
|
///<summary> Is Visible State Check Method. as Index Item </summary> |
|
public bool IsVisibleItemFromIndex(int index) |
|
{ |
|
if (index >= OnGetItemCount()) |
|
return false; |
|
|
|
foreach (var item in itemList) |
|
{ |
|
if (item.index == index && item.gameObject.activeSelf) |
|
{ |
|
UIWidget[] widgets = item.gameObject.GetComponentsInChildren<UIWidget>(); |
|
foreach (UIWidget widget in widgets) |
|
{ |
|
if (panel.IsVisible(widget)) |
|
return true; |
|
} |
|
} |
|
} |
|
|
|
return false; |
|
} |
|
} |
|
} |