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