| | |
| | | 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, |
| | | } |
| | | } |
| | | |