229 lines
7.2 KiB
C#
229 lines
7.2 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
namespace FairyGUI
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 滑动手势。你可以通过onBegin+onMove+onEnd关心整个滑动过程,也可以只使用onAction关注最后的滑动结果。滑动结果包括方向和加速度,可以从position和velocity获得。
|
|||
|
/// 注意onAction仅当滑动超过一定距离(actionDistance)时才触发。
|
|||
|
/// </summary>
|
|||
|
public class SwipeGesture : EventDispatcher
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
public GObject host { get; private set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 当手指开始扫动时派发该事件。
|
|||
|
/// </summary>
|
|||
|
public EventListener onBegin { get; private set; }
|
|||
|
/// <summary>
|
|||
|
/// 手指离开屏幕时派发该事件。
|
|||
|
/// </summary>
|
|||
|
public EventListener onEnd { get; private set; }
|
|||
|
/// <summary>
|
|||
|
/// 手指在滑动时派发该事件。
|
|||
|
/// </summary>
|
|||
|
public EventListener onMove { get; private set; }
|
|||
|
/// <summary>
|
|||
|
/// 当手指从按下到离开经过的距离大于actionDistance时派发该事件。
|
|||
|
/// </summary>
|
|||
|
public EventListener onAction { get; private set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 手指离开时的加速度
|
|||
|
/// </summary>
|
|||
|
public Vector2 velocity;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 你可以在onBegin事件中设置这个值,那个后续将根据手指移动的距离修改这个值。如果不设置,那position初始为(0,0),反映手指扫过的距离。
|
|||
|
/// </summary>
|
|||
|
public Vector2 position;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 移动的变化值
|
|||
|
/// </summary>
|
|||
|
public Vector2 delta;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The min distance to fire onAction event
|
|||
|
/// 派发onAction事件的最小距离。如果手指扫过的距离少于此值,onAction不会触发(但onEnd仍然会派发)
|
|||
|
/// </summary>
|
|||
|
public int actionDistance;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 是否把变化量强制为整数。默认true。
|
|||
|
/// </summary>
|
|||
|
public bool snapping;
|
|||
|
|
|||
|
Vector2 _startPoint;
|
|||
|
Vector2 _lastPoint;
|
|||
|
float _time;
|
|||
|
bool _started;
|
|||
|
bool _touchBegan;
|
|||
|
|
|||
|
public static int ACTION_DISTANCE = 200;
|
|||
|
|
|||
|
public SwipeGesture(GObject host)
|
|||
|
{
|
|||
|
this.host = host;
|
|||
|
actionDistance = ACTION_DISTANCE;
|
|||
|
snapping = true;
|
|||
|
Enable(true);
|
|||
|
|
|||
|
onBegin = new EventListener(this, "onSwipeBegin");
|
|||
|
onEnd = new EventListener(this, "onSwipeEnd");
|
|||
|
onMove = new EventListener(this, "onSwipeMove");
|
|||
|
onAction = new EventListener(this, "onnSwipeAction");
|
|||
|
}
|
|||
|
|
|||
|
public void Dispose()
|
|||
|
{
|
|||
|
Enable(false);
|
|||
|
host = null;
|
|||
|
}
|
|||
|
|
|||
|
public void Enable(bool value)
|
|||
|
{
|
|||
|
if (value)
|
|||
|
{
|
|||
|
if (host == GRoot.inst)
|
|||
|
{
|
|||
|
Stage.inst.onTouchBegin.Add(__touchBegin);
|
|||
|
Stage.inst.onTouchMove.Add(__touchMove);
|
|||
|
Stage.inst.onTouchEnd.Add(__touchEnd);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
host.onTouchBegin.Add(__touchBegin);
|
|||
|
host.onTouchMove.Add(__touchMove);
|
|||
|
host.onTouchEnd.Add(__touchEnd);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
_started = false;
|
|||
|
_touchBegan = false;
|
|||
|
if (host == GRoot.inst)
|
|||
|
{
|
|||
|
Stage.inst.onTouchBegin.Remove(__touchBegin);
|
|||
|
Stage.inst.onTouchMove.Remove(__touchMove);
|
|||
|
Stage.inst.onTouchEnd.Remove(__touchEnd);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
host.onTouchBegin.Remove(__touchBegin);
|
|||
|
host.onTouchMove.Remove(__touchMove);
|
|||
|
host.onTouchEnd.Remove(__touchEnd);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void __touchBegin(EventContext context)
|
|||
|
{
|
|||
|
if (Stage.inst.touchCount > 1)
|
|||
|
{
|
|||
|
_touchBegan = false;
|
|||
|
if (_started)
|
|||
|
{
|
|||
|
_started = false;
|
|||
|
onEnd.Call(context.inputEvent);
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
InputEvent evt = context.inputEvent;
|
|||
|
_startPoint = _lastPoint = host.GlobalToLocal(new Vector2(evt.x, evt.y));
|
|||
|
_lastPoint = _startPoint;
|
|||
|
|
|||
|
_time = Time.unscaledTime;
|
|||
|
_started = false;
|
|||
|
velocity = Vector2.zero;
|
|||
|
position = Vector2.zero;
|
|||
|
_touchBegan = true;
|
|||
|
|
|||
|
context.CaptureTouch();
|
|||
|
}
|
|||
|
|
|||
|
void __touchMove(EventContext context)
|
|||
|
{
|
|||
|
if (!_touchBegan || Stage.inst.touchCount > 1)
|
|||
|
return;
|
|||
|
|
|||
|
InputEvent evt = context.inputEvent;
|
|||
|
Vector2 pt = host.GlobalToLocal(new Vector2(evt.x, evt.y));
|
|||
|
delta = pt - _lastPoint;
|
|||
|
if (snapping)
|
|||
|
{
|
|||
|
delta.x = Mathf.Round(delta.x);
|
|||
|
delta.y = Mathf.Round(delta.y);
|
|||
|
if (delta.x == 0 && delta.y == 0)
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
float deltaTime = Time.unscaledDeltaTime;
|
|||
|
float elapsed = (Time.unscaledTime - _time) * 60 - 1;
|
|||
|
if (elapsed > 1) //速度衰减
|
|||
|
velocity = velocity * Mathf.Pow(0.833f, elapsed);
|
|||
|
velocity = Vector3.Lerp(velocity, delta / deltaTime, deltaTime * 10);
|
|||
|
_time = Time.unscaledTime;
|
|||
|
position += delta;
|
|||
|
_lastPoint = pt;
|
|||
|
|
|||
|
if (!_started)
|
|||
|
{ //灵敏度检查,为了和点击区分
|
|||
|
int sensitivity;
|
|||
|
if (Stage.touchScreen)
|
|||
|
sensitivity = UIConfig.touchDragSensitivity;
|
|||
|
else
|
|||
|
sensitivity = 5;
|
|||
|
|
|||
|
if (Mathf.Abs(delta.x) < sensitivity && Mathf.Abs(delta.y) < sensitivity)
|
|||
|
return;
|
|||
|
|
|||
|
_started = true;
|
|||
|
onBegin.Call(evt);
|
|||
|
}
|
|||
|
|
|||
|
onMove.Call(evt);
|
|||
|
}
|
|||
|
|
|||
|
void __touchEnd(EventContext context)
|
|||
|
{
|
|||
|
_touchBegan = false;
|
|||
|
|
|||
|
if (!_started)
|
|||
|
return;
|
|||
|
|
|||
|
_started = false;
|
|||
|
|
|||
|
InputEvent evt = context.inputEvent;
|
|||
|
Vector2 pt = host.GlobalToLocal(new Vector2(evt.x, evt.y));
|
|||
|
delta = pt - _lastPoint;
|
|||
|
if (snapping)
|
|||
|
{
|
|||
|
delta.x = Mathf.Round(delta.x);
|
|||
|
delta.y = Mathf.Round(delta.y);
|
|||
|
}
|
|||
|
position += delta;
|
|||
|
|
|||
|
//更新速度
|
|||
|
float elapsed = (Time.unscaledTime - _time) * 60 - 1;
|
|||
|
if (elapsed > 1)
|
|||
|
velocity = velocity * Mathf.Pow(0.833f, elapsed);
|
|||
|
if (snapping)
|
|||
|
{
|
|||
|
velocity.x = Mathf.Round(velocity.x);
|
|||
|
velocity.y = Mathf.Round(velocity.y);
|
|||
|
}
|
|||
|
onEnd.Call(evt);
|
|||
|
|
|||
|
pt -= _startPoint;
|
|||
|
if (Mathf.Abs(pt.x) > actionDistance || Mathf.Abs(pt.y) > actionDistance)
|
|||
|
onAction.Call(evt);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|