Assignment for RMIT Mixed Reality in 2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

267 lines
11 KiB

// Headset Controller Aware|Presence|70040
namespace VRTK
{
using UnityEngine;
/// <summary>
/// Event Payload
/// </summary>
/// <param name="raycastHit">The Raycast Hit struct of item that is obscuring the path to the controller.</param>
/// <param name="controllerReference">The reference to the controller that is being or has been obscured or being or has been glanced.</param>
public struct HeadsetControllerAwareEventArgs
{
public RaycastHit raycastHit;
public VRTK_ControllerReference controllerReference;
}
/// <summary>
/// Event Payload
/// </summary>
/// <param name="sender">this object</param>
/// <param name="e"><see cref="HeadsetControllerAwareEventArgs"/></param>
public delegate void HeadsetControllerAwareEventHandler(object sender, HeadsetControllerAwareEventArgs e);
/// <summary>
/// Determines whether the HMD is in line of sight to the controllers or if the headset is directly looking at one of the controllers.
/// </summary>
/// <remarks>
/// **Script Usage:**
/// * Place the `VRTK_HeadsetControllerAware` script on any active scene GameObject.
/// </remarks>
/// <example>
/// `VRTK/Examples/029_Controller_Tooltips` displays tooltips that have been added to the controllers and are only visible when the controller is being looked at.
/// </example>
[AddComponentMenu("VRTK/Scripts/Presence/VRTK_HeadsetControllerAware")]
public class VRTK_HeadsetControllerAware : MonoBehaviour
{
[Tooltip("If this is checked then the left controller will be checked if items obscure it's path from the headset.")]
public bool trackLeftController = true;
[Tooltip("If this is checked then the right controller will be checked if items obscure it's path from the headset.")]
public bool trackRightController = true;
[Tooltip("The radius of the accepted distance from the controller origin point to determine if the controller is being looked at.")]
public float controllerGlanceRadius = 0.15f;
[Tooltip("A custom transform to provide the world space position of the right controller.")]
public Transform customRightControllerOrigin;
[Tooltip("A custom transform to provide the world space position of the left controller.")]
public Transform customLeftControllerOrigin;
[Tooltip("A custom raycaster to use when raycasting to find controllers.")]
public VRTK_CustomRaycast customRaycast;
/// <summary>
/// Emitted when the controller is obscured by another object.
/// </summary>
public event HeadsetControllerAwareEventHandler ControllerObscured;
/// <summary>
/// Emitted when the controller is no longer obscured by an object.
/// </summary>
public event HeadsetControllerAwareEventHandler ControllerUnobscured;
/// <summary>
/// Emitted when the controller is seen by the headset view.
/// </summary>
public event HeadsetControllerAwareEventHandler ControllerGlanceEnter;
/// <summary>
/// Emitted when the controller is no longer seen by the headset view.
/// </summary>
public event HeadsetControllerAwareEventHandler ControllerGlanceExit;
protected GameObject leftController;
protected GameObject rightController;
protected Transform headset;
protected bool leftControllerObscured = false;
protected bool rightControllerObscured = false;
protected bool leftControllerLastState = false;
protected bool rightControllerLastState = false;
protected bool leftControllerGlance = false;
protected bool rightControllerGlance = false;
protected bool leftControllerGlanceLastState = false;
protected bool rightControllerGlanceLastState = false;
public virtual void OnControllerObscured(HeadsetControllerAwareEventArgs e)
{
if (ControllerObscured != null)
{
ControllerObscured(this, e);
}
}
public virtual void OnControllerUnobscured(HeadsetControllerAwareEventArgs e)
{
if (ControllerUnobscured != null)
{
ControllerUnobscured(this, e);
}
}
public virtual void OnControllerGlanceEnter(HeadsetControllerAwareEventArgs e)
{
if (ControllerGlanceEnter != null)
{
ControllerGlanceEnter(this, e);
}
}
public virtual void OnControllerGlanceExit(HeadsetControllerAwareEventArgs e)
{
if (ControllerGlanceExit != null)
{
ControllerGlanceExit(this, e);
}
}
/// <summary>
/// The LeftControllerObscured method returns the state of if the left controller is being obscured from the path of the headset.
/// </summary>
/// <returns>Returns `true` if the path between the headset and the controller is obscured.</returns>
public virtual bool LeftControllerObscured()
{
return leftControllerObscured;
}
/// <summary>
/// The RightControllerObscured method returns the state of if the right controller is being obscured from the path of the headset.
/// </summary>
/// <returns>Returns `true` if the path between the headset and the controller is obscured.</returns>
public virtual bool RightControllerObscured()
{
return rightControllerObscured;
}
/// <summary>
/// the LeftControllerGlanced method returns the state of if the headset is currently looking at the left controller or not.
/// </summary>
/// <returns>Returns `true` if the headset can currently see the controller within the given radius threshold.</returns>
public virtual bool LeftControllerGlanced()
{
return leftControllerGlance;
}
/// <summary>
/// the RightControllerGlanced method returns the state of if the headset is currently looking at the right controller or not.
/// </summary>
/// <returns>Returns `true` if the headset can currently see the controller within the given radius threshold.</returns>
public virtual bool RightControllerGlanced()
{
return rightControllerGlance;
}
protected virtual void Awake()
{
VRTK_SDKManager.AttemptAddBehaviourToToggleOnLoadedSetupChange(this);
}
protected virtual void OnEnable()
{
headset = VRTK_DeviceFinder.HeadsetTransform();
leftController = VRTK_DeviceFinder.GetControllerLeftHand();
rightController = VRTK_DeviceFinder.GetControllerRightHand();
}
protected virtual void OnDisable()
{
leftController = null;
rightController = null;
}
protected virtual void OnDestroy()
{
VRTK_SDKManager.AttemptRemoveBehaviourToToggleOnLoadedSetupChange(this);
}
protected virtual void Update()
{
if (trackLeftController)
{
RayCastToController(leftController, customLeftControllerOrigin, ref leftControllerObscured, ref leftControllerLastState);
}
if (trackRightController)
{
RayCastToController(rightController, customRightControllerOrigin, ref rightControllerObscured, ref rightControllerLastState);
}
CheckHeadsetView(leftController, customLeftControllerOrigin, ref leftControllerGlance, ref leftControllerGlanceLastState);
CheckHeadsetView(rightController, customRightControllerOrigin, ref rightControllerGlance, ref rightControllerGlanceLastState);
}
protected virtual HeadsetControllerAwareEventArgs SetHeadsetControllerAwareEvent(RaycastHit raycastHit, VRTK_ControllerReference controllerReference)
{
HeadsetControllerAwareEventArgs e;
e.raycastHit = raycastHit;
e.controllerReference = controllerReference;
return e;
}
protected virtual void RayCastToController(GameObject controller, Transform customDestination, ref bool obscured, ref bool lastState)
{
obscured = false;
if (controller != null && controller.gameObject.activeInHierarchy)
{
Vector3 destination = (customDestination ? customDestination.position : controller.transform.position);
RaycastHit hitInfo;
if (VRTK_CustomRaycast.Linecast(customRaycast, headset.position, destination, out hitInfo, Physics.IgnoreRaycastLayer, QueryTriggerInteraction.Ignore))
{
obscured = true;
}
if (lastState != obscured)
{
ObscuredStateChanged(controller.gameObject, obscured, hitInfo);
}
lastState = obscured;
}
}
protected virtual void ObscuredStateChanged(GameObject controller, bool obscured, RaycastHit hitInfo)
{
VRTK_ControllerReference controllerReference = VRTK_ControllerReference.GetControllerReference(controller);
if (obscured)
{
OnControllerObscured(SetHeadsetControllerAwareEvent(hitInfo, controllerReference));
}
else
{
OnControllerUnobscured(SetHeadsetControllerAwareEvent(hitInfo, controllerReference));
}
}
protected virtual void CheckHeadsetView(GameObject controller, Transform customDestination, ref bool controllerGlance, ref bool controllerGlanceLastState)
{
controllerGlance = false;
if (controller != null && controller.gameObject.activeInHierarchy)
{
Vector3 controllerPosition = (customDestination ? customDestination.position : controller.transform.position);
float distanceFromHeadsetToController = Vector3.Distance(headset.position, controllerPosition);
Vector3 lookPoint = headset.position + (headset.forward * distanceFromHeadsetToController);
if (Vector3.Distance(controllerPosition, lookPoint) <= controllerGlanceRadius)
{
controllerGlance = true;
}
if (controllerGlanceLastState != controllerGlance)
{
GlanceStateChanged(controller.gameObject, controllerGlance);
}
controllerGlanceLastState = controllerGlance;
}
}
protected virtual void GlanceStateChanged(GameObject controller, bool glance)
{
RaycastHit emptyHit = new RaycastHit();
VRTK_ControllerReference controllerReference = VRTK_ControllerReference.GetControllerReference(controller);
if (glance)
{
OnControllerGlanceEnter(SetHeadsetControllerAwareEvent(emptyHit, controllerReference));
}
else
{
OnControllerGlanceExit(SetHeadsetControllerAwareEvent(emptyHit, controllerReference));
}
}
}
}