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