Files
ImaageQ_Unity_App/Assets/Common/InputSystem/TouchManager.cs
Ignacio Gómez Puga 5847d844a5 Removed TOTU 103
2025-03-04 12:04:52 -06:00

299 lines
7.9 KiB
C#

// Copyright 2022-2024 Niantic.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.UI;
using Touch = UnityEngine.InputSystem.EnhancedTouch.Touch;
using TouchPhase = UnityEngine.TouchPhase;
public class TouchManager : MonoBehaviour
{
[Serializable]
public class FloatEvent : UnityEvent<float> { };
[Serializable]
public class Vector2Event : UnityEvent<Vector2> { };
[SerializeField] private float _pinchScrollSpeed;
[SerializeField] private float _mouseScrollSpeed;
[SerializeField] private float _touchPanSpeed;
[SerializeField] private float _mousePanSpeed;
private LightshipInput _lightshipInput;
private bool _isPointerDown;
private bool IsPointerDown
{
get { return _isPointerDown; }
set
{
_isPointerDown = value;
if ((value == false) && (_IsPanActive))
{
_IsPanActive = false;
PanEnded?.Invoke();
}
}
}
private bool _IsPanActive = false;
private Dictionary<int, TouchState> _activeTouches = new Dictionary<int, TouchState>();
private float _lastPinchDistance = 0f;
private bool _resetPinchDistance = false;
private Coroutine activePinchCoroutine = null;
[SerializeField] public FloatEvent PinchEvent = new FloatEvent();
[SerializeField] public Vector2Event PanEvent = new Vector2Event();
[SerializeField] public UnityEvent PanEnded = new UnityEvent();
[SerializeField] public Vector2Event TouchUpEvent = new Vector2Event();
private void Awake()
{
_lightshipInput = new LightshipInput();
}
private void OnEnable()
{
_lightshipInput.Enable();
}
private void OnDisable()
{
_lightshipInput.Disable();
}
private void Start()
{
_lightshipInput.Input.PrimaryTouch.performed += ctx => PrimaryTouchCallback(ctx);
_lightshipInput.Input.PrimaryTouch.started += ctx => PrimaryTouchCallback(ctx);
_lightshipInput.Input.PrimaryTouch.canceled += ctx => PrimaryTouchCallback(ctx);
_lightshipInput.Input.SecondaryTouch.performed += ctx => SecondaryTouchCallback(ctx);
_lightshipInput.Input.SecondaryTouch.started += ctx => SecondaryTouchCallback(ctx);
_lightshipInput.Input.SecondaryTouch.canceled += ctx => SecondaryTouchCallback(ctx);
_lightshipInput.Input.MouseScroll.performed += ctx => MouseScrollCallback(ctx);
_lightshipInput.Input.MousePan.performed += ctx => MousePanCallback(ctx);
_lightshipInput.Input.MousePan.canceled += ctx => MousePanCallback(ctx);
_lightshipInput.Input.MouseHold.started += ctx => MouseHoldCallback(ctx);
_lightshipInput.Input.MouseHold.performed += ctx => MouseHoldCallback(ctx);
_lightshipInput.Input.MouseHold.canceled += ctx => MouseHoldCallback(ctx);
}
private void MouseHoldCallback(InputAction.CallbackContext ctx)
{
switch (ctx.phase)
{
case InputActionPhase.Started :
IsPointerDown = true;
break;
case InputActionPhase.Canceled :
IsPointerDown = false;
if (!_IsPanActive)
{
TouchUpEvent?.Invoke(Mouse.current.position.ReadValue());
}
break;
}
}
private void MousePanCallback(InputAction.CallbackContext ctx)
{
var mousepan = ctx.ReadValue<Vector2>();
if (ctx.phase == InputActionPhase.Performed)
{
_IsPanActive = true;
}
ProcessPan(mousepan * _mousePanSpeed);
}
private void MouseScrollCallback(InputAction.CallbackContext ctx)
{
var mousecroll = ctx.ReadValue<Vector2>();
ProcessScrollZoom(mousecroll);
}
private void SecondaryTouchCallback(InputAction.CallbackContext ctx)
{
var touch = ctx.ReadValue<TouchState>();
PreprocessTouch(touch);
}
private void PrimaryTouchCallback(InputAction.CallbackContext ctx)
{
var touch = ctx.ReadValue<TouchState>();
PreprocessTouch(touch);
}
private void PreprocessTouch(TouchState touch)
{
switch (touch.phase)
{
case UnityEngine.InputSystem.TouchPhase.Began :
_activeTouches.TryAdd(touch.touchId, touch);
break;
case UnityEngine.InputSystem.TouchPhase.Ended :
_activeTouches.Remove(touch.touchId);
break;
case UnityEngine.InputSystem.TouchPhase.Canceled :
_activeTouches.Remove(touch.touchId);
break;
case UnityEngine.InputSystem.TouchPhase.None :
break;
default :
_activeTouches[touch.touchId] = touch;
break;
}
if (_activeTouches.Count > 1)
{
if (activePinchCoroutine == null)
{
activePinchCoroutine = StartCoroutine(ProcessPinch());
}
}
else
{
if (activePinchCoroutine != null)
{
StopCoroutine(activePinchCoroutine);
activePinchCoroutine = null;
}
if (_activeTouches.Count == 1)
{
ProcessTouch();
}
else
{
IsPointerDown = false;
}
}
if (IsPointerDown == false)
if (_IsPanActive)
{
_IsPanActive = false;
PanEnded?.Invoke();
}
else
{
TouchUpEvent?.Invoke(touch.position);
}
}
#region Process Gestures
private void ProcessPan(Vector2 delta)
{
PanEvent?.Invoke(delta);
}
private IEnumerator ProcessPinch()
{
_resetPinchDistance = true;
while (true)
{
yield return null;
var orderedTouches = _activeTouches.OrderBy(x => x.Key).ToArray();
var touchOne = orderedTouches[0];
var touchTwo = orderedTouches[1];
var pinchDistance = Vector2.Distance(touchOne.Value.position, touchTwo.Value.position);
if (_resetPinchDistance)
{
_lastPinchDistance = pinchDistance;
_resetPinchDistance = false;
}
float pinchDelta = (pinchDistance - _lastPinchDistance);
_lastPinchDistance = pinchDistance;
PinchEvent?.Invoke(pinchDelta * _pinchScrollSpeed);
}
}
private void ProcessScrollZoom(Vector2 MouseScrollDelta)
{
var yScrollDelta = MouseScrollDelta.y * _mouseScrollSpeed;
PinchEvent?.Invoke(yScrollDelta);
}
private void ProcessMouseMap()
{
}
private void ProcessTouch()
{
var orderedTouches = _activeTouches.OrderBy(x => x.Key).ToArray();
var touch = orderedTouches[0].Value;
switch (touch.phase)
{
case UnityEngine.InputSystem.TouchPhase.Began :
IsPointerDown = true;
break;
case UnityEngine.InputSystem.TouchPhase.Ended :
break;
case UnityEngine.InputSystem.TouchPhase.Moved:
_IsPanActive = true;
var delta = touch.delta;
if (delta.x + delta.y != 0)
{
ProcessPan(delta);
}
break;
}
}
#endregion
}