您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

484 行
16 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. namespace CIG
  6. {
  7. [AddComponentMenu("Layout/Recycler Grid Layout Group", 153)]
  8. public class RecyclerGridLayoutGroup : LayoutGroup
  9. {
  10. public enum RecyclerConstraint
  11. {
  12. FixedColumnCount,
  13. FixedRowCount
  14. }
  15. public enum Corner
  16. {
  17. UpperLeft
  18. }
  19. [SerializeField]
  20. protected Corner _startCorner;
  21. [SerializeField]
  22. protected GridLayoutGroup.Axis _startAxis;
  23. [SerializeField]
  24. protected Vector2 _cellSize = new Vector2(100f, 100f);
  25. [SerializeField]
  26. protected Vector2 _spacing = Vector2.zero;
  27. [SerializeField]
  28. protected RecyclerConstraint _constraint;
  29. [SerializeField]
  30. protected int _constraintCount = 2;
  31. [SerializeField]
  32. protected int _recyclerChildCount = 2;
  33. [SerializeField]
  34. private ObjectPool _objectPool;
  35. private DrivenRectTransformTracker _tracker;
  36. private int _maxChildren;
  37. private Func<GameObject, int, bool> _initCallback;
  38. private List<GameObject> _instances = new List<GameObject>();
  39. private Dictionary<int, int> _indexMapping = new Dictionary<int, int>();
  40. private float _lastPosition;
  41. private int _startIndex;
  42. public Corner StartCorner
  43. {
  44. get
  45. {
  46. return _startCorner;
  47. }
  48. set
  49. {
  50. SetProperty(ref _startCorner, value);
  51. }
  52. }
  53. public GridLayoutGroup.Axis StartAxis => _startAxis;
  54. public Vector2 CellSize
  55. {
  56. get
  57. {
  58. return _cellSize;
  59. }
  60. set
  61. {
  62. SetProperty(ref _cellSize, value);
  63. }
  64. }
  65. public Vector2 Spacing
  66. {
  67. get
  68. {
  69. return _spacing;
  70. }
  71. set
  72. {
  73. SetProperty(ref _spacing, value);
  74. }
  75. }
  76. public RecyclerConstraint Constraint => _constraint;
  77. public int ConstraintCount
  78. {
  79. get
  80. {
  81. return _constraintCount;
  82. }
  83. set
  84. {
  85. SetProperty(ref _constraintCount, Mathf.Max(1, value));
  86. }
  87. }
  88. public int RecyclerChildCount
  89. {
  90. get
  91. {
  92. return _recyclerChildCount;
  93. }
  94. set
  95. {
  96. SetProperty(ref _recyclerChildCount, Mathf.Max(1, value));
  97. }
  98. }
  99. public int MaxChildren
  100. {
  101. get
  102. {
  103. return _maxChildren;
  104. }
  105. set
  106. {
  107. SetProperty(ref _maxChildren, Mathf.Max(1, value));
  108. }
  109. }
  110. protected override void OnEnable()
  111. {
  112. base.OnEnable();
  113. _tracker.Add(this, base.rectTransform, DrivenTransformProperties.SizeDelta);
  114. }
  115. protected override void OnDisable()
  116. {
  117. base.OnDisable();
  118. _tracker.Clear();
  119. }
  120. private void Update()
  121. {
  122. if (MaxChildren == RecyclerChildCount)
  123. {
  124. return;
  125. }
  126. float num;
  127. if (_constraint == RecyclerConstraint.FixedRowCount)
  128. {
  129. Vector2 anchoredPosition = base.rectTransform.anchoredPosition;
  130. num = anchoredPosition.x * -1f;
  131. }
  132. else
  133. {
  134. if (_constraint != 0)
  135. {
  136. UnityEngine.Debug.LogWarningFormat("Unknown constraint '{0}'", _constraint);
  137. return;
  138. }
  139. Vector2 anchoredPosition2 = base.rectTransform.anchoredPosition;
  140. num = anchoredPosition2.y;
  141. }
  142. if (Mathf.Approximately(num, _lastPosition))
  143. {
  144. return;
  145. }
  146. _lastPosition = num;
  147. float num2;
  148. if (_constraint == RecyclerConstraint.FixedRowCount)
  149. {
  150. Vector2 cellSize = CellSize;
  151. float x = cellSize.x;
  152. Vector2 spacing = Spacing;
  153. num2 = x + spacing.x;
  154. }
  155. else
  156. {
  157. if (_constraint != 0)
  158. {
  159. UnityEngine.Debug.LogWarningFormat("Unknown constraint '{0}'", _constraint);
  160. return;
  161. }
  162. Vector2 cellSize2 = CellSize;
  163. float y = cellSize2.y;
  164. Vector2 spacing2 = Spacing;
  165. num2 = y + spacing2.y;
  166. }
  167. int num3 = Mathf.Clamp(Mathf.FloorToInt((_lastPosition - num2) / num2 * (float)_constraintCount), 0, Mathf.Max(0, MaxChildren - RecyclerChildCount));
  168. if (_startIndex != num3)
  169. {
  170. _startIndex = num3;
  171. UpdateInstances();
  172. }
  173. }
  174. private void SetPosition(float position)
  175. {
  176. if (_constraint == RecyclerConstraint.FixedRowCount)
  177. {
  178. Vector2 anchoredPosition = base.rectTransform.anchoredPosition;
  179. anchoredPosition.x = position * -1f;
  180. base.rectTransform.anchoredPosition = anchoredPosition;
  181. }
  182. else if (_constraint == RecyclerConstraint.FixedColumnCount)
  183. {
  184. Vector2 anchoredPosition2 = base.rectTransform.anchoredPosition;
  185. anchoredPosition2.y = position;
  186. base.rectTransform.anchoredPosition = anchoredPosition2;
  187. }
  188. else
  189. {
  190. UnityEngine.Debug.LogWarningFormat("Unknown constraint '{0}'", _constraint);
  191. }
  192. }
  193. public void Init(int maxChildren, ObjectPool objectPool, Func<GameObject, int, bool> initCallback)
  194. {
  195. _objectPool = objectPool;
  196. Init(maxChildren, initCallback);
  197. }
  198. public void Init(int maxChildren, Func<GameObject, int, bool> initCallback)
  199. {
  200. MaxChildren = maxChildren;
  201. _initCallback = initCallback;
  202. _lastPosition = 0f;
  203. _startIndex = 0;
  204. if (_objectPool.AvailableInstances < _recyclerChildCount)
  205. {
  206. UnityEngine.Debug.LogWarningFormat("Insufficient elements available. Expected {0} elements, found {1}", _recyclerChildCount, _objectPool.AvailableInstances);
  207. }
  208. PopInstances();
  209. UpdateInstances();
  210. }
  211. public void Init(int maxChildren, List<GameObject> instances, Func<GameObject, int, bool> initCallback)
  212. {
  213. MaxChildren = maxChildren;
  214. _initCallback = initCallback;
  215. _lastPosition = 0f;
  216. _startIndex = 0;
  217. if (instances.Count < _recyclerChildCount)
  218. {
  219. UnityEngine.Debug.LogErrorFormat("Insufficient elements available. Expected {0} elements, found {1}", _recyclerChildCount, instances.Count);
  220. }
  221. int count = instances.Count;
  222. for (int i = 0; i < count; i++)
  223. {
  224. _instances.Add(instances[i]);
  225. _indexMapping[i] = -1;
  226. }
  227. UpdateInstances();
  228. }
  229. public void PushInstances()
  230. {
  231. if (_objectPool != null)
  232. {
  233. _objectPool.Push(_instances);
  234. }
  235. _instances.Clear();
  236. _indexMapping.Clear();
  237. }
  238. public void ScrollToElement(int index)
  239. {
  240. index = Mathf.Clamp(index, 0, MaxChildren - 1);
  241. RecyclerConstraint constraint = _constraint;
  242. float num = (constraint != RecyclerConstraint.FixedRowCount && constraint == RecyclerConstraint.FixedColumnCount) ? (_cellSize.y + _spacing.y) : (_cellSize.x + _spacing.x);
  243. SetPosition((float)index * num);
  244. }
  245. public override void CalculateLayoutInputHorizontal()
  246. {
  247. base.CalculateLayoutInputHorizontal();
  248. int num = 0;
  249. int num2 = 0;
  250. if (_constraint == RecyclerConstraint.FixedColumnCount)
  251. {
  252. num = (num2 = _constraintCount);
  253. }
  254. else if (_constraint == RecyclerConstraint.FixedRowCount)
  255. {
  256. num = (num2 = Mathf.CeilToInt((float)_maxChildren / (float)_constraintCount - 0.001f));
  257. }
  258. else
  259. {
  260. num = 1;
  261. num2 = Mathf.CeilToInt(Mathf.Sqrt(_maxChildren));
  262. }
  263. float num3 = base.padding.horizontal;
  264. Vector2 cellSize = CellSize;
  265. float x = cellSize.x;
  266. Vector2 spacing = Spacing;
  267. float num4 = num3 + (x + spacing.x) * (float)num;
  268. Vector2 spacing2 = Spacing;
  269. float totalMin = Mathf.Max(0f, num4 - spacing2.x);
  270. float num5 = base.padding.horizontal;
  271. Vector2 cellSize2 = CellSize;
  272. float x2 = cellSize2.x;
  273. Vector2 spacing3 = Spacing;
  274. float num6 = num5 + (x2 + spacing3.x) * (float)num2;
  275. Vector2 spacing4 = Spacing;
  276. SetLayoutInputForAxis(totalMin, Mathf.Max(0f, num6 - spacing4.x), -1f, 0);
  277. }
  278. public override void CalculateLayoutInputVertical()
  279. {
  280. int num = 0;
  281. if (_constraint == RecyclerConstraint.FixedColumnCount)
  282. {
  283. num = Mathf.CeilToInt((float)_maxChildren / (float)_constraintCount - 0.001f);
  284. }
  285. else if (_constraint == RecyclerConstraint.FixedRowCount)
  286. {
  287. num = _constraintCount;
  288. }
  289. else
  290. {
  291. Vector2 size = base.rectTransform.rect.size;
  292. float x = size.x;
  293. float num2 = x - (float)base.padding.horizontal;
  294. Vector2 spacing = Spacing;
  295. float num3 = num2 + spacing.x + 0.001f;
  296. Vector2 cellSize = CellSize;
  297. float x2 = cellSize.x;
  298. Vector2 spacing2 = Spacing;
  299. int num4 = Mathf.Max(1, Mathf.FloorToInt(num3 / (x2 + spacing2.x)));
  300. num = Mathf.CeilToInt((float)_maxChildren / (float)num4);
  301. }
  302. float num5 = base.padding.vertical;
  303. Vector2 cellSize2 = CellSize;
  304. float y = cellSize2.y;
  305. Vector2 spacing3 = Spacing;
  306. float num6 = num5 + (y + spacing3.y) * (float)num;
  307. Vector2 spacing4 = Spacing;
  308. float num7 = Mathf.Max(0f, num6 - spacing4.y);
  309. SetLayoutInputForAxis(num7, num7, -1f, 1);
  310. }
  311. public override void SetLayoutHorizontal()
  312. {
  313. SetCellsAlongAxis(0);
  314. }
  315. public override void SetLayoutVertical()
  316. {
  317. SetCellsAlongAxis(1);
  318. }
  319. private void PopInstances()
  320. {
  321. for (int i = 0; i < _recyclerChildCount; i++)
  322. {
  323. GameObject item = _objectPool.Pop(base.transform);
  324. _instances.Add(item);
  325. _indexMapping[i] = -1;
  326. }
  327. }
  328. private void UpdateInstances()
  329. {
  330. if (_initCallback != null)
  331. {
  332. if (_instances.Count < _recyclerChildCount)
  333. {
  334. UnityEngine.Debug.LogWarningFormat("Insufficient elements available. Expected {0} elements, found {1}", _recyclerChildCount, _instances.Count);
  335. }
  336. int count = _instances.Count;
  337. for (int i = 0; i < count; i++)
  338. {
  339. _instances[i].SetActive(i < _recyclerChildCount);
  340. int num = _startIndex + i;
  341. if (_indexMapping[i] != num)
  342. {
  343. _indexMapping[i] = num;
  344. if (!_initCallback(_instances[i], _indexMapping[i]))
  345. {
  346. _instances[i].SetActive(value: false);
  347. }
  348. }
  349. }
  350. }
  351. SetCellsAlongAxis(1);
  352. }
  353. private void SetCellsAlongAxis(int axis)
  354. {
  355. base.rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, GetTotalPreferredSize(axis));
  356. if (axis == 0)
  357. {
  358. for (int i = 0; i < base.rectChildren.Count; i++)
  359. {
  360. RectTransform rectTransform = base.rectChildren[i];
  361. m_Tracker.Add(this, rectTransform, DrivenTransformProperties.AnchoredPositionX | DrivenTransformProperties.AnchoredPositionY | DrivenTransformProperties.AnchorMinX | DrivenTransformProperties.AnchorMinY | DrivenTransformProperties.AnchorMaxX | DrivenTransformProperties.AnchorMaxY | DrivenTransformProperties.SizeDeltaX | DrivenTransformProperties.SizeDeltaY);
  362. rectTransform.anchorMin = Vector2.up;
  363. rectTransform.anchorMax = Vector2.up;
  364. rectTransform.sizeDelta = CellSize;
  365. }
  366. return;
  367. }
  368. int num = 1;
  369. int num2 = 1;
  370. if (_constraint == RecyclerConstraint.FixedColumnCount)
  371. {
  372. num = _constraintCount;
  373. num2 = Mathf.CeilToInt((float)_maxChildren / (float)num - 0.001f);
  374. }
  375. else if (_constraint == RecyclerConstraint.FixedRowCount)
  376. {
  377. num2 = _constraintCount;
  378. num = Mathf.CeilToInt((float)_maxChildren / (float)num2 - 0.001f);
  379. }
  380. int num3 = (int)StartCorner % 2;
  381. int num4 = (int)StartCorner / 2;
  382. int num5;
  383. int num6;
  384. int num7;
  385. if (StartAxis == GridLayoutGroup.Axis.Horizontal)
  386. {
  387. num5 = num;
  388. num6 = Mathf.Clamp(num, 1, base.rectChildren.Count);
  389. num7 = Mathf.Clamp(num2, 1, Mathf.CeilToInt((float)base.rectChildren.Count / (float)num5));
  390. }
  391. else
  392. {
  393. num5 = num2;
  394. num7 = Mathf.Clamp(num2, 1, base.rectChildren.Count);
  395. num6 = Mathf.Clamp(num, 1, Mathf.CeilToInt((float)base.rectChildren.Count / (float)num5));
  396. }
  397. float num8 = num6;
  398. Vector2 cellSize = CellSize;
  399. float num9 = num8 * cellSize.x;
  400. float num10 = num6 - 1;
  401. Vector2 spacing = Spacing;
  402. float x = num9 + num10 * spacing.x;
  403. float num11 = num7;
  404. Vector2 cellSize2 = CellSize;
  405. float num12 = num11 * cellSize2.y;
  406. float num13 = num7 - 1;
  407. Vector2 spacing2 = Spacing;
  408. Vector2 vector = new Vector2(x, num12 + num13 * spacing2.y);
  409. Vector2 vector2 = new Vector2(GetStartOffset(0, vector.x), GetStartOffset(1, vector.y));
  410. for (int j = 0; j < base.rectChildren.Count; j++)
  411. {
  412. int value;
  413. if (!_indexMapping.TryGetValue(j, out value))
  414. {
  415. value = j;
  416. }
  417. int num14;
  418. int num15;
  419. if (StartAxis == GridLayoutGroup.Axis.Horizontal)
  420. {
  421. num14 = value % num5;
  422. num15 = value / num5;
  423. }
  424. else
  425. {
  426. num14 = value / num5;
  427. num15 = value % num5;
  428. }
  429. if (num3 == 1)
  430. {
  431. num14 = num6 - 1 - num14;
  432. }
  433. if (num4 == 1)
  434. {
  435. num15 = num7 - 1 - num15;
  436. }
  437. SetChildAlongAxis(base.rectChildren[j], 0, vector2.x + (CellSize[0] + Spacing[0]) * (float)num14, CellSize[0]);
  438. SetChildAlongAxis(base.rectChildren[j], 1, vector2.y + (CellSize[1] + Spacing[1]) * (float)num15, CellSize[1]);
  439. }
  440. }
  441. }
  442. }