392 lines
12 KiB
C#
392 lines
12 KiB
C#
/*
|
|
* @author Valentin Simonov / http://va.lent.in/
|
|
*/
|
|
|
|
using System;
|
|
using System.Text;
|
|
using TouchScript.Core;
|
|
using TouchScript.Hit;
|
|
using TouchScript.InputSources;
|
|
using TouchScript.Layers;
|
|
using TouchScript.Utils;
|
|
using UnityEngine;
|
|
|
|
namespace TouchScript.Pointers
|
|
{
|
|
/// <summary>
|
|
/// <para>Representation of a pointer (touch, mouse) within TouchScript.</para>
|
|
/// <para>An instance of this class is created when user touches the screen. A unique id is assigned to it which doesn't change throughout its life.</para>
|
|
/// <para><b>Attention!</b> Do not store references to these objects beyond pointer's lifetime (i.e. when target finger is lifted off). These objects may be reused internally. Store unique ids instead.</para>
|
|
/// </summary>
|
|
public class Pointer : IPointer, IEquatable<Pointer>
|
|
{
|
|
#region Constants
|
|
|
|
/// <summary>
|
|
/// Invalid pointer id.
|
|
/// </summary>
|
|
public const int INVALID_POINTER = -1;
|
|
|
|
/// <summary>
|
|
/// This pointer is generated by script and is not mapped to any device input.
|
|
/// </summary>
|
|
public const uint FLAG_ARTIFICIAL = 1 << 0;
|
|
|
|
/// <summary>
|
|
/// This pointer was returned to the system after it was cancelled.
|
|
/// </summary>
|
|
public const uint FLAG_RETURNED = 1 << 1;
|
|
|
|
/// <summary>
|
|
/// This pointer is internal and shouldn't be shown on screen.
|
|
/// </summary>
|
|
public const uint FLAG_INTERNAL = 1 << 2;
|
|
|
|
/// <summary>
|
|
/// Pointer type.
|
|
/// </summary>
|
|
public enum PointerType
|
|
{
|
|
/// <summary>
|
|
/// Unknown.
|
|
/// </summary>
|
|
Unknown,
|
|
|
|
/// <summary>
|
|
/// Touch.
|
|
/// </summary>
|
|
Touch,
|
|
|
|
/// <summary>
|
|
/// Mouse.
|
|
/// </summary>
|
|
Mouse,
|
|
|
|
/// <summary>
|
|
/// Pen.
|
|
/// </summary>
|
|
Pen,
|
|
|
|
/// <summary>
|
|
/// Object.
|
|
/// </summary>
|
|
Object
|
|
}
|
|
|
|
/// <summary>
|
|
/// The state of buttons for a pointer. Combines 3 types of button events: Pressed (holding a button), Down (just pressed this frame) and Up (released this frame).
|
|
/// </summary>
|
|
[Flags]
|
|
public enum PointerButtonState
|
|
{
|
|
/// <summary>
|
|
/// No button is pressed.
|
|
/// </summary>
|
|
Nothing = 0,
|
|
|
|
/// <summary>
|
|
/// Indicates a primary action, analogous to a left mouse button down.
|
|
/// A <see cref="TouchPointer"/> or <see cref="ObjectPointer"/> has this flag set when it is in contact with the digitizer surface.
|
|
/// A <see cref="PenPointer"/> has this flag set when it is in contact with the digitizer surface with no buttons pressed.
|
|
/// A <see cref="MousePointer"/> has this flag set when the left mouse button is down.
|
|
/// </summary>
|
|
FirstButtonPressed = 1 << 0,
|
|
|
|
/// <summary>
|
|
/// Indicates a secondary action, analogous to a right mouse button down.
|
|
/// A <see cref="TouchPointer"/> or <see cref="ObjectPointer"/> does not use this flag.
|
|
/// A <see cref="PenPointer"/> has this flag set when it is in contact with the digitizer surface with the pen barrel button pressed.
|
|
/// A <see cref="MousePointer"/> has this flag set when the right mouse button is down.
|
|
/// </summary>
|
|
SecondButtonPressed = 1 << 1,
|
|
|
|
/// <summary>
|
|
/// Analogous to a mouse wheel button down.
|
|
/// A <see cref="TouchPointer"/>, <see cref="PenPointer"/> or <see cref="ObjectPointer"/> does not use this flag.
|
|
/// A <see cref="MousePointer"/> has this flag set when the mouse wheel button is down.
|
|
/// </summary>
|
|
ThirdButtonPressed = 1 << 2,
|
|
|
|
/// <summary>
|
|
/// Analogous to the first extended button button down.
|
|
/// A <see cref="TouchPointer"/>, <see cref="PenPointer"/> or <see cref="ObjectPointer"/> does not use this flag.
|
|
/// A <see cref="MousePointer"/> has this flag set when the first extended button is down.
|
|
/// </summary>
|
|
FourthButtonPressed = 1 << 3,
|
|
|
|
/// <summary>
|
|
/// Analogous to the second extended button button down.
|
|
/// A <see cref="TouchPointer"/>, <see cref="PenPointer"/> or <see cref="ObjectPointer"/> does not use this flag.
|
|
/// A <see cref="MousePointer"/> has this flag set when the second extended button is down.
|
|
/// </summary>
|
|
FifthButtonPressed = 1 << 4,
|
|
|
|
/// <summary>
|
|
/// First button pressed this frame.
|
|
/// </summary>
|
|
FirstButtonDown = 1 << 11,
|
|
|
|
/// <summary>
|
|
/// First button released this frame.
|
|
/// </summary>
|
|
FirstButtonUp = 1 << 12,
|
|
|
|
/// <summary>
|
|
/// Second button pressed this frame.
|
|
/// </summary>
|
|
SecondButtonDown = 1 << 13,
|
|
|
|
/// <summary>
|
|
/// Second button released this frame.
|
|
/// </summary>
|
|
SecondButtonUp = 1 << 14,
|
|
|
|
/// <summary>
|
|
/// Third button pressed this frame.
|
|
/// </summary>
|
|
ThirdButtonDown = 1 << 15,
|
|
|
|
/// <summary>
|
|
/// Third button released this frame.
|
|
/// </summary>
|
|
ThirdButtonUp = 1 << 16,
|
|
|
|
/// <summary>
|
|
/// Fourth button pressed this frame.
|
|
/// </summary>
|
|
FourthButtonDown = 1 << 17,
|
|
|
|
/// <summary>
|
|
/// Fourth button released this frame.
|
|
/// </summary>
|
|
FourthButtonUp = 1 << 18,
|
|
|
|
/// <summary>
|
|
/// Fifth button pressed this frame.
|
|
/// </summary>
|
|
FifthButtonDown = 1 << 19,
|
|
|
|
/// <summary>
|
|
/// Fifth button released this frame.
|
|
/// </summary>
|
|
FifthButtonUp = 1 << 20,
|
|
|
|
/// <summary>
|
|
/// Any button is pressed.
|
|
/// </summary>
|
|
AnyButtonPressed = FirstButtonPressed | SecondButtonPressed | ThirdButtonPressed | FourthButtonPressed | FifthButtonPressed,
|
|
|
|
/// <summary>
|
|
/// Any button down this frame.
|
|
/// </summary>
|
|
AnyButtonDown = FirstButtonDown | SecondButtonDown | ThirdButtonDown | FourthButtonDown | FifthButtonDown,
|
|
|
|
/// <summary>
|
|
/// Any button up this frame.
|
|
/// </summary>
|
|
AnyButtonUp = FirstButtonUp | SecondButtonUp | ThirdButtonUp | FourthButtonUp | FifthButtonUp
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public properties
|
|
|
|
/// <inheritdoc />
|
|
public int Id { get; private set; }
|
|
|
|
/// <inheritdoc />
|
|
public PointerType Type { get; protected set; }
|
|
|
|
/// <inheritdoc />
|
|
public PointerButtonState Buttons { get; set; }
|
|
|
|
/// <inheritdoc />
|
|
public IInputSource InputSource { get; private set; }
|
|
|
|
/// <inheritdoc />
|
|
public Vector2 Position
|
|
{
|
|
get { return position; }
|
|
set { newPosition = value; }
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Vector2 PreviousPosition { get; private set; }
|
|
|
|
/// <inheritdoc />
|
|
public uint Flags { get; set; }
|
|
|
|
/// <summary>
|
|
/// Projection parameters for the layer which created this pointer.
|
|
/// </summary>
|
|
public ProjectionParams ProjectionParams
|
|
{
|
|
get
|
|
{
|
|
if (pressData.Layer == null) return null;
|
|
return pressData.Layer.GetProjectionParams(this);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private variables
|
|
|
|
private static StringBuilder builder;
|
|
|
|
private LayerManagerInstance layerManager;
|
|
private int refCount = 0;
|
|
private Vector2 position, newPosition;
|
|
private HitData pressData, overData;
|
|
private bool overDataIsDirty = true;
|
|
|
|
#endregion
|
|
|
|
#region Public methods
|
|
|
|
/// <inheritdoc />
|
|
public HitData GetOverData(bool forceRecalculate = false)
|
|
{
|
|
if (overDataIsDirty || forceRecalculate)
|
|
{
|
|
layerManager.GetHitTarget(this, out overData);
|
|
overDataIsDirty = false;
|
|
}
|
|
return overData;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns <see cref="HitData"/> when the pointer was pressed. If the pointer is not pressed uninitialized <see cref="HitData"/> is returned.
|
|
/// </summary>
|
|
public HitData GetPressData()
|
|
{
|
|
return pressData;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies values from the target.
|
|
/// </summary>
|
|
/// <param name="target">The target pointer to copy values from.</param>
|
|
public virtual void CopyFrom(Pointer target)
|
|
{
|
|
Type = target.Type;
|
|
Flags = target.Flags;
|
|
Buttons = target.Buttons;
|
|
position = target.position;
|
|
newPosition = target.newPosition;
|
|
PreviousPosition = target.PreviousPosition;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override bool Equals(object other)
|
|
{
|
|
return Equals(other as Pointer);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public bool Equals(Pointer other)
|
|
{
|
|
if (other == null)
|
|
return false;
|
|
|
|
return Id == other.Id;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override int GetHashCode()
|
|
{
|
|
return Id;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override string ToString()
|
|
{
|
|
if (builder == null) builder = new StringBuilder();
|
|
builder.Length = 0;
|
|
builder.Append("(Pointer type: ");
|
|
builder.Append(Type);
|
|
builder.Append(", id: ");
|
|
builder.Append(Id);
|
|
builder.Append(", buttons: ");
|
|
PointerUtils.PressedButtonsToString(Buttons, builder);
|
|
builder.Append(", flags: ");
|
|
BinaryUtils.ToBinaryString(Flags, builder, 8);
|
|
builder.Append(", position: ");
|
|
builder.Append(Position);
|
|
builder.Append(")");
|
|
return builder.ToString();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Constructor
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="Pointer"/> class.
|
|
/// </summary>
|
|
public Pointer(IInputSource input)
|
|
{
|
|
layerManager = LayerManager.Instance as LayerManagerInstance;
|
|
Type = PointerType.Unknown;
|
|
InputSource = input;
|
|
INTERNAL_Reset();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Internal methods
|
|
|
|
internal virtual void INTERNAL_Init(int id)
|
|
{
|
|
Id = id;
|
|
PreviousPosition = position = newPosition;
|
|
}
|
|
|
|
internal virtual void INTERNAL_Reset()
|
|
{
|
|
Id = INVALID_POINTER;
|
|
INTERNAL_ClearPressData();
|
|
position = newPosition = PreviousPosition = Vector2.zero;
|
|
Flags = 0;
|
|
Buttons = PointerButtonState.Nothing;
|
|
overDataIsDirty = true;
|
|
}
|
|
|
|
internal virtual void INTERNAL_FrameStarted()
|
|
{
|
|
Buttons &= ~(PointerButtonState.AnyButtonDown | PointerButtonState.AnyButtonUp);
|
|
overDataIsDirty = true;
|
|
}
|
|
|
|
internal virtual void INTERNAL_UpdatePosition()
|
|
{
|
|
PreviousPosition = position;
|
|
position = newPosition;
|
|
}
|
|
|
|
internal void INTERNAL_Retain()
|
|
{
|
|
refCount++;
|
|
}
|
|
|
|
internal int INTERNAL_Release()
|
|
{
|
|
return --refCount;
|
|
}
|
|
|
|
internal void INTERNAL_SetPressData(HitData data)
|
|
{
|
|
pressData = data;
|
|
overData = data;
|
|
overDataIsDirty = false;
|
|
}
|
|
|
|
internal void INTERNAL_ClearPressData()
|
|
{
|
|
pressData = default(HitData);
|
|
refCount = 0;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |