Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ protected override void drawGeneral()
type.intValue = newType;
EditorGUI.indentLevel++;

EditorGUIUtility.labelWidth = 160;
EditorGUIUtility.labelWidth = 200;
EditorGUILayout.PropertyField(simultaneousTransform, TEXT_SIMULTANEOUS_TRANSFORM);
EditorGUILayout.PropertyField(screenTransformThreshold, TEXT_SCREEN_TRANSFORM_THRESHOLD);

base.drawGeneral();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal class TransformGestureBaseEditor : GestureEditor
public static readonly GUIContent TEXT_TYPE_TRANSLATION = new GUIContent("Translation", "Dragging with one ore more fingers.");
public static readonly GUIContent TEXT_TYPE_ROTATION = new GUIContent("Rotation", "Rotating with two or more fingers.");
public static readonly GUIContent TEXT_TYPE_SCALING = new GUIContent("Scaling", "Scaling with two or more fingers.");
public static readonly GUIContent TEXT_SIMULTANEOUS_TRANSFORM = new GUIContent("Simultaneous Transformations", "Whether multiple types of transformations can occur each time this gesture is used.");
public static readonly GUIContent TEXT_MIN_SCREEN_POINTS_DISTANCE = new GUIContent("Min Points Distance (cm)", "Minimum distance between two pointers (clusters) in cm to consider this gesture started. Used to prevent fake pointers spawned near real ones on cheap multitouch hardware to mess everything up.");
public static readonly GUIContent TEXT_SCREEN_TRANSFORM_THRESHOLD = new GUIContent("Movement Threshold (cm)", "Minimum distance in cm pointers must move for the gesture to begin.");

Expand All @@ -27,7 +28,7 @@ internal class TransformGestureBaseEditor : GestureEditor
public static readonly GUIContent TEXT_PROJECTION_NORMAL = new GUIContent("Projection Normal", "Normal of the plane in 3d space where pointers' positions are projected.");


protected SerializedProperty type, minScreenPointsDistance, screenTransformThreshold;
protected SerializedProperty type, simultaneousTransform, minScreenPointsDistance, screenTransformThreshold;
protected SerializedProperty OnTransformStart, OnTransform, OnTransformComplete;

public SerializedProperty projection, projectionPlaneNormal;
Expand All @@ -41,6 +42,7 @@ internal class TransformGestureBaseEditor : GestureEditor
protected override void OnEnable()
{
type = serializedObject.FindProperty("type");
simultaneousTransform = serializedObject.FindProperty("simultaneousTransforms");
minScreenPointsDistance = serializedObject.FindProperty("minScreenPointsDistance");
screenTransformThreshold = serializedObject.FindProperty("screenTransformThreshold");
OnTransformStart = serializedObject.FindProperty("OnTransformStart");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ protected override void drawGeneral()

EditorGUI.indentLevel++;

EditorGUIUtility.labelWidth = 160;
EditorGUIUtility.labelWidth = 200;
EditorGUILayout.PropertyField(simultaneousTransform, TEXT_SIMULTANEOUS_TRANSFORM);
EditorGUILayout.PropertyField(minScreenPointsDistance, TEXT_MIN_SCREEN_POINTS_DISTANCE);
EditorGUILayout.PropertyField(screenTransformThreshold, TEXT_SCREEN_TRANSFORM_THRESHOLD);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,20 @@ protected override void pointersUpdated(IList<Pointer> pointers)
}
}

if (!simultaneousTransforms)
{
if (isTransforming)
{
var fixedType = getIndicatedType(screenCenter, oldScreenPos, newScreenPos, projectionParams);
transformLock.TrySetValue(fixedType);

var singleType = transformLock.Value;
if (singleType != TransformGesture.TransformType.Rotation) dR = 0;
if (singleType != TransformGesture.TransformType.Scaling) dS = 1;
if (singleType != 0 && type.HasFlag(singleType)) transformLock.SetLock();
}
}

