/*
* @author Valentin Simonov / http://va.lent.in/
*/
using System;
using System.Collections.Generic;
using TouchScript.Core;
using TouchScript.Devices.Display;
using TouchScript.Layers;
using TouchScript.Pointers;
using TouchScript.Utils.Attributes;
using UnityEngine;
using UnityEngine.Events;
using Object = UnityEngine.Object;
namespace TouchScript
{
///
/// A facade object to configure and hold parameters for an instance of . Contains constants used throughout the library.
///
///
///
/// An instance of may be added to a Unity scene to hold (i.e. serialize them to the scene) parameters needed to configure an instance of used in application. Which can be accessed via static property.
/// Though it's not required it is a convenient way to configure TouchScript for your scene. You can use different configuration options for different scenes.
///
[AddComponentMenu("TouchScript/Touch Manager")]
[HelpURL("http://touchscript.github.io/docs/html/T_TouchScript_TouchManager.htm")]
public sealed class TouchManager : DebuggableMonoBehaviour
{
#region Constants
#if TOUCHSCRIPT_DEBUG
public const int DEBUG_GL_START = int.MinValue;
public const int DEBUG_GL_TOUCH = DEBUG_GL_START;
#endif
///
/// Event implementation in Unity EventSystem for pointer events.
///
[Serializable]
public class PointerEvent : UnityEvent> {}
///
/// Event implementation in Unity EventSystem for frame events.
///
///
[Serializable]
public class FrameEvent : UnityEvent {}
///
/// Values of a bit-mask representing which Unity messages an instance of will dispatch.
///
[Flags]
public enum MessageType
{
///
/// Pointer frame started.
///
FrameStarted = 1 << 0,
///
/// Pointer frame finished.
///
FrameFinished = 1 << 1,
///
/// Some pointers were added during the frame.
///
PointersAdded = 1 << 2,
///
/// Some pointers were updated during the frame.
///
PointersUpdated = 1 << 3,
///
/// Some pointers have touched the surface during the frame.
///
PointersPressed = 1 << 4,
///
/// Some pointers were released during the frame.
///
PointersReleased = 1 << 5,
///
/// Some pointers were removed during the frame.
///
PointersRemoved = 1 << 6,
///
/// Some pointers were cancelled during the frame.
///
PointersCancelled = 1 << 7
}
///
/// Names of dispatched Unity messages.
///
public enum MessageName
{
///
/// Pointer frame started.
///
OnFrameStart = MessageType.FrameStarted,
///
/// Pointer frame finished.
///
OnFrameFinish = MessageType.FrameFinished,
///
/// Some pointers were added during the frame.
///
OnPointersAdd = MessageType.PointersAdded,
///
/// Some pointers have updated during the frame.
///
OnPointersUpdate = MessageType.PointersUpdated,
///
/// Some pointers have touched the surface during the frame.
///
OnPointersPress = MessageType.PointersPressed,
///
/// Some pointers were released during the frame.
///
OnPointersRelease = MessageType.PointersReleased,
///
/// Some pointers were removed during the frame.
///
OnPointersRemove = MessageType.PointersRemoved,
///
/// Some pointers were cancelled during the frame.
///
OnPointersCancel = MessageType.PointersCancelled
}
///
/// Centimeter to inch ratio to be used in DPI calculations.
///
public const float CM_TO_INCH = 0.393700787f;
///
/// Inch to centimeter ratio to be used in DPI calculations.
///
public const float INCH_TO_CM = 1 / CM_TO_INCH;
///
/// The value used to represent an unknown state of a screen position. Use to check if a point has unknown value.
///
public static readonly Vector2 INVALID_POSITION = new Vector2(float.NaN, float.NaN);
///
/// TouchScript version.
///
public static readonly Version VERSION = new Version(9, 0);
///
/// TouchScript version suffix.
///
public static readonly string VERSION_SUFFIX = "";
#endregion
#region Events
///
/// Occurs when a new frame is started before all other events.
///
public FrameEvent OnFrameStart = new FrameEvent();
///
/// Occurs when a frame is finished. After all other events.
///
[SerializeField]
public FrameEvent OnFrameFinish = new FrameEvent();
///
/// Occurs when new hovering pointers are added.
///
[SerializeField]
public PointerEvent OnPointersAdd = new PointerEvent();
///
/// Occurs when pointers are updated.
///
[SerializeField]
public PointerEvent OnPointersUpdate = new PointerEvent();
///
/// Occurs when pointers touch the surface.
///
[SerializeField]
public PointerEvent OnPointersPress = new PointerEvent();
///
/// Occurs when pointers are released.
///
[SerializeField]
public PointerEvent OnPointersRelease = new PointerEvent();
///
/// Occurs when pointers are removed from the system.
///
[SerializeField]
public PointerEvent OnPointersRemove = new PointerEvent();
///
/// Occurs when pointers are cancelled.
///
[SerializeField]
public PointerEvent OnPointersCancel = new PointerEvent();
#endregion
#region Public properties
///
/// Gets the instance of implementation used in the application.
///
/// An instance of which is in charge of global pointer input control in the application.
public static ITouchManager Instance
{
get { return TouchManagerInstance.Instance; }
}
///
/// Gets or sets current display device.
///
/// Object which holds properties of current display device, like DPI and others.
/// A shortcut for which is also serialized into scene.
public IDisplayDevice DisplayDevice
{
get
{
if (Instance == null) return displayDevice as IDisplayDevice;
return Instance.DisplayDevice;
}
set
{
if (Instance == null)
{
displayDevice = value as Object;
return;
}
Instance.DisplayDevice = value;
}
}
///
/// Indicates if TouchScript should create a CameraLayer for you if no layers present in a scene.
///
/// true if a CameraLayer should be created on startup; otherwise, false.
/// This is usually a desired behavior but sometimes you would want to turn this off if you are using TouchScript only to get pointer input from some device.
public bool ShouldCreateCameraLayer
{
get { return shouldCreateCameraLayer; }
set { shouldCreateCameraLayer = value; }
}
///
/// Gets or sets a value indicating whether a should be created in scene if no inputs present.
///
/// true if StandardInput should be created; otherwise, false.
/// This is usually a desired behavior but sometimes you would want to turn this off.
public bool ShouldCreateStandardInput
{
get { return shouldCreateStandardInput; }
set { shouldCreateStandardInput = value; }
}
///
/// Gets or sets a value indicating whether Unity messages are sent when dispatches events.
///
/// true if Unity messages are used; otherwise, false.
/// If Unity messages are used they are sent to an object set as a value of property or to TouchManager's GameObject if it's null.
public bool UseSendMessage
{
get { return useSendMessage; }
set
{
if (value == useSendMessage) return;
useSendMessage = value;
updateSendMessageSubscription();
}
}
///
/// Gets or sets the bit-mask which indicates which events from an instance of are sent as Unity messages.
///
/// Bit-mask with corresponding bits for used events.
public MessageType SendMessageEvents
{
get { return sendMessageEvents; }
set
{
if (sendMessageEvents == value) return;
sendMessageEvents = value;
updateSendMessageSubscription();
}
}
///
/// Gets or sets the SendMessage target GameObject.
///
/// Which GameObject to use to dispatch Unity messages. If null, TouchManager's GameObject is used.
public GameObject SendMessageTarget
{
get { return sendMessageTarget; }
set
{
sendMessageTarget = value;
if (value == null) sendMessageTarget = gameObject;
}
}
///
/// Gets or sets a value indicating whether Unity Events should be used.
///
///
/// true if TouchManager should use Unity Events; otherwise, false.
///
public bool UseUnityEvents
{
get { return useUnityEvents; }
set
{
if (useUnityEvents == value) return;
useUnityEvents = value;
updateUnityEventsSubscription();
}
}
#if TOUCHSCRIPT_DEBUG
///
public override bool DebugMode
{
get { return base.DebugMode; }
set
{
base.DebugMode = value;
if (Application.isPlaying) (Instance as TouchManagerInstance).DebugMode = value;
}
}
#endif
#endregion
#region Public methods
///
/// Determines whether a Vector2 represents an invalid position, i.e. if it is equal to .
///
/// Screen position.
/// true if position is invalid; otherwise, false.
public static bool IsInvalidPosition(Vector2 position)
{
return position.x == INVALID_POSITION.x && position.y == INVALID_POSITION.y;
}
#endregion
#region Private variables
#pragma warning disable CS0414
[SerializeField]
[HideInInspector]
private bool basicEditor = true;
#pragma warning restore CS0414
[SerializeField]
private Object displayDevice;
[SerializeField]
[ToggleLeft]
private bool shouldCreateCameraLayer = true;
[SerializeField]
[ToggleLeft]
private bool shouldCreateStandardInput = true;
[SerializeField]
[ToggleLeft]
private bool useSendMessage = false;
[SerializeField]
private MessageType sendMessageEvents = MessageType.PointersPressed | MessageType.PointersCancelled |
MessageType.PointersReleased | MessageType.PointersUpdated |
MessageType.PointersAdded | MessageType.PointersRemoved;
[SerializeField]
private GameObject sendMessageTarget;
[SerializeField]
private bool useUnityEvents = false;
[SerializeField]
private List layers = new List();
#endregion
#region Unity
private void Awake()
{
if (Instance == null) return;
#if TOUCHSCRIPT_DEBUG
if (DebugMode) (Instance as TouchManagerInstance).DebugMode = true;
#endif
Instance.DisplayDevice = displayDevice as IDisplayDevice;
Instance.ShouldCreateCameraLayer = ShouldCreateCameraLayer;
Instance.ShouldCreateStandardInput = ShouldCreateStandardInput;
for (var i = 0; i < layers.Count; i++)
{
var layer = layers[i];
if (layer != null) LayerManager.Instance.AddLayer(layer, i);
}
}
private void OnEnable()
{
updateSendMessageSubscription();
updateUnityEventsSubscription();
}
private void OnDisable()
{
removeSendMessageSubscriptions();
removeUnityEventsSubscriptions();
}
[ContextMenu("Basic Editor")]
private void switchToBasicEditor()
{
basicEditor = true;
}
#endregion
#region Private functions
private void updateSendMessageSubscription()
{
if (!Application.isPlaying) return;
if (Instance == null) return;
if (sendMessageTarget == null) sendMessageTarget = gameObject;
removeSendMessageSubscriptions();
if (!useSendMessage) return;
if ((SendMessageEvents & MessageType.FrameStarted) != 0) Instance.FrameStarted += frameStartedSendMessageHandler;
if ((SendMessageEvents & MessageType.FrameFinished) != 0) Instance.FrameFinished += frameFinishedSendMessageHandler;
if ((SendMessageEvents & MessageType.PointersAdded) != 0) Instance.PointersAdded += pointersAddedSendMessageHandler;
if ((SendMessageEvents & MessageType.PointersUpdated) != 0) Instance.PointersUpdated += pointersUpdatedSendMessageHandler;
if ((SendMessageEvents & MessageType.PointersPressed) != 0) Instance.PointersPressed += pointersPressedSendMessageHandler;
if ((SendMessageEvents & MessageType.PointersReleased) != 0) Instance.PointersReleased += pointersReleasedSendMessageHandler;
if ((SendMessageEvents & MessageType.PointersRemoved) != 0) Instance.PointersRemoved += pointersRemovedSendMessageHandler;
if ((SendMessageEvents & MessageType.PointersCancelled) != 0) Instance.PointersCancelled += pointersCancelledSendMessageHandler;
}
private void removeSendMessageSubscriptions()
{
if (!Application.isPlaying) return;
if (Instance == null) return;
Instance.FrameStarted -= frameStartedSendMessageHandler;
Instance.FrameFinished -= frameFinishedSendMessageHandler;
Instance.PointersAdded -= pointersAddedSendMessageHandler;
Instance.PointersUpdated -= pointersUpdatedSendMessageHandler;
Instance.PointersPressed -= pointersPressedSendMessageHandler;
Instance.PointersReleased -= pointersReleasedSendMessageHandler;
Instance.PointersRemoved -= pointersRemovedSendMessageHandler;
Instance.PointersCancelled -= pointersCancelledSendMessageHandler;
}
private void pointersAddedSendMessageHandler(object sender, PointerEventArgs e)
{
sendMessageTarget.SendMessage(MessageName.OnPointersAdd.ToString(), e.Pointers,
SendMessageOptions.DontRequireReceiver);
}
private void pointersUpdatedSendMessageHandler(object sender, PointerEventArgs e)
{
sendMessageTarget.SendMessage(MessageName.OnPointersUpdate.ToString(), e.Pointers,
SendMessageOptions.DontRequireReceiver);
}
private void pointersPressedSendMessageHandler(object sender, PointerEventArgs e)
{
sendMessageTarget.SendMessage(MessageName.OnPointersPress.ToString(), e.Pointers,
SendMessageOptions.DontRequireReceiver);
}
private void pointersReleasedSendMessageHandler(object sender, PointerEventArgs e)
{
sendMessageTarget.SendMessage(MessageName.OnPointersRelease.ToString(), e.Pointers,
SendMessageOptions.DontRequireReceiver);
}
private void pointersRemovedSendMessageHandler(object sender, PointerEventArgs e)
{
sendMessageTarget.SendMessage(MessageName.OnPointersRemove.ToString(), e.Pointers,
SendMessageOptions.DontRequireReceiver);
}
private void pointersCancelledSendMessageHandler(object sender, PointerEventArgs e)
{
sendMessageTarget.SendMessage(MessageName.OnPointersCancel.ToString(), e.Pointers,
SendMessageOptions.DontRequireReceiver);
}
private void frameStartedSendMessageHandler(object sender, EventArgs e)
{
sendMessageTarget.SendMessage(MessageName.OnFrameStart.ToString(),
SendMessageOptions.DontRequireReceiver);
}
private void frameFinishedSendMessageHandler(object sender, EventArgs e)
{
sendMessageTarget.SendMessage(MessageName.OnFrameFinish.ToString(),
SendMessageOptions.DontRequireReceiver);
}
private void updateUnityEventsSubscription()
{
if (!Application.isPlaying) return;
if (Instance == null) return;
removeUnityEventsSubscriptions();
if (!useUnityEvents) return;
Instance.FrameStarted += frameStartedUnityEventsHandler;
Instance.FrameFinished += frameFinishedUnityEventsHandler;
Instance.PointersAdded += pointersAddedUnityEventsHandler;
Instance.PointersUpdated += pointersUpdatedUnityEventsHandler;
Instance.PointersPressed += pointersPressedUnityEventsHandler;
Instance.PointersReleased += pointersReleasedUnityEventsHandler;
Instance.PointersRemoved += pointersRemovedUnityEventsHandler;
Instance.PointersCancelled += pointersCancelledUnityEventsHandler;
}
private void removeUnityEventsSubscriptions()
{
if (!Application.isPlaying) return;
if (Instance == null) return;
Instance.FrameStarted -= frameStartedUnityEventsHandler;
Instance.FrameFinished -= frameFinishedUnityEventsHandler;
Instance.PointersAdded -= pointersAddedUnityEventsHandler;
Instance.PointersUpdated -= pointersUpdatedUnityEventsHandler;
Instance.PointersPressed -= pointersPressedUnityEventsHandler;
Instance.PointersReleased -= pointersReleasedUnityEventsHandler;
Instance.PointersRemoved -= pointersRemovedUnityEventsHandler;
Instance.PointersCancelled -= pointersCancelledUnityEventsHandler;
}
private void pointersAddedUnityEventsHandler(object sender, PointerEventArgs e)
{
OnPointersAdd.Invoke(e.Pointers);
}
private void pointersUpdatedUnityEventsHandler(object sender, PointerEventArgs e)
{
OnPointersUpdate.Invoke(e.Pointers);
}
private void pointersPressedUnityEventsHandler(object sender, PointerEventArgs e)
{
OnPointersPress.Invoke(e.Pointers);
}
private void pointersReleasedUnityEventsHandler(object sender, PointerEventArgs e)
{
OnPointersRelease.Invoke(e.Pointers);
}
private void pointersRemovedUnityEventsHandler(object sender, PointerEventArgs e)
{
OnPointersRemove.Invoke(e.Pointers);
}
private void pointersCancelledUnityEventsHandler(object sender, PointerEventArgs e)
{
OnPointersCancel.Invoke(e.Pointers);
}
private void frameStartedUnityEventsHandler(object sender, EventArgs e)
{
OnFrameStart.Invoke();
}
private void frameFinishedUnityEventsHandler(object sender, EventArgs e)
{
OnFrameFinish.Invoke();
}
#endregion
}
}