using System.Collections; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; namespace UIWidgets { public class SlideBlock : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler, IEventSystemHandler { [SerializeField] [Tooltip("Requirements: start value should be less than end value; Recommended start value = 0; end value = 1;")] public AnimationCurve Curve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); public SlideBlockAxis Direction; [SerializeField] private bool isOpen; [SerializeField] private bool scrollRectSupport; [SerializeField] private GameObject optionalHandle; public UnityEvent OnOpen = new UnityEvent(); public UnityEvent OnClose = new UnityEvent(); private RectTransform rectTransform; private Vector2 closePosition; private IEnumerator currentAnimation; private float size; public bool IsOpen { get { return isOpen; } set { isOpen = value; ResetPosition(); } } public bool ScrollRectSupport { get { return scrollRectSupport; } set { if (scrollRectSupport) { GetComponentsInChildren().ForEach(RemoveHandleEvents); } scrollRectSupport = value; if (scrollRectSupport) { GetComponentsInChildren().ForEach(AddHandleEvents); } } } public GameObject OptionalHandle { get { return optionalHandle; } set { if (optionalHandle != null) { RemoveHandleEvents(optionalHandle); } optionalHandle = value; if (optionalHandle != null) { AddHandleEvents(optionalHandle); } } } protected RectTransform RectTransform { get { if (rectTransform == null) { rectTransform = base.transform as RectTransform; } return rectTransform; } } private string GetWarning() { Keyframe[] keys = Curve.keys; if (keys[0].value >= keys[keys.Length - 1].value) { return string.Format("Curve requirements: start value (current: {0}) should be less than end value (current: {1}).", keys[0].value, keys[keys.Length - 1].value); } return string.Empty; } private void Start() { string warning = GetWarning(); if (warning != string.Empty) { Debug.LogWarning(warning, this); } closePosition = RectTransform.anchoredPosition; size = ((!IsHorizontal()) ? RectTransform.rect.height : RectTransform.rect.width); if (IsOpen) { if (Direction == SlideBlockAxis.LeftToRight) { closePosition = new Vector2(closePosition.x - size, closePosition.y); } if (Direction == SlideBlockAxis.RightToLeft) { closePosition = new Vector2(closePosition.x + size, closePosition.y); } else if (Direction == SlideBlockAxis.TopToBottom) { closePosition = new Vector2(closePosition.x, closePosition.y - size); } else if (Direction == SlideBlockAxis.BottomToTop) { closePosition = new Vector2(closePosition.x, closePosition.y + size); } } OptionalHandle = optionalHandle; ScrollRectSupport = scrollRectSupport; } private void AddScrollRectHandle() { GetComponentsInChildren().ForEach(AddHandleEvents); } private void RemoveScrollRectHandle() { GetComponentsInChildren().ForEach(RemoveHandleEvents); } private void AddHandleEvents(Component handleComponent) { AddHandleEvents(handleComponent.gameObject); } private void AddHandleEvents(GameObject handleObject) { SlideBlockHandle slideBlockHandle = handleObject.GetComponent() ?? handleObject.AddComponent(); slideBlockHandle.BeginDragEvent.AddListener(OnBeginDrag); slideBlockHandle.DragEvent.AddListener(OnDrag); slideBlockHandle.EndDragEvent.AddListener(OnEndDrag); } private void RemoveHandleEvents(Component handleComponent) { RemoveHandleEvents(handleComponent.gameObject); } private void RemoveHandleEvents(GameObject handleObject) { SlideBlockHandle component = handleObject.GetComponent(); if (component != null) { component.BeginDragEvent.RemoveListener(OnBeginDrag); component.DragEvent.RemoveListener(OnDrag); component.EndDragEvent.RemoveListener(OnEndDrag); } } private void ResetPosition() { if (isOpen) { size = ((!IsHorizontal()) ? RectTransform.rect.height : RectTransform.rect.width); if (Direction == SlideBlockAxis.LeftToRight) { RectTransform.anchoredPosition = new Vector2(closePosition.x + size, RectTransform.anchoredPosition.y); } else if (Direction == SlideBlockAxis.RightToLeft) { RectTransform.anchoredPosition = new Vector2(closePosition.x - size, RectTransform.anchoredPosition.y); } else if (Direction == SlideBlockAxis.TopToBottom) { RectTransform.anchoredPosition = new Vector2(RectTransform.anchoredPosition.x, closePosition.y - size); } else if (Direction == SlideBlockAxis.BottomToTop) { RectTransform.anchoredPosition = new Vector2(RectTransform.anchoredPosition.x, closePosition.y + size); } } else { RectTransform.anchoredPosition = closePosition; } } public void Toggle() { if (IsOpen) { Close(); } else { Open(); } } public void OnBeginDrag(PointerEventData eventData) { size = ((!IsHorizontal()) ? RectTransform.rect.height : RectTransform.rect.width); } public void OnEndDrag(PointerEventData eventData) { float num = ((!IsHorizontal()) ? (RectTransform.anchoredPosition.y - closePosition.y) : (RectTransform.anchoredPosition.x - closePosition.x)); if (num == 0f) { isOpen = false; OnClose.Invoke(); return; } int num2 = ((!IsReverse()) ? 1 : (-1)); if (num == size * (float)num2) { isOpen = true; OnOpen.Invoke(); return; } float num3 = num / (size * (float)num2); if (num3 >= 0.5f) { isOpen = false; Open(); } else { isOpen = true; Close(); } } public void OnDrag(PointerEventData eventData) { if (currentAnimation != null) { StopCoroutine(currentAnimation); } Vector2 localPoint; RectTransformUtility.ScreenPointToLocalPointInRectangle(RectTransform, eventData.position, eventData.pressEventCamera, out localPoint); Vector2 localPoint2; RectTransformUtility.ScreenPointToLocalPointInRectangle(RectTransform, eventData.position - eventData.delta, eventData.pressEventCamera, out localPoint2); Vector2 vector = localPoint - localPoint2; if (Direction == SlideBlockAxis.LeftToRight) { float x = Mathf.Clamp(RectTransform.anchoredPosition.x + vector.x, closePosition.x, closePosition.x + size); RectTransform.anchoredPosition = new Vector2(x, RectTransform.anchoredPosition.y); } else if (Direction == SlideBlockAxis.RightToLeft) { float x2 = Mathf.Clamp(RectTransform.anchoredPosition.x + vector.x, closePosition.x - size, closePosition.x); RectTransform.anchoredPosition = new Vector2(x2, RectTransform.anchoredPosition.y); } else if (Direction == SlideBlockAxis.TopToBottom) { float y = Mathf.Clamp(RectTransform.anchoredPosition.y + vector.y, closePosition.y - size, closePosition.y); RectTransform.anchoredPosition = new Vector2(RectTransform.anchoredPosition.x, y); } else if (Direction == SlideBlockAxis.BottomToTop) { float y2 = Mathf.Clamp(RectTransform.anchoredPosition.y + vector.y, closePosition.y, closePosition.y + size); RectTransform.anchoredPosition = new Vector2(RectTransform.anchoredPosition.x, y2); } } public void Open() { if (!IsOpen) { Animate(); } } public void Close() { if (IsOpen) { Animate(); } } private bool IsHorizontal() { return Direction == SlideBlockAxis.LeftToRight || SlideBlockAxis.RightToLeft == Direction; } private bool IsReverse() { return Direction == SlideBlockAxis.RightToLeft || SlideBlockAxis.TopToBottom == Direction; } private void Animate() { if (currentAnimation != null) { StopCoroutine(currentAnimation); } float time = Curve.keys[Curve.keys.Length - 1].time; size = ((!IsHorizontal()) ? RectTransform.rect.height : RectTransform.rect.width); float num = ((!IsHorizontal()) ? RectTransform.anchoredPosition.y : RectTransform.anchoredPosition.x); float num2 = num - ((!IsHorizontal()) ? closePosition.y : closePosition.x); int num3 = ((!IsReverse()) ? 1 : (-1)); float num4 = ((!isOpen) ? (size * (float)num3 - num2) : (size * (float)num3)); float num5 = ((num4 != 0f) ? (size / num4) : 1f); if (IsReverse()) { num5 *= -1f; } currentAnimation = RunAnimation(Time.time, time, num, num4, num5); StartCoroutine(currentAnimation); } private IEnumerator RunAnimation(float startTime, float animationLength, float startPosition, float movement, float acceleration) { int direction = ((!isOpen) ? 1 : (-1)); float delta; do { delta = (Time.time - startTime) * acceleration; float value = Curve.Evaluate(delta); if (IsHorizontal()) { RectTransform.anchoredPosition = new Vector2(startPosition + value * movement * (float)direction, RectTransform.anchoredPosition.y); } else { RectTransform.anchoredPosition = new Vector2(RectTransform.anchoredPosition.x, startPosition + value * movement * (float)direction); } yield return null; } while (delta < animationLength); isOpen = !isOpen; ResetPosition(); if (IsOpen) { OnOpen.Invoke(); } else { OnClose.Invoke(); } } } }