| 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; | 
|         } | 
|     } | 
|   | 
| } |