| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 | 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);        }    }}
 |