Main/System/Skill/FlipScroll.cs
@@ -7,312 +7,310 @@
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;
namespace vnxbqy.UI
public class FlipScroll : MaskableGraphic, IBeginDragHandler, IEndDragHandler, IDragHandler
{
    public class FlipScroll : MaskableGraphic, IBeginDragHandler, IEndDragHandler, IDragHandler
    public enum FlipDirEnum
    {
        public enum FlipDirEnum
        {
            Horizon,
            Vertical,
        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;
        }
        private int page = 0;
        /// <summary>
        /// 当前页
        /// </summary>
        public int Page {
            get { return page; }
        set {
            flipType = value;
        }
        [SerializeField]
        private FlipDirEnum flipType = FlipDirEnum.Horizon;
        public FlipDirEnum FlipType {
            get {
                return flipType;
    }
    [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;
            }
            set {
                flipType = value;
            }
            page = 0;
        }
        [SerializeField]
        private bool m_Loop = false;
        public bool loop {
            get {
                return m_Loop;
            }
            set {
                m_Loop = value;
            }
        }
        presentFlipRT = presentRT;
        lastFlipRT = lastRT;
        RefreshActive();
    }
        [SerializeField]
        private TweenType _tweenType = TweenType.Linear;
        public TweenType tweenType {
            get { return _tweenType; }
            set { _tweenType = value; }
        }
        [SerializeField]
        private float sensitive = 5.0f;
    private Vector2 lastPos = Vector2.zero;
    public void OnBeginDrag(PointerEventData eventData)
    {
        lastPos = eventData.position;
    }
        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;
    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;
            }
            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;
            else {
                page = pageCnt - 1;
                return;
            }
        }
        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;
        switch (FlipType) {
            case FlipDirEnum.Horizon: {
                    lastFlipRT.localPosition = rectTransform.localPosition.SetX(rectTransform.sizeDelta.x);
                    pos = rectTransform.localPosition.SetX(-rectTransform.sizeDelta.x);
                }
                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();
                break;
            case FlipDirEnum.Vertical: {
                    lastFlipRT.localPosition = rectTransform.localPosition.SetY(-rectTransform.sizeDelta.y);
                    pos = rectTransform.localPosition.SetY(rectTransform.sizeDelta.y);
                }
                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();
                break;
        }
        StartCoroutine(TweenPosition(presentFlipRT.localPosition, pos, lastFlipRT.localPosition));
    }
        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;
        }
    public void OnDrag(PointerEventData eventData)
    {
        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,
        }
    public enum TweenType
    {
        Immediate,
        Linear,
        Smooth,
    }
}