WXGame/box1/Assets/WX-WASM-SDK-V2/Runtime/WXTouchInputOverride.cs

273 lines
7.9 KiB
C#
Raw Normal View History

2024-10-25 18:09:59 +08:00
#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