//-------------------------------------------------------- 
 | 
//    [Author]:           玩个游戏 
 | 
//    [  Date ]:           Monday, September 11, 2017 
 | 
//-------------------------------------------------------- 
 | 
using UnityEngine; 
 | 
using System.Collections; 
 | 
using UnityEngine.UI; 
 | 
using UnityEngine.EventSystems; 
 | 
using System; 
 | 
  
 | 
public class FlipScroll : MaskableGraphic, IBeginDragHandler, IEndDragHandler, IDragHandler 
 | 
{ 
 | 
    public enum FlipDirEnum 
 | 
    { 
 | 
        Horizon, 
 | 
        Vertical, 
 | 
    } 
 | 
    private int page = 0; 
 | 
    /// <summary> 
 | 
    /// 当前页 
 | 
    /// </summary> 
 | 
    public int Page { 
 | 
        get { return page; } 
 | 
    } 
 | 
    [SerializeField] 
 | 
    private FlipDirEnum flipType = FlipDirEnum.Horizon; 
 | 
    public FlipDirEnum FlipType { 
 | 
        get { 
 | 
            return flipType; 
 | 
        } 
 | 
        set { 
 | 
            flipType = value; 
 | 
        } 
 | 
    } 
 | 
    [SerializeField] 
 | 
    private bool m_Loop = false; 
 | 
    public bool loop { 
 | 
        get { 
 | 
            return m_Loop; 
 | 
        } 
 | 
        set { 
 | 
            m_Loop = value; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    [SerializeField] 
 | 
    private TweenType _tweenType = TweenType.Linear; 
 | 
    public TweenType tweenType { 
 | 
        get { return _tweenType; } 
 | 
        set { _tweenType = value; } 
 | 
    } 
 | 
    [SerializeField] 
 | 
    private float sensitive = 5.0f; 
 | 
  
 | 
    public float Sensitive { 
 | 
        get { return sensitive; } 
 | 
        set { sensitive = value; } 
 | 
    } 
 | 
    [SerializeField] 
 | 
    public bool resetOnEnable = true; 
 | 
  
 | 
    private bool tweening = false; 
 | 
    public bool IsTweening { get { return tweening; } } 
 | 
    [SerializeField] 
 | 
    private float _tweenTime = 1.0f; 
 | 
    public float TweenTime { 
 | 
        get { return _tweenTime; } 
 | 
        set { _tweenTime = value; } 
 | 
    } 
 | 
  
 | 
    public RectTransform presentRT; 
 | 
    public RectTransform lastRT; 
 | 
  
 | 
    private RectTransform presentFlipRT; 
 | 
    private RectTransform lastFlipRT; 
 | 
  
 | 
    public event Action<int, RectTransform> OnRefreshData; 
 | 
    public event Action OnTweenCompt; 
 | 
  
 | 
    public int pageCnt = 0; 
 | 
    [HideInInspector] 
 | 
    public bool locked = false; 
 | 
  
 | 
    protected override void Awake() 
 | 
    { 
 | 
        base.Awake(); 
 | 
        if (presentRT == null || lastRT == null) return; 
 | 
        presentRT.SetActive(false); 
 | 
        lastRT.SetActive(false); 
 | 
        presentFlipRT = presentRT; 
 | 
        lastFlipRT = lastRT; 
 | 
    } 
 | 
  
 | 
    protected override void OnEnable() 
 | 
    { 
 | 
        base.OnEnable(); 
 | 
        if (presentRT == null || lastRT == null || pageCnt == 0) return; 
 | 
        presentRT.SetActive(true); 
 | 
        lastRT.SetActive(true); 
 | 
        presentRT.localPosition = Vector3.zero; 
 | 
        if (resetOnEnable) { 
 | 
            switch (FlipType) { 
 | 
                case FlipDirEnum.Horizon: 
 | 
                    lastRT.localPosition = rectTransform.localPosition.SetX(rectTransform.sizeDelta.x); 
 | 
                    break; 
 | 
                case FlipDirEnum.Vertical: 
 | 
                    lastRT.localPosition = rectTransform.localPosition.SetY(-rectTransform.sizeDelta.y); 
 | 
                    break; 
 | 
            } 
 | 
            page = 0; 
 | 
        } 
 | 
        presentFlipRT = presentRT; 
 | 
        lastFlipRT = lastRT; 
 | 
        RefreshActive(); 
 | 
    } 
 | 
  
 | 
    private Vector2 lastPos = Vector2.zero; 
 | 
    public void OnBeginDrag(PointerEventData eventData) 
 | 
    { 
 | 
        lastPos = eventData.position; 
 | 
    } 
 | 
  
 | 
    public void OnEndDrag(PointerEventData eventData) 
 | 
    { 
 | 
        if (IsTweening || locked) return; 
 | 
        Vector2 nPos = lastPos - eventData.position; 
 | 
        switch (FlipType) { 
 | 
            case FlipDirEnum.Horizon: { 
 | 
                    if (Math.Abs(nPos.x) < sensitive) return; 
 | 
                    if (nPos.x > 0) { 
 | 
                        FlipRight(); 
 | 
                    } 
 | 
                    else { 
 | 
                        FlipLeft(); 
 | 
                    } 
 | 
                } 
 | 
                break; 
 | 
            case FlipDirEnum.Vertical: { 
 | 
                    if (Math.Abs(nPos.y) < sensitive) return; 
 | 
                    Vector3 pos = Vector3.zero; 
 | 
                    if (nPos.y < 0) { 
 | 
                        FlipLeft(); 
 | 
                    } 
 | 
                    else { 
 | 
                        FlipRight(); 
 | 
                    } 
 | 
                } 
 | 
                break; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    protected override void OnDisable() 
 | 
    { 
 | 
        tweening = false; 
 | 
        StopAllCoroutines(); 
 | 
        base.OnDisable(); 
 | 
    } 
 | 
  
 | 
  
 | 
  
 | 
  
 | 
    IEnumerator TweenPosition(Vector3 lPos, Vector3 nPos, Vector3 lastRtPos) 
 | 
    { 
 | 
        float time = 0; 
 | 
        Vector3 newPresentPos = Vector3.zero; 
 | 
        Vector3 newLastPos = Vector3.zero; 
 | 
        bool InView = false; 
 | 
        tweening = true; 
 | 
        while (time < _tweenTime) { 
 | 
            float per = 0; 
 | 
            switch (tweenType) { 
 | 
                case TweenType.Immediate: per = 1; break; 
 | 
                case TweenType.Linear: per = Linear(time / _tweenTime); break; 
 | 
                case TweenType.Smooth: per = Smooth(time / _tweenTime); break; 
 | 
            } 
 | 
            newPresentPos = Vector3.Lerp(lPos, nPos, per); 
 | 
            newLastPos = Vector3.Lerp(lastRtPos, Vector3.zero, per); 
 | 
            presentFlipRT.localPosition = newPresentPos; 
 | 
            lastFlipRT.localPosition = newLastPos; 
 | 
            time += Time.unscaledDeltaTime; 
 | 
            if (!InView) { 
 | 
                InView = InViewSide(); 
 | 
            } 
 | 
            if (tweenType == TweenType.Immediate) { 
 | 
                break; 
 | 
            } 
 | 
            yield return null; 
 | 
        } 
 | 
        tweening = false; 
 | 
        presentFlipRT.localPosition = nPos; 
 | 
        lastFlipRT.localPosition = Vector3.zero; 
 | 
        RectTransform temp = presentFlipRT; 
 | 
        presentFlipRT = lastFlipRT; 
 | 
        lastFlipRT = temp; 
 | 
        if (OnTweenCompt != null) OnTweenCompt(); 
 | 
    } 
 | 
  
 | 
    public bool InViewSide() 
 | 
    { 
 | 
        switch (FlipType) { 
 | 
            case FlipDirEnum.Horizon: { 
 | 
                    if (Vector3.Distance(Vector3.zero, lastFlipRT.localPosition) < lastFlipRT.sizeDelta.x + rectTransform.sizeDelta.x) { 
 | 
                        if (OnRefreshData != null) { 
 | 
                            lastFlipRT.SetActive(true); 
 | 
                            OnRefreshData(page, lastFlipRT); 
 | 
                        } 
 | 
                        return true; 
 | 
                    } 
 | 
                } 
 | 
                break; 
 | 
            case FlipDirEnum.Vertical: { 
 | 
                    if (Vector3.Distance(Vector3.zero, lastFlipRT.localPosition) < lastFlipRT.sizeDelta.y + rectTransform.sizeDelta.y) { 
 | 
                        if (OnRefreshData != null) { 
 | 
                            lastFlipRT.SetActive(true); 
 | 
                            OnRefreshData(page, lastFlipRT); 
 | 
                        } 
 | 
                        return true; 
 | 
                    } 
 | 
                } 
 | 
                break; 
 | 
        } 
 | 
        return false; 
 | 
    } 
 | 
  
 | 
    private float Linear(float val) 
 | 
    { 
 | 
        return Mathf.Lerp(0, 1, val); 
 | 
    } 
 | 
  
 | 
    private float Smooth(float val) 
 | 
    { 
 | 
        float result = Mathf.SmoothStep(0, 1, val); 
 | 
        result = Mathf.Clamp(result, 0, 1); 
 | 
        return result; 
 | 
    } 
 | 
  
 | 
    public void RefreshActive() 
 | 
    { 
 | 
        if (pageCnt == 0 || presentFlipRT == null) return; 
 | 
        if (OnRefreshData != null) { 
 | 
            presentFlipRT.SetActive(true); 
 | 
            OnRefreshData(page, presentFlipRT); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    public void FlipLeft() 
 | 
    { 
 | 
        if (IsTweening || pageCnt == 0) return; 
 | 
        Vector3 pos = Vector3.zero; 
 | 
        page--; 
 | 
        if (page < 0) { 
 | 
            if (loop) { 
 | 
                page = pageCnt - 1; 
 | 
            } 
 | 
            else { 
 | 
                page = 0; 
 | 
                return; 
 | 
            } 
 | 
        } 
 | 
        switch (FlipType) { 
 | 
            case FlipDirEnum.Horizon: { 
 | 
                    lastFlipRT.localPosition = rectTransform.localPosition.SetX(-rectTransform.sizeDelta.x); 
 | 
                    pos = rectTransform.localPosition.SetX(rectTransform.sizeDelta.x); 
 | 
                } 
 | 
                break; 
 | 
            case FlipDirEnum.Vertical: { 
 | 
                    lastFlipRT.localPosition = rectTransform.localPosition.SetY(rectTransform.sizeDelta.y); 
 | 
                    pos = rectTransform.localPosition.SetY(-rectTransform.sizeDelta.y); 
 | 
                } 
 | 
                break; 
 | 
        } 
 | 
        StartCoroutine(TweenPosition(presentFlipRT.localPosition, pos, lastFlipRT.localPosition)); 
 | 
    } 
 | 
  
 | 
    public void FlipRight() 
 | 
    { 
 | 
        if (IsTweening || pageCnt == 0) return; 
 | 
        Vector3 pos = Vector3.zero; 
 | 
        page++; 
 | 
        if (page >= pageCnt) { 
 | 
            if (loop) { 
 | 
                page = 0; 
 | 
            } 
 | 
            else { 
 | 
                page = pageCnt - 1; 
 | 
                return; 
 | 
            } 
 | 
        } 
 | 
        switch (FlipType) { 
 | 
            case FlipDirEnum.Horizon: { 
 | 
                    lastFlipRT.localPosition = rectTransform.localPosition.SetX(rectTransform.sizeDelta.x); 
 | 
                    pos = rectTransform.localPosition.SetX(-rectTransform.sizeDelta.x); 
 | 
                } 
 | 
                break; 
 | 
            case FlipDirEnum.Vertical: { 
 | 
                    lastFlipRT.localPosition = rectTransform.localPosition.SetY(-rectTransform.sizeDelta.y); 
 | 
                    pos = rectTransform.localPosition.SetY(rectTransform.sizeDelta.y); 
 | 
                } 
 | 
                break; 
 | 
        } 
 | 
        StartCoroutine(TweenPosition(presentFlipRT.localPosition, pos, lastFlipRT.localPosition)); 
 | 
    } 
 | 
  
 | 
    public void OnDrag(PointerEventData eventData) 
 | 
    { 
 | 
  
 | 
    } 
 | 
  
 | 
    public enum TweenType 
 | 
    { 
 | 
        Immediate, 
 | 
        Linear, 
 | 
        Smooth, 
 | 
    } 
 | 
} 
 |