LMQT/Assets/TouchScript/Scripts/Hit/HitData.cs
2024-12-10 09:03:45 +08:00

318 lines
8.9 KiB
C#

/*
* @author Valentin Simonov / http://va.lent.in/
*/
using System;
using TouchScript.Layers;
using UnityEngine;
namespace TouchScript.Hit
{
/// <summary>
/// An object representing a point hit by a pointer in 3D, 2D or UI space.
/// </summary>
public struct HitData
{
#region Consts
/// <summary>
/// Type of hit
/// </summary>
[Flags]
public enum HitType
{
/// <summary>
/// An unknown hit.
/// </summary>
Unknown,
/// <summary>
/// Nothing hit, but some object grabbed the pointer.
/// </summary>
Screen,
/// <summary>
/// 3D hit.
/// </summary>
World3D,
/// <summary>
/// 2D hit.
/// </summary>
World2D,
/// <summary>
/// UI hit.
/// </summary>
UI
}
#endregion
#region Public properties
/// <summary>
/// Gets the type of the hit.
/// </summary>
/// <value> The type. </value>
public HitType Type
{
get { return type; }
}
/// <summary>
/// Gets target Target the hit.
/// </summary>
/// <value> Hit Target. </value>
public Transform Target
{
get { return target; }
}
/// <summary>
/// Gets the layer which detected the hit.
/// </summary>
/// <value> Hit layer. </value>
public TouchLayer Layer
{
get { return layer; }
}
/// <summary>
/// Gets raycast hit object for a 3D hit.
/// </summary>
/// <value> Raycast hit object. </value>
public RaycastHit RaycastHit
{
get { return raycastHit; }
}
/// <summary>
/// Gets 2D raycast hit object for a 2D hit.
/// </summary>
/// <value> 2D raycast hit object. </value>
public RaycastHit2D RaycastHit2D
{
get { return raycastHit2D; }
}
/// <summary>
/// Gets raycast hit for a UI hit.
/// </summary>
/// <value> UI raycast hit object. </value>
public RaycastHitUI RaycastHitUI
{
get { return raycastHitUI; }
}
/// <summary>
/// Indicates if this is a Screen Space hit.
/// </summary>
public bool ScreenSpace
{
get { return screenSpace; }
}
/// <summary>
/// Gets the point in 3D where raycast hit the object.
/// </summary>
/// <value> Point in 3D. </value>
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;
}
}
/// <summary>
/// Gets the normal at the point in 3D wher eraycast hit the object.
/// </summary>
/// <value> Normal vector. </value>
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;
}
}
/// <summary>
/// Distance to the hit point.
/// </summary>
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;
}
}
/// <summary>
/// Sorting layer of the hit target.
/// </summary>
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;
}
}
/// <summary>
/// Sorting order of the hit target.
/// </summary>
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
/// <summary>
/// Initializes a new instance of the <see cref="HitData"/> struct.
/// </summary>
/// <param name="target"> Target Target. </param>
/// <param name="layer"> Touch layer this hit came from. </param>
/// <param name="screenSpace"> If the hit is screenspace UI. </param>
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;
}
/// <summary>
/// Initializes a new instance of the <see cref="HitData"/> struct from a 3D raycast.
/// </summary>
/// <param name="value"> 3D raycast value. </param>
/// <param name="layer"> Touch layer this hit came from. </param>
/// <param name="screenSpace"> If the hit is screenspace UI. </param>
public HitData(RaycastHit value, TouchLayer layer, bool screenSpace = false) : this(value.collider.transform, layer, screenSpace)
{
raycastHit = value;
type = HitType.World3D;
}
/// <summary>
/// Initializes a new instance of the <see cref="HitData"/> struct from a 2D raycast.
/// </summary>
/// <param name="value"> 2D raycast value. </param>
/// <param name="layer"> Touch layer this hit came from. </param>
/// <param name="screenSpace"> If the hit is screenspace UI. </param>
public HitData(RaycastHit2D value, TouchLayer layer, bool screenSpace = false) :
this(value.collider.transform, layer, screenSpace)
{
raycastHit2D = value;
type = HitType.World2D;
}
/// <summary>
/// Initializes a new instance of the <see cref="HitData"/> struct from a UI raycast.
/// </summary>
/// <param name="value"> UI raycast value. </param>
/// <param name="layer"> Touch layer this hit came from. </param>
/// <param name="screenSpace"> If the hit is screenspace UI. </param>
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<SpriteRenderer>();
if (sprite == null)
{
sortingLayer = 0;
sortingOrder = 0;
}
else
{
sortingLayer = sprite.sortingLayerID;
sortingOrder = sprite.sortingOrder;
}
}
#endregion
}
}