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