using UnityEngine;
using System.Collections;
///
/// Detect multiple consecutive tap gestures at the same location
///
[AddComponentMenu( "FingerGestures/Gesture Recognizers/Tap (Multi)" )]
public class MultiTapGestureRecognizer : AveragedGestureRecognizer
{
///
/// Event fired when a tap occurs (if RequiredTaps is 0) or when the exact number of RequiredTaps has been reached
///
public event EventDelegate OnTap;
///
/// Exact number of taps required to succesfully recognize the tap gesture.
/// If RequiredTaps is set to a positive value, the gesture recognizer will reset once the number of consecutive taps performed is equal to
/// this value.
///
///
public int RequiredTaps = 0;
///
/// When set to true, the OnTap event will fire each time a tap occurs.
/// When set to false, the OnTap event will only be fired on the last tap produced (either by time-out or when reaching the RequiredTaps count)
///
///
public bool RaiseEventOnEachTap = false;
///
/// The maximum amount of the time that can elapse between two consecutive taps without causing the recognizer to reset.
/// Set to 0 to ignore this setting.
///
public float MaxDelayBetweenTaps = 0.25f;
///
/// The maximum total duration of a tap sequence, in seconds. The tap recognizer automatically resets after this duration.
/// Set to 0 to ignore this setting.
///
public float MaxDuration = 0.0f;
///
/// How far the finger can move from its initial position without making the gesture fail
///
public float MoveTolerance = 5.0f;
int taps = 0;
bool down = false;
bool wasDown = false;
float lastDownTime = 0;
float lastTapTime = 0;
///
/// Get the current number of consecutive taps achieved
///
public int Taps
{
get { return taps; }
}
bool HasTimedOut()
{
// check elapsed time since last tap
if( MaxDelayBetweenTaps > 0 && ( Time.time - lastTapTime > MaxDelayBetweenTaps ) )
return true;
// check elapsed time since beginning of gesture
if( MaxDuration > 0 && ( ElapsedTime > MaxDuration ) )
return true;
return false;
}
protected override void Reset()
{
taps = 0;
down = false;
wasDown = false;
base.Reset();
}
protected override void OnBegin( FingerGestures.IFingerList touches )
{
Position = touches.GetAveragePosition();
StartPosition = Position;
lastTapTime = Time.time;
//UnityEngine.Debug.Log( this + " OnBegin @ " + StartPosition );
}
protected override GestureState OnActive( FingerGestures.IFingerList touches )
{
wasDown = down;
down = false;
if( touches.Count == RequiredFingerCount )
{
down = true;
lastDownTime = Time.time;
}
else if( touches.Count == 0 )
{
down = false;
}
else
{
// some fingers were lifted off
if( touches.Count < RequiredFingerCount )
{
// give a bit of buffer time to lift-off the remaining fingers
if( Time.time - lastDownTime > 0.25f )
return GestureState.Failed;
}
else // fingers were added
{
if( !Young( touches ) )
return GestureState.Failed;
}
}
if( HasTimedOut() )
{
// if we requested unlimited taps and landed at least one, consider this a success
if( RequiredTaps == 0 && Taps > 0 )
{
// if we didn't raise a tap event on each tap, at least raise the event once at the end of the tap sequence
if( !RaiseEventOnEachTap )
RaiseOnTap();
return GestureState.Recognized;
}
// else, timed out
return GestureState.Failed;
}
if( down )
{
// check if finger moved too far from start position
float sqrDist = Vector3.SqrMagnitude( touches.GetAveragePosition() - StartPosition );
if( sqrDist >= MoveTolerance * MoveTolerance )
return GestureState.Failed;
}
if( wasDown != down )
{
// fingers were just released
if( !down )
{
++taps;
lastTapTime = Time.time;
// If the requested tap count has been reached, validate the gesture and stop
if( RequiredTaps > 0 && taps >= RequiredTaps )
{
RaiseOnTap();
return GestureState.Recognized;
}
if( RaiseEventOnEachTap )
RaiseOnTap();
}
}
return GestureState.InProgress;
}
protected void RaiseOnTap()
{
if( OnTap != null )
OnTap( this );
}
}