273 lines
7.9 KiB
C#
273 lines
7.9 KiB
C#
|
#if UNITY_WEBGL || WEIXINMINIGAME || UNITY_EDITOR
|
||
|
using System.Collections.Generic;
|
||
|
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.EventSystems;
|
||
|
using UnityEngine.Events;
|
||
|
using UnityEngine.UI;
|
||
|
|
||
|
using WeChatWASM;
|
||
|
|
||
|
using Touch = UnityEngine.Touch;
|
||
|
|
||
|
internal class TouchData
|
||
|
{
|
||
|
public Touch touch;
|
||
|
public long timeStamp;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 由于Unity WebGL发布的多点触控存在问题, 导致在微信中多点触控存在粘连的情况
|
||
|
* 所以需要使用WX的触控接口重新覆盖Unity的BaseInput关于触控方面的接口
|
||
|
* 通过设置StandaloneInputModule.inputOverride的方式来实现
|
||
|
*/
|
||
|
[RequireComponent(typeof(StandaloneInputModule))]
|
||
|
public class WXTouchInputOverride : BaseInput
|
||
|
{
|
||
|
private bool _isInitWechatSDK;
|
||
|
private readonly List<TouchData> _touches = new List<TouchData>();
|
||
|
private StandaloneInputModule _standaloneInputModule = null;
|
||
|
|
||
|
protected override void Awake()
|
||
|
{
|
||
|
base.Awake();
|
||
|
_standaloneInputModule = GetComponent<StandaloneInputModule>();
|
||
|
}
|
||
|
|
||
|
protected override void OnEnable()
|
||
|
{
|
||
|
base.OnEnable();
|
||
|
#if UNITY_WEBGL && !UNITY_EDITOR
|
||
|
if (string.IsNullOrEmpty(WeChatWASM.WX.GetDeviceInfo().platform)) return;
|
||
|
#else
|
||
|
return;
|
||
|
#endif
|
||
|
InitWechatTouchEvents();
|
||
|
if (_standaloneInputModule)
|
||
|
{
|
||
|
_standaloneInputModule.inputOverride = this;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override void OnDisable()
|
||
|
{
|
||
|
base.OnDisable();
|
||
|
UnregisterWechatTouchEvents();
|
||
|
if (_standaloneInputModule)
|
||
|
{
|
||
|
_standaloneInputModule.inputOverride = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void InitWechatTouchEvents()
|
||
|
{
|
||
|
if (!_isInitWechatSDK)
|
||
|
{
|
||
|
WX.InitSDK((code) =>
|
||
|
{
|
||
|
_isInitWechatSDK = true;
|
||
|
RegisterWechatTouchEvents();
|
||
|
});
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RegisterWechatTouchEvents();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void RegisterWechatTouchEvents()
|
||
|
{
|
||
|
WX.OnTouchStart(OnWxTouchStart);
|
||
|
WX.OnTouchMove(OnWxTouchMove);
|
||
|
WX.OnTouchEnd(OnWxTouchEnd);
|
||
|
WX.OnTouchCancel(OnWxTouchCancel);
|
||
|
}
|
||
|
|
||
|
private void UnregisterWechatTouchEvents()
|
||
|
{
|
||
|
WX.OffTouchStart(OnWxTouchStart);
|
||
|
WX.OffTouchMove(OnWxTouchMove);
|
||
|
WX.OffTouchEnd(OnWxTouchEnd);
|
||
|
WX.OffTouchCancel(OnWxTouchCancel);
|
||
|
}
|
||
|
|
||
|
private void OnWxTouchStart(OnTouchStartListenerResult touchEvent)
|
||
|
{
|
||
|
foreach (var wxTouch in touchEvent.changedTouches)
|
||
|
{
|
||
|
var data = FindOrCreateTouchData(wxTouch.identifier);
|
||
|
data.touch.phase = TouchPhase.Began;
|
||
|
data.touch.position = new Vector2(wxTouch.clientX, wxTouch.clientY);
|
||
|
data.touch.rawPosition = data.touch.position;
|
||
|
data.timeStamp = touchEvent.timeStamp;
|
||
|
|
||
|
// Debug.Log($"OnWxTouchStart:{wxTouch.identifier}, {data.touch.phase}");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void OnWxTouchMove(OnTouchStartListenerResult touchEvent)
|
||
|
{
|
||
|
foreach (var wxTouch in touchEvent.changedTouches)
|
||
|
{
|
||
|
var data = FindOrCreateTouchData(wxTouch.identifier);
|
||
|
UpdateTouchData(data, new Vector2(wxTouch.clientX, wxTouch.clientY), touchEvent.timeStamp, TouchPhase.Moved);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void OnWxTouchEnd(OnTouchStartListenerResult touchEvent)
|
||
|
{
|
||
|
foreach (var wxTouch in touchEvent.changedTouches)
|
||
|
{
|
||
|
TouchData data = FindTouchData(wxTouch.identifier);
|
||
|
if (data == null)
|
||
|
{
|
||
|
Debug.LogError($"OnWxTouchEnd, error identifier:{wxTouch.identifier}");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (data.touch.phase == TouchPhase.Canceled || data.touch.phase == TouchPhase.Ended)
|
||
|
{
|
||
|
Debug.LogWarning($"OnWxTouchEnd, error phase:{wxTouch.identifier}, phase:{data.touch.phase}");
|
||
|
}
|
||
|
|
||
|
// Debug.Log($"OnWxTouchEnd:{wxTouch.identifier}");
|
||
|
UpdateTouchData(data, new Vector2(wxTouch.clientX, wxTouch.clientY), touchEvent.timeStamp, TouchPhase.Ended);
|
||
|
}
|
||
|
|
||
|
GameObject selectedObject = EventSystem.current.currentSelectedGameObject;
|
||
|
if (selectedObject != null)
|
||
|
{
|
||
|
Button button = selectedObject.GetComponent<Button>();
|
||
|
if (button != null)
|
||
|
{
|
||
|
int clickListenerCount = button.onClick.GetPersistentEventCount();
|
||
|
if (clickListenerCount > 0) {
|
||
|
button.onClick.SetPersistentListenerState(0, UnityEventCallState.EditorAndRuntime);
|
||
|
button.onClick.Invoke();
|
||
|
button.onClick.SetPersistentListenerState(0, UnityEventCallState.Off);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void OnWxTouchCancel(OnTouchStartListenerResult touchEvent)
|
||
|
{
|
||
|
foreach (var wxTouch in touchEvent.changedTouches)
|
||
|
{
|
||
|
TouchData data = FindTouchData(wxTouch.identifier);
|
||
|
if (data == null)
|
||
|
{
|
||
|
Debug.LogError($"OnWxTouchCancel, error identifier:{wxTouch.identifier}");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (data.touch.phase == TouchPhase.Canceled || data.touch.phase == TouchPhase.Ended)
|
||
|
{
|
||
|
Debug.LogWarning($"OnWxTouchCancel, error phase:{wxTouch.identifier}, phase:{data.touch.phase}");
|
||
|
}
|
||
|
|
||
|
// Debug.Log($"OnWxTouchCancel:{wxTouch.identifier}");
|
||
|
UpdateTouchData(data, new Vector2(wxTouch.clientX, wxTouch.clientY), touchEvent.timeStamp, TouchPhase.Canceled);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void LateUpdate()
|
||
|
{
|
||
|
foreach (var t in _touches)
|
||
|
{
|
||
|
if (t.touch.phase == TouchPhase.Began)
|
||
|
{
|
||
|
t.touch.phase = TouchPhase.Stationary;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RemoveEndedTouches();
|
||
|
}
|
||
|
|
||
|
private void RemoveEndedTouches()
|
||
|
{
|
||
|
if (_touches.Count > 0)
|
||
|
{
|
||
|
_touches.RemoveAll(touchData =>
|
||
|
{
|
||
|
var touch = touchData.touch;
|
||
|
return touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled;
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private TouchData FindTouchData(int identifier)
|
||
|
{
|
||
|
foreach (var touchData in _touches)
|
||
|
{
|
||
|
var touch = touchData.touch;
|
||
|
if (touch.fingerId == identifier)
|
||
|
{
|
||
|
return touchData;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
private TouchData FindOrCreateTouchData(int identifier)
|
||
|
{
|
||
|
var touchData = FindTouchData(identifier);
|
||
|
if (touchData != null)
|
||
|
{
|
||
|
return touchData;
|
||
|
}
|
||
|
|
||
|
var data = new TouchData();
|
||
|
data.touch.pressure = 1.0f;
|
||
|
data.touch.maximumPossiblePressure = 1.0f;
|
||
|
data.touch.type = TouchType.Direct;
|
||
|
data.touch.tapCount = 1;
|
||
|
data.touch.fingerId = identifier;
|
||
|
data.touch.radius = 0;
|
||
|
data.touch.radiusVariance = 0;
|
||
|
data.touch.altitudeAngle = 0;
|
||
|
data.touch.azimuthAngle = 0;
|
||
|
data.touch.deltaTime = 0;
|
||
|
_touches.Add(data);
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
private static void UpdateTouchData(TouchData data, Vector2 pos, long timeStamp, TouchPhase phase)
|
||
|
{
|
||
|
data.touch.phase = phase;
|
||
|
data.touch.deltaPosition = pos - data.touch.position;
|
||
|
data.touch.position = pos;
|
||
|
data.touch.deltaTime = (timeStamp - data.timeStamp) / 1000000.0f;
|
||
|
}
|
||
|
|
||
|
#if !UNITY_EDITOR
|
||
|
public override bool touchSupported
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
public override bool mousePresent
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
public override int touchCount
|
||
|
{
|
||
|
get { return _touches.Count; }
|
||
|
}
|
||
|
|
||
|
public override Touch GetTouch(int index)
|
||
|
{
|
||
|
// Debug.LogError($"GetTouch touchCount:{touchCount}, index:{index}, touch:{_touches[index].touch.fingerId}, {_touches[index].touch.phase}");
|
||
|
return _touches[index].touch;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
}
|
||
|
#endif
|