322 lines
10 KiB
C#
322 lines
10 KiB
C#
/*
|
|
* @author Valentin Simonov / http://va.lent.in/
|
|
*/
|
|
|
|
using System.Collections.Generic;
|
|
using TouchScript.Layers;
|
|
using TouchScript.Pointers;
|
|
using TouchScript.Utils.Geom;
|
|
using UnityEngine;
|
|
|
|
#if TOUCHSCRIPT_DEBUG
|
|
using System.Collections;
|
|
using TouchScript.Debugging.GL;
|
|
#endif
|
|
|
|
namespace TouchScript.Gestures.TransformGestures.Base
|
|
{
|
|
/// <summary>
|
|
/// Abstract base class for Pinned Transform Gestures.
|
|
/// </summary>
|
|
public abstract class OnePointTrasformGestureBase : TransformGestureBase
|
|
{
|
|
#region Constants
|
|
|
|
#endregion
|
|
|
|
#region Events
|
|
|
|
#endregion
|
|
|
|
#region Public properties
|
|
|
|
/// <inheritdoc />
|
|
public override Vector2 ScreenPosition
|
|
{
|
|
get
|
|
{
|
|
if (NumPointers == 0) return TouchManager.INVALID_POSITION;
|
|
return activePointers[0].Position;
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override Vector2 PreviousScreenPosition
|
|
{
|
|
get
|
|
{
|
|
if (NumPointers == 0) return TouchManager.INVALID_POSITION;
|
|
return activePointers[0].PreviousPosition;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private variables
|
|
|
|
/// <summary>
|
|
/// Translation buffer.
|
|
/// </summary>
|
|
protected Vector2 screenPixelTranslationBuffer;
|
|
|
|
/// <summary>
|
|
/// Rotation buffer.
|
|
/// </summary>
|
|
protected float screenPixelRotationBuffer;
|
|
|
|
/// <summary>
|
|
/// Angle buffer.
|
|
/// </summary>
|
|
protected float angleBuffer;
|
|
|
|
/// <summary>
|
|
/// Screen space scaling buffer.
|
|
/// </summary>
|
|
protected float screenPixelScalingBuffer;
|
|
|
|
/// <summary>
|
|
/// Scaling buffer.
|
|
/// </summary>
|
|
protected float scaleBuffer;
|
|
|
|
#endregion
|
|
|
|
#region Unity methods
|
|
|
|
#if TOUCHSCRIPT_DEBUG
|
|
/// <inheritdoc />
|
|
protected override void Awake()
|
|
{
|
|
base.Awake();
|
|
|
|
debugID = DebugHelper.GetDebugId(this);
|
|
debugPointerSize = Vector2.one * TouchManager.Instance.DotsPerCentimeter * 1.1f;
|
|
}
|
|
#endif
|
|
|
|
#endregion
|
|
|
|
#region Gesture callbacks
|
|
|
|
/// <inheritdoc />
|
|
protected override void pointersUpdated(IList<Pointer> pointers)
|
|
{
|
|
base.pointersUpdated(pointers);
|
|
|
|
var projectionParams = activePointers[0].ProjectionParams;
|
|
var dR = deltaRotation = 0;
|
|
var dS = deltaScale = 1f;
|
|
|
|
#if TOUCHSCRIPT_DEBUG
|
|
var worldCenter = cachedTransform.position;
|
|
var screenCenter = projectionParams.ProjectFrom(worldCenter);
|
|
var newScreenPos = getPointScreenPosition();
|
|
drawDebug(screenCenter, newScreenPos);
|
|
#endif
|
|
|
|
if (pointersNumState != PointersNumState.InRange) return;
|
|
|
|
var rotationEnabled = (Type & TransformGesture.TransformType.Rotation) == TransformGesture.TransformType.Rotation;
|
|
var scalingEnabled = (Type & TransformGesture.TransformType.Scaling) == TransformGesture.TransformType.Scaling;
|
|
if (!rotationEnabled && !scalingEnabled) return;
|
|
if (!relevantPointers(pointers)) return;
|
|
|
|
#if !TOUCHSCRIPT_DEBUG
|
|
var thePointer = activePointers[0];
|
|
var worldCenter = cachedTransform.position;
|
|
var screenCenter = projectionParams.ProjectFrom(worldCenter);
|
|
var newScreenPos = thePointer.Position;
|
|
#endif
|
|
|
|
// Here we can't reuse last frame screen positions because points 0 and 1 can change.
|
|
// For example if the first of 3 fingers is lifted off.
|
|
var oldScreenPos = getPointPreviousScreenPosition();
|
|
|
|
if (rotationEnabled)
|
|
{
|
|
if (isTransforming)
|
|
{
|
|
dR = doRotation(worldCenter, oldScreenPos, newScreenPos, projectionParams);
|
|
}
|
|
else
|
|
{
|
|
// Find how much we moved perpendicular to the line (center, oldScreenPos)
|
|
screenPixelRotationBuffer += TwoD.PointToLineDistance(screenCenter, oldScreenPos, newScreenPos);
|
|
angleBuffer += doRotation(worldCenter, oldScreenPos, newScreenPos, projectionParams);
|
|
|
|
if (screenPixelRotationBuffer * screenPixelRotationBuffer >=
|
|
screenTransformPixelThresholdSquared)
|
|
{
|
|
isTransforming = true;
|
|
dR = angleBuffer;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (scalingEnabled)
|
|
{
|
|
if (isTransforming)
|
|
{
|
|
dS *= doScaling(worldCenter, oldScreenPos, newScreenPos, projectionParams);
|
|
}
|
|
else
|
|
{
|
|
screenPixelScalingBuffer += (newScreenPos - screenCenter).magnitude -
|
|
(oldScreenPos - screenCenter).magnitude;
|
|
scaleBuffer *= doScaling(worldCenter, oldScreenPos, newScreenPos, projectionParams);
|
|
|
|
if (screenPixelScalingBuffer * screenPixelScalingBuffer >=
|
|
screenTransformPixelThresholdSquared)
|
|
{
|
|
isTransforming = true;
|
|
dS = scaleBuffer;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dR != 0) transformMask |= TransformGesture.TransformType.Rotation;
|
|
if (dS != 1) transformMask |= TransformGesture.TransformType.Scaling;
|
|
|
|
if (transformMask != 0)
|
|
{
|
|
if (State == GestureState.Possible) setState(GestureState.Began);
|
|
switch (State)
|
|
{
|
|
case GestureState.Began:
|
|
case GestureState.Changed:
|
|
deltaRotation = dR;
|
|
deltaScale = dS;
|
|
setState(GestureState.Changed);
|
|
resetValues();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override void reset()
|
|
{
|
|
base.reset();
|
|
|
|
screenPixelTranslationBuffer = Vector2.zero;
|
|
screenPixelRotationBuffer = 0f;
|
|
angleBuffer = 0;
|
|
screenPixelScalingBuffer = 0f;
|
|
scaleBuffer = 1f;
|
|
|
|
#if TOUCHSCRIPT_DEBUG
|
|
clearDebug();
|
|
#endif
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Protected methods
|
|
|
|
/// <summary>
|
|
/// Calculates rotation.
|
|
/// </summary>
|
|
/// <param name="center"> Center screen position. </param>
|
|
/// <param name="oldScreenPos"> Pointer old screen position. </param>
|
|
/// <param name="newScreenPos"> Pointer new screen position. </param>
|
|
/// <param name="projectionParams"> Layer projection parameters. </param>
|
|
/// <returns> Angle in degrees. </returns>
|
|
protected virtual float doRotation(Vector3 center, Vector2 oldScreenPos, Vector2 newScreenPos,
|
|
ProjectionParams projectionParams)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculates scaling.
|
|
/// </summary>
|
|
/// <param name="center"> Center screen position. </param>
|
|
/// <param name="oldScreenPos"> Pointer old screen position. </param>
|
|
/// <param name="newScreenPos"> Pointer new screen position. </param>
|
|
/// <param name="projectionParams"> Layer projection parameters. </param>
|
|
/// <returns> Multiplicative delta scaling. </returns>
|
|
protected virtual float doScaling(Vector3 center, Vector2 oldScreenPos, Vector2 newScreenPos,
|
|
ProjectionParams projectionParams)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if there are pointers in the list which matter for the gesture.
|
|
/// </summary>
|
|
/// <param name="pointers"> List of pointers </param>
|
|
/// <returns> <c>true</c> if there are relevant pointers; <c>false</c> otherwise.</returns>
|
|
protected virtual bool relevantPointers(IList<Pointer> pointers)
|
|
{
|
|
// We care only about the first pointer
|
|
var count = pointers.Count;
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
if (pointers[i] == activePointers[0]) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns screen position of a point with index 0.
|
|
/// </summary>
|
|
protected virtual Vector2 getPointScreenPosition()
|
|
{
|
|
return activePointers[0].Position;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns previous screen position of a point with index 0.
|
|
/// </summary>
|
|
protected virtual Vector2 getPointPreviousScreenPosition()
|
|
{
|
|
return activePointers[0].PreviousPosition;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override void updateType()
|
|
{
|
|
type = type & ~TransformGesture.TransformType.Translation;
|
|
}
|
|
|
|
#if TOUCHSCRIPT_DEBUG
|
|
protected virtual void clearDebug()
|
|
{
|
|
GLDebug.RemoveFigure(debugID);
|
|
GLDebug.RemoveFigure(debugID + 1);
|
|
GLDebug.RemoveFigure(debugID + 2);
|
|
|
|
if (debugCoroutine != null) StopCoroutine(debugCoroutine);
|
|
debugCoroutine = null;
|
|
}
|
|
|
|
protected void drawDebugDelayed(Vector2 point1, Vector2 point2)
|
|
{
|
|
if (debugCoroutine != null) StopCoroutine(debugCoroutine);
|
|
debugCoroutine = StartCoroutine(doDrawDebug(point1, point2));
|
|
}
|
|
|
|
protected virtual void drawDebug(Vector2 point1, Vector2 point2)
|
|
{
|
|
if (!DebugMode) return;
|
|
|
|
var color = State == GestureState.Possible ? Color.red : Color.green;
|
|
GLDebug.DrawSquareScreenSpace(debugID + 1, point2, 0f, debugPointerSize, color, float.PositiveInfinity);
|
|
GLDebug.DrawLineScreenSpace(debugID + 2, point1, point2, color, float.PositiveInfinity);
|
|
}
|
|
|
|
private IEnumerator doDrawDebug(Vector2 point1, Vector2 point2)
|
|
{
|
|
yield return new WaitForEndOfFrame();
|
|
|
|
drawDebug(point1, point2);
|
|
}
|
|
#endif
|
|
|
|
#endregion
|
|
|
|
#region Private functions
|
|
|
|
#endregion
|
|
}
|
|
} |