//--------------------------------------------------------
// [Author]: 第二世界
// [ Date ]: Monday, September 11, 2017
//--------------------------------------------------------
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;
namespace vnxbqy.UI
{
public class FlipScroll : MaskableGraphic, IBeginDragHandler, IEndDragHandler, IDragHandler
{
public enum FlipDirEnum
{
Horizon,
Vertical,
}
private int page = 0;
///
/// 当前页
///
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 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,
}
}
}