using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; namespace CIG { [AddComponentMenu("Layout/Recycler Grid Layout Group", 153)] public class RecyclerGridLayoutGroup : LayoutGroup { public enum RecyclerConstraint { FixedColumnCount, FixedRowCount } public enum Corner { UpperLeft } [SerializeField] protected Corner _startCorner; [SerializeField] protected GridLayoutGroup.Axis _startAxis; [SerializeField] protected Vector2 _cellSize = new Vector2(100f, 100f); [SerializeField] protected Vector2 _spacing = Vector2.zero; [SerializeField] protected RecyclerConstraint _constraint; [SerializeField] protected int _constraintCount = 2; [SerializeField] protected int _recyclerChildCount = 2; [SerializeField] private ObjectPool _objectPool; private DrivenRectTransformTracker _tracker; private int _maxChildren; private Func _initCallback; private List _instances = new List(); private Dictionary _indexMapping = new Dictionary(); private float _lastPosition; private int _startIndex; public Corner StartCorner { get { return _startCorner; } set { SetProperty(ref _startCorner, value); } } public GridLayoutGroup.Axis StartAxis => _startAxis; public Vector2 CellSize { get { return _cellSize; } set { SetProperty(ref _cellSize, value); } } public Vector2 Spacing { get { return _spacing; } set { SetProperty(ref _spacing, value); } } public RecyclerConstraint Constraint => _constraint; public int ConstraintCount { get { return _constraintCount; } set { SetProperty(ref _constraintCount, Mathf.Max(1, value)); } } public int RecyclerChildCount { get { return _recyclerChildCount; } set { SetProperty(ref _recyclerChildCount, Mathf.Max(1, value)); } } public int MaxChildren { get { return _maxChildren; } set { SetProperty(ref _maxChildren, Mathf.Max(1, value)); } } protected override void OnEnable() { base.OnEnable(); _tracker.Add(this, base.rectTransform, DrivenTransformProperties.SizeDelta); } protected override void OnDisable() { base.OnDisable(); _tracker.Clear(); } private void Update() { if (MaxChildren == RecyclerChildCount) { return; } float num; if (_constraint == RecyclerConstraint.FixedRowCount) { Vector2 anchoredPosition = base.rectTransform.anchoredPosition; num = anchoredPosition.x * -1f; } else { if (_constraint != 0) { UnityEngine.Debug.LogWarningFormat("Unknown constraint '{0}'", _constraint); return; } Vector2 anchoredPosition2 = base.rectTransform.anchoredPosition; num = anchoredPosition2.y; } if (Mathf.Approximately(num, _lastPosition)) { return; } _lastPosition = num; float num2; if (_constraint == RecyclerConstraint.FixedRowCount) { Vector2 cellSize = CellSize; float x = cellSize.x; Vector2 spacing = Spacing; num2 = x + spacing.x; } else { if (_constraint != 0) { UnityEngine.Debug.LogWarningFormat("Unknown constraint '{0}'", _constraint); return; } Vector2 cellSize2 = CellSize; float y = cellSize2.y; Vector2 spacing2 = Spacing; num2 = y + spacing2.y; } int num3 = Mathf.Clamp(Mathf.FloorToInt((_lastPosition - num2) / num2 * (float)_constraintCount), 0, Mathf.Max(0, MaxChildren - RecyclerChildCount)); if (_startIndex != num3) { _startIndex = num3; UpdateInstances(); } } private void SetPosition(float position) { if (_constraint == RecyclerConstraint.FixedRowCount) { Vector2 anchoredPosition = base.rectTransform.anchoredPosition; anchoredPosition.x = position * -1f; base.rectTransform.anchoredPosition = anchoredPosition; } else if (_constraint == RecyclerConstraint.FixedColumnCount) { Vector2 anchoredPosition2 = base.rectTransform.anchoredPosition; anchoredPosition2.y = position; base.rectTransform.anchoredPosition = anchoredPosition2; } else { UnityEngine.Debug.LogWarningFormat("Unknown constraint '{0}'", _constraint); } } public void Init(int maxChildren, ObjectPool objectPool, Func initCallback) { _objectPool = objectPool; Init(maxChildren, initCallback); } public void Init(int maxChildren, Func initCallback) { MaxChildren = maxChildren; _initCallback = initCallback; _lastPosition = 0f; _startIndex = 0; if (_objectPool.AvailableInstances < _recyclerChildCount) { UnityEngine.Debug.LogWarningFormat("Insufficient elements available. Expected {0} elements, found {1}", _recyclerChildCount, _objectPool.AvailableInstances); } PopInstances(); UpdateInstances(); } public void Init(int maxChildren, List instances, Func initCallback) { MaxChildren = maxChildren; _initCallback = initCallback; _lastPosition = 0f; _startIndex = 0; if (instances.Count < _recyclerChildCount) { UnityEngine.Debug.LogErrorFormat("Insufficient elements available. Expected {0} elements, found {1}", _recyclerChildCount, instances.Count); } int count = instances.Count; for (int i = 0; i < count; i++) { _instances.Add(instances[i]); _indexMapping[i] = -1; } UpdateInstances(); } public void PushInstances() { if (_objectPool != null) { _objectPool.Push(_instances); } _instances.Clear(); _indexMapping.Clear(); } public void ScrollToElement(int index) { index = Mathf.Clamp(index, 0, MaxChildren - 1); RecyclerConstraint constraint = _constraint; float num = (constraint != RecyclerConstraint.FixedRowCount && constraint == RecyclerConstraint.FixedColumnCount) ? (_cellSize.y + _spacing.y) : (_cellSize.x + _spacing.x); SetPosition((float)index * num); } public override void CalculateLayoutInputHorizontal() { base.CalculateLayoutInputHorizontal(); int num = 0; int num2 = 0; if (_constraint == RecyclerConstraint.FixedColumnCount) { num = (num2 = _constraintCount); } else if (_constraint == RecyclerConstraint.FixedRowCount) { num = (num2 = Mathf.CeilToInt((float)_maxChildren / (float)_constraintCount - 0.001f)); } else { num = 1; num2 = Mathf.CeilToInt(Mathf.Sqrt(_maxChildren)); } float num3 = base.padding.horizontal; Vector2 cellSize = CellSize; float x = cellSize.x; Vector2 spacing = Spacing; float num4 = num3 + (x + spacing.x) * (float)num; Vector2 spacing2 = Spacing; float totalMin = Mathf.Max(0f, num4 - spacing2.x); float num5 = base.padding.horizontal; Vector2 cellSize2 = CellSize; float x2 = cellSize2.x; Vector2 spacing3 = Spacing; float num6 = num5 + (x2 + spacing3.x) * (float)num2; Vector2 spacing4 = Spacing; SetLayoutInputForAxis(totalMin, Mathf.Max(0f, num6 - spacing4.x), -1f, 0); } public override void CalculateLayoutInputVertical() { int num = 0; if (_constraint == RecyclerConstraint.FixedColumnCount) { num = Mathf.CeilToInt((float)_maxChildren / (float)_constraintCount - 0.001f); } else if (_constraint == RecyclerConstraint.FixedRowCount) { num = _constraintCount; } else { Vector2 size = base.rectTransform.rect.size; float x = size.x; float num2 = x - (float)base.padding.horizontal; Vector2 spacing = Spacing; float num3 = num2 + spacing.x + 0.001f; Vector2 cellSize = CellSize; float x2 = cellSize.x; Vector2 spacing2 = Spacing; int num4 = Mathf.Max(1, Mathf.FloorToInt(num3 / (x2 + spacing2.x))); num = Mathf.CeilToInt((float)_maxChildren / (float)num4); } float num5 = base.padding.vertical; Vector2 cellSize2 = CellSize; float y = cellSize2.y; Vector2 spacing3 = Spacing; float num6 = num5 + (y + spacing3.y) * (float)num; Vector2 spacing4 = Spacing; float num7 = Mathf.Max(0f, num6 - spacing4.y); SetLayoutInputForAxis(num7, num7, -1f, 1); } public override void SetLayoutHorizontal() { SetCellsAlongAxis(0); } public override void SetLayoutVertical() { SetCellsAlongAxis(1); } private void PopInstances() { for (int i = 0; i < _recyclerChildCount; i++) { GameObject item = _objectPool.Pop(base.transform); _instances.Add(item); _indexMapping[i] = -1; } } private void UpdateInstances() { if (_initCallback != null) { if (_instances.Count < _recyclerChildCount) { UnityEngine.Debug.LogWarningFormat("Insufficient elements available. Expected {0} elements, found {1}", _recyclerChildCount, _instances.Count); } int count = _instances.Count; for (int i = 0; i < count; i++) { _instances[i].SetActive(i < _recyclerChildCount); int num = _startIndex + i; if (_indexMapping[i] != num) { _indexMapping[i] = num; if (!_initCallback(_instances[i], _indexMapping[i])) { _instances[i].SetActive(value: false); } } } } SetCellsAlongAxis(1); } private void SetCellsAlongAxis(int axis) { base.rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, GetTotalPreferredSize(axis)); if (axis == 0) { for (int i = 0; i < base.rectChildren.Count; i++) { RectTransform rectTransform = base.rectChildren[i]; m_Tracker.Add(this, rectTransform, DrivenTransformProperties.AnchoredPositionX | DrivenTransformProperties.AnchoredPositionY | DrivenTransformProperties.AnchorMinX | DrivenTransformProperties.AnchorMinY | DrivenTransformProperties.AnchorMaxX | DrivenTransformProperties.AnchorMaxY | DrivenTransformProperties.SizeDeltaX | DrivenTransformProperties.SizeDeltaY); rectTransform.anchorMin = Vector2.up; rectTransform.anchorMax = Vector2.up; rectTransform.sizeDelta = CellSize; } return; } int num = 1; int num2 = 1; if (_constraint == RecyclerConstraint.FixedColumnCount) { num = _constraintCount; num2 = Mathf.CeilToInt((float)_maxChildren / (float)num - 0.001f); } else if (_constraint == RecyclerConstraint.FixedRowCount) { num2 = _constraintCount; num = Mathf.CeilToInt((float)_maxChildren / (float)num2 - 0.001f); } int num3 = (int)StartCorner % 2; int num4 = (int)StartCorner / 2; int num5; int num6; int num7; if (StartAxis == GridLayoutGroup.Axis.Horizontal) { num5 = num; num6 = Mathf.Clamp(num, 1, base.rectChildren.Count); num7 = Mathf.Clamp(num2, 1, Mathf.CeilToInt((float)base.rectChildren.Count / (float)num5)); } else { num5 = num2; num7 = Mathf.Clamp(num2, 1, base.rectChildren.Count); num6 = Mathf.Clamp(num, 1, Mathf.CeilToInt((float)base.rectChildren.Count / (float)num5)); } float num8 = num6; Vector2 cellSize = CellSize; float num9 = num8 * cellSize.x; float num10 = num6 - 1; Vector2 spacing = Spacing; float x = num9 + num10 * spacing.x; float num11 = num7; Vector2 cellSize2 = CellSize; float num12 = num11 * cellSize2.y; float num13 = num7 - 1; Vector2 spacing2 = Spacing; Vector2 vector = new Vector2(x, num12 + num13 * spacing2.y); Vector2 vector2 = new Vector2(GetStartOffset(0, vector.x), GetStartOffset(1, vector.y)); for (int j = 0; j < base.rectChildren.Count; j++) { int value; if (!_indexMapping.TryGetValue(j, out value)) { value = j; } int num14; int num15; if (StartAxis == GridLayoutGroup.Axis.Horizontal) { num14 = value % num5; num15 = value / num5; } else { num14 = value / num5; num15 = value % num5; } if (num3 == 1) { num14 = num6 - 1 - num14; } if (num4 == 1) { num15 = num7 - 1 - num15; } SetChildAlongAxis(base.rectChildren[j], 0, vector2.x + (CellSize[0] + Spacing[0]) * (float)num14, CellSize[0]); SetChildAlongAxis(base.rectChildren[j], 1, vector2.y + (CellSize[1] + Spacing[1]) * (float)num15, CellSize[1]); } } } }