if (dR != 0) transformMask |= TransformGesture.TransformType.Rotation;
if (dS != 1) transformMask |= TransformGesture.TransformType.Scaling;

Expand Down Expand Up @@ -241,6 +255,25 @@ protected virtual float doScaling(Vector3 center, Vector2 oldScreenPos, Vector2
return 1;
}

/// <summary>
/// Return the <see cref="TransformGesture.TransformType"/> indicated by the finger's movement.
/// </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> TransformType indicated by the movement of the pointer. </returns>
protected virtual TransformGesture.TransformType getIndicatedType(Vector2 screenCenter, Vector2 oldScreenPos, Vector2 newScreenPos, ProjectionParams projectionParams)
{
var centerLine = oldScreenPos - screenCenter;
var pointerDelta = newScreenPos - oldScreenPos;

if (TwoD.IsPerpendicular(centerLine, pointerDelta))
return TransformGesture.TransformType.Rotation;
else
return TransformGesture.TransformType.Scaling;
}

/// <summary>
/// Checks if there are pointers in the list which matter for the gesture.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ public TransformGesture.TransformType Type
}
}

/// <summary>
/// Gets or sets whether multiple types of transformations can occur each time this gesture is used.
/// </summary>
public bool SimultaneousTransforms
{
get { return simultaneousTransforms; }
set { simultaneousTransforms = value; }
}

/// <summary>
/// Gets or sets minimum distance in cm for pointers to move for gesture to begin.
/// </summary>
Expand Down Expand Up @@ -163,6 +172,11 @@ public Vector3 RotationAxis
/// </summary>
protected TransformGesture.TransformType transformMask;

/// <summary>
/// The single transform type this gesture is restricted to. <see cref="SimultaneousTransforms"/>
/// </summary>
protected Lock<TransformGesture.TransformType> transformLock = new Lock<TransformGesture.TransformType>();

/// <summary>
/// Calculated delta position.
/// </summary>
Expand Down Expand Up @@ -206,6 +220,12 @@ public Vector3 RotationAxis
protected TransformGesture.TransformType type = TransformGesture.TransformType.Translation | TransformGesture.TransformType.Scaling |
TransformGesture.TransformType.Rotation;

/// <summary>
/// Whether multiple types of transformations can occur each time this gesture is used.
/// </summary>
[SerializeField]
protected bool simultaneousTransforms = true;

[SerializeField]
private float screenTransformThreshold = 0.1f;

Expand Down Expand Up @@ -262,6 +282,7 @@ protected override void pointersPressed(IList<Pointer> pointers)
{
case GestureState.Began:
case GestureState.Changed:
transformLock.ClearLock();
setState(GestureState.Ended);
break;
}
Expand All @@ -282,6 +303,7 @@ protected override void pointersReleased(IList<Pointer> pointers)
{
case GestureState.Began:
case GestureState.Changed:
transformLock.ClearLock();
setState(GestureState.Ended);
break;
case GestureState.Possible:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ protected override void pointersUpdated(IList<Pointer> pointers)

// translate using one point
dP = doOnePointTranslation(getPointPreviousScreenPosition(0), getPointScreenPosition(0), projectionParams);

if (!simultaneousTransforms && isTransforming)
{
transformLock.TrySetValue(TransformGesture.TransformType.Translation);
}
}
else
{
Expand Down Expand Up @@ -211,14 +216,34 @@ protected override void pointersUpdated(IList<Pointer> pointers)
else
dP = doTwoPointTranslation(oldScreenPos1, oldScreenPos2, newScreenPos1, newScreenPos2, dR, dS, projectionParams);
}

if (!simultaneousTransforms && isTransforming)
{
var fixedType = getIndicatedType(oldScreenPos1, oldScreenPos2, newScreenPos1, newScreenPos2, projectionParams);
transformLock.TrySetValue(fixedType);
}
}
else if (translationEnabled)
{
// points are too close, translate using one point
dP = doOnePointTranslation(oldScreenPos1, newScreenPos1, projectionParams);

if (!simultaneousTransforms && isTransforming)
{
transformLock.TrySetValue(TransformGesture.TransformType.Translation);
}
}
}

if (!simultaneousTransforms && isTransforming)
{
var singleType = transformLock.Value;
if (singleType != TransformGesture.TransformType.Translation) dP = Vector3.zero;
if (singleType != TransformGesture.TransformType.Rotation) dR = 0;
if (singleType != TransformGesture.TransformType.Scaling) dS = 1;
if (singleType != 0 && type.HasFlag(singleType)) transformLock.SetLock();
}

if (dP != Vector3.zero) transformMask |= TransformGesture.TransformType.Translation;
if (dR != 0) transformMask |= TransformGesture.TransformType.Rotation;
if (dS != 1) transformMask |= TransformGesture.TransformType.Scaling;
Expand Down Expand Up @@ -320,6 +345,39 @@ protected virtual Vector3 doTwoPointTranslation(Vector2 oldScreenPos1, Vector2 o
return Vector3.zero;
}

/// <summary>
/// Return the <see cref="TransformGesture.TransformType"/> indicated by the both fingers' movement.
/// </summary>
/// <param name="oldScreenPos1"> Finger one old screen position. </param>
/// <param name="oldScreenPos2"> Finger two old screen position. </param>
/// <param name="newScreenPos1"> Finger one new screen position. </param>
/// <param name="newScreenPos2"> Finger two new screen position. </param>
/// <param name="projectionParams"> Layer projection parameters. </param>
/// <returns> TransformType indicated by the movement of both fingers. </returns>
protected virtual TransformGesture.TransformType getIndicatedType(Vector2 oldScreenPos1, Vector2 oldScreenPos2,
Vector2 newScreenPos1, Vector2 newScreenPos2,
ProjectionParams projectionParams)
{
var pointerDelta1 = newScreenPos1 - oldScreenPos1;
var pointerDelta2 = newScreenPos2 - oldScreenPos2;
var deg = Vector2.Angle(pointerDelta1, pointerDelta2);

if (deg < 90)
{
// pointers moved in same direction
return TransformGesture.TransformType.Translation;
}
else
{
// pointers moved in opposite directions
var oldScreenDelta = oldScreenPos2 - oldScreenPos1;
if (TwoD.IsPerpendicular(pointerDelta1, oldScreenDelta) && TwoD.IsPerpendicular(pointerDelta2, oldScreenDelta))
return TransformGesture.TransformType.Rotation;
else
return TransformGesture.TransformType.Scaling;
}
}

/// <summary>
/// Gets the number of points.
/// </summary>
Expand Down
12 changes: 12 additions & 0 deletions Source/Assets/TouchScript/Scripts/Utils/Geom/TwoD.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,17 @@ public static Vector2 Rotate(Vector2 point, float angle)
var sin = Mathf.Sin(rad);
return new Vector2(point.x * cos - point.y * sin, point.x * sin + point.y * cos);
}

/// <summary>
/// Determines if two lines are approximately perpendicular.
/// </summary>
/// <param name="line1">Line to check.</param>
/// <param name="line2">Line to check.</param>
/// <returns> <c>true</c> if both lines are approximately perpendicular; <c>false</c> otherwise.</returns>
public static bool IsPerpendicular(Vector2 line1, Vector2 line2)
{
var deg = Vector2.Angle(line1, line2);
return (45 < deg) && (deg < 135);
}
}
}
33 changes: 33 additions & 0 deletions Source/Assets/TouchScript/Scripts/Utils/Lock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace TouchScript.Utils
{
/// <summary>
/// Holds a value which can only be changed when unlocked.
/// </summary>
public class Lock<T>
{
public T Value { get; private set; }

public bool Locked { get; private set; }

/// <summary>
/// If unlocked, set the value.
/// </summary>
public void TrySetValue(T value)
{
if (!Locked)
{
Value = value;
}
}

public void SetLock()
{
Locked = true;
}

public void ClearLock()
{
Locked = false;
}
}
}