// Object Touch Auto Interact|Interactables|35050
|
|
namespace VRTK
|
|
{
|
|
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
|
|
/// <summary>
|
|
/// Allows for Interact Grab or Interact Use interactions to automatically happen upon touching an Interactable Object.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// **Required Components:**
|
|
/// * `VRTK_InteractableObject` - The Interactable Object component to detect interactions on. This must be applied on the same GameObject as this script if one is not provided via the `Interactable Object` parameter.
|
|
///
|
|
/// **Script Usage:**
|
|
/// * Place the `VRTK_ObjectTouchAutoInteract` script on either:
|
|
/// * The GameObject of the Interactable Object to detect interactions on.
|
|
/// * Any other scene GameObject and provide a valid `VRTK_InteractableObject` component to the `Interactable Object` parameter of this script.
|
|
/// </remarks>
|
|
[AddComponentMenu("VRTK/Scripts/Interactions/Interactables/VRTK_ObjectTouchAutoInteract")]
|
|
public class VRTK_ObjectTouchAutoInteract : VRTK_InteractableListener
|
|
{
|
|
/// <summary>
|
|
/// Situation when auto interaction can occur.
|
|
/// </summary>
|
|
public enum AutoInteractions
|
|
{
|
|
/// <summary>
|
|
/// Auto interaction can never occur on touch.
|
|
/// </summary>
|
|
Never,
|
|
/// <summary>
|
|
/// Auto interaction will occur on touch even if the specified interaction button is not held down.
|
|
/// </summary>
|
|
NoButtonHeld,
|
|
/// <summary>
|
|
/// Auto interaction will only occur on touch if the specified interaction button is held down.
|
|
/// </summary>
|
|
ButtonHeld
|
|
}
|
|
|
|
[Header("Auto Grab")]
|
|
|
|
[Tooltip("Determines when a grab on touch should occur.")]
|
|
public AutoInteractions grabOnTouchWhen = AutoInteractions.Never;
|
|
[Tooltip("After being ungrabbed, another auto grab on touch can only occur after this time.")]
|
|
public float regrabDelay = 0.1f;
|
|
[Tooltip("If this is checked then the grab on touch check will happen every frame and not only on the first touch of the Interactable Object.")]
|
|
public bool continuousGrabCheck = false;
|
|
|
|
[Header("Auto Use")]
|
|
|
|
[Tooltip("Determines when a use on touch should occur.")]
|
|
public AutoInteractions useOnTouchWhen = AutoInteractions.Never;
|
|
[Tooltip("After being unused, another auto use on touch can only occur after this time.")]
|
|
public float reuseDelay = 0.1f;
|
|
[Tooltip("If this is checked then the use on touch check will happen every frame and not only on the first touch of the Interactable Object.")]
|
|
public bool continuousUseCheck = false;
|
|
|
|
[Header("Custom Settings")]
|
|
|
|
[Tooltip("The Interactable Object that the auto interaction will occur on. If this is blank then the script must be on the same GameObject as the Interactable Object script.")]
|
|
public VRTK_InteractableObject interactableObject;
|
|
|
|
protected float regrabTimer;
|
|
protected float reuseTimer;
|
|
protected List<GameObject> touchers = new List<GameObject>();
|
|
|
|
protected virtual void OnEnable()
|
|
{
|
|
regrabTimer = 0f;
|
|
reuseTimer = 0f;
|
|
touchers.Clear();
|
|
EnableListeners();
|
|
}
|
|
|
|
protected virtual void OnDisable()
|
|
{
|
|
TearDownListeners();
|
|
}
|
|
|
|
protected virtual void Update()
|
|
{
|
|
if (interactableObject != null && (continuousGrabCheck || continuousUseCheck))
|
|
{
|
|
for (int i = 0; i < touchers.Count; i++)
|
|
{
|
|
if (continuousGrabCheck)
|
|
{
|
|
CheckGrab(touchers[i]);
|
|
}
|
|
if (continuousUseCheck)
|
|
{
|
|
CheckUse(touchers[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override bool SetupListeners(bool throwError)
|
|
{
|
|
interactableObject = (interactableObject != null ? interactableObject : GetComponentInParent<VRTK_InteractableObject>());
|
|
if (interactableObject != null)
|
|
{
|
|
interactableObject.InteractableObjectTouched += InteractableObjectTouched;
|
|
interactableObject.InteractableObjectUntouched += InteractableObjectUntouched;
|
|
interactableObject.InteractableObjectUngrabbed += InteractableObjectUngrabbed;
|
|
interactableObject.InteractableObjectUnused += InteractableObjectUnused;
|
|
return true;
|
|
}
|
|
else if (throwError)
|
|
{
|
|
VRTK_Logger.Error(VRTK_Logger.GetCommonMessage(VRTK_Logger.CommonMessageKeys.REQUIRED_COMPONENT_MISSING_FROM_GAMEOBJECT, "VRTK_ObjectTouchAutoInteract", "VRTK_InteractableObject", "the same or parent"));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected override void TearDownListeners()
|
|
{
|
|
if (interactableObject != null)
|
|
{
|
|
interactableObject.InteractableObjectTouched -= InteractableObjectTouched;
|
|
interactableObject.InteractableObjectUntouched -= InteractableObjectUntouched;
|
|
interactableObject.InteractableObjectUngrabbed -= InteractableObjectUngrabbed;
|
|
interactableObject.InteractableObjectUnused -= InteractableObjectUnused;
|
|
}
|
|
}
|
|
|
|
protected virtual void InteractableObjectTouched(object sender, InteractableObjectEventArgs e)
|
|
{
|
|
ManageTouchers(e.interactingObject, true);
|
|
CheckGrab(e.interactingObject);
|
|
CheckUse(e.interactingObject);
|
|
}
|
|
|
|
protected virtual void InteractableObjectUntouched(object sender, InteractableObjectEventArgs e)
|
|
{
|
|
ManageTouchers(e.interactingObject, false);
|
|
}
|
|
|
|
protected virtual void InteractableObjectUngrabbed(object sender, InteractableObjectEventArgs e)
|
|
{
|
|
regrabTimer = regrabDelay + Time.time;
|
|
}
|
|
|
|
|
|
protected virtual void InteractableObjectUnused(object sender, InteractableObjectEventArgs e)
|
|
{
|
|
reuseTimer = reuseDelay + Time.time;
|
|
}
|
|
|
|
protected virtual void ManageTouchers(GameObject interactingObject, bool add)
|
|
{
|
|
if (add)
|
|
{
|
|
VRTK_SharedMethods.AddListValue(touchers, interactingObject, true);
|
|
}
|
|
else
|
|
{
|
|
touchers.Remove(interactingObject);
|
|
}
|
|
}
|
|
|
|
protected virtual void CheckGrab(GameObject interactingObject)
|
|
{
|
|
if (grabOnTouchWhen != AutoInteractions.Never && regrabTimer < Time.time)
|
|
{
|
|
VRTK_InteractGrab interactGrabScript = interactingObject.GetComponentInChildren<VRTK_InteractGrab>();
|
|
if (interactGrabScript != null && (grabOnTouchWhen == AutoInteractions.NoButtonHeld || (grabOnTouchWhen == AutoInteractions.ButtonHeld && interactGrabScript.IsGrabButtonPressed())))
|
|
{
|
|
interactGrabScript.AttemptGrab();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected virtual void CheckUse(GameObject interactingObject)
|
|
{
|
|
if (useOnTouchWhen != AutoInteractions.Never && reuseTimer < Time.time)
|
|
{
|
|
VRTK_InteractUse interactUseScript = interactingObject.GetComponentInChildren<VRTK_InteractUse>();
|
|
if (interactUseScript != null && (useOnTouchWhen == AutoInteractions.NoButtonHeld || (useOnTouchWhen == AutoInteractions.ButtonHeld && interactUseScript.IsUseButtonPressed())))
|
|
{
|
|
if (!interactableObject.holdButtonToUse && interactableObject.IsUsing())
|
|
{
|
|
interactableObject.ForceStopInteracting();
|
|
}
|
|
else
|
|
{
|
|
interactUseScript.AttemptUse();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|