| using System.Collections; | 
| using System.Collections.Generic; | 
| using UnityEngine; | 
| using UnityEngine.EventSystems; | 
| using System; | 
| using Cysharp.Threading.Tasks; | 
| using System.Diagnostics; | 
|   | 
| [DisallowMultipleComponent] | 
|   | 
| public class CyclicScroll : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler | 
| { | 
|     [SerializeField] RectTransform m_Content; | 
|     public RectTransform content { get { return m_Content; } } | 
|   | 
|     [SerializeField] protected BoundOffset m_BoundOffset; | 
|     [SerializeField] protected Vector2 m_CellSize = new Vector2(100, 100); | 
|     public Vector2 cellSize { get { return m_CellSize; } } | 
|   | 
|     [SerializeField] protected Vector2 m_Spacing; | 
|     public Vector2 spacing { get { return m_Spacing; } } | 
|   | 
|     [SerializeField] Align m_Align = Align.Top; | 
|     public Align align { get { return m_Align; } } | 
|   | 
|     [SerializeField] bool m_ElasticityOn = true; | 
|     public bool elasticityOn { get { return m_ElasticityOn; } } | 
|   | 
|     [SerializeField] private float m_Elasticity = 0.1f; | 
|     public float elasticity { get { return m_Elasticity; } } | 
|   | 
|     [SerializeField] private float m_DecelerationRate = 0.135f; | 
|     public float decelerationRate { get { return m_DecelerationRate; } } | 
|   | 
|     [SerializeField] string m_ChildPrefabName = string.Empty; | 
|     [SerializeField] string m_ChildDisplayName = string.Empty; | 
|     [SerializeField] int m_ChildCount = 5; | 
|   | 
|     public float normalizedPosition { | 
|         get { | 
|             if (content == null) | 
|             { | 
|                 return 0f; | 
|             } | 
|   | 
|             var offset = (dataMaxOffset - dataMinOffset); | 
|             switch (align) | 
|             { | 
|                 case Align.Top: | 
|                 case Align.Bottom: | 
|                     return Mathf.Clamp01(Mathf.Abs((content.anchoredPosition.y - dataMinOffset.y) / offset.y)); | 
|                 case Align.Left: | 
|                 case Align.Right: | 
|                     return Mathf.Clamp01(Mathf.Abs((content.anchoredPosition.x - dataMinOffset.x) / offset.x)); | 
|                 default: | 
|                     return 0f; | 
|             } | 
|         } | 
|         set { | 
|             if (content == null) | 
|             { | 
|                 return; | 
|             } | 
|   | 
|             value = Mathf.Clamp01(value); | 
|             var normalize = 0f; | 
|             var offset = (dataMaxOffset - dataMinOffset); | 
|             switch (align) | 
|             { | 
|                 case Align.Top: | 
|                 case Align.Bottom: | 
|                     normalize = (content.anchoredPosition.y - dataMinOffset.y) / offset.y; | 
|                     if (Mathf.Abs(normalize - value) > 0.0001f) | 
|                     { | 
|                         targetOffset = dataMinOffset + new Vector2(0, dataMaxOffset.y * value); | 
|                         velocity = 0f; | 
|                         autoLerp = true; | 
|                         refAutoLerpPosition = Vector2.zero; | 
|                     } | 
|                     break; | 
|                 case Align.Left: | 
|                 case Align.Right: | 
|                     normalize = (content.anchoredPosition.x - dataMinOffset.x) / offset.x; | 
|                     if (Mathf.Abs(normalize - value) > 0.0001f) | 
|                     { | 
|                         targetOffset = dataMinOffset + new Vector2(dataMaxOffset.x * value, 0); | 
|                         velocity = 0f; | 
|                         autoLerp = true; | 
|                         refAutoLerpPosition = Vector2.zero; | 
|                     } | 
|                     break; | 
|             } | 
|         } | 
|     } | 
|   | 
|     protected Vector2 dataMaxOffset = Vector2.zero; | 
|     protected Vector2 dataMinOffset = Vector2.zero; | 
|   | 
|     public bool autoLerp { get; private set; } | 
|   | 
|     Vector2 targetOffset = Vector2.zero; | 
|     Vector2 refAutoLerpPosition = Vector2.zero; | 
|   | 
|     protected IList datas; | 
|     protected List<ScrollItem> infiniteItems = new List<ScrollItem>(); | 
|     List<ScrollItem> tempList = new List<ScrollItem>(); | 
|   | 
|     Vector2 startMousePosition = Vector2.zero; | 
|     Vector2 startContentPosition = Vector2.zero; | 
|     Vector2 prevPosition = Vector2.zero; | 
|   | 
|     protected float velocity = 0f; | 
|     protected bool dragging = false; | 
|   | 
|     public int dataCount { | 
|         get { | 
|             return datas == null ? 0 : datas.Count; | 
|         } | 
|     } | 
|     bool moveNextable { | 
|         get { | 
|             return hostIndex < dataCount - 1; | 
|         } | 
|     } | 
|     bool moveLastable { | 
|         get { | 
|             return preIndex > 0; | 
|         } | 
|     } | 
|   | 
|     public RectTransform rectTransform { get { return this.transform as RectTransform; } } | 
|   | 
|     private Vector2 maxOffset { get { return rectTransform.GetMaxReferencePosition(rectTransform); } } | 
|     private Vector2 minOffset { get { return rectTransform.GetMinReferencePosition(rectTransform); } } | 
|   | 
|     protected int preIndex { | 
|         get; set; | 
|     } | 
|   | 
|     protected int hostIndex { | 
|         get; set; | 
|     } | 
|   | 
|     public void LuaInit(int[] indexs, bool stepByStep) | 
|     { | 
|         Init(new List<int>(indexs), stepByStep); | 
|     } | 
|   | 
|     public virtual void Init<T>(List<T> _datas, bool _stepByStep = false) | 
|     { | 
|         if (_datas == null) | 
|         { | 
|             this.SetActive(false); | 
|             return; | 
|         } | 
|   | 
|         datas = _datas; | 
|   | 
|         ReArrange(); | 
|         FillBatchData(0); | 
|   | 
|         if (_stepByStep) | 
|         { | 
|             for (int i = 0; i < infiniteItems.Count; i++) | 
|             { | 
|                 var infiniteItem = infiniteItems[i]; | 
|                 if (infiniteItem != null) | 
|                 { | 
|                     infiniteItem.SetActive(false); | 
|                 } | 
|             } | 
|         } | 
|   | 
|         this.SetActive(true); | 
|   | 
|         dataMinOffset = content.anchoredPosition; | 
|         var totalOffset = dataCount == 0 ? Vector2.zero : cellSize * dataCount + spacing * (dataCount - 1) | 
|             + new Vector2(m_BoundOffset.left + m_BoundOffset.right, m_BoundOffset.top + m_BoundOffset.bottom); | 
|   | 
|         var longer = Mathf.Abs(totalOffset.x) > Mathf.Abs(rectTransform.rect.width); | 
|         var higher = Mathf.Abs(totalOffset.y) > Mathf.Abs(rectTransform.rect.height); | 
|         switch (align) | 
|         { | 
|             case Align.Left: | 
|                 dataMaxOffset = longer ? dataMinOffset - new Vector2(totalOffset.x - rectTransform.rect.width, 0) : dataMinOffset; | 
|                 break; | 
|             case Align.Right: | 
|                 dataMaxOffset = longer ? dataMinOffset + new Vector2(totalOffset.x - rectTransform.rect.width, 0) : dataMinOffset; | 
|                 break; | 
|             case Align.Top: | 
|                 dataMaxOffset = higher ? dataMinOffset + new Vector2(0, totalOffset.y - rectTransform.rect.height) : dataMinOffset; | 
|                 break; | 
|             case Align.Bottom: | 
|                 dataMaxOffset = higher ? dataMinOffset - new Vector2(0, totalOffset.y - rectTransform.rect.height) : dataMinOffset; | 
|                 break; | 
|         } | 
|   | 
|         if (_stepByStep) | 
|         { | 
|             Co_StepByStepAppear(); | 
|             // StartCoroutine("Co_StepByStepAppear"); | 
|         } | 
|     } | 
|   | 
|     public void Dispose() | 
|     { | 
|         velocity = 0f; | 
|         StopAllCoroutines(); | 
|         for (int i = 0; i < infiniteItems.Count; i++) | 
|         { | 
|             var infiniteItem = infiniteItems[i]; | 
|             if (infiniteItem != null) | 
|             { | 
|                 infiniteItem.Dispose(); | 
|             } | 
|         } | 
|     } | 
|   | 
|     public void HideAll() | 
|     { | 
|         StopAllCoroutines(); | 
|         for (int i = 0; i < content.childCount; i++) | 
|         { | 
|             content.GetChild(i).SetActive(false); | 
|         } | 
|     } | 
|   | 
|     private async UniTask Co_StepByStepAppear() | 
|     { | 
|         for (int i = 0; i < infiniteItems.Count; i++) | 
|         { | 
|             var infiniteItem = infiniteItems[i]; | 
|             if (infiniteItem != null && i < datas.Count) | 
|             { | 
|                 infiniteItem.SetActive(true); | 
|                 infiniteItem.OpeningShow(); | 
|                 await UniTask.Delay(1000); | 
|             } | 
|         } | 
|     } | 
|   | 
|     public void MoveToCenter(int _dataIndex) | 
|     { | 
|         if (_dataIndex < 0 || _dataIndex >= dataCount) | 
|         { | 
|             return; | 
|         } | 
|   | 
|         switch (align) | 
|         { | 
|             case Align.Left: | 
|                 var leftOffsetX = Mathf.Clamp(m_BoundOffset.left + (_dataIndex + 0.5f) * cellSize.x + _dataIndex * spacing.x - rectTransform.rect.width * 0.5f, 0, Mathf.Abs(dataMaxOffset.x)); | 
|                 targetOffset = new Vector2(dataMinOffset.x - leftOffsetX, 0); | 
|                 break; | 
|             case Align.Right: | 
|                 var rightOffsetX = Mathf.Clamp(m_BoundOffset.right + (_dataIndex + 0.5f) * cellSize.x + _dataIndex * spacing.x - rectTransform.rect.width * 0.5f, 0, Mathf.Abs(dataMaxOffset.x)); | 
|                 targetOffset = new Vector2(dataMinOffset.x + rightOffsetX, 0); | 
|                 break; | 
|             case Align.Top: | 
|                 var topOffsetY = Mathf.Clamp(m_BoundOffset.top + (_dataIndex + 0.5f) * cellSize.y + _dataIndex * spacing.y - rectTransform.rect.height * 0.5f, 0, Mathf.Abs(dataMaxOffset.y)); | 
|                 targetOffset = new Vector2(0, dataMinOffset.y + topOffsetY); | 
|                 break; | 
|             case Align.Bottom: | 
|                 var bottomOffsetY = Mathf.Clamp(m_BoundOffset.bottom + (_dataIndex + 0.5f) * cellSize.y + _dataIndex * spacing.y - rectTransform.rect.height * 0.5f, 0, Mathf.Abs(dataMaxOffset.y)); | 
|                 targetOffset = new Vector2(0, dataMinOffset.y - bottomOffsetY); | 
|                 break; | 
|         } | 
|   | 
|         autoLerp = true; | 
|     } | 
|   | 
|     #region Drag Process | 
|   | 
|     public void OnBeginDrag(PointerEventData eventData) | 
|     { | 
|         if (autoLerp || eventData.button != PointerEventData.InputButton.Left) | 
|         { | 
|             return; | 
|         } | 
|   | 
|         startMousePosition = Vector2.zero; | 
|         RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out startMousePosition); | 
|         prevPosition = startContentPosition = content.anchoredPosition; | 
|         velocity = 0f; | 
|         dragging = true; | 
|     } | 
|   | 
|     public void OnDrag(PointerEventData eventData) | 
|     { | 
|         // if (NewBieCenter.Instance.inGuiding) | 
|         // { | 
|         //     return; | 
|         // } | 
|   | 
|         if (autoLerp || eventData.button != PointerEventData.InputButton.Left) | 
|         { | 
|             return; | 
|         } | 
|   | 
|         var localMouse = new Vector2(); | 
|         if (RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out localMouse)) | 
|         { | 
|             var pointerDelta = localMouse - startMousePosition; | 
|             var position = startContentPosition + pointerDelta; | 
|             SetContentAnchoredPosition(position, align); | 
|         } | 
|     } | 
|   | 
|     public void OnEndDrag(PointerEventData eventData) | 
|     { | 
|         if (autoLerp || eventData.button != PointerEventData.InputButton.Left) | 
|         { | 
|             return; | 
|         } | 
|   | 
|         dragging = false; | 
|     } | 
|     #endregion | 
|   | 
|     private void Update() | 
|     { | 
|         if (autoLerp && Vector2.Distance(content.anchoredPosition, targetOffset) > 0.1f) | 
|         { | 
|             var newPosition = Vector2.SmoothDamp(content.anchoredPosition, targetOffset, ref refAutoLerpPosition, m_Elasticity, Mathf.Infinity, Time.unscaledDeltaTime); | 
|             SetContentAnchoredPosition(newPosition, align); | 
|         } | 
|         else | 
|         { | 
|             autoLerp = false; | 
|         } | 
|     } | 
|   | 
|     protected virtual void LateUpdate() | 
|     { | 
|         if (content == null) | 
|         { | 
|             return; | 
|         } | 
|   | 
|         var deltaTime = Time.unscaledDeltaTime; | 
|         var offset = CalculateOffset(align); | 
|   | 
|         if (!dragging && (velocity != 0f || Vector2.SqrMagnitude(offset - Vector2.zero) > 0.1f)) | 
|         { | 
|             Vector2 position = content.anchoredPosition; | 
|             if (Vector2.SqrMagnitude(offset - Vector2.zero) > 0.1f) | 
|             { | 
|                 float speed = velocity; | 
|                 switch (align) | 
|                 { | 
|                     case Align.Left: | 
|                     case Align.Right: | 
|                         position[0] = Mathf.SmoothDamp(content.anchoredPosition[0], content.anchoredPosition[0] - offset.x, ref speed, m_Elasticity, Mathf.Infinity, deltaTime); | 
|                         break; | 
|                     case Align.Bottom: | 
|                     case Align.Top: | 
|                         position[1] = Mathf.SmoothDamp(content.anchoredPosition[1], content.anchoredPosition[1] - offset.y, ref speed, m_Elasticity, Mathf.Infinity, deltaTime); | 
|                         break; | 
|                 } | 
|   | 
|                 if (Mathf.Abs(speed) < 1) | 
|                 { | 
|                     speed = 0f; | 
|                 } | 
|                 velocity = speed; | 
|             } | 
|             else | 
|             { | 
|                 velocity *= Mathf.Pow(m_DecelerationRate, deltaTime); | 
|                 if (Mathf.Abs(velocity) < 50) | 
|                 { | 
|                     velocity = 0; | 
|                 } | 
|                 switch (align) | 
|                 { | 
|                     case Align.Left: | 
|                     case Align.Right: | 
|                         position[0] += velocity * deltaTime; | 
|                         break; | 
|                     case Align.Bottom: | 
|                     case Align.Top: | 
|                         position[1] += velocity * deltaTime; | 
|                         break; | 
|                 } | 
|   | 
|             } | 
|   | 
|             SetContentAnchoredPosition(position, align); | 
|         } | 
|   | 
|         if (dragging /*&& content.anchoredPosition != prevPosition*/) | 
|         { | 
|             var newVelocity = 0f; | 
|             switch (align) | 
|             { | 
|                 case Align.Left: | 
|                 case Align.Right: | 
|                     newVelocity = (content.anchoredPosition[0] - prevPosition[0]) / deltaTime; | 
|                     break; | 
|                 case Align.Bottom: | 
|                 case Align.Top: | 
|                     newVelocity = (content.anchoredPosition[1] - prevPosition[1]) / deltaTime; | 
|                     break; | 
|             } | 
|   | 
|             velocity = Mathf.Lerp(velocity, newVelocity, deltaTime * 10); | 
|             prevPosition = content.anchoredPosition; | 
|         } | 
|   | 
|     } | 
|   | 
|     protected virtual void ProcessMoveNext() | 
|     { | 
|         ScrollItem lastRect = null; | 
|         ScrollItem item = null; | 
|   | 
|         tempList.Clear(); | 
|         for (int i = 0; i < infiniteItems.Count; i++) | 
|         { | 
|             tempList.Add(infiniteItems[i]); | 
|         } | 
|         if (tempList.Count <= 0) | 
|         { | 
|             return; | 
|         } | 
|         lastRect = tempList[tempList.Count - 1]; | 
|         for (int i = 0; i < tempList.Count; i++) | 
|         { | 
|             item = tempList[i]; | 
|             var able = moveNextable && TestMoveNext(align, item); | 
|             if (able) | 
|             { | 
|                 infiniteItems.Remove(item); | 
|                 infiniteItems.Add(item); | 
|                 var offset = CalculateElementOffset(align); | 
|                 item.rectTransform.anchoredPosition = lastRect.rectTransform.anchoredPosition + offset; | 
|                 lastRect = item; | 
|   | 
|                 hostIndex++; | 
|                 preIndex++; | 
|                 item.Dispose(); | 
|                 item.LuaDispose(); | 
|                 item.Display(datas[hostIndex]); | 
|                 item.LuaDisplay(hostIndex); | 
|             } | 
|             else | 
|             { | 
|                 break; | 
|             } | 
|         } | 
|     } | 
|   | 
|     protected virtual void ProcessMoveLast() | 
|     { | 
|         ScrollItem firstRect = null; | 
|         ScrollItem item = null; | 
|   | 
|         tempList.Clear(); | 
|         for (int i = 0; i < infiniteItems.Count; i++) | 
|         { | 
|             tempList.Add(infiniteItems[i]); | 
|         } | 
|   | 
|         firstRect = tempList[0]; | 
|         for (int i = tempList.Count - 1; i >= 0; i--) | 
|         { | 
|             item = tempList[i]; | 
|             var able = moveLastable && TestMoveLast(align, item); | 
|             if (able) | 
|             { | 
|                 infiniteItems.Remove(item); | 
|                 infiniteItems.Insert(0, item); | 
|                 var offset = CalculateElementOffset(align); | 
|                 item.rectTransform.anchoredPosition = firstRect.rectTransform.anchoredPosition - offset; | 
|                 firstRect = item; | 
|                 hostIndex--; | 
|                 preIndex--; | 
|                 item.Dispose(); | 
|                 item.LuaDispose(); | 
|                 item.Display(datas[preIndex]); | 
|                 item.LuaDisplay(preIndex); | 
|             } | 
|             else | 
|             { | 
|                 break; | 
|             } | 
|         } | 
|     } | 
|   | 
|     private void SetContentAnchoredPosition(Vector2 _position, Align _align) | 
|     { | 
|         if (_position == content.anchoredPosition) | 
|         { | 
|             return; | 
|         } | 
|   | 
|         if (!elasticityOn) | 
|         { | 
|             _position.y = Mathf.Clamp(_position.y, dataMinOffset.y, dataMaxOffset.y); | 
|             _position.x = Mathf.Clamp(_position.x, dataMinOffset.x, dataMaxOffset.x); | 
|         } | 
|   | 
|         var offset = _position - content.anchoredPosition; | 
|   | 
|         switch (_align) | 
|         { | 
|             case Align.Left: | 
|             case Align.Right: | 
|                 _position[1] = content.anchoredPosition[1]; | 
|                 content.anchoredPosition = _position; | 
|                 break; | 
|             case Align.Top: | 
|             case Align.Bottom: | 
|                 _position[0] = content.anchoredPosition[0]; | 
|                 content.anchoredPosition = _position; | 
|                 break; | 
|         } | 
|   | 
|         var moveNext = (_align == Align.Left && offset.x < 0f) || (_align == Align.Right && offset.x > 0f) || | 
|             (_align == Align.Top && offset.y > 0f) || (_align == Align.Bottom && offset.y < 0f); | 
|   | 
|         if (moveNext) | 
|         { | 
|             ProcessMoveNext(); | 
|         } | 
|         else | 
|         { | 
|             ProcessMoveLast(); | 
|         } | 
|     } | 
|   | 
|     private Vector2 CalculateOffset(Align _align) | 
|     { | 
|         var offset = Vector2.zero; | 
|         switch (_align) | 
|         { | 
|             case Align.Left: | 
|                 if (content.anchoredPosition.x > dataMinOffset.x) | 
|                 { | 
|                     offset = content.anchoredPosition - dataMinOffset; | 
|                 } | 
|                 else if (content.anchoredPosition.x < dataMaxOffset.x) | 
|                 { | 
|                     offset = content.anchoredPosition - dataMaxOffset; | 
|                 } | 
|                 break; | 
|             case Align.Right: | 
|                 if (content.anchoredPosition.x < dataMinOffset.x) | 
|                 { | 
|                     offset = content.anchoredPosition - dataMinOffset; | 
|                 } | 
|                 else if (content.anchoredPosition.x > dataMaxOffset.x) | 
|                 { | 
|                     offset = content.anchoredPosition - dataMaxOffset; | 
|                 } | 
|                 break; | 
|             case Align.Bottom: | 
|                 if (content.anchoredPosition.y > dataMinOffset.y) | 
|                 { | 
|                     offset = content.anchoredPosition - dataMinOffset; | 
|                 } | 
|                 else if (content.anchoredPosition.y < dataMaxOffset.y) | 
|                 { | 
|                     offset = content.anchoredPosition - dataMaxOffset; | 
|                 } | 
|                 break; | 
|             case Align.Top: | 
|                 if (content.anchoredPosition.y < dataMinOffset.y) | 
|                 { | 
|                     offset = content.anchoredPosition - dataMinOffset; | 
|                 } | 
|                 else if (content.anchoredPosition.y > dataMaxOffset.y) | 
|                 { | 
|                     offset = content.anchoredPosition - dataMaxOffset; | 
|                 } | 
|                 break; | 
|         } | 
|   | 
|         return offset; | 
|     } | 
|   | 
|     [ContextMenu("Arrange")] | 
|     public virtual void ReArrange() | 
|     { | 
|         velocity = 0f; | 
|         autoLerp = false; | 
|         CreateElements(); | 
|         ElementsMatch(); | 
|         Arrange(align); | 
|     } | 
|   | 
|     private void CreateElements() | 
|     { | 
|         var items = this.content.GetComponentsInChildren<ScrollItem>(true); | 
|         if (items.Length < m_ChildCount) | 
|         { | 
|             var dif = m_ChildCount - items.Length; | 
|             if (!string.IsNullOrEmpty(m_ChildPrefabName) && !string.IsNullOrEmpty(m_ChildDisplayName)) | 
|             { | 
|                 for (var i = 0; i < dif; i++) | 
|                 { | 
|                     var instance = UIUtility.CreateWidget(m_ChildPrefabName, m_ChildDisplayName); | 
|                     instance.transform.SetParentEx(this.m_Content, Vector3.zero, Quaternion.identity, Vector3.one); | 
|                 } | 
|             } | 
|         } | 
|     } | 
|   | 
|     private void Arrange(Align _align) | 
|     { | 
|         var head = infiniteItems[0]; | 
|   | 
|         var offset1 = Vector2.zero; | 
|         switch (_align) | 
|         { | 
|             case Align.Left: | 
|                 offset1 = new Vector2(-content.rect.width * 0.5f + head.rectTransform.rect.width * 0.5f + m_BoundOffset.left, 0); | 
|                 break; | 
|             case Align.Right: | 
|                 offset1 = new Vector2(content.rect.width * 0.5f - head.rectTransform.rect.width * 0.5f - m_BoundOffset.right, 0); | 
|                 break; | 
|             case Align.Top: | 
|                 offset1 = new Vector2(0f, content.rect.height * 0.5f - head.rectTransform.rect.height * 0.5f - m_BoundOffset.top); | 
|                 break; | 
|             case Align.Bottom: | 
|                 offset1 = new Vector2(0f, -content.rect.height * 0.5f + head.rectTransform.rect.height * 0.5f + m_BoundOffset.bottom); | 
|                 break; | 
|         } | 
|   | 
|         head.rectTransform.anchoredPosition = content.anchoredPosition + offset1; | 
|   | 
|         var offset2 = CalculateElementOffset(_align); | 
|         for (int i = 1; i < infiniteItems.Count; i++) | 
|         { | 
|             var item = infiniteItems[i]; | 
|             item.rectTransform.anchoredPosition = head.rectTransform.anchoredPosition + offset2 * i; | 
|         } | 
|     } | 
|   | 
|     private void ElementsMatch() | 
|     { | 
|         if (content == null) | 
|         { | 
|             UnityEngine.Debug.Log("Content 不能为空!"); | 
|             return; | 
|         } | 
|   | 
|         infiniteItems.Clear(); | 
|         for (int i = 0; i < content.childCount; i++) | 
|         { | 
|             var infiniteItem = content.GetChild(i).GetComponent<ScrollItem>(); | 
|             if (infiniteItem != null) | 
|             { | 
|                 infiniteItems.Add(infiniteItem); | 
|                 infiniteItem.rectTransform.sizeDelta = cellSize; | 
|                 infiniteItem.rectTransform.anchorMax = Vector2.one * 0.5f; | 
|                 infiniteItem.rectTransform.anchorMin = Vector2.one * 0.5f; | 
|                 infiniteItem.rectTransform.pivot = Vector2.one * 0.5f; | 
|             } | 
|         } | 
|   | 
|         content.anchorMax = content.anchorMin = content.pivot = Vector2.one * 0.5f; | 
|         content.sizeDelta = rectTransform.sizeDelta; | 
|         content.anchoredPosition = Vector2.zero; | 
|     } | 
|   | 
|     private void FillBatchData(int _startIndex) | 
|     { | 
|         int min = Mathf.Min(infiniteItems.Count, dataCount); | 
|         preIndex = Mathf.Clamp(_startIndex, 0, dataCount - min); | 
|         hostIndex = preIndex + min - 1; | 
|   | 
|         for (int i = 0; i < infiniteItems.Count; i++) | 
|         { | 
|             var item = infiniteItems[i]; | 
|             if (i <= hostIndex - preIndex) | 
|             { | 
|                 item.SetActive(true); | 
|                 item.Display(datas[preIndex + i]); | 
|                 item.LuaDisplay(preIndex + i); | 
|             } | 
|             else | 
|             { | 
|                 item.SetActive(false); | 
|                 item.Dispose(); | 
|                 item.LuaDispose(); | 
|             } | 
|         } | 
|     } | 
|   | 
|     private Vector2 CalculateElementOffset(Align _align) | 
|     { | 
|         switch (_align) | 
|         { | 
|             case Align.Left: | 
|                 return new Vector2(cellSize.x + spacing.x, 0); | 
|             case Align.Right: | 
|                 return new Vector2(-cellSize.x - spacing.x, 0); | 
|             case Align.Top: | 
|                 return new Vector2(0, -cellSize.y - spacing.y); | 
|             case Align.Bottom: | 
|                 return new Vector2(0, cellSize.y + spacing.y); | 
|             default: | 
|                 return Vector2.zero; | 
|         } | 
|     } | 
|   | 
|     private bool TestMoveNext(Align _align, ScrollItem _item) | 
|     { | 
|         var itemMinPosition = _item.rectTransform.GetMinReferencePosition(rectTransform); | 
|         var itemMaxPosition = _item.rectTransform.GetMaxReferencePosition(rectTransform); | 
|   | 
|         switch (_align) | 
|         { | 
|             case Align.Left: | 
|                 return itemMaxPosition.x < minOffset.x; | 
|             case Align.Bottom: | 
|                 return itemMaxPosition.y < minOffset.y; | 
|             case Align.Right: | 
|                 return itemMinPosition.x > maxOffset.x; | 
|             case Align.Top: | 
|                 return itemMinPosition.y > maxOffset.y; | 
|             default: | 
|                 return false; | 
|         } | 
|     } | 
|   | 
|     private bool TestMoveLast(Align _align, ScrollItem _item) | 
|     { | 
|         var itemMinPosition = _item.rectTransform.GetMinReferencePosition(rectTransform); | 
|         var itemMaxPosition = _item.rectTransform.GetMaxReferencePosition(rectTransform); | 
|   | 
|         switch (_align) | 
|         { | 
|             case Align.Left: | 
|                 return itemMinPosition.x > maxOffset.x; | 
|             case Align.Bottom: | 
|                 return itemMinPosition.y > maxOffset.y; | 
|             case Align.Right: | 
|                 return itemMaxPosition.x < minOffset.x; | 
|             case Align.Top: | 
|                 return itemMaxPosition.y < minOffset.y; | 
|             default: | 
|                 return false; | 
|         } | 
|     } | 
|   | 
|     public enum Align | 
|     { | 
|         Left, | 
|         Right, | 
|         Top, | 
|         Bottom, | 
|     } | 
|   | 
|     [Serializable] | 
|     public struct BoundOffset | 
|     { | 
|         public float left; | 
|         public float right; | 
|         public float top; | 
|         public float bottom; | 
|     } | 
|   | 
| } |