using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace UIWidgets { [RequireComponent(typeof(LayoutGroup))] public class ResizableHeader : MonoBehaviour, IDropSupport { [SerializeField] public ListViewBase List; [SerializeField] public bool AllowResize = true; [SerializeField] public bool AllowReorder = true; [NonSerialized] [HideInInspector] public bool ProcessCellReorder; [SerializeField] public bool OnDragUpdate = true; [SerializeField] public float ActiveRegion = 5f; [SerializeField] public Camera CurrentCamera; [SerializeField] public Texture2D CursorTexture; [SerializeField] public Vector2 CursorHotSpot = new Vector2(16f, 16f); [SerializeField] public Texture2D AllowDropCursor; [SerializeField] public Vector2 AllowDropCursorHotSpot = new Vector2(4f, 2f); [SerializeField] public Texture2D DeniedDropCursor; [SerializeField] public Vector2 DeniedDropCursorHotSpot = new Vector2(4f, 2f); [SerializeField] public Texture2D DefaultCursorTexture; [SerializeField] public Vector2 DefaultCursorHotSpot; private RectTransform rectTransform; private Canvas canvas; private RectTransform canvasRect; private List childrenLayouts = new List(); private List children = new List(); private List positions; private LayoutElement leftTarget; private LayoutElement rightTarget; private bool processDrag; private List widths; private LayoutGroup layout; private bool inActiveRegion; private float widthLimit; private List raycastResults = new List(); public RectTransform RectTransform { get { if (rectTransform == null) { rectTransform = base.transform as RectTransform; } return rectTransform; } } public bool InActiveRegion { get { return inActiveRegion; } } private void Start() { layout = GetComponent(); if (layout != null) { Utilites.UpdateLayout(layout); } Init(); } public void OnInitializePotentialDrag(PointerEventData eventData) { } public void Init() { canvasRect = Utilites.FindCanvas(base.transform) as RectTransform; canvas = canvasRect.GetComponent(); children.Clear(); childrenLayouts.Clear(); int num = 0; foreach (Transform item2 in base.transform) { LayoutElement item = item2.GetComponent() ?? item2.gameObject.AddComponent(); children.Add(item2 as RectTransform); childrenLayouts.Add(item); ResizableHeaderDragCell resizableHeaderDragCell = item2.gameObject.AddComponent(); resizableHeaderDragCell.Position = num; resizableHeaderDragCell.ResizableHeader = this; resizableHeaderDragCell.AllowDropCursor = AllowDropCursor; resizableHeaderDragCell.AllowDropCursorHotSpot = AllowDropCursorHotSpot; resizableHeaderDragCell.DeniedDropCursor = DeniedDropCursor; resizableHeaderDragCell.DeniedDropCursorHotSpot = DeniedDropCursorHotSpot; ResizableHeaderCell resizableHeaderCell = item2.gameObject.AddComponent(); resizableHeaderCell.OnInitializePotentialDragEvent.AddListener(OnInitializePotentialDrag); resizableHeaderCell.OnBeginDragEvent.AddListener(OnBeginDrag); resizableHeaderCell.OnDragEvent.AddListener(OnDrag); resizableHeaderCell.OnEndDragEvent.AddListener(OnEndDrag); num++; } positions = Enumerable.Range(0, num).ToList(); CalculateWidths(); } private void LateUpdate() { if (AllowResize && !processDrag && !ProcessCellReorder && !(CursorTexture == null) && Input.mousePresent) { inActiveRegion = CheckInActiveRegion(Input.mousePosition, CurrentCamera); if (inActiveRegion) { Cursor.SetCursor(CursorTexture, CursorHotSpot, Utilites.GetCursorMode()); } else { Cursor.SetCursor(DefaultCursorTexture, DefaultCursorHotSpot, Utilites.GetCursorMode()); } } } private bool CheckInActiveRegion(Vector2 position, Camera currentCamera) { bool flag = false; Vector2 localPoint; if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(RectTransform, position, currentCamera, out localPoint)) { return false; } Rect rect = RectTransform.rect; if (!rect.Contains(localPoint)) { return false; } localPoint += new Vector2(rect.width * RectTransform.pivot.x, 0f); int num = 0; foreach (RectTransform child in children) { if (num != 0) { flag = CheckLeft(child, localPoint); if (flag) { break; } } if (num != children.Count - 1) { flag = CheckRight(child, localPoint); if (flag) { break; } } num++; } return flag; } public virtual void OnBeginDrag(PointerEventData eventData) { if (!AllowResize || ProcessCellReorder) { return; } processDrag = false; Vector2 localPoint; if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(RectTransform, eventData.pressPosition, eventData.pressEventCamera, out localPoint)) { return; } localPoint += new Vector2(RectTransform.rect.width * RectTransform.pivot.x, 0f); int num = 0; foreach (RectTransform child in children) { if (num != 0) { processDrag = CheckLeft(child, localPoint); if (processDrag) { leftTarget = childrenLayouts[num - 1]; rightTarget = childrenLayouts[num]; widthLimit = children[num - 1].rect.width + children[num].rect.width; break; } } if (num != children.Count - 1) { processDrag = CheckRight(child, localPoint); if (processDrag) { leftTarget = childrenLayouts[num]; rightTarget = childrenLayouts[num + 1]; widthLimit = children[num].rect.width + children[num + 1].rect.width; break; } } num++; } } private bool CheckLeft(RectTransform childRectTransform, Vector2 point) { Rect rect = childRectTransform.rect; rect.position += new Vector2(childRectTransform.anchoredPosition.x, 0f); rect.width = ActiveRegion; return rect.Contains(point); } private bool CheckRight(RectTransform childRectTransform, Vector2 point) { Rect rect = childRectTransform.rect; rect.position += new Vector2(childRectTransform.anchoredPosition.x, 0f); rect.position = new Vector2(rect.position.x + rect.width - ActiveRegion - 1f, rect.position.y); rect.width = ActiveRegion + 1f; return rect.Contains(point); } public void OnEndDrag(PointerEventData eventData) { if (processDrag) { Cursor.SetCursor(DefaultCursorTexture, DefaultCursorHotSpot, Utilites.GetCursorMode()); CalculateWidths(); ResetChildren(); if (!OnDragUpdate) { Resize(); } processDrag = false; } } public void OnDrag(PointerEventData eventData) { if (processDrag) { if (canvas == null) { throw new MissingComponentException(base.gameObject.name + " not in Canvas hierarchy."); } Cursor.SetCursor(CursorTexture, CursorHotSpot, Utilites.GetCursorMode()); Vector2 localPoint; RectTransformUtility.ScreenPointToLocalPointInRectangle(RectTransform, eventData.position, CurrentCamera, out localPoint); Vector2 localPoint2; RectTransformUtility.ScreenPointToLocalPointInRectangle(RectTransform, eventData.position - eventData.delta, CurrentCamera, out localPoint2); Vector2 vector = localPoint - localPoint2; if (vector.x > 0f) { leftTarget.preferredWidth = Mathf.Min(leftTarget.preferredWidth + vector.x, widthLimit - rightTarget.minWidth); rightTarget.preferredWidth = widthLimit - leftTarget.preferredWidth; } else { rightTarget.preferredWidth = Mathf.Min(rightTarget.preferredWidth - vector.x, widthLimit - leftTarget.minWidth); leftTarget.preferredWidth = widthLimit - rightTarget.preferredWidth; } if (layout != null) { Utilites.UpdateLayout(layout); } if (OnDragUpdate) { CalculateWidths(); Resize(); } } } private float GetRectWidth(RectTransform rect) { return rect.rect.width; } private void CalculateWidths() { widths = children.Select(GetRectWidth).ToList(); } private void ResetChildren() { childrenLayouts.ForEach(ResetChildrenWidth); } private void ResetChildrenWidth(LayoutElement element, int index) { element.preferredWidth = widths[index]; } public void Resize() { if (!(List == null) && widths.Count >= 2) { List.Start(); List.ForEachComponent(ResizeComponent); } } private void Reorder() { if (!(List == null) && widths.Count >= 2) { List.Start(); List.ForEachComponent(ReorderComponent); } } private void ResizeGameObject(GameObject go, int i) { LayoutElement component = go.GetComponent(); int index = positions.IndexOf(i); if ((bool)component) { component.preferredWidth = widths[index]; } else { (go.transform as RectTransform).SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, widths[index]); } } private void ResizeComponent(ListViewItem component) { IResizableItem resizableItem = component as IResizableItem; if (resizableItem != null) { resizableItem.ObjectsToResize.ForEach(ResizeGameObject); } } private void ReorderComponent(ListViewItem component) { IResizableItem resizableItem = component as IResizableItem; if (resizableItem == null) { return; } GameObject[] objectsToResize = resizableItem.ObjectsToResize; int num = 0; foreach (int position in positions) { objectsToResize[position].transform.SetSiblingIndex(num); num++; } } public void Reorder(int oldColumnPosition, int newColumnPosition) { int num = positions.IndexOf(oldColumnPosition); int num2 = positions.IndexOf(newColumnPosition); children[num].SetSiblingIndex(num2); ChangePosition(childrenLayouts, num, num2); ChangePosition(children, num, num2); ChangePosition(positions, num, num2); Reorder(); } public bool CanReceiveDrop(ResizableHeaderDragCell cell, PointerEventData eventData) { if (!AllowReorder) { return false; } ResizableHeaderDragCell resizableHeaderDragCell = FindTarget(eventData); return resizableHeaderDragCell != null && resizableHeaderDragCell != cell; } public void Drop(ResizableHeaderDragCell cell, PointerEventData eventData) { ResizableHeaderDragCell resizableHeaderDragCell = FindTarget(eventData); Reorder(cell.Position, resizableHeaderDragCell.Position); } public void DropCanceled(ResizableHeaderDragCell cell, PointerEventData eventData) { } private void ChangePosition(List list, int oldPosition, int newPosition) { T item = list[oldPosition]; list.RemoveAt(oldPosition); list.Insert(newPosition, item); } private ResizableHeaderDragCell FindTarget(PointerEventData eventData) { raycastResults.Clear(); EventSystem.current.RaycastAll(eventData, raycastResults); foreach (RaycastResult raycastResult in raycastResults) { if (raycastResult.isValid) { ResizableHeaderDragCell component = raycastResult.gameObject.GetComponent(); if (component != null && component.transform.IsChildOf(base.transform)) { return component; } } } return null; } private void OnDestroy() { children.Clear(); childrenLayouts.Clear(); foreach (Transform item in base.transform) { ResizableHeaderCell component = item.GetComponent(); if (!(component == null)) { component.OnInitializePotentialDragEvent.RemoveListener(OnInitializePotentialDrag); component.OnBeginDragEvent.RemoveListener(OnBeginDrag); component.OnDragEvent.RemoveListener(OnDrag); component.OnEndDragEvent.RemoveListener(OnEndDrag); } } } } }