ZK_Framework/Assets/Scripts/Game/Touch/TouchManager.cs

323 lines
8.9 KiB
C#

using System;
using System.Collections;
using System.Threading;
using Cysharp.Threading.Tasks;
using Game;
using Game.Pool;
using UnityEngine;
public enum TouchType
{
None, // 无状态输入
, // 超过0.3s未再次点击判定为单击
, // 第二次点击时间为0.3s内,判定为双击
, // 长按某个位置时间超过1.5s,判定为长按
, // 双指内掐
, //双指外扩
,
,
,
,
}
public interface ITouchManager
{
TouchType TouchType { get; }
}
public class TouchManager : ManagerBase, ITouchManager
{
private TouchType oldType;
private TouchType touchType;
public TouchType TouchType => this.touchType;
private float currentDoubleTime;
private float currentLongTime;
private float maxDoubleTime = 0.3f;
private float maxLongTime = 1.5f;
private bool isDoubleStarting;
private bool isLongStarting;
private float f = 5f;
// events
public Action OnClick; // 单击
public Action OnDoubleClick; // 双击
public Action OnLongClick; // 长按
public Action OnBlowUp; // 放大
public Action OnBlowDown; // 缩小
public Action OnLeftToRight; // 由左向右滑动
public Action OnRightToLeft; // 由右向左滑动
public Action OnFrontToBack; // 由前向后滑动
public Action OnBackToFront; // 由后向前滑动
private void Start()
{
this.isDoubleStarting = false;
this.isLongStarting = false;
}
private void Update()
{
if (Input.touchCount == 1)
{
this.One();
}
else if (Input.touchCount == 2)
{
this.IsEnlarge();
}
}
private string oldId;
private string newId;
private string currentId;
void One()
{
Touch touch0 = Input.GetTouch(0);
var vector2 = touch0.deltaPosition;
switch (touch0.phase)
{
case TouchPhase.Began:
this.newId = Guid.NewGuid().ToString();
this.currentId = this.newId;
break;
case TouchPhase.Moved:
if (this.currentId != this.newId)
{
return;
}
if (vector2.x > f)
ChangeState(TouchType.);
else if (vector2.x < -f)
ChangeState(TouchType.);
if (vector2.y > f)
ChangeState(TouchType.);
else if (vector2.y < -f)
ChangeState(TouchType.);
break;
case TouchPhase.Stationary:
break;
case TouchPhase.Ended:
this.oldId = this.newId;
ChangeState(TouchType.None);
break;
case TouchPhase.Canceled:
break;
default:
throw new ArgumentOutOfRangeException();
}
if (vector2 == Vector2.zero) // 使用实现
{
if (touch0.phase == TouchPhase.Began && !this.isDoubleStarting)
{
this.isDoubleStarting = true;
// if (this.Double != null)
// StopCoroutine(this.Double);
// Double = this.UpdateDouble();
// StartCoroutine(this.Double);
if (this.doubleToken != null && !this.doubleToken.isDispose)
{
this.doubleToken.Cancel();
}
this.doubleToken = TokenPool.GetToken();
this.Double = UpdateDouble(this.doubleToken);
this.Double.Forget();
}
if (touch0.phase == TouchPhase.Began && !this.isLongStarting)
{
this.isLongStarting = true;
// if (this.Long != null)
// StopCoroutine(this.Long);
// Long = this.UpdateLong();
// StartCoroutine(this.Long);
if (this.longToken != null && !this.longToken.isDispose)
{
this.longToken.Cancel();
}
this.longToken = TokenPool.GetToken();
this.Long = UpdateLong(this.longToken);
this.Long.Forget();
}
}
}
// TODO: add
private bool isFinish;
private UniTask Double;
private ITokenInfo doubleToken;
private UniTask Long;
private ITokenInfo longToken;
async UniTask UpdateDouble(ITokenInfo tokenInfo)
{
if (this.isFinish)
this.isFinish = false;
string tmpId = this.currentId;
this.currentDoubleTime = 0;
while (this.currentDoubleTime < this.maxDoubleTime)
{
if (tokenInfo.isDispose)
{
return;
}
await UniTask.Yield();
this.currentDoubleTime += Time.deltaTime;
if (Input.touchCount == 1 && tmpId != this.currentId && Input.GetTouch(0).phase == TouchPhase.Ended)
{
// 双击
ChangeState(TouchType.);
this.isFinish = true;
this.isDoubleStarting = false;
tokenInfo.Dispose();
return;
}
if (this.isFinish)
{
this.isDoubleStarting = false;
tokenInfo.Cancel();
return;
}
}
if (tmpId == this.currentId)
{
if (!this.isFinish && Input.touchCount == 0)
{
ChangeState(TouchType.);
this.isFinish = true;
}
}
this.isDoubleStarting = false;
tokenInfo.Dispose();
// 双击不成立
}
async UniTask UpdateLong(ITokenInfo tokenInfo)
{
if (this.isFinish)
this.isFinish = false;
this.currentLongTime = 0;
while (this.currentLongTime < this.maxLongTime)
{
await UniTask.Yield();
this.currentLongTime += Time.deltaTime;
if (this.isFinish)
{
tokenInfo.Cancel();
return;
}
if (Input.touchCount == 0 || Input.GetTouch(0).phase != TouchPhase.Stationary)
{
this.touchType = TouchType.None;
isLongStarting = false;
tokenInfo.Dispose();
return;
}
}
while (Input.GetTouch(0).phase == TouchPhase.Ended)
{
await UniTask.Yield();
}
if (!this.isFinish)
{
ChangeState(TouchType.);
this.isLongStarting = false;
this.isFinish = true;
}
tokenInfo.Dispose();
}
private Vector2 old1;
private Vector2 old2;
void IsEnlarge()
{
Touch touch0 = Input.GetTouch(0);
Touch touch1 = Input.GetTouch(1);
Vector2 new1 = touch0.position;
Vector2 new2 = touch1.position;
float length1 = Mathf.Sqrt((old1.x - old2.x) * (old1.x - old2.x) + (old1.y - old2.y) * (old1.y - old2.y));
float length2 = Mathf.Sqrt((new1.x - new2.x) * (new1.x - new2.x) + (new1.y - new2.y) * (new1.y - new2.y));
if (length1 < length2)
ChangeState(TouchType.);
else if (length1 > length2)
ChangeState(TouchType.);
else
ChangeState(TouchType.None);
this.old1 = new1;
this.old2 = new2;
}
private void ChangeState(TouchType newType)
{
this.oldType = this.touchType;
this.touchType = newType;
FireEvent(newType);
}
void FireEvent(TouchType newType)
{
switch (newType)
{
case TouchType.None:
break;
case TouchType.:
this.OnClick?.Invoke();
break;
case TouchType.:
this.OnDoubleClick?.Invoke();
break;
case TouchType.:
this.OnLongClick?.Invoke();
break;
case TouchType.:
this.OnBlowUp?.Invoke();
break;
case TouchType.:
this.OnBlowDown?.Invoke();
break;
case TouchType.:
this.OnLeftToRight?.Invoke();
break;
case TouchType.:
this.OnRightToLeft?.Invoke();
break;
case TouchType.:
this.OnBackToFront?.Invoke();
break;
case TouchType.:
this.OnFrontToBack?.Invoke();
break;
default:
throw new ArgumentOutOfRangeException(nameof(newType), newType, null);
}
}
}