109 lines
3.5 KiB
C#
109 lines
3.5 KiB
C#
using Cryville.Common.Buffers;
|
|
using UnityEngine;
|
|
using UnityEngine.EventSystems;
|
|
|
|
namespace Cryville.Unity.EventSystems {
|
|
[AddComponentMenu("Event/GC-less Standalone Input Module")]
|
|
public class StandaloneInputModule : UnityEngine.EventSystems.StandaloneInputModule {
|
|
private bool ShouldIgnoreEventsOnNoFocus() {
|
|
#if UNITY_EDITOR
|
|
return !UnityEditor.EditorApplication.isRemoteConnected;
|
|
#else
|
|
return true;
|
|
#endif
|
|
}
|
|
public override void Process() {
|
|
if (!eventSystem.isFocused && ShouldIgnoreEventsOnNoFocus()) {
|
|
return;
|
|
}
|
|
bool usedEvent = SendUpdateEventToSelectedObject();
|
|
if (!ProcessTouchEvents() && input.mousePresent) {
|
|
ProcessMouseEvent();
|
|
}
|
|
if (eventSystem.sendNavigationEvents) {
|
|
if (!usedEvent) {
|
|
usedEvent |= SendMoveEventToSelectedObject();
|
|
}
|
|
if (!usedEvent) {
|
|
SendSubmitEventToSelectedObject();
|
|
}
|
|
}
|
|
}
|
|
private bool ProcessTouchEvents() {
|
|
for (int i = 0; i < input.touchCount; i++) {
|
|
Touch touch = input.GetTouch(i);
|
|
if (touch.type != TouchType.Indirect) {
|
|
PointerEventData pointer = GetTouchPointerEventData(touch, out bool pressed, out bool released);
|
|
ProcessTouchPress(pointer, pressed, released);
|
|
if (!released) {
|
|
ProcessMove(pointer);
|
|
ProcessDrag(pointer);
|
|
}
|
|
else {
|
|
RemovePointerData(pointer);
|
|
}
|
|
}
|
|
}
|
|
return input.touchCount > 0;
|
|
}
|
|
protected new PointerEventData GetTouchPointerEventData(Touch input, out bool pressed, out bool released) {
|
|
bool created = GetPointerData(input.fingerId, out PointerEventData pointerData, create: true);
|
|
pointerData.Reset();
|
|
pressed = created || input.phase == TouchPhase.Began;
|
|
released = input.phase == TouchPhase.Canceled || input.phase == TouchPhase.Ended;
|
|
if (created) {
|
|
pointerData.position = input.position;
|
|
}
|
|
if (pressed) {
|
|
pointerData.delta = Vector2.zero;
|
|
}
|
|
else {
|
|
pointerData.delta = input.position - pointerData.position;
|
|
}
|
|
pointerData.position = input.position;
|
|
pointerData.button = PointerEventData.InputButton.Left;
|
|
if (input.phase == TouchPhase.Canceled) {
|
|
pointerData.pointerCurrentRaycast = default;
|
|
}
|
|
else {
|
|
eventSystem.RaycastAll(pointerData, m_RaycastResultCache);
|
|
pointerData.pointerCurrentRaycast = FindFirstRaycast(m_RaycastResultCache);
|
|
m_RaycastResultCache.Clear();
|
|
}
|
|
pointerData.pressure = input.pressure;
|
|
pointerData.altitudeAngle = input.altitudeAngle;
|
|
pointerData.azimuthAngle = input.azimuthAngle;
|
|
pointerData.radius = Vector2.one * input.radius;
|
|
pointerData.radiusVariance = Vector2.one * input.radiusVariance;
|
|
return pointerData;
|
|
}
|
|
class PointerEventDataPool : ObjectPool<PointerEventData> {
|
|
readonly EventSystem _eventSystem;
|
|
public PointerEventDataPool(EventSystem eventSystem, int capacity) : base(capacity) {
|
|
_eventSystem = eventSystem;
|
|
}
|
|
protected override PointerEventData Construct() {
|
|
return new PointerEventData(_eventSystem);
|
|
}
|
|
}
|
|
PointerEventDataPool _pool;
|
|
protected override void OnEnable() {
|
|
base.OnEnable();
|
|
_pool = new PointerEventDataPool(eventSystem, 64);
|
|
}
|
|
protected new bool GetPointerData(int id, out PointerEventData data, bool create) {
|
|
if (!m_PointerData.TryGetValue(id, out data) && create) {
|
|
data = _pool.Rent();
|
|
data.pointerId = id;
|
|
m_PointerData.Add(id, data);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
protected new void RemovePointerData(PointerEventData data) {
|
|
m_PointerData.Remove(data.pointerId);
|
|
_pool.Return(data);
|
|
}
|
|
}
|
|
}
|