Files
crtr/Assets/Plugins/Cryville.Unity.EventSystems/StandaloneInputModule.cs

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);
}
}
}