443 lines
15 KiB
C#
443 lines
15 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using UnityEngine.EventSystems;
|
|
|
|
namespace BF
|
|
{
|
|
public enum TouchEventType
|
|
{
|
|
Down = 0,
|
|
Touching,
|
|
Up,
|
|
Hit,
|
|
Slide,
|
|
Dead,
|
|
}
|
|
|
|
public class BFTouchManager : ManagerBase
|
|
{
|
|
static BFTouchManager instance;
|
|
public static BFTouchManager Create()
|
|
{
|
|
BFLog.LogAssert(instance == null, "This method only allows BFMain to call once");
|
|
instance = new BFTouchManager();
|
|
instance.Init();
|
|
return instance;
|
|
}
|
|
|
|
public BFEvent<TouchEventType, BFFinger> onFinger;
|
|
public BFEvent<List<BFFinger>> onGesture;
|
|
|
|
public List<BFFinger> fingers = new List<BFFinger>(10);
|
|
public float hitThresholdTime = 0.2f; // 点击触发的最大触摸时间间隔
|
|
public float slideThresholdPixels = 50.0f; // 滑动拉起至少需要的滑动距离
|
|
public LayerMask targetLayers = (1 << 17) | (1 << 13) | (1 << 14) | (1 << 5); // 事件接收layer (地宫,CityBuilding,CityGroundEvent,UI)
|
|
public bool recordFingers = false; // 是否记录手指快照
|
|
public float recordThresholdPixels = 5.0f; // 记录快照阀值
|
|
public float recordTimeLimit = 10.0f; // 快照清理时间
|
|
public bool simulateMultiFingers = true;
|
|
public int maxFinger = 2; // 多指触碰最多手指数量
|
|
|
|
List<BFFinger> inactiveFingers = new List<BFFinger>(10);
|
|
List<BFFinger> filteredFingers = new List<BFFinger>(10);
|
|
int highestMounseButton = 7;
|
|
List<RaycastResult> tempRaycastResults = new List<RaycastResult>(10);
|
|
PointerEventData tempPointerEventData;
|
|
EventSystem tempEventSystem;
|
|
bool guideMask = false; // 是否屏蔽手势
|
|
|
|
// Vector2 pivot = new Vector2(0.5f, 0.5f);
|
|
// KeyCode pinchTwistKey = KeyCode.LeftAlt;
|
|
// KeyCode movePivotKey = KeyCode.RightAlt;
|
|
|
|
//设置手势是否有效
|
|
public void SetGuideMask(bool mask)
|
|
{
|
|
guideMask = mask;
|
|
}
|
|
|
|
bool AnyMouseButtonSet
|
|
{
|
|
get
|
|
{
|
|
for (var i = 0; i < highestMounseButton; i++)
|
|
{
|
|
if (Input.GetMouseButton(i) == true)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private BFTouchManager() { }
|
|
|
|
public override void Init()
|
|
{
|
|
onFinger = new BFEvent<TouchEventType, BFFinger>(20);
|
|
onGesture = new BFEvent<List<BFFinger>>(20);
|
|
}
|
|
|
|
public override void Destroy()
|
|
{
|
|
instance = null;
|
|
}
|
|
|
|
public Transform RaycastFindTrans(Vector2 screenPosition)
|
|
{
|
|
var results = RaycastFind(screenPosition);
|
|
if (results.Count > 0)
|
|
{
|
|
return results[0].gameObject.transform;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public bool PointOverTargetLayer(Vector2 screenPosition)
|
|
{
|
|
return RaycastFind(screenPosition).Count > 0;
|
|
}
|
|
|
|
public bool PointOverLayer(Vector2 screenPosition, LayerMask layer)
|
|
{
|
|
return RaycastFind(screenPosition, layer).Count > 0;
|
|
}
|
|
|
|
public List<RaycastResult> RaycastFind(Vector2 screenPosition)
|
|
{
|
|
return RaycastFind(screenPosition, targetLayers);
|
|
}
|
|
|
|
public bool RaycastResultContains(Vector2 screenPosition, Transform transform)
|
|
{
|
|
var raycastResult = RaycastFind(screenPosition);
|
|
for (var i = 0; i < raycastResult.Count; i++)
|
|
{
|
|
if (raycastResult[i].gameObject.transform == transform)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public List<RaycastResult> RaycastFind(Vector2 screenPosition, LayerMask layerMask)
|
|
{
|
|
tempRaycastResults.Clear();
|
|
var currentEventSystem = EventSystem.current;
|
|
if (currentEventSystem != null)
|
|
{
|
|
if (currentEventSystem != tempEventSystem)
|
|
{
|
|
tempEventSystem = currentEventSystem;
|
|
if (tempPointerEventData == null)
|
|
{
|
|
tempPointerEventData = new PointerEventData(tempEventSystem);
|
|
}
|
|
else
|
|
{
|
|
tempPointerEventData.Reset();
|
|
}
|
|
}
|
|
tempPointerEventData.position = screenPosition;
|
|
currentEventSystem.RaycastAll(tempPointerEventData, tempRaycastResults);
|
|
if (tempRaycastResults.Count > 0)
|
|
{
|
|
for (int i = tempRaycastResults.Count - 1; i >= 0; i--)
|
|
{
|
|
var raycastResult = tempRaycastResults[i];
|
|
var raycastLayer = 1 << raycastResult.gameObject.layer;
|
|
if ((raycastLayer & layerMask) == 0)
|
|
{
|
|
tempRaycastResults.RemoveAt(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Failed to RaycastGui because your scene doesn't have an event system! To add one, go to: GameObject/UI/EventSystem");
|
|
}
|
|
return tempRaycastResults;
|
|
}
|
|
|
|
public List<BFFinger> GetFingers(bool ignoreIfStartedOverGui, bool ignoreIfOverGui, int fingerCount = 0)
|
|
{
|
|
filteredFingers.Clear();
|
|
|
|
for (int i = 0; i < fingers.Count; i++)
|
|
{
|
|
var finger = fingers[i];
|
|
if (ignoreIfStartedOverGui == true && finger.startOverTargetLayer == true)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (ignoreIfOverGui == true && finger.IsOverTargetLayer == true)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
filteredFingers.Add(finger);
|
|
}
|
|
|
|
if (fingerCount > 0 && filteredFingers.Count != fingerCount)
|
|
{
|
|
filteredFingers.Clear();
|
|
return filteredFingers;
|
|
}
|
|
return filteredFingers;
|
|
}
|
|
|
|
public override void Update()
|
|
{
|
|
BeginFingers();
|
|
PollFingers();
|
|
EndFingers();
|
|
UpdateEvents();
|
|
}
|
|
|
|
void BeginFingers()
|
|
{
|
|
for (int i = inactiveFingers.Count - 1; i >= 0; i--)
|
|
{
|
|
var inactiveFinger = inactiveFingers[i];
|
|
inactiveFinger.age += Time.unscaledDeltaTime;
|
|
if (inactiveFinger.dead == false && inactiveFinger.age > hitThresholdTime)
|
|
{
|
|
inactiveFinger.dead = true;
|
|
onFinger.Invoke(TouchEventType.Dead, inactiveFinger);
|
|
}
|
|
}
|
|
for (int i = fingers.Count - 1; i >= 0; i--)
|
|
{
|
|
var finger = fingers[i];
|
|
if (finger.Up == true)
|
|
{
|
|
fingers.RemoveAt(i);
|
|
inactiveFingers.Add(finger);
|
|
finger.age = 0.0f;
|
|
finger.ClearSnapshots();
|
|
}
|
|
else
|
|
{
|
|
finger.lastTouching = finger.touching;
|
|
finger.lastPressure = finger.pressure;
|
|
finger.lastScreenPos = finger.curScreenPos;
|
|
finger.touching = false;
|
|
finger.hit = false;
|
|
finger.slide = false;
|
|
finger.cantTriggerHit = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PollFingers()
|
|
{
|
|
if (Input.touchCount > 0)
|
|
{
|
|
for (var i = 0; i < Input.touchCount; i++)
|
|
{
|
|
var touch = Input.GetTouch(i);
|
|
if (touch.phase == TouchPhase.Began || touch.phase == TouchPhase.Stationary
|
|
|| touch.phase == TouchPhase.Moved)
|
|
{
|
|
AddFinger(touch.fingerId, touch.position, touch.pressure);
|
|
}
|
|
}
|
|
}
|
|
else if (AnyMouseButtonSet)
|
|
{
|
|
var screen = new Rect(0, 0, Screen.width, Screen.height);
|
|
var mousePosition = Input.mousePosition;
|
|
if (screen.Contains(mousePosition))
|
|
{
|
|
AddFinger(-1, mousePosition, 1.0f);
|
|
// if (simulateMultiFingers)
|
|
// {
|
|
// if (Input.GetKey(movePivotKey))
|
|
// {
|
|
// pivot.x = mousePosition.x / Screen.width;
|
|
// pivot.y = mousePosition.y / Screen.height;
|
|
// }
|
|
// if (Input.GetKey(pinchTwistKey))
|
|
// {
|
|
// Vector2 center = new Vector2(Screen.width * pivot.x, Screen.height * pivot.y);
|
|
// AddFinger(-2, center - (mousePosition - center), 1.0f);
|
|
// }
|
|
// }
|
|
}
|
|
}
|
|
else if (Input.mouseScrollDelta.magnitude > 0)
|
|
{
|
|
var screen = new Rect(0, 0, Screen.width, Screen.height);
|
|
var mousePosition = Input.mousePosition;
|
|
if (screen.Contains(mousePosition))
|
|
{
|
|
AddFinger(-1, mousePosition, 1.0f);
|
|
AddFinger(-2, mousePosition, 1.0f);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void EndFingers()
|
|
{
|
|
for (var i = fingers.Count - 1; i >= 0; i--)
|
|
{
|
|
var finger = fingers[i];
|
|
finger.cantTriggerHit = finger.cantTriggerHit || Input.touchCount > 1;
|
|
if (finger.Up)
|
|
{
|
|
if (finger.age <= hitThresholdTime)
|
|
{
|
|
if (finger.SlideScreenDelta.magnitude < slideThresholdPixels)
|
|
{
|
|
finger.hit = true;
|
|
finger.hitCount += 1;
|
|
}
|
|
else
|
|
{
|
|
finger.hitCount = 0;
|
|
finger.slide = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
finger.hitCount = 0;
|
|
}
|
|
}
|
|
else if (!finger.Down)
|
|
{
|
|
finger.age += Time.unscaledDeltaTime;
|
|
}
|
|
}
|
|
}
|
|
|
|
void UpdateEvents()
|
|
{
|
|
//如果处于屏蔽阶段 不处理
|
|
if (guideMask)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var fingerCount = fingers.Count;
|
|
if (fingerCount > 0)
|
|
{
|
|
for (var i = 0; i < fingerCount; i++)
|
|
{
|
|
var finger = fingers[i];
|
|
if (finger.hit) onFinger.Invoke(TouchEventType.Hit, finger);
|
|
if (finger.slide) onFinger.Invoke(TouchEventType.Slide, finger);
|
|
if (finger.Down) onFinger.Invoke(TouchEventType.Down, finger);
|
|
if (finger.touching) onFinger.Invoke(TouchEventType.Touching, finger);
|
|
if (finger.Up) onFinger.Invoke(TouchEventType.Up, finger);
|
|
}
|
|
if (onGesture != null)
|
|
{
|
|
filteredFingers.Clear();
|
|
filteredFingers.AddRange(fingers);
|
|
onGesture.Invoke(filteredFingers);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AddFinger(int index, Vector2 screenPos, float pressure)
|
|
{
|
|
var finger = FindFinger(index);
|
|
if (finger == null)
|
|
{
|
|
if (fingers.Count >= maxFinger)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var inactiveIndex = FindInactiveFingerIndex(index);
|
|
if (inactiveIndex >= 0)
|
|
{
|
|
finger = inactiveFingers[inactiveIndex];
|
|
inactiveFingers.RemoveAt(inactiveIndex);
|
|
if (finger.age > hitThresholdTime)
|
|
{
|
|
finger.hitCount = 0;
|
|
}
|
|
|
|
finger.age = 0.0f;
|
|
finger.touching = false;
|
|
finger.lastTouching = false;
|
|
finger.hit = false;
|
|
finger.slide = false;
|
|
finger.dead = false;
|
|
}
|
|
else
|
|
{
|
|
finger = new BFFinger();
|
|
finger.index = index;
|
|
}
|
|
|
|
finger.startScreenPos = screenPos;
|
|
finger.lastScreenPos = screenPos;
|
|
finger.lastPressure = pressure;
|
|
finger.startTargetTrans = RaycastFindTrans(screenPos);
|
|
finger.startOverTargetLayer = finger.startTargetTrans != null;
|
|
fingers.Add(finger);
|
|
}
|
|
|
|
finger.touching = true;
|
|
finger.curScreenPos = screenPos;
|
|
finger.pressure = pressure;
|
|
|
|
if (recordFingers)
|
|
{
|
|
if (recordTimeLimit > 0.0f)
|
|
{
|
|
if (finger.SnapshotDuration > recordTimeLimit)
|
|
{
|
|
int removeCount = BFFingerSnapshot.GetLowerIndex(finger.snapshotList, finger.age - recordTimeLimit);
|
|
finger.ClearSnapshots(removeCount);
|
|
}
|
|
}
|
|
if (recordThresholdPixels > 0.0f)
|
|
{
|
|
if (finger.snapshotList.Count == 0 || finger.LastSnapshotScreenDelta.magnitude >= recordThresholdPixels)
|
|
{
|
|
finger.RecordSnapshot();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
finger.RecordSnapshot();
|
|
}
|
|
}
|
|
}
|
|
|
|
BFFinger FindFinger(int index)
|
|
{
|
|
for (var i = fingers.Count - 1; i >= 0; i--)
|
|
{
|
|
var finger = fingers[i];
|
|
if (finger.index == index)
|
|
{
|
|
return finger;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
int FindInactiveFingerIndex(int index)
|
|
{
|
|
for (var i = inactiveFingers.Count - 1; i >= 0; i--)
|
|
{
|
|
if (inactiveFingers[i].index == index)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
} |