416 lines
13 KiB
C#
416 lines
13 KiB
C#
using System.Diagnostics;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace BF
|
|
{
|
|
public class BFScrollRectGrid : BFScrollRectBase
|
|
{
|
|
public BFCell bfCell;
|
|
public float spacing;
|
|
public float padding;
|
|
public float topRecoveryOffset;
|
|
public float downRecoveryOffset;
|
|
public int preLineCount = 4;
|
|
public BFUIDirection direction;
|
|
|
|
Stack<BFCell> cellPool = new Stack<BFCell>();
|
|
List<BFCell> activeCells = new List<BFCell>();
|
|
|
|
float lineSize;
|
|
float cellSize;
|
|
int instantiateCount = 0;
|
|
int totalCount = 0;
|
|
int topFillCount;
|
|
int bottomFillCount;
|
|
|
|
void Awake()
|
|
{
|
|
lineSize = direction == BFUIDirection.Vertical ? bfCell.Height + spacing : bfCell.Width + spacing;
|
|
cellSize = direction == BFUIDirection.Vertical ? bfCell.Width + padding : bfCell.Height + padding;
|
|
if (bfCell.gameObject.activeSelf)
|
|
{
|
|
bfCell.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
|
|
int GetTotalLines(int totalCount)
|
|
{
|
|
if (totalCount % preLineCount == 0)
|
|
{
|
|
return totalCount / preLineCount;
|
|
}
|
|
return totalCount / preLineCount + 1;
|
|
}
|
|
|
|
public override void RefillCells(int totalCount, int targetIndex)
|
|
{
|
|
bottomFillCount = 0;
|
|
topFillCount = 0;
|
|
this.totalCount = totalCount;
|
|
if (activeCells.Count != 0)
|
|
{
|
|
while (activeCells.Count != 0)
|
|
{
|
|
Pool(activeCells[0]);
|
|
}
|
|
UnityScrollRect.StopMovement();
|
|
}
|
|
ContentTrans.anchoredPosition = Vector2.zero;
|
|
if (direction == BFUIDirection.Vertical)
|
|
{
|
|
ContentTrans.sizeDelta = new Vector2(ContentTrans.sizeDelta.x, lineSize * GetTotalLines(totalCount) - spacing);
|
|
}
|
|
else
|
|
{
|
|
ContentTrans.sizeDelta = new Vector2(lineSize * GetTotalLines(totalCount) - spacing, ContentTrans.sizeDelta.y);
|
|
}
|
|
TryFullFill();
|
|
|
|
if (targetIndex > 0)
|
|
{
|
|
MoveToIndex(targetIndex);
|
|
}
|
|
}
|
|
|
|
public override void SetTotalCount(int totalCount)
|
|
{
|
|
this.totalCount = totalCount;
|
|
if (totalCount < activeCells.Count)
|
|
{
|
|
for (int i = activeCells.Count - 1; i > totalCount - 1; i--)
|
|
{
|
|
Pool(activeCells[i]);
|
|
if (bottomFillCount > 0)
|
|
{
|
|
bottomFillCount--;
|
|
}
|
|
else
|
|
{
|
|
if (totalCount <= preLineCount)
|
|
{
|
|
topFillCount--;
|
|
}
|
|
else
|
|
{
|
|
bottomFillCount = preLineCount - 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (direction == BFUIDirection.Vertical)
|
|
{
|
|
ContentTrans.sizeDelta = new Vector2(ContentTrans.sizeDelta.x, lineSize * GetTotalLines(totalCount) - spacing);
|
|
}
|
|
else
|
|
{
|
|
ContentTrans.sizeDelta = new Vector2(lineSize * totalCount - spacing, ContentTrans.sizeDelta.y);
|
|
}
|
|
}
|
|
|
|
public override void SetSelected(int index)
|
|
{
|
|
selectedIndex = index;
|
|
int count = activeCells.Count;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
var cell = activeCells[i];
|
|
Selected?.Invoke(cell.dataIndex == index, cell.objIndex);
|
|
}
|
|
}
|
|
|
|
public override void RefreshAll()
|
|
{
|
|
int count = activeCells.Count;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
var cell = activeCells[i];
|
|
RefreshAction?.Invoke(cell.dataIndex, cell.objIndex);
|
|
}
|
|
}
|
|
|
|
public override void ClearCells()
|
|
{
|
|
while (activeCells.Count != 0)
|
|
{
|
|
Pool(activeCells[0]);
|
|
}
|
|
ContentTrans.anchoredPosition = Vector2.zero;
|
|
bottomFillCount = 0;
|
|
topFillCount = 0;
|
|
}
|
|
|
|
public override void AnchoredPositionChange()
|
|
{
|
|
|
|
}
|
|
|
|
protected override void TryFullFill()
|
|
{
|
|
int i = 0;
|
|
while (CheckBorder() && i < totalCount)
|
|
{
|
|
i++;
|
|
}
|
|
}
|
|
|
|
bool CheckBorder()
|
|
{
|
|
if (activeCells.Count == 0)
|
|
{
|
|
TryStartAdd();
|
|
return false;
|
|
}
|
|
|
|
var cell = activeCells[0];
|
|
var delta = direction == BFUIDirection.Vertical ?
|
|
cell.AnchoredPosition.y + ContentTrans.anchoredPosition.y :
|
|
cell.AnchoredPosition.x + ContentTrans.anchoredPosition.x;
|
|
if (delta < topRecoveryOffset && TryAddUp())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (topFillCount < preLineCount && TryAddUp())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
cell = activeCells[activeCells.Count - 1];
|
|
delta = direction == BFUIDirection.Vertical ?
|
|
cell.AnchoredPosition.y - lineSize + ContentTrans.anchoredPosition.y :
|
|
cell.AnchoredPosition.x - lineSize + ContentTrans.anchoredPosition.x;
|
|
if (delta > -ViewPortTrans.sizeDelta.y - downRecoveryOffset && TryAddDown())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (bottomFillCount < preLineCount && TryAddDown())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (activeCells.Count <= preLineCount)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (NeedCull(activeCells[0]))
|
|
{
|
|
CullLineUp();
|
|
return true;
|
|
}
|
|
if (NeedCull(activeCells[activeCells.Count - 1]))
|
|
{
|
|
CullLineDown(activeCells.Count - 1);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void TryStartAdd()
|
|
{
|
|
if (totalCount == 0)
|
|
{
|
|
return;
|
|
}
|
|
var cell = GetCell();
|
|
cell.dataIndex = 1;
|
|
cell.name = StringConst.GetScrollRectCellName(0);
|
|
topFillCount = 1;
|
|
cell.CachedRectTransform.anchoredPosition = Vector2.zero;
|
|
activeCells.Add(cell);
|
|
cell.gameObject.SetActive(true);
|
|
RefreshAction?.Invoke(cell.dataIndex, cell.objIndex);
|
|
}
|
|
|
|
bool TryAddUp()
|
|
{
|
|
var topIndex = activeCells[0].dataIndex;
|
|
if (topIndex == 1 && (topFillCount == preLineCount || activeCells.Count == totalCount))
|
|
{
|
|
return false;
|
|
}
|
|
var cell = GetCell();
|
|
if (topFillCount == preLineCount)
|
|
{
|
|
topFillCount = 0;
|
|
cell.dataIndex = topIndex - preLineCount;
|
|
}
|
|
else if (topFillCount == 0)
|
|
{
|
|
cell.dataIndex = topIndex - preLineCount;
|
|
}
|
|
else
|
|
{
|
|
cell.dataIndex = topIndex + topFillCount;
|
|
}
|
|
|
|
var x = direction == BFUIDirection.Vertical ? topFillCount * cellSize : -GetLineIndex(cell.dataIndex) * lineSize;
|
|
var y = direction == BFUIDirection.Vertical ? -GetLineIndex(cell.dataIndex) * lineSize : topFillCount * cellSize;
|
|
cell.CachedRectTransform.anchoredPosition = new Vector2(x, y);
|
|
cell.gameObject.SetActive(true);
|
|
cell.name = StringConst.GetScrollRectCellName(cell.dataIndex - 1);
|
|
|
|
if (topFillCount == activeCells.Count)
|
|
{
|
|
activeCells.Add(cell);
|
|
}
|
|
else
|
|
{
|
|
activeCells.Insert(topFillCount, cell);
|
|
}
|
|
topFillCount++;
|
|
|
|
RefreshAction?.Invoke(cell.dataIndex, cell.objIndex);
|
|
return true;
|
|
}
|
|
|
|
bool TryAddDown()
|
|
{
|
|
var downIndex = activeCells[activeCells.Count - 1].dataIndex;
|
|
if (downIndex == totalCount)
|
|
{
|
|
return false;
|
|
}
|
|
if (bottomFillCount == preLineCount)
|
|
{
|
|
bottomFillCount = 0;
|
|
}
|
|
|
|
var cell = GetCell();
|
|
cell.dataIndex = downIndex + 1;
|
|
cell.name = StringConst.GetScrollRectCellName(cell.dataIndex - 1);
|
|
var x = direction == BFUIDirection.Vertical ? bottomFillCount * cellSize : -GetLineIndex(cell.dataIndex) * lineSize;
|
|
var y = direction == BFUIDirection.Vertical ? -GetLineIndex(cell.dataIndex) * lineSize : bottomFillCount * cellSize;
|
|
cell.CachedRectTransform.anchoredPosition = new Vector2(x, y);
|
|
activeCells.Add(cell);
|
|
cell.gameObject.SetActive(true);
|
|
bottomFillCount++;
|
|
RefreshAction?.Invoke(cell.dataIndex, cell.objIndex);
|
|
return true;
|
|
}
|
|
|
|
int GetLineIndex(int index)
|
|
{
|
|
if (index % preLineCount == 0)
|
|
{
|
|
return index / preLineCount - 1;
|
|
}
|
|
return index / preLineCount;
|
|
}
|
|
|
|
BFCell GetCell()
|
|
{
|
|
if (cellPool.Count > 0)
|
|
{
|
|
return cellPool.Pop();
|
|
}
|
|
else
|
|
{
|
|
var t = Instantiate(bfCell.CachedRectTransform);
|
|
t.SetParent(ContentTrans);
|
|
t.localScale = Vector3.one;
|
|
t.anchoredPosition3D = Vector3.zero;
|
|
instantiateCount++;
|
|
var newCell = t.GetComponent<BFCell>();
|
|
newCell.objIndex = instantiateCount;
|
|
OnInstantiateCell?.Invoke(newCell.gameObject);
|
|
return newCell;
|
|
}
|
|
}
|
|
|
|
void Pool(BFCell cell)
|
|
{
|
|
activeCells.Remove(cell);
|
|
cell.gameObject.SetActive(false);
|
|
cellPool.Push(cell);
|
|
}
|
|
|
|
bool NeedCull(BFCell cell)
|
|
{
|
|
if (activeCells.IndexOf(cell) == 0)
|
|
{
|
|
var d1 = direction == BFUIDirection.Vertical ?
|
|
cell.AnchoredPosition.y - lineSize + ContentTrans.anchoredPosition.y :
|
|
cell.AnchoredPosition.x - lineSize + ContentTrans.anchoredPosition.x;
|
|
if (d1 > 0.01 + topRecoveryOffset)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
var d2 = direction == BFUIDirection.Vertical ?
|
|
cell.AnchoredPosition.y + ContentTrans.anchoredPosition.y :
|
|
cell.AnchoredPosition.x + ContentTrans.anchoredPosition.x;
|
|
var d3 = direction == BFUIDirection.Vertical ?
|
|
-ViewPortTrans.sizeDelta.y : -ViewPortTrans.sizeDelta.x;
|
|
if (d2 < d3 - (0.01 + downRecoveryOffset))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (cell.dataIndex > totalCount)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void CullLineUp()
|
|
{
|
|
for (int i = topFillCount - 1; i >= 0; i--)
|
|
{
|
|
Pool(activeCells[i]);
|
|
topFillCount--;
|
|
if (topFillCount == 0)
|
|
{
|
|
topFillCount = preLineCount;
|
|
return;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void CullLineDown(int lastIndex)
|
|
{
|
|
for (int i = lastIndex; i >= 0; i--)
|
|
{
|
|
Pool(activeCells[i]);
|
|
bottomFillCount--;
|
|
if (bottomFillCount == 0)
|
|
{
|
|
bottomFillCount = preLineCount;
|
|
return;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public override void MoveToIndex(int index)
|
|
{
|
|
if (index > totalCount)
|
|
{
|
|
return;
|
|
}
|
|
int line = (index - 1) / preLineCount;
|
|
line = line >= 0 ? line : 0;
|
|
if (direction == BFUIDirection.Vertical)
|
|
{
|
|
float moveHeight = Mathf.Min(lineSize * line, ContentTrans.sizeDelta.y - ViewPortTrans.sizeDelta.y);
|
|
moveHeight = Mathf.Max(0, moveHeight);
|
|
ContentTrans.anchoredPosition = new Vector2(ContentTrans.anchoredPosition.x, moveHeight);
|
|
}
|
|
else
|
|
{
|
|
float moveWidth = Mathf.Min(lineSize * line, ContentTrans.sizeDelta.x - ViewPortTrans.sizeDelta.x);
|
|
moveWidth = Mathf.Max(0, moveWidth);
|
|
ContentTrans.anchoredPosition = new Vector2(-moveWidth, ContentTrans.anchoredPosition.y);
|
|
}
|
|
}
|
|
}
|
|
} |