2019-05-29 18:52:27 +02:00

110 lines
3.9 KiB
C#

using System;
using UnityEngine;
using UnityEngine.Serialization;
namespace UnityAtoms.Mobile
{
[AddComponentMenu("Unity Atoms/Listeners/DetectTap (TouchUserInput)")]
[Serializable]
public class DetectTap : IGameEventListener<TouchUserInput>
{
[FormerlySerializedAs("FirstTapTimer")]
[SerializeField]
private Timer _firstTapTimer = null;
[FormerlySerializedAs("SecondTapTimer")]
[SerializeField]
private Timer _secondTapTimer = null;
[FormerlySerializedAs("MaxTimeBetweenTaps")]
[SerializeField]
private FloatReference _maxTimeBetweenTaps = null;
[FormerlySerializedAs("MaxDistanceBetweenTaps")]
[SerializeField]
private FloatReference _maxDistanceBetweenTaps = null;
[FormerlySerializedAs("MaxMovementToCountAsTap")]
[SerializeField]
private FloatReference _maxMovementToCountAsTap = null;
[FormerlySerializedAs("OnTapDetectedEvent")]
[SerializeField]
private TouchUserInputGameEvent _onTapDetectedEvent = null;
[FormerlySerializedAs("OnDoubleTapDetectedEvent")]
[SerializeField]
private TouchUserInputGameEvent _onDoubleTapDetectedEvent = null;
private Vector2 _inputPosFirstTapDown;
public void OnEventRaised(TouchUserInput touchUserInput)
{
if (!IsPotentialDoubleTapInProgress())
{
_firstTapTimer.Stop();
_secondTapTimer.Stop();
}
if (touchUserInput.InputState == TouchUserInput.State.Down && CanStartDoubleTap())
{
_inputPosFirstTapDown = touchUserInput.InputPos;
_firstTapTimer.Start();
}
else if (touchUserInput.InputState == TouchUserInput.State.Drag && _firstTapTimer.IsStarted() && Vector2.Distance(touchUserInput.InputPos, _inputPosFirstTapDown) > _maxMovementToCountAsTap.Value)
{
_firstTapTimer.Stop();
}
else if (touchUserInput.InputState == TouchUserInput.State.Up && WaitingForFinishingFirstTap())
{
if (_firstTapTimer.GetElapsedTime() <= _maxTimeBetweenTaps.Value)
{
if (_onTapDetectedEvent != null)
{
_onTapDetectedEvent.Raise(touchUserInput);
}
_secondTapTimer.Start();
}
_firstTapTimer.Stop();
}
else if (touchUserInput.InputState == TouchUserInput.State.Down && WaitingForSecondTap())
{
if (Vector2.Distance(touchUserInput.InputPos, _inputPosFirstTapDown) <= _maxDistanceBetweenTaps.Value && _secondTapTimer.GetElapsedTime() <= _maxTimeBetweenTaps.Value)
{
if (_onDoubleTapDetectedEvent != null)
{
_onDoubleTapDetectedEvent.Raise(touchUserInput); // OPEN POINT: Should we raise event on state up or down?
}
}
_secondTapTimer.Stop();
}
}
private bool CanStartDoubleTap()
{
return !_secondTapTimer.IsStarted();
}
private bool WaitingForFinishingFirstTap()
{
return _firstTapTimer.IsStarted();
}
private bool WaitingForSecondTap()
{
return _secondTapTimer.IsStarted();
}
public bool IsPotentialDoubleTapInProgress()
{
return (_firstTapTimer.IsStarted() && _firstTapTimer.GetElapsedTime() <= _maxTimeBetweenTaps.Value) || (_secondTapTimer.IsStarted() && _secondTapTimer.GetElapsedTime() <= _maxTimeBetweenTaps.Value);
}
public bool InUse()
{
return _firstTapTimer != null && _secondTapTimer != null && _onDoubleTapDetectedEvent != null;
}
}
}