/*
* @author Valentin Simonov / http://va.lent.in/
*/
using System;
using TouchScript.Layers;
using UnityEngine;
namespace TouchScript.Hit
{
///
/// An object representing a point hit by a pointer in 3D, 2D or UI space.
///
public struct HitData
{
#region Consts
///
/// Type of hit
///
[Flags]
public enum HitType
{
///
/// An unknown hit.
///
Unknown,
///
/// Nothing hit, but some object grabbed the pointer.
///
Screen,
///
/// 3D hit.
///
World3D,
///
/// 2D hit.
///
World2D,
///
/// UI hit.
///
UI
}
#endregion
#region Public properties
///
/// Gets the type of the hit.
///
/// The type.
public HitType Type
{
get { return type; }
}
///
/// Gets target Target the hit.
///
/// Hit Target.
public Transform Target
{
get { return target; }
}
///
/// Gets the layer which detected the hit.
///
/// Hit layer.
public TouchLayer Layer
{
get { return layer; }
}
///
/// Gets raycast hit object for a 3D hit.
///
/// Raycast hit object.
public RaycastHit RaycastHit
{
get { return raycastHit; }
}
///
/// Gets 2D raycast hit object for a 2D hit.
///
/// 2D raycast hit object.
public RaycastHit2D RaycastHit2D
{
get { return raycastHit2D; }
}
///
/// Gets raycast hit for a UI hit.
///
/// UI raycast hit object.
public RaycastHitUI RaycastHitUI
{
get { return raycastHitUI; }
}
///
/// Indicates if this is a Screen Space hit.
///
public bool ScreenSpace
{
get { return screenSpace; }
}
///
/// Gets the point in 3D where raycast hit the object.
///
/// Point in 3D.
public Vector3 Point
{
get
{
switch (type)
{
case HitType.World3D:
return raycastHit.point;
case HitType.World2D:
return raycastHit2D.point;
case HitType.UI:
return raycastHitUI.WorldPosition;
}
return Vector3.zero;
}
}
///
/// Gets the normal at the point in 3D wher eraycast hit the object.
///
/// Normal vector.
public Vector3 Normal
{
get
{
switch (type)
{
case HitType.World3D:
return raycastHit.normal;
case HitType.World2D:
return raycastHit2D.normal;
case HitType.UI:
return raycastHitUI.WorldNormal;
}
return Vector3.forward;
}
}
///
/// Distance to the hit point.
///
public float Distance
{
get
{
switch (type)
{
case HitType.World3D:
return raycastHit.distance;
case HitType.World2D:
return raycastHit2D.distance;
case HitType.UI:
return raycastHitUI.Distance;
}
return 0f;
}
}
///
/// Sorting layer of the hit target.
///
public int SortingLayer
{
get
{
switch (type)
{
case HitType.World3D:
return 0;
case HitType.World2D:
if (sortingLayer == -1) updateSortingValues();
return sortingLayer;
case HitType.UI:
return raycastHitUI.SortingLayer;
}
return 0;
}
}
///
/// Sorting order of the hit target.
///
public int SortingOrder
{
get
{
switch (type)
{
case HitType.World3D:
return 0;
case HitType.World2D:
if (sortingLayer == -1) updateSortingValues();
return sortingOrder;
case HitType.UI:
return raycastHitUI.SortingOrder;
}
return 0;
}
}
#endregion
#region Private variables
private HitType type;
private Transform target;
private bool screenSpace;
private TouchLayer layer;
private RaycastHit raycastHit;
private RaycastHit2D raycastHit2D;
private RaycastHitUI raycastHitUI;
private int sortingLayer;
private int sortingOrder;
#endregion
#region Constructors
///
/// Initializes a new instance of the struct.
///
/// Target Target.
/// Touch layer this hit came from.
/// If the hit is screenspace UI.
public HitData(Transform target, TouchLayer layer, bool screenSpace = false)
{
this.target = target;
this.layer = layer;
this.screenSpace = screenSpace;
sortingLayer = -1;
sortingOrder = -1;
raycastHit = default(RaycastHit);
raycastHit2D = default(RaycastHit2D);
raycastHitUI = default(RaycastHitUI);
type = HitType.Screen;
}
///
/// Initializes a new instance of the struct from a 3D raycast.
///
/// 3D raycast value.
/// Touch layer this hit came from.
/// If the hit is screenspace UI.
public HitData(RaycastHit value, TouchLayer layer, bool screenSpace = false) : this(value.collider.transform, layer, screenSpace)
{
raycastHit = value;
type = HitType.World3D;
}
///
/// Initializes a new instance of the struct from a 2D raycast.
///
/// 2D raycast value.
/// Touch layer this hit came from.
/// If the hit is screenspace UI.
public HitData(RaycastHit2D value, TouchLayer layer, bool screenSpace = false) :
this(value.collider.transform, layer, screenSpace)
{
raycastHit2D = value;
type = HitType.World2D;
}
///
/// Initializes a new instance of the struct from a UI raycast.
///
/// UI raycast value.
/// Touch layer this hit came from.
/// If the hit is screenspace UI.
public HitData(RaycastHitUI value, TouchLayer layer, bool screenSpace = false) :
this(value.Target, layer, screenSpace)
{
raycastHitUI = value;
type = HitType.UI;
}
#endregion
#region Private functions
private void updateSortingValues()
{
var sprite = target.GetComponent();
if (sprite == null)
{
sortingLayer = 0;
sortingOrder = 0;
}
else
{
sortingLayer = sprite.sortingLayerID;
sortingOrder = sprite.sortingOrder;
}
}
#endregion
}
}