//-------------------------------------------------------- 
 | 
//    [Author]:           第二世界 
 | 
//    [  Date ]:           Wednesday, September 06, 2017 
 | 
//-------------------------------------------------------- 
 | 
using UnityEngine; 
 | 
using System.Collections; 
 | 
using UnityEngine.UI; 
 | 
using System.Collections.Generic; 
 | 
using UnityEngine.EventSystems; 
 | 
using System; 
 | 
  
 | 
  
 | 
    public class BoundedDrag : MonoBehaviour, IEndDragHandler, IBeginDragHandler, IDragHandler 
 | 
    { 
 | 
  
 | 
        [SerializeField] 
 | 
        RectTransform m_Target; 
 | 
        public RectTransform target { 
 | 
            get { return m_Target; } 
 | 
            set { 
 | 
                m_Target = value; 
 | 
            } 
 | 
        } 
 | 
  
 | 
        public RectTransform rectTransform { get { return this.transform as RectTransform; } } 
 | 
  
 | 
        [SerializeField] 
 | 
        ScaleRange m_ScaleRange; 
 | 
        public ScaleRange scaleRange { 
 | 
            get { return m_ScaleRange; } 
 | 
            set { m_ScaleRange = value; } 
 | 
        } 
 | 
  
 | 
        [SerializeField] 
 | 
        float m_DefaultScale; 
 | 
        public float defaultScale { get { return m_DefaultScale; } } 
 | 
  
 | 
        [SerializeField] 
 | 
        float m_DestScale = 1f; 
 | 
        public float destScale { 
 | 
            get { return m_DestScale; } 
 | 
            set { m_DestScale = Mathf.Clamp(value, scaleRange.min, scaleRange.max); } 
 | 
        } 
 | 
  
 | 
        float refScale = 0f; 
 | 
  
 | 
        public float currentScale { 
 | 
            get { 
 | 
                return target.localScale.x; 
 | 
            } 
 | 
            set { 
 | 
                target.localScale = Vector3.one * Mathf.Clamp(value, scaleRange.min, scaleRange.max); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        [SerializeField] 
 | 
        MoveArea m_MoveArea; 
 | 
        public MoveArea moveArea { 
 | 
            get { return m_MoveArea; } 
 | 
            set { m_MoveArea = value; } 
 | 
        } 
 | 
  
 | 
        [SerializeField] 
 | 
        Vector2 m_DestPosition = Vector2.zero; 
 | 
        public Vector2 destPosition { 
 | 
            get { return m_DestPosition; } 
 | 
            set { m_DestPosition = new Vector2(Mathf.Clamp(value.x, moveArea.Left * destScale, moveArea.Right * destScale), Mathf.Clamp(value.y, moveArea.Bottom * destScale, moveArea.Top * destScale)); } 
 | 
        } 
 | 
  
 | 
        Vector3 refPosition = Vector3.zero; 
 | 
  
 | 
        public Vector2 currentPosition { 
 | 
            get { return target.anchoredPosition; } 
 | 
            set { target.anchoredPosition = value; } 
 | 
        } 
 | 
  
 | 
        Vector2 startTouchPosition01; 
 | 
        Vector2 startGroundPosition; 
 | 
  
 | 
        Vector2 lastTouchPosition01; 
 | 
        Vector2 curTouchPosition01; 
 | 
        Vector2 lastTouchPosition02; 
 | 
        Vector2 curTouchPosition02; 
 | 
  
 | 
        [SerializeField] 
 | 
        Action m_OnBeginDrag; 
 | 
        public Action onBeginDrag { 
 | 
            get { return m_OnBeginDrag; } 
 | 
        } 
 | 
  
 | 
        bool m_Actionable = true; 
 | 
        public bool actionable { 
 | 
            get { return m_Actionable; } 
 | 
            set { m_Actionable = value; } 
 | 
        } 
 | 
  
 | 
        private void OnEnable() 
 | 
        { 
 | 
            destPosition = currentPosition = Vector3.zero; 
 | 
        } 
 | 
  
 | 
        public void OnBeginDrag(PointerEventData eventData) 
 | 
        { 
 | 
  
 | 
#if UNITY_EDITOR || UNITY_STANDALONE 
 | 
            if (Input.GetKey(KeyCode.LeftControl) && eventData.button == PointerEventData.InputButton.Left) 
 | 
            { 
 | 
                TwoFingerHandleBegin(); 
 | 
            } 
 | 
            else if (eventData.button == PointerEventData.InputButton.Left) 
 | 
            { 
 | 
                OneFingerHandleBegin(eventData); 
 | 
            } 
 | 
#else 
 | 
        if (Input.touchCount == 2) { 
 | 
            TwoFingerHandleBegin(); 
 | 
        } 
 | 
        if (Input.touchCount == 1) { 
 | 
            OneFingerHandleBegin(eventData); 
 | 
        } 
 | 
#endif 
 | 
            onBeginDrag?.Invoke(); 
 | 
        } 
 | 
  
 | 
        public void OnDrag(PointerEventData eventData) 
 | 
        { 
 | 
#if UNITY_EDITOR || UNITY_STANDALONE 
 | 
            if (Input.GetKey(KeyCode.LeftControl) && eventData.button == PointerEventData.InputButton.Left) 
 | 
            { 
 | 
                TwoFingerHandle(); 
 | 
            } 
 | 
            else if (eventData.button == PointerEventData.InputButton.Left) 
 | 
            { 
 | 
                OneFingerHandle(eventData); 
 | 
            } 
 | 
#else 
 | 
        if (Input.touchCount == 2) { 
 | 
            TwoFingerHandle(); 
 | 
        } 
 | 
        if (Input.touchCount == 1) { 
 | 
            OneFingerHandle(eventData); 
 | 
        } 
 | 
#endif 
 | 
        } 
 | 
  
 | 
        public void OnEndDrag(PointerEventData eventData) 
 | 
        { 
 | 
        } 
 | 
  
 | 
        void LateUpdate() 
 | 
        { 
 | 
            if (!actionable) 
 | 
            { 
 | 
                return; 
 | 
            } 
 | 
  
 | 
            if (Mathf.Abs(currentScale - destScale) > 0.01f) 
 | 
            { 
 | 
                float newScale = Mathf.SmoothDamp(currentScale, destScale, ref refScale, 0.15f); 
 | 
                currentScale = newScale; 
 | 
            } 
 | 
  
 | 
            if (Vector2.Distance(currentPosition, destPosition) > 0.1f) 
 | 
            { 
 | 
                Vector2 newPosition = Vector3.SmoothDamp(currentPosition, destPosition, ref refPosition, 0.15f); 
 | 
                currentPosition = newPosition; 
 | 
            } 
 | 
        } 
 | 
  
 | 
        private void OneFingerHandleBegin(PointerEventData eventData) 
 | 
        { 
 | 
            startTouchPosition01 = Vector2.zero; 
 | 
            RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out startTouchPosition01); 
 | 
            startGroundPosition = currentPosition; 
 | 
  
 | 
        } 
 | 
  
 | 
        private void OneFingerHandle(PointerEventData eventData) 
 | 
        { 
 | 
            Vector2 localMouse; 
 | 
            if (RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out localMouse)) 
 | 
            { 
 | 
                var pointerDelta = localMouse - startTouchPosition01; 
 | 
                destPosition = startGroundPosition + pointerDelta; 
 | 
            } 
 | 
        } 
 | 
  
 | 
        private void TwoFingerHandle() 
 | 
        { 
 | 
            // 方便PC调试逻辑 
 | 
#if UNITY_EDITOR || UNITY_STANDALONE 
 | 
            curTouchPosition01 = new Vector2(Screen.width / 2, Screen.height / 2); 
 | 
            curTouchPosition02 = new Vector2(Input.mousePosition.x, Input.mousePosition.y); 
 | 
#else 
 | 
        Touch touchFirst = Input.touches[0]; 
 | 
        Touch touchSecond = Input.touches[1]; 
 | 
        curTouchPosition01 = touchFirst.position; 
 | 
        curTouchPosition02 = touchSecond.position; 
 | 
#endif 
 | 
  
 | 
            float lastLength = Vector2.Distance(lastTouchPosition01, lastTouchPosition02); 
 | 
            float curLength = Vector2.Distance(curTouchPosition01, curTouchPosition02); 
 | 
            destScale *= curLength / Mathf.Clamp(lastLength, 1, float.MaxValue); 
 | 
  
 | 
            lastTouchPosition01 = curTouchPosition01; 
 | 
            lastTouchPosition02 = curTouchPosition02; 
 | 
        } 
 | 
  
 | 
        private void TwoFingerHandleBegin() 
 | 
        { 
 | 
            // 方便PC调试逻辑 
 | 
#if UNITY_EDITOR || UNITY_STANDALONE 
 | 
            curTouchPosition01 = new Vector2(Screen.width / 2, Screen.height / 2); 
 | 
            curTouchPosition02 = new Vector2(Input.mousePosition.x, Input.mousePosition.y); 
 | 
#else 
 | 
        Touch touchFirst = Input.touches[0]; 
 | 
        Touch touchSecond = Input.touches[1]; 
 | 
        curTouchPosition01 = touchFirst.position; 
 | 
        curTouchPosition02 = touchSecond.position; 
 | 
#endif 
 | 
  
 | 
            lastTouchPosition01 = curTouchPosition01; 
 | 
            lastTouchPosition02 = curTouchPosition02; 
 | 
        } 
 | 
  
 | 
        [Serializable] 
 | 
        public struct ScaleRange 
 | 
        { 
 | 
            public float min; 
 | 
            public float max; 
 | 
        } 
 | 
  
 | 
        [Serializable] 
 | 
        public struct MoveArea 
 | 
        { 
 | 
            public float Left; 
 | 
            public float Right; 
 | 
            public float Top; 
 | 
            public float Bottom; 
 | 
  
 | 
            public MoveArea(float _left, float _right, float _top, float _bottom) 
 | 
            { 
 | 
                this.Left = _left; 
 | 
                this.Right = _right; 
 | 
                this.Top = _top; 
 | 
                this.Bottom = _bottom; 
 | 
            } 
 | 
  
 | 
        } 
 | 
    } 
 |