hellbound/Assets/Sources/Lean/Touch+/Scripts/LeanMultiSwipe.cs

227 lines
7.7 KiB
C#

using UnityEngine;
using UnityEngine.Events;
using System.Collections.Generic;
using Lean.Common;
using FSA = UnityEngine.Serialization.FormerlySerializedAsAttribute;
namespace Lean.Touch
{
/// <summary>This script calculates the multi-swipe event.
/// A multi-swipe is where you swipe multiple fingers at the same time, and OnSwipe gets called when the first finger is released from the screen.</summary>
[HelpURL(LeanTouch.PlusHelpUrlPrefix + "LeanMultiSwipe")]
[AddComponentMenu(LeanTouch.ComponentPathPrefix + "Multi Swipe")]
public class LeanMultiSwipe : MonoBehaviour
{
[System.Serializable] public class FingerListEvent : UnityEvent<List<LeanFinger>> {}
[System.Serializable] public class Vector2Event : UnityEvent<Vector2> {}
[System.Serializable] public class FloatEvent : UnityEvent<float> {}
/// <summary>The method used to find fingers to use with this component. See LeanFingerFilter documentation for more information.</summary>
public LeanFingerFilter Use = new LeanFingerFilter(true);
/// <summary>Each finger touching the screen must have moved at least this distance for a multi swipe to be considered. This prevents the scenario where multiple fingers are touching, but only one swipes.</summary>
public float ScaledDistanceThreshold { set { scaledDistanceThreshold = value; } get { return scaledDistanceThreshold; } } [FSA("ScaledDistanceThreshold")] [SerializeField] private float scaledDistanceThreshold = 50.0f;
/// <summary>This allows you to set the maximum angle between parallel swiping fingers for the OnSwipeParallel event to be fired.</summary>
public float ParallelAngleThreshold { set { parallelAngleThreshold = value; } get { return parallelAngleThreshold; } } [FSA("ParallelAngleThreshold")] [SerializeField] private float parallelAngleThreshold = 20.0f;
/// <summary>This allows you to set the minimum pinch distance for the OnSwipeIn and OnSwipeOut events to be fired.</summary>
public float PinchScaledDistanceThreshold { set { pinchScaledDistanceThreshold = value; } get { return pinchScaledDistanceThreshold; } } [FSA("PinchScaledDistanceThreshold")] [SerializeField] private float pinchScaledDistanceThreshold = 100.0f;
// Called when a multi-swipe occurs
public FingerListEvent OnFingers { get { if (onFingers == null) onFingers = new FingerListEvent(); return onFingers; } } [FSA("onSwipe")] [FSA("OnSwipe")] [SerializeField] private FingerListEvent onFingers;
// Called when a multi-swipe occurs where each finger moves parallel to each other (Vector2 = ScaledDirection)
public Vector2Event OnSwipeParallel { get { if (onSwipeParallel == null) onSwipeParallel = new Vector2Event(); return onSwipeParallel; } } [FSA("OnSwipeParallel")] [SerializeField] private Vector2Event onSwipeParallel;
// Called when a multi-swipe occurs where each finger pinches in (Float = ScaledDistance)
public FloatEvent OnSwipeIn { get { if (onSwipeIn == null) onSwipeIn = new FloatEvent(); return onSwipeIn; } } [FSA("OnSwipeIn")] [SerializeField] private FloatEvent onSwipeIn;
// Called when a multi-swipe occurs where each finger pinches out (Float = ScaledDistance)
public FloatEvent OnSwipeOut { get { if (onSwipeOut == null) onSwipeOut = new FloatEvent(); return onSwipeOut; } } [FSA("OnSwipeOut")] [SerializeField] private FloatEvent onSwipeOut;
// Set to prevent multiple invocation
private bool swiped;
/// <summary>If you've set Use to ManuallyAddedFingers, then you can call this method to manually add a finger.</summary>
public void AddFinger(LeanFinger finger)
{
Use.AddFinger(finger);
}
/// <summary>If you've set Use to ManuallyAddedFingers, then you can call this method to manually remove a finger.</summary>
public void RemoveFinger(LeanFinger finger)
{
Use.RemoveFinger(finger);
}
/// <summary>If you've set Use to ManuallyAddedFingers, then you can call this method to manually remove all fingers.</summary>
public void RemoveAllFingers()
{
Use.RemoveAllFingers();
}
#if UNITY_EDITOR
protected virtual void Reset()
{
Use.UpdateRequiredSelectable(gameObject);
}
#endif
protected virtual void Awake()
{
Use.UpdateRequiredSelectable(gameObject);
}
protected virtual void Update()
{
// Get all valid fingers for swipe
var fingers = Use.UpdateAndGetFingers();
if (fingers.Count > 0)
{
if (swiped == false)
{
for (var i = fingers.Count - 1; i >= 0; i--)
{
var finger = fingers[i];
if (finger.Swipe == true)
{
FingerSwipe(fingers, finger);
break;
}
}
}
}
else
{
swiped = false;
}
}
private void FingerSwipe(List<LeanFinger> fingers, LeanFinger swipedFinger)
{
var scaledDelta = swipedFinger.SwipeScaledDelta;
var isParallel = true;
swiped = true;
// Go through all fingers
for (var i = fingers.Count - 1; i >= 0; i--)
{
var finger = fingers[i];
// If it's too old to swipe, skip
if (finger.Age > LeanTouch.CurrentTapThreshold)
{
return;
}
// If it didn't move far enough to swipe, skip
if (finger.SwipeScaledDelta.magnitude < scaledDistanceThreshold)
{
return;
}
// If the finger didn't move parallel the others, make the OnSwipeParallel event ineligible
if (finger != swipedFinger)
{
var angle = Vector2.Angle(scaledDelta, finger.SwipeScaledDelta);
if (angle > parallelAngleThreshold)
{
isParallel = false;
}
}
}
if (onFingers != null)
{
onFingers.Invoke(fingers);
}
if (fingers.Count > 1)
{
var centerA = LeanGesture.GetStartScreenCenter(fingers);
var centerB = LeanGesture.GetScreenCenter(fingers);
if (onSwipeParallel != null && isParallel == true)
{
var delta = centerA - centerB;
onSwipeParallel.Invoke(delta * LeanTouch.ScalingFactor);
}
else
{
var pinch = LeanGesture.GetScaledDistance(fingers, centerB) - LeanGesture.GetStartScaledDistance(fingers, centerA);
if (onSwipeIn != null && pinch <= -pinchScaledDistanceThreshold)
{
onSwipeIn.Invoke(-pinch);
}
if (onSwipeOut != null && pinch >= pinchScaledDistanceThreshold)
{
onSwipeOut.Invoke(pinch);
}
}
}
}
}
}
#if UNITY_EDITOR
namespace Lean.Touch.Editor
{
using TARGET = LeanMultiSwipe;
[UnityEditor.CanEditMultipleObjects]
[UnityEditor.CustomEditor(typeof(TARGET), true)]
public class LeanMultiSwipe_Editor : LeanEditor
{
protected override void OnInspector()
{
TARGET tgt; TARGET[] tgts; GetTargets(out tgt, out tgts);
Draw("Use");
Separator();
Draw("scaledDistanceThreshold", "Each finger touching the screen must have moved at least this distance for a multi swipe to be considered. This prevents the scenario where multiple fingers are touching, but only one swipes.");
Draw("parallelAngleThreshold", "This allows you to set the maximum angle between parallel swiping fingers for the OnSwipeParallel event to be fired.");
Draw("pinchScaledDistanceThreshold", "This allows you to set the minimum pinch distance for the OnSwipeIn and OnSwipeOut events to be fired.");
Separator();
var usedA = Any(tgts, t => t.OnFingers.GetPersistentEventCount() > 0);
var usedB = Any(tgts, t => t.OnSwipeParallel.GetPersistentEventCount() > 0);
var usedC = Any(tgts, t => t.OnSwipeIn.GetPersistentEventCount() > 0);
var usedD = Any(tgts, t => t.OnSwipeOut.GetPersistentEventCount() > 0);
var showUnusedEvents = DrawFoldout("Show Unused Events", "Show all events?");
if (usedA == true || showUnusedEvents == true)
{
Draw("onFingers");
}
if (usedB == true || showUnusedEvents == true)
{
Draw("onSwipeParallel");
}
if (usedC == true || showUnusedEvents == true)
{
Draw("onSwipeIn");
}
if (usedD == true || showUnusedEvents == true)
{
Draw("onSwipeOut");
}
}
}
}
#endif