using System; using System.Collections.Generic; using UnityEngine; namespace FairyGUI { /// /// 手指反向操作的手势。 /// public class RotationGesture : EventDispatcher { /// /// /// public GObject host { get; private set; } /// /// 当两个手指开始呈反向操作时派发该事件。 /// public EventListener onBegin { get; private set; } /// /// 当其中一个手指离开屏幕时派发该事件。 /// public EventListener onEnd { get; private set; } /// /// 当手势动作时派发该事件。 /// public EventListener onAction { get; private set; } /// /// 总共旋转的角度。 /// public float rotation; /// /// 从上次通知后的改变量。 /// public float delta; /// /// 是否把变化量强制为整数。默认true。 /// public bool snapping; Vector2 _startVector; float _lastRotation; int[] _touches; bool _started; bool _touchBegan; public RotationGesture(GObject host) { this.host = host; Enable(true); _touches = new int[2]; snapping = true; onBegin = new EventListener(this, "onRotationBegin"); onEnd = new EventListener(this, "onRotationEnd"); onAction = new EventListener(this, "onRotationAction"); } 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 == 2) { if (!_started && !_touchBegan) { _touchBegan = true; Stage.inst.GetAllTouch(_touches); Vector2 pt1 = host.GlobalToLocal(Stage.inst.GetTouchPosition(_touches[0])); Vector2 pt2 = host.GlobalToLocal(Stage.inst.GetTouchPosition(_touches[1])); _startVector = pt1 - pt2; context.CaptureTouch(); } } } void __touchMove(EventContext context) { if (!_touchBegan || Stage.inst.touchCount != 2) return; InputEvent evt = context.inputEvent; Vector2 pt1 = host.GlobalToLocal(Stage.inst.GetTouchPosition(_touches[0])); Vector2 pt2 = host.GlobalToLocal(Stage.inst.GetTouchPosition(_touches[1])); Vector2 vec = pt1 - pt2; float rot = Mathf.Rad2Deg * ((Mathf.Atan2(vec.y, vec.x) - Mathf.Atan2(_startVector.y, _startVector.x))); if (snapping) { rot = Mathf.Round(rot); if (rot == 0) return; } if (!_started && rot > 5) { _started = true; rotation = 0; _lastRotation = 0; onBegin.Call(evt); } if (_started) { delta = rot - _lastRotation; _lastRotation = rot; this.rotation += delta; onAction.Call(evt); } } void __touchEnd(EventContext context) { _touchBegan = false; if (_started) { _started = false; onEnd.Call(context.inputEvent); } } } }