using UnityEngine;
using System.Collections.Generic;
using Lean.Common;
namespace Lean.Touch
{
/// This class stores information about a single touch (or simulated touch).
public class LeanFinger
{
/// This is the hardware ID of the finger.
/// NOTE: Simulated fingers will use hardware ID -1 and -2.
public int Index;
/// This tells you how long this finger has been active (or inactive) in seconds.
public float Age;
/// Is this finger currently touching the screen?
public bool Set;
/// This tells you the 'Set' value of the last frame.
public bool LastSet;
/// Did this finger just tap the screen?
public bool Tap;
/// This tells you how many times this finger has been tapped.
public int TapCount;
/// Did this finger just swipe the screen?
public bool Swipe;
/// If this finger has been touching the screen for more than TapThreshold, this will be true.
public bool Old;
/// If this finger has been inactive for more than TapThreshold, this will be true.
public bool Expired;
/// This tells you the Pressure value last frame.
public float LastPressure;
/// This tells you the current pressure of this finger (NOTE: only some devices support this).
public float Pressure;
/// This tells you the 'ScreenPosition' value of this finger when it began touching the screen.
public Vector2 StartScreenPosition;
/// This tells you the last screen position of the finger.
public Vector2 LastScreenPosition;
/// This tells you the current screen position of the finger in pixels, where 0,0 = bottom left.
public Vector2 ScreenPosition;
/// This tells you if the current finger had 'IsOverGui' set to true when it began touching the screen.
public bool StartedOverGui;
/// Used to store position snapshots, enable RecordFingers in LeanTouch to use this.
public List Snapshots = new List(1000);
/// This will return true if this finger is currently touching the screen.
public bool IsActive
{
get
{
return LeanTouch.Fingers.Contains(this);
}
}
/// This will tell you how many seconds of snapshot footage is stored for this finger.
public float SnapshotDuration
{
get
{
if (Snapshots.Count > 0)
{
return Age - Snapshots[0].Age;
}
return 0.0f;
}
}
/// This will return true if the current finger is over any Unity GUI elements.
public bool IsOverGui
{
get
{
return LeanTouch.PointOverGui(ScreenPosition);
}
}
/// Did this finger begin touching the screen this frame?
public bool Down
{
get
{
return Set == true && LastSet == false;
}
}
/// Did the finger stop touching the screen this frame?
public bool Up
{
get
{
return Set == false && LastSet == true;
}
}
/// This will return how far in pixels the finger has moved since the last recorded snapshot.
public Vector2 LastSnapshotScreenDelta
{
get
{
var snapshotCount = Snapshots.Count;
if (snapshotCount > 0)
{
var snapshot = Snapshots[snapshotCount - 1];
if (snapshot != null)
{
return ScreenPosition - snapshot.ScreenPosition;
}
}
return Vector2.zero;
}
}
/// This returns a resolution-independent 'LastSnapshotScreenDelta' value.
public Vector2 LastSnapshotScaledDelta
{
get
{
return LastSnapshotScreenDelta * LeanTouch.ScalingFactor;
}
}
/// This will return how far in pixels the finger has moved since the last frame.
public Vector2 ScreenDelta
{
get
{
return ScreenPosition - LastScreenPosition;
}
}
/// This returns a resolution-independent 'ScreenDelta' value.
public Vector2 ScaledDelta
{
get
{
return ScreenDelta * LeanTouch.ScalingFactor;
}
}
/// This tells you how far this finger has moved since it began touching the screen.
public Vector2 SwipeScreenDelta
{
get
{
return ScreenPosition - StartScreenPosition;
}
}
/// This returns a resolution-independent 'SwipeScreenDelta' value.
public Vector2 SwipeScaledDelta
{
get
{
return SwipeScreenDelta * LeanTouch.ScalingFactor;
}
}
/// This returns a smooth point between the previous and current screen position based on a 0..1 progress value.
public Vector2 GetSmoothScreenPosition(float t)
{
if (Snapshots.Count > 0 && Set == true)
{
var d = Snapshots[Mathf.Max(0, Snapshots.Count - 4)].ScreenPosition;
var c = Snapshots[Mathf.Max(0, Snapshots.Count - 3)].ScreenPosition;
var b = Snapshots[Mathf.Max(0, Snapshots.Count - 2)].ScreenPosition;
var a = Snapshots[Mathf.Max(0, Snapshots.Count - 1)].ScreenPosition;
return LeanHelper.Hermite(d, c, b, a, t);
}
return Vector2.LerpUnclamped(LastScreenPosition, ScreenPosition, t);
}
/// This returns the screen space distance between the 0 and 1 smooth screen positions.
public float SmoothScreenPositionDelta
{
get
{
if (Snapshots.Count > 0 && Set == true)
{
var c = Snapshots[Mathf.Max(0, Snapshots.Count - 3)].ScreenPosition;
var b = Snapshots[Mathf.Max(0, Snapshots.Count - 2)].ScreenPosition;
return Vector2.Distance(c, b);
}
return Vector2.Distance(LastScreenPosition, ScreenPosition);
}
}
/// This will return the ray of the finger's current position relative to the specified camera (none/null = Main Camera).
public Ray GetRay(Camera camera = null)
{
// Make sure the camera exists
camera = LeanHelper.GetCamera(camera);
if (camera != null)
{
return camera.ScreenPointToRay(ScreenPosition);
}
else
{
Debug.LogError("Failed to find camera. Either tag your cameras MainCamera, or set one in this component.");
}
return default(Ray);
}
/// This will return the ray of the finger's start position relative to the specified camera (none/null = Main Camera).
public Ray GetStartRay(Camera camera = null)
{
// Make sure the camera exists
camera = LeanHelper.GetCamera(camera);
if (camera != null)
{
return camera.ScreenPointToRay(StartScreenPosition);
}
else
{
Debug.LogError("Failed to find camera. Either tag your cameras MainCamera, or set one in this component.");
}
return default(Ray);
}
/// This will tell you how far the finger has moved in the past 'deltaTime' seconds.
public Vector2 GetSnapshotScreenDelta(float deltaTime)
{
return ScreenPosition - GetSnapshotScreenPosition(Age - deltaTime);
}
/// This returns a resolution-independent 'GetSnapshotScreenDelta' value.
public Vector2 GetSnapshotScaledDelta(float deltaTime)
{
return GetSnapshotScreenDelta(deltaTime) * LeanTouch.ScalingFactor;
}
/// This will return the recorded position of the current finger when it was at 'targetAge'.
public Vector2 GetSnapshotScreenPosition(float targetAge)
{
var screenPosition = ScreenPosition;
LeanSnapshot.TryGetScreenPosition(Snapshots, targetAge, ref screenPosition);
return screenPosition;
}
/// This will return the recorded world of the current finger when it was at 'targetAge'.
public Vector3 GetSnapshotWorldPosition(float targetAge, float distance, Camera camera = null)
{
// Make sure the camera exists
camera = LeanHelper.GetCamera(camera);
if (camera != null)
{
var screenPosition = GetSnapshotScreenPosition(targetAge);
var point = new Vector3(screenPosition.x, screenPosition.y, distance);
return camera.ScreenToWorldPoint(point);
}
else
{
Debug.LogError("Failed to find camera. Either tag your cameras MainCamera, or set one in this component.");
}
return default(Vector3);
}
/// This will return the angle between the finger and the reference point, relative to the screen.
public float GetRadians(Vector2 referencePoint)
{
return Mathf.Atan2(ScreenPosition.x - referencePoint.x, ScreenPosition.y - referencePoint.y);
}
/// This will return the angle between the finger and the reference point, relative to the screen.
public float GetDegrees(Vector2 referencePoint)
{
return GetRadians(referencePoint) * Mathf.Rad2Deg;
}
/// This will return the angle between the last finger position and the reference point, relative to the screen.
public float GetLastRadians(Vector2 referencePoint)
{
return Mathf.Atan2(LastScreenPosition.x - referencePoint.x, LastScreenPosition.y - referencePoint.y);
}
/// This will return the angle between the last finger position and the reference point, relative to the screen.
public float GetLastDegrees(Vector2 referencePoint)
{
return GetLastRadians(referencePoint) * Mathf.Rad2Deg;
}
/// This will return the delta angle between the last and current finger position relative to the reference point.
public float GetDeltaRadians(Vector2 referencePoint)
{
return GetDeltaRadians(referencePoint, referencePoint);
}
/// This will return the delta angle between the last and current finger position relative to the reference point and the last reference point.
public float GetDeltaRadians(Vector2 referencePoint, Vector2 lastReferencePoint)
{
var a = GetLastRadians(lastReferencePoint);
var b = GetRadians(referencePoint);
var d = Mathf.Repeat(a - b, Mathf.PI * 2.0f);
if (d > Mathf.PI)
{
d -= Mathf.PI * 2.0f;
}
return d;
}
/// This will return the delta angle between the last and current finger position relative to the reference point.
public float GetDeltaDegrees(Vector2 referencePoint)
{
return GetDeltaRadians(referencePoint, referencePoint) * Mathf.Rad2Deg;
}
/// This will return the delta angle between the last and current finger position relative to the reference point and the last reference point.
public float GetDeltaDegrees(Vector2 referencePoint, Vector2 lastReferencePoint)
{
return GetDeltaRadians(referencePoint, lastReferencePoint) * Mathf.Rad2Deg;
}
/// This will return the distance between the finger and the reference point.
public float GetScreenDistance(Vector2 point)
{
return Vector2.Distance(ScreenPosition, point);
}
/// This returns a resolution-independent 'GetScreenDistance' value.
public float GetScaledDistance(Vector2 point)
{
return GetScreenDistance(point) * LeanTouch.ScalingFactor;
}
/// This will return the distance between the last finger and the reference point.
public float GetLastScreenDistance(Vector2 point)
{
return Vector2.Distance(LastScreenPosition, point);
}
/// This returns a resolution-independent 'GetLastScreenDistance' value.
public float GetLastScaledDistance(Vector2 point)
{
return GetLastScreenDistance(point) * LeanTouch.ScalingFactor;
}
/// This will return the distance between the start finger and the reference point.
public float GetStartScreenDistance(Vector2 point)
{
return Vector2.Distance(StartScreenPosition, point);
}
/// This returns a resolution-independent 'GetStartScreenDistance' value.
public float GetStartScaledDistance(Vector2 point)
{
return GetStartScreenDistance(point) * LeanTouch.ScalingFactor;
}
/// This will return the start world position of this finger based on the distance from the camera.
public Vector3 GetStartWorldPosition(float distance, Camera camera = null)
{
// Make sure the camera exists
camera = LeanHelper.GetCamera(camera);
if (camera != null)
{
var point = new Vector3(StartScreenPosition.x, StartScreenPosition.y, distance);
return camera.ScreenToWorldPoint(point);
}
else
{
Debug.LogError("Failed to find camera. Either tag your cameras MainCamera, or set one in this component.");
}
return default(Vector3);
}
/// This will return the last world position of this finger based on the distance from the camera.
public Vector3 GetLastWorldPosition(float distance, Camera camera = null)
{
// Make sure the camera exists
camera = LeanHelper.GetCamera(camera);
if (camera != null)
{
var point = new Vector3(LastScreenPosition.x, LastScreenPosition.y, distance);
return camera.ScreenToWorldPoint(point);
}
else
{
Debug.LogError("Failed to find camera. Either tag your cameras MainCamera, or set one in this component.");
}
return default(Vector3);
}
/// This will return the world position of this finger based on the distance from the camera.
public Vector3 GetWorldPosition(float distance, Camera camera = null)
{
// Make sure the camera exists
camera = LeanHelper.GetCamera(camera);
if (camera != null)
{
var point = new Vector3(ScreenPosition.x, ScreenPosition.y, distance);
return camera.ScreenToWorldPoint(point);
}
else
{
Debug.LogError("Failed to find camera. Either tag your cameras MainCamera, or set one in this component.");
}
return default(Vector3);
}
/// This will return the change in world position of this finger based on the distance from the camera.
public Vector3 GetWorldDelta(float distance, Camera camera = null)
{
return GetWorldDelta(distance, distance, camera);
}
/// This will return the change in world position of this finger based on the last and current distance from the camera.
public Vector3 GetWorldDelta(float lastDistance, float distance, Camera camera = null)
{
// Make sure the camera exists
camera = LeanHelper.GetCamera(camera);
if (camera != null)
{
return GetWorldPosition(distance, camera) - GetLastWorldPosition(lastDistance, camera);
}
else
{
Debug.LogError("Failed to find camera. Either tag your cameras MainCamera, or set one in this component.");
}
return default(Vector3);
}
/// This will clear all snapshots for this finger and pool them, count = -1 for all.
public void ClearSnapshots(int count = -1)
{
// Clear old ones only?
if (count > 0 && count <= Snapshots.Count)
{
for (var i = 0; i < count; i++)
{
LeanSnapshot.InactiveSnapshots.Add(Snapshots[i]);
}
Snapshots.RemoveRange(0, count);
}
// Clear all?
else if (count < 0)
{
LeanSnapshot.InactiveSnapshots.AddRange(Snapshots);
Snapshots.Clear();
}
}
/// Calling this will instantly store a snapshot of the current finger position.
public void RecordSnapshot()
{
// Get an unused snapshot and set it up
var snapshot = LeanSnapshot.Pop();
snapshot.Age = Age;
snapshot.ScreenPosition = ScreenPosition;
// Add to list
Snapshots.Add(snapshot);
}
}
}