/* * @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 { /// /// Representation of a pointer (touch, mouse) within TouchScript. /// 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. /// Attention! 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. /// public class Pointer : IPointer, IEquatable { #region Constants /// /// Invalid pointer id. /// public const int INVALID_POINTER = -1; /// /// This pointer is generated by script and is not mapped to any device input. /// public const uint FLAG_ARTIFICIAL = 1 << 0; /// /// This pointer was returned to the system after it was cancelled. /// public const uint FLAG_RETURNED = 1 << 1; /// /// This pointer is internal and shouldn't be shown on screen. /// public const uint FLAG_INTERNAL = 1 << 2; /// /// Pointer type. /// public enum PointerType { /// /// Unknown. /// Unknown, /// /// Touch. /// Touch, /// /// Mouse. /// Mouse, /// /// Pen. /// Pen, /// /// Object. /// Object } /// /// 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). /// [Flags] public enum PointerButtonState { /// /// No button is pressed. /// Nothing = 0, /// /// Indicates a primary action, analogous to a left mouse button down. /// A or has this flag set when it is in contact with the digitizer surface. /// A has this flag set when it is in contact with the digitizer surface with no buttons pressed. /// A has this flag set when the left mouse button is down. /// FirstButtonPressed = 1 << 0, /// /// Indicates a secondary action, analogous to a right mouse button down. /// A or does not use this flag. /// A has this flag set when it is in contact with the digitizer surface with the pen barrel button pressed. /// A has this flag set when the right mouse button is down. /// SecondButtonPressed = 1 << 1, /// /// Analogous to a mouse wheel button down. /// A , or does not use this flag. /// A has this flag set when the mouse wheel button is down. /// ThirdButtonPressed = 1 << 2, /// /// Analogous to the first extended button button down. /// A , or does not use this flag. /// A has this flag set when the first extended button is down. /// FourthButtonPressed = 1 << 3, /// /// Analogous to the second extended button button down. /// A , or does not use this flag. /// A has this flag set when the second extended button is down. /// FifthButtonPressed = 1 << 4, /// /// First button pressed this frame. /// FirstButtonDown = 1 << 11, /// /// First button released this frame. /// FirstButtonUp = 1 << 12, /// /// Second button pressed this frame. /// SecondButtonDown = 1 << 13, /// /// Second button released this frame. /// SecondButtonUp = 1 << 14, /// /// Third button pressed this frame. /// ThirdButtonDown = 1 << 15, /// /// Third button released this frame. /// ThirdButtonUp = 1 << 16, /// /// Fourth button pressed this frame. /// FourthButtonDown = 1 << 17, /// /// Fourth button released this frame. /// FourthButtonUp = 1 << 18, /// /// Fifth button pressed this frame. /// FifthButtonDown = 1 << 19, /// /// Fifth button released this frame. /// FifthButtonUp = 1 << 20, /// /// Any button is pressed. /// AnyButtonPressed = FirstButtonPressed | SecondButtonPressed | ThirdButtonPressed | FourthButtonPressed | FifthButtonPressed, /// /// Any button down this frame. /// AnyButtonDown = FirstButtonDown | SecondButtonDown | ThirdButtonDown | FourthButtonDown | FifthButtonDown, /// /// Any button up this frame. /// AnyButtonUp = FirstButtonUp | SecondButtonUp | ThirdButtonUp | FourthButtonUp | FifthButtonUp } #endregion #region Public properties /// public int Id { get; private set; } /// public PointerType Type { get; protected set; } /// public PointerButtonState Buttons { get; set; } /// public IInputSource InputSource { get; private set; } /// public Vector2 Position { get { return position; } set { newPosition = value; } } /// public Vector2 PreviousPosition { get; private set; } /// public uint Flags { get; set; } /// /// Projection parameters for the layer which created this pointer. /// 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 /// public HitData GetOverData(bool forceRecalculate = false) { if (overDataIsDirty || forceRecalculate) { layerManager.GetHitTarget(this, out overData); overDataIsDirty = false; } return overData; } /// /// Returns when the pointer was pressed. If the pointer is not pressed uninitialized is returned. /// public HitData GetPressData() { return pressData; } /// /// Copies values from the target. /// /// The target pointer to copy values from. public virtual void CopyFrom(Pointer target) { Type = target.Type; Flags = target.Flags; Buttons = target.Buttons; position = target.position; newPosition = target.newPosition; PreviousPosition = target.PreviousPosition; } /// public override bool Equals(object other) { return Equals(other as Pointer); } /// public bool Equals(Pointer other) { if (other == null) return false; return Id == other.Id; } /// public override int GetHashCode() { return Id; } /// 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 /// /// Initializes a new instance of the class. /// 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 } }