SyncLayoutGroupLimit.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. using System;
  2. using UnityEngine;
  3. using UnityEngine.EventSystems;
  4. using UnityEngine.UI;
  5. using FitMode = UnityEngine.UI.ContentSizeFitter.FitMode;
  6. [AddComponentMenu("Layout/Sync Layout Group Limit", 149)]
  7. [RequireComponent(typeof(RectTransform))]
  8. [ExecuteInEditMode]
  9. public class SyncLayoutGroupLimit : LayoutElement, ILayoutSelfController
  10. {
  11. [SerializeField] protected RectTransform m_SyncTargetRect;
  12. [SerializeField] protected FitMode m_HorizontalFit = FitMode.Unconstrained;
  13. [SerializeField] protected FitMode m_VerticalFit = FitMode.Unconstrained;
  14. [SerializeField]
  15. private float m_MaxWidth = -1f;
  16. [SerializeField]
  17. private float m_MaxHeight = -1f;
  18. [System.NonSerialized] private RectTransform m_Rect;
  19. private DrivenRectTransformTracker m_Tracker;
  20. private Vector2 m_TotalPreferredSize = Vector2.zero;
  21. public RectTransform SyncTarget
  22. {
  23. get { return m_SyncTargetRect; }
  24. set
  25. {
  26. if (m_SyncTargetRect == value) return;
  27. m_SyncTargetRect = value;
  28. SetDirty();
  29. }
  30. }
  31. /// <summary>
  32. /// The fit mode to use to determine the width.
  33. /// </summary>
  34. public FitMode horizontalFit { get { return m_HorizontalFit; } set { if (SetPropertyUtility.SetStruct(ref m_HorizontalFit, value)) SetDirty(); } }
  35. /// <summary>
  36. /// The fit mode to use to determine the height.
  37. /// </summary>
  38. public FitMode verticalFit { get { return m_VerticalFit; } set { if (SetPropertyUtility.SetStruct(ref m_VerticalFit, value)) SetDirty(); } }
  39. public float maxWidth { get { return m_MaxWidth; } set { if (SetPropertyUtility.SetStruct(ref m_MaxWidth, value)) SetDirty(); } }
  40. public float maxHeight { get { return m_MaxHeight; } set { if (SetPropertyUtility.SetStruct(ref m_MaxHeight, value)) SetDirty(); } }
  41. public override float preferredWidth
  42. {
  43. get { return m_TotalPreferredSize[0]; }
  44. }
  45. public override float preferredHeight
  46. {
  47. get { return m_TotalPreferredSize[1]; }
  48. }
  49. private RectTransform rectTransform
  50. {
  51. get
  52. {
  53. if ((UnityEngine.Object)m_Rect == (UnityEngine.Object)null)
  54. {
  55. m_Rect = base.GetComponent<RectTransform>();
  56. }
  57. return m_Rect;
  58. }
  59. }
  60. protected override void OnEnable()
  61. {
  62. base.OnEnable();
  63. SetDirty();
  64. }
  65. protected override void OnDisable()
  66. {
  67. m_Tracker.Clear();
  68. LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
  69. base.OnDisable();
  70. }
  71. protected override void OnRectTransformDimensionsChange()
  72. {
  73. SetDirty();
  74. }
  75. protected void CalcAlongAxis(int axis)
  76. {
  77. FitMode fitting = (axis == 0 ? horizontalFit : verticalFit);
  78. if (fitting == FitMode.Unconstrained)
  79. {
  80. m_TotalPreferredSize[axis] = -1;
  81. return;
  82. }
  83. float max = (axis == 0 ? maxWidth : maxHeight);
  84. // Set size to min or preferred size
  85. if (fitting == FitMode.MinSize)
  86. {
  87. float minSize;
  88. if (max > -1)
  89. minSize = Mathf.Min(max, LayoutUtility.GetMinSize(m_SyncTargetRect, axis));
  90. else
  91. minSize = LayoutUtility.GetMinSize(m_SyncTargetRect, axis);
  92. m_TotalPreferredSize[axis] = minSize;
  93. }
  94. else
  95. {
  96. float maxSize;
  97. if (max > -1)
  98. maxSize = Mathf.Min(max, LayoutUtility.GetPreferredSize(m_SyncTargetRect, axis));
  99. else
  100. maxSize = LayoutUtility.GetPreferredSize(m_SyncTargetRect, axis);
  101. m_TotalPreferredSize[axis] = maxSize;
  102. }
  103. }
  104. private void HandleSelfFittingAlongAxis(int axis)
  105. {
  106. FitMode fitting = (axis == 0 ? horizontalFit : verticalFit);
  107. if (fitting == FitMode.Unconstrained)
  108. {
  109. // Keep a reference to the tracked transform, but don't control its properties:
  110. m_Tracker.Add(this, rectTransform, DrivenTransformProperties.None);
  111. return;
  112. }
  113. m_Tracker.Add(this, rectTransform, (axis == 0 ? DrivenTransformProperties.SizeDeltaX : DrivenTransformProperties.SizeDeltaY));
  114. rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, m_TotalPreferredSize[axis]);
  115. }
  116. public override void CalculateLayoutInputHorizontal()
  117. {
  118. CalcAlongAxis(0);
  119. }
  120. public override void CalculateLayoutInputVertical()
  121. {
  122. CalcAlongAxis(1);
  123. }
  124. public virtual void SetLayoutHorizontal()
  125. {
  126. m_Tracker.Clear();
  127. HandleSelfFittingAlongAxis(0);
  128. }
  129. public virtual void SetLayoutVertical()
  130. {
  131. HandleSelfFittingAlongAxis(1);
  132. }
  133. }