| using System.Collections; | 
| using System.Collections.Generic; | 
| using UnityEngine; | 
| using UnityEngine.UI; | 
| using System; | 
| using Cysharp.Threading.Tasks; | 
|   | 
|     [ExecuteAlways] | 
|     public class AdaptiveLayout : MonoBehaviour | 
|     { | 
|         [SerializeField] HorizonOrVertical m_HorizonOrVerticle; | 
|         [SerializeField] CanvasGroup m_CanvasGroup; | 
|         [SerializeField] List<AdaptiveElement> m_AdapElements; | 
|         [SerializeField] bool m_AutoIncludeChild=false; | 
|         [SerializeField] float m_LeastHeight = 0f; | 
|         [SerializeField] float m_LeastWidth = 0f; | 
|         [SerializeField] float m_MaxHeight = 0f; | 
|         [SerializeField] float m_MaxWidth = 0f; | 
|         [NonSerialized] RectTransform m_Rect; | 
|         public RectTransform rectTransform | 
|         { | 
|             get | 
|             { | 
|                 if (m_Rect == null) | 
|                 { | 
|                     m_Rect = GetComponent<RectTransform>(); | 
|                 } | 
|                 return m_Rect; | 
|             } | 
|         } | 
|         public float Size | 
|         { | 
|             get | 
|             { | 
|                 return m_HorizonOrVerticle == HorizonOrVertical.Horizon ? rectTransform.sizeDelta.x : rectTransform.sizeDelta.y; | 
|             } | 
|         } | 
|   | 
|         public event Action adaptiveUpdateEvent; | 
|   | 
|         private void OnEnable() | 
|         { | 
|             if (m_AdapElements == null) | 
|             { | 
|                 enabled = false; | 
|                 return; | 
|             } | 
|             if (m_CanvasGroup != null) | 
|             { | 
|                 m_CanvasGroup.alpha = 0; | 
|                 m_CanvasGroup.interactable = true; | 
|                 Co_DelayShow(); | 
|             } | 
|         } | 
|   | 
|         private void TrackerRect(RectTransform _rect) | 
|         { | 
|             var _pivot = _rect.pivot; | 
|             var _anchorMax = _rect.anchorMax; | 
|             var _anchorMin = _rect.anchorMin; | 
|             if (m_HorizonOrVerticle == HorizonOrVertical.Horizon) | 
|             { | 
|                 _pivot.x = 0; _pivot.y = 0.5f; | 
|                 _anchorMax.x = 0; _anchorMax.y = 0.5f; | 
|                 _anchorMin.x = 0; _anchorMin.y = 0.5f; | 
|             } | 
|             else | 
|             { | 
|                 _pivot.x = 0.5f; _pivot.y = 1f; | 
|                 _anchorMax.x = 0.5f; _anchorMax.y = 1; | 
|                 _anchorMin.x = 0.5f; _anchorMin.y = 1; | 
|             } | 
|             if (_rect.pivot != _pivot || _rect.anchorMax != _anchorMax || _rect.anchorMin != _anchorMin) | 
|             { | 
|                 _rect.pivot = _pivot; | 
|                 _rect.anchorMax = _anchorMax; | 
|                 _rect.anchorMin = _anchorMin; | 
|             } | 
|         } | 
|   | 
|         private void CalculateLayout() | 
|         { | 
|             var _offset = 0.0f; | 
|             var _horizon = m_HorizonOrVerticle == HorizonOrVertical.Horizon; | 
|             for (int i = 0; i < m_AdapElements.Count; i++) | 
|             { | 
|                 if (m_AdapElements[i].rect == null || !m_AdapElements[i].rect.gameObject.activeInHierarchy) | 
|                 { | 
|                     continue; | 
|                 } | 
|                 _offset += _horizon ? m_AdapElements[i].padding.left : m_AdapElements[i].padding.top; | 
|                 var _pos = m_AdapElements[i].rect.localPosition; | 
|                 if (_horizon) | 
|                 { | 
|                     _pos.x = _offset; | 
|                 } | 
|                 else | 
|                 { | 
|                     _pos.y = -_offset; | 
|                 } | 
|                 if (m_AdapElements[i].rect.localPosition != _pos) | 
|                 { | 
|                     m_AdapElements[i].rect.localPosition = _pos; | 
|                 } | 
|                 _offset += _horizon ? m_AdapElements[i].rect.sizeDelta.x : m_AdapElements[i].rect.sizeDelta.y; | 
|                 _offset += _horizon ? m_AdapElements[i].padding.right : m_AdapElements[i].padding.bottom; | 
|             } | 
|             var _sizeDelta = rectTransform.sizeDelta; | 
|             if (_horizon) | 
|             { | 
|                 if (m_LeastWidth > 1f) | 
|                 { | 
|                     _offset = Mathf.Max(_offset, m_LeastWidth); | 
|                 } | 
|                 if (m_MaxWidth > 1f) | 
|                 { | 
|                     _offset = Mathf.Min(_offset, m_MaxWidth); | 
|                 } | 
|                 _sizeDelta.x = _offset; | 
|             } | 
|             else | 
|             { | 
|                 if (m_LeastHeight > 1f) | 
|                 { | 
|                     _offset = Mathf.Max(_offset, m_LeastHeight); | 
|                 } | 
|                 if (m_MaxHeight > 1f) | 
|                 { | 
|                     _offset = Mathf.Min(_offset, m_MaxHeight); | 
|                 } | 
|                 _sizeDelta.y = _offset; | 
|             } | 
|             if (rectTransform.sizeDelta != _sizeDelta) | 
|             { | 
|                 rectTransform.sizeDelta = _sizeDelta; | 
|                 if (adaptiveUpdateEvent != null) | 
|                 { | 
|                     adaptiveUpdateEvent(); | 
|                 } | 
|             } | 
|         } | 
|   | 
|         private void LateUpdate() | 
|         { | 
|             if (m_AdapElements == null) | 
|             { | 
|                 return; | 
|             } | 
|             TrackerRect(rectTransform); | 
|             for (int i = 0; i < m_AdapElements.Count; i++) | 
|             { | 
|                 if (m_AdapElements[i].rect == null) | 
|                 { | 
|                     continue; | 
|                 } | 
|                 TrackerRect(m_AdapElements[i].rect); | 
|             } | 
|             CalculateLayout(); | 
|         } | 
|   | 
|         private void OnTransformChildrenChanged() | 
|         { | 
|             if (m_AutoIncludeChild) | 
|             { | 
|                 AutoIncludeChild(); | 
|             } | 
|         } | 
|   | 
|         private void AutoIncludeChild() | 
|         { | 
|             var _index = 0; | 
|             foreach (Transform _child in transform) | 
|             { | 
|                 if (m_AdapElements == null) | 
|                 { | 
|                     m_AdapElements = new List<AdaptiveElement>(); | 
|                 } | 
|                 var _rect = m_AdapElements.Find((x) => | 
|                  { | 
|                      return x.rect == _child; | 
|                  }); | 
|                 var _rectOffset= _child.GetComponent<AdaptiveRectOffset>(); | 
|                 if (_rect == null) | 
|                 { | 
|                     m_AdapElements.Insert(_index, new AdaptiveElement(_child as RectTransform, _rectOffset)); | 
|                 } | 
|                 _index++; | 
|             } | 
|             if (m_AdapElements != null) | 
|             { | 
|                 m_AdapElements.RemoveAll((x) => | 
|                 { | 
|                     return x.rect == null; | 
|                 }); | 
|             } | 
|             LateUpdate(); | 
|         } | 
|   | 
|         async UniTask Co_DelayShow() | 
|         { | 
|             await UniTask.Delay(100); | 
|             if (m_CanvasGroup != null) | 
|             { | 
|                 m_CanvasGroup.alpha = 1; | 
|             } | 
|         } | 
|   | 
|         public enum HorizonOrVertical | 
|         { | 
|             Horizon, | 
|             Vertical, | 
|         } | 
|         [Serializable] | 
|         public class AdaptiveElement | 
|         { | 
|             [SerializeField] RectTransform m_Rect; | 
|             public RectTransform rect | 
|             { | 
|                 get | 
|                 { | 
|                     return m_Rect; | 
|                 } | 
|             } | 
|             [SerializeField] RectOffset m_Padding; | 
|             public RectOffset padding | 
|             { | 
|                 get | 
|                 { | 
|                     return m_Padding; | 
|                 } | 
|             } | 
|   | 
|             public AdaptiveElement(RectTransform _rect, AdaptiveRectOffset _offset) | 
|             { | 
|                 m_Rect = _rect; | 
|                 m_Padding = _offset == null ? new RectOffset() : _offset.rectOffset; | 
|             } | 
|         } | 
|   | 
|     } |