Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Interact Grab|Interactors|30040
- namespace VRTK
- {
- using UnityEngine;
- /// <summary>
- /// Determines if the Interact Touch can initiate a grab with the touched Interactable Object.
- /// </summary>
- /// <remarks>
- /// **Required Components:**
- /// * `VRTK_InteractTouch` - The touch component to determine when a valid touch has taken place to denote a grab can occur. This must be applied on the same GameObject as this script if one is not provided via the `Interact Touch` parameter.
- ///
- /// **Optional Components:**
- /// * `VRTK_ControllerEvents` - The events component to listen for the button presses on. This must be applied on the same GameObject as this script if one is not provided via the `Controller Events` parameter.
- ///
- /// **Script Usage:**
- /// * Place the `VRTK_InteractGrab` script on either:
- /// * The GameObject with the Interact Touch and Controller Events scripts.
- /// * Any other scene GameObject and provide a valid `VRTK_ControllerEvents` component to the `Controller Events` parameter and a valid `VRTK_InteractTouch` component to the `Interact Touch` parameter of this script.
- /// </remarks>
- /// <example>
- /// `VRTK/Examples/005_Controller/BasicObjectGrabbing` demonstrates the grabbing of interactable objects that have the `VRTK_InteractableObject` script attached to them. The objects can be picked up and thrown around.
- ///
- /// `VRTK/Examples/013_Controller_UsingAndGrabbingMultipleObjects` demonstrates that each controller can grab and use objects independently and objects can also be toggled to their use state simultaneously.
- ///
- /// `VRTK/Examples/014_Controller_SnappingObjectsOnGrab` demonstrates the different mechanisms for snapping a grabbed object to the controller.
- /// </example>
- [AddComponentMenu("VRTK/Scripts/Interactions/Interactors/VRTK_InteractGrab")]
- public class VRTK_InteractGrab : MonoBehaviour
- {
- [Header("Grab Settings")]
- [Tooltip("The button used to grab/release a touched Interactable Object.")]
- public VRTK_ControllerEvents.ButtonAlias grabButton = VRTK_ControllerEvents.ButtonAlias.GripPress;
- [Tooltip("An amount of time between when the grab button is pressed to when the controller is touching an Interactable Object to grab it.")]
- public float grabPrecognition = 0f;
- [Tooltip("An amount to multiply the velocity of any Interactable Object being thrown.")]
- public float throwMultiplier = 1f;
- [Tooltip("If this is checked and the Interact Touch is not touching an Interactable Object when the grab button is pressed then a Rigidbody is added to the interacting object to allow it to push other Rigidbody objects around.")]
- public bool createRigidBodyWhenNotTouching = false;
- [Header("Custom Settings")]
- [Tooltip("The rigidbody point on the controller model to snap the grabbed Interactable Object to. If blank it will be set to the SDK default.")]
- public Rigidbody controllerAttachPoint = null;
- [Tooltip("The Controller Events to listen for the events on. If the script is being applied onto a controller then this parameter can be left blank as it will be auto populated by the controller the script is on at runtime.")]
- public VRTK_ControllerEvents controllerEvents;
- [Tooltip("The Interact Touch to listen for touches on. If the script is being applied onto a controller then this parameter can be left blank as it will be auto populated by the controller the script is on at runtime.")]
- public VRTK_InteractTouch interactTouch;
- /// <summary>
- /// Emitted when the grab button is pressed.
- /// </summary>
- public event ControllerInteractionEventHandler GrabButtonPressed;
- /// <summary>
- /// Emitted when the grab button is released.
- /// </summary>
- public event ControllerInteractionEventHandler GrabButtonReleased;
- /// <summary>
- /// Emitted when a grab of a valid object is started.
- /// </summary>
- public event ObjectInteractEventHandler ControllerStartGrabInteractableObject;
- /// <summary>
- /// Emitted when a valid object is grabbed.
- /// </summary>
- public event ObjectInteractEventHandler ControllerGrabInteractableObject;
- /// <summary>
- /// Emitted when a ungrab of a valid object is started.
- /// </summary>
- public event ObjectInteractEventHandler ControllerStartUngrabInteractableObject;
- /// <summary>
- /// Emitted when a valid object is released from being grabbed.
- /// </summary>
- public event ObjectInteractEventHandler ControllerUngrabInteractableObject;
- protected VRTK_ControllerEvents.ButtonAlias subscribedGrabButton = VRTK_ControllerEvents.ButtonAlias.Undefined;
- protected VRTK_ControllerEvents.ButtonAlias savedGrabButton = VRTK_ControllerEvents.ButtonAlias.Undefined;
- protected bool grabPressed;
- protected GameObject grabbedObject = null;
- protected bool influencingGrabbedObject = false;
- protected int grabEnabledState = 0;
- protected float grabPrecognitionTimer = 0f;
- protected GameObject undroppableGrabbedObject;
- protected Rigidbody originalControllerAttachPoint;
- protected VRTK_ControllerReference controllerReference
- {
- get
- {
- return VRTK_ControllerReference.GetControllerReference((interactTouch != null ? interactTouch.gameObject : null));
- }
- }
- public virtual void OnControllerStartGrabInteractableObject(ObjectInteractEventArgs e)
- {
- if (ControllerStartGrabInteractableObject != null)
- {
- ControllerStartGrabInteractableObject(this, e);
- }
- }
- public virtual void OnControllerGrabInteractableObject(ObjectInteractEventArgs e)
- {
- if (ControllerGrabInteractableObject != null)
- {
- ControllerGrabInteractableObject(this, e);
- }
- }
- public virtual void OnControllerStartUngrabInteractableObject(ObjectInteractEventArgs e)
- {
- if (ControllerStartUngrabInteractableObject != null)
- {
- ControllerStartUngrabInteractableObject(this, e);
- }
- }
- public virtual void OnControllerUngrabInteractableObject(ObjectInteractEventArgs e)
- {
- if (ControllerUngrabInteractableObject != null)
- {
- ControllerUngrabInteractableObject(this, e);
- }
- }
- public virtual void OnGrabButtonPressed(ControllerInteractionEventArgs e)
- {
- if (GrabButtonPressed != null)
- {
- GrabButtonPressed(this, e);
- }
- }
- public virtual void OnGrabButtonReleased(ControllerInteractionEventArgs e)
- {
- if (GrabButtonReleased != null)
- {
- GrabButtonReleased(this, e);
- }
- }
- /// <summary>
- /// The IsGrabButtonPressed method determines whether the current grab alias button is being pressed down.
- /// </summary>
- /// <returns>Returns `true` if the grab alias button is being held down.</returns>
- public virtual bool IsGrabButtonPressed()
- {
- return grabPressed;
- }
- /// <summary>
- /// The ForceRelease method will force the Interact Grab to stop grabbing the currently grabbed Interactable Object.
- /// </summary>
- /// <param name="applyGrabbingObjectVelocity">If this is true then upon releasing the Interactable Object any velocity on the Interact Touch GameObject will be applied to the Interactable Object to essentiall throw it. Defaults to `false`.</param>
- public virtual void ForceRelease(bool applyGrabbingObjectVelocity = false)
- {
- InitUngrabbedObject(applyGrabbingObjectVelocity);
- }
- /// <summary>
- /// The AttemptGrab method will attempt to grab the currently touched Interactable Object without needing to press the grab button on the controller.
- /// </summary>
- public virtual void AttemptGrab()
- {
- AttemptGrabObject();
- }
- /// <summary>
- /// The GetGrabbedObject method returns the current Interactable Object being grabbed by the this Interact Grab.
- /// </summary>
- /// <returns>The game object of what is currently being grabbed by this controller.</returns>
- public virtual GameObject GetGrabbedObject()
- {
- return grabbedObject;
- }
- /// <summary>
- /// The ForceControllerAttachPoint method updates the rigidbody being used as the controller grab attach position.
- /// </summary>
- /// <param name="forcedAttachPoint">The rigidbody to use as the controller attach point.</param>
- public virtual void ForceControllerAttachPoint(Rigidbody forcedAttachPoint)
- {
- originalControllerAttachPoint = forcedAttachPoint;
- controllerAttachPoint = forcedAttachPoint;
- }
- protected virtual void Awake()
- {
- originalControllerAttachPoint = controllerAttachPoint;
- controllerEvents = (controllerEvents != null ? controllerEvents : GetComponentInParent<VRTK_ControllerEvents>());
- interactTouch = (interactTouch != null ? interactTouch : GetComponentInParent<VRTK_InteractTouch>());
- if (interactTouch == null)
- {
- VRTK_Logger.Error(VRTK_Logger.GetCommonMessage(VRTK_Logger.CommonMessageKeys.REQUIRED_COMPONENT_MISSING_NOT_INJECTED, "VRTK_InteractGrab", "VRTK_InteractTouch", "interactTouch", "the same or parent"));
- }
- VRTK_SDKManager.AttemptAddBehaviourToToggleOnLoadedSetupChange(this);
- }
- protected virtual void OnEnable()
- {
- RegrabUndroppableObject();
- ManageGrabListener(true);
- ManageInteractTouchListener(true);
- if (controllerEvents != null)
- {
- controllerEvents.ControllerIndexChanged += DoControllerModelUpdate;
- controllerEvents.ControllerModelAvailable += DoControllerModelUpdate;
- }
- SetControllerAttachPoint();
- }
- protected virtual void OnDisable()
- {
- SetUndroppableObject();
- ForceRelease();
- ManageGrabListener(false);
- ManageInteractTouchListener(false);
- if (controllerEvents != null)
- {
- controllerEvents.ControllerIndexChanged -= DoControllerModelUpdate;
- controllerEvents.ControllerModelAvailable -= DoControllerModelUpdate;
- }
- }
- protected virtual void OnDestroy()
- {
- VRTK_SDKManager.AttemptRemoveBehaviourToToggleOnLoadedSetupChange(this);
- }
- protected virtual void Update()
- {
- ManageGrabListener(true);
- CheckControllerAttachPointSet();
- CreateNonTouchingRigidbody();
- CheckPrecognitionGrab();
- }
- protected virtual void DoControllerModelUpdate(object sender, ControllerInteractionEventArgs e)
- {
- SetControllerAttachPoint();
- }
- protected virtual void ManageInteractTouchListener(bool state)
- {
- if (interactTouch != null && !state)
- {
- interactTouch.ControllerTouchInteractableObject -= ControllerTouchInteractableObject;
- interactTouch.ControllerUntouchInteractableObject -= ControllerUntouchInteractableObject;
- }
- if (interactTouch != null && state)
- {
- interactTouch.ControllerTouchInteractableObject += ControllerTouchInteractableObject;
- interactTouch.ControllerUntouchInteractableObject += ControllerUntouchInteractableObject;
- }
- }
- protected virtual void ControllerTouchInteractableObject(object sender, ObjectInteractEventArgs e)
- {
- if (e.target != null)
- {
- VRTK_InteractableObject touchedObjectScript = e.target.GetComponent<VRTK_InteractableObject>();
- if (touchedObjectScript != null && touchedObjectScript.grabOverrideButton != VRTK_ControllerEvents.ButtonAlias.Undefined)
- {
- savedGrabButton = subscribedGrabButton;
- grabButton = touchedObjectScript.grabOverrideButton;
- ManageGrabListener(true);
- }
- }
- }
- protected virtual void ControllerUntouchInteractableObject(object sender, ObjectInteractEventArgs e)
- {
- if (e.target != null)
- {
- VRTK_InteractableObject touchedObjectScript = e.target.GetComponent<VRTK_InteractableObject>();
- if (!touchedObjectScript.IsGrabbed() && savedGrabButton != VRTK_ControllerEvents.ButtonAlias.Undefined)
- {
- grabButton = savedGrabButton;
- savedGrabButton = VRTK_ControllerEvents.ButtonAlias.Undefined;
- ManageGrabListener(true);
- }
- }
- }
- protected virtual void ManageGrabListener(bool state)
- {
- if (controllerEvents != null && subscribedGrabButton != VRTK_ControllerEvents.ButtonAlias.Undefined && (!state || grabButton != subscribedGrabButton))
- {
- controllerEvents.UnsubscribeToButtonAliasEvent(subscribedGrabButton, true, DoGrabObject);
- controllerEvents.UnsubscribeToButtonAliasEvent(subscribedGrabButton, false, DoReleaseObject);
- subscribedGrabButton = VRTK_ControllerEvents.ButtonAlias.Undefined;
- }
- if (controllerEvents != null && state && grabButton != VRTK_ControllerEvents.ButtonAlias.Undefined && grabButton != subscribedGrabButton)
- {
- controllerEvents.SubscribeToButtonAliasEvent(grabButton, true, DoGrabObject);
- controllerEvents.SubscribeToButtonAliasEvent(grabButton, false, DoReleaseObject);
- subscribedGrabButton = grabButton;
- }
- }
- protected virtual void RegrabUndroppableObject()
- {
- if (undroppableGrabbedObject != null)
- {
- VRTK_InteractableObject undroppableGrabbedObjectScript = undroppableGrabbedObject.GetComponent<VRTK_InteractableObject>();
- if (interactTouch != null && undroppableGrabbedObjectScript != null && !undroppableGrabbedObjectScript.IsGrabbed())
- {
- undroppableGrabbedObject.SetActive(true);
- interactTouch.ForceTouch(undroppableGrabbedObject);
- AttemptGrab();
- }
- }
- else
- {
- undroppableGrabbedObject = null;
- }
- }
- protected virtual void SetUndroppableObject()
- {
- if (undroppableGrabbedObject != null)
- {
- VRTK_InteractableObject undroppableGrabbedObjectScript = undroppableGrabbedObject.GetComponent<VRTK_InteractableObject>();
- if (undroppableGrabbedObjectScript != null && undroppableGrabbedObjectScript.IsDroppable())
- {
- undroppableGrabbedObject = null;
- }
- else
- {
- undroppableGrabbedObject.SetActive(false);
- }
- }
- }
- protected virtual void SetControllerAttachPoint()
- {
- //If no attach point has been specified then just use the tip of the controller
- if (controllerReference.model != null && originalControllerAttachPoint == null)
- {
- //attempt to find the attach point on the controller
- SDK_BaseController.ControllerHand handType = VRTK_DeviceFinder.GetControllerHand(interactTouch.gameObject);
- string elementPath = VRTK_SDK_Bridge.GetControllerElementPath(SDK_BaseController.ControllerElements.AttachPoint, handType);
- Transform defaultAttachPoint = controllerReference.model.transform.Find(elementPath);
- if (defaultAttachPoint != null)
- {
- controllerAttachPoint = defaultAttachPoint.GetComponent<Rigidbody>();
- if (controllerAttachPoint == null)
- {
- Rigidbody autoGenRB = defaultAttachPoint.gameObject.AddComponent<Rigidbody>();
- autoGenRB.isKinematic = true;
- controllerAttachPoint = autoGenRB;
- }
- }
- }
- }
- protected virtual bool IsObjectGrabbable(GameObject obj)
- {
- VRTK_InteractableObject objScript = obj.GetComponent<VRTK_InteractableObject>();
- return (interactTouch != null && interactTouch.IsObjectInteractable(obj) && objScript != null && (objScript.isGrabbable || objScript.PerformSecondaryAction()));
- }
- protected virtual bool IsObjectHoldOnGrab(GameObject obj)
- {
- if (obj != null)
- {
- VRTK_InteractableObject objScript = obj.GetComponent<VRTK_InteractableObject>();
- return (objScript != null && objScript.holdButtonToGrab);
- }
- return false;
- }
- protected virtual void ChooseGrabSequence(VRTK_InteractableObject grabbedObjectScript)
- {
- if (!grabbedObjectScript.IsGrabbed() || grabbedObjectScript.IsSwappable())
- {
- InitPrimaryGrab(grabbedObjectScript);
- }
- else
- {
- InitSecondaryGrab(grabbedObjectScript);
- }
- }
- protected virtual void ToggleControllerVisibility(bool visible)
- {
- if (grabbedObject != null)
- {
- ///[Obsolete]
- #pragma warning disable 0618
- VRTK_InteractControllerAppearance[] controllerAppearanceScript = grabbedObject.GetComponentsInParent<VRTK_InteractControllerAppearance>(true);
- #pragma warning restore 0618
- if (controllerAppearanceScript.Length > 0)
- {
- controllerAppearanceScript[0].ToggleControllerOnGrab(visible, controllerReference.model, grabbedObject);
- }
- }
- else if (visible)
- {
- VRTK_ObjectAppearance.SetRendererVisible(controllerReference.model, grabbedObject);
- }
- }
- protected virtual void InitGrabbedObject()
- {
- grabbedObject = (interactTouch != null ? interactTouch.GetTouchedObject() : null);
- if (grabbedObject != null)
- {
- OnControllerStartGrabInteractableObject(interactTouch.SetControllerInteractEvent(grabbedObject));
- VRTK_InteractableObject grabbedObjectScript = grabbedObject.GetComponent<VRTK_InteractableObject>();
- ChooseGrabSequence(grabbedObjectScript);
- ToggleControllerVisibility(false);
- OnControllerGrabInteractableObject(interactTouch.SetControllerInteractEvent(grabbedObject));
- }
- }
- protected virtual void InitPrimaryGrab(VRTK_InteractableObject currentGrabbedObject)
- {
- if (!currentGrabbedObject.IsValidInteractableController(gameObject, currentGrabbedObject.allowedGrabControllers))
- {
- grabbedObject = null;
- if (interactTouch != null && currentGrabbedObject.IsGrabbed(gameObject))
- {
- interactTouch.ForceStopTouching();
- }
- return;
- }
- influencingGrabbedObject = false;
- currentGrabbedObject.SaveCurrentState();
- currentGrabbedObject.Grabbed(this);
- currentGrabbedObject.ZeroVelocity();
- currentGrabbedObject.isKinematic = false;
- }
- protected virtual void InitSecondaryGrab(VRTK_InteractableObject currentGrabbedObject)
- {
- influencingGrabbedObject = true;
- currentGrabbedObject.Grabbed(this);
- }
- protected virtual void CheckInfluencingObjectOnRelease()
- {
- if (!influencingGrabbedObject && interactTouch != null)
- {
- interactTouch.ForceStopTouching();
- ToggleControllerVisibility(true);
- }
- influencingGrabbedObject = false;
- }
- protected virtual void InitUngrabbedObject(bool applyGrabbingObjectVelocity)
- {
- if (grabbedObject != null && interactTouch != null)
- {
- OnControllerStartUngrabInteractableObject(interactTouch.SetControllerInteractEvent(grabbedObject));
- VRTK_InteractableObject grabbedObjectScript = grabbedObject.GetComponent<VRTK_InteractableObject>();
- if (grabbedObjectScript != null)
- {
- if (!influencingGrabbedObject)
- {
- grabbedObjectScript.grabAttachMechanicScript.StopGrab(applyGrabbingObjectVelocity);
- }
- grabbedObjectScript.Ungrabbed(this);
- ToggleControllerVisibility(true);
- OnControllerUngrabInteractableObject(interactTouch.SetControllerInteractEvent(grabbedObject));
- }
- }
- CheckInfluencingObjectOnRelease();
- grabEnabledState = 0;
- grabbedObject = null;
- }
- protected virtual GameObject GetGrabbableObject()
- {
- GameObject obj = (interactTouch != null ? interactTouch.GetTouchedObject() : null);
- if (obj != null && interactTouch.IsObjectInteractable(obj))
- {
- return obj;
- }
- return grabbedObject;
- }
- protected virtual void IncrementGrabState()
- {
- if (interactTouch != null && !IsObjectHoldOnGrab(interactTouch.GetTouchedObject()))
- {
- grabEnabledState++;
- }
- }
- protected virtual GameObject GetUndroppableObject()
- {
- if (grabbedObject != null)
- {
- VRTK_InteractableObject grabbedObjectScript = grabbedObject.GetComponent<VRTK_InteractableObject>();
- return (grabbedObjectScript != null && !grabbedObjectScript.IsDroppable() ? grabbedObject : null);
- }
- return null;
- }
- protected virtual void AttemptGrabObject()
- {
- GameObject objectToGrab = GetGrabbableObject();
- if (objectToGrab != null)
- {
- PerformGrabAttempt(objectToGrab);
- }
- else
- {
- grabPrecognitionTimer = Time.time + grabPrecognition;
- }
- }
- protected virtual void PerformGrabAttempt(GameObject objectToGrab)
- {
- IncrementGrabState();
- IsValidGrabAttempt(objectToGrab);
- undroppableGrabbedObject = GetUndroppableObject();
- }
- protected virtual bool ScriptValidGrab(VRTK_InteractableObject objectToGrabScript)
- {
- return (objectToGrabScript != null && objectToGrabScript.grabAttachMechanicScript != null && objectToGrabScript.grabAttachMechanicScript.ValidGrab(controllerAttachPoint));
- }
- protected virtual bool IsValidGrabAttempt(GameObject objectToGrab)
- {
- bool initialGrabAttempt = false;
- VRTK_InteractableObject objectToGrabScript = (objectToGrab != null ? objectToGrab.GetComponent<VRTK_InteractableObject>() : null);
- if (grabbedObject == null && interactTouch != null && IsObjectGrabbable(interactTouch.GetTouchedObject()) && ScriptValidGrab(objectToGrabScript))
- {
- InitGrabbedObject();
- if (!influencingGrabbedObject)
- {
- initialGrabAttempt = objectToGrabScript.grabAttachMechanicScript.StartGrab(gameObject, grabbedObject, controllerAttachPoint);
- }
- }
- return initialGrabAttempt;
- }
- protected virtual bool CanRelease()
- {
- if (grabbedObject != null)
- {
- VRTK_InteractableObject objectToGrabScript = grabbedObject.GetComponent<VRTK_InteractableObject>();
- return (objectToGrabScript != null && objectToGrabScript.IsDroppable());
- }
- return false;
- }
- protected virtual void AttemptReleaseObject()
- {
- if (CanRelease() && (IsObjectHoldOnGrab(grabbedObject) || grabEnabledState >= 2))
- {
- InitUngrabbedObject(true);
- }
- }
- protected virtual void DoGrabObject(object sender, ControllerInteractionEventArgs e)
- {
- OnGrabButtonPressed(controllerEvents.SetControllerEvent(ref grabPressed, true));
- AttemptGrabObject();
- }
- protected virtual void DoReleaseObject(object sender, ControllerInteractionEventArgs e)
- {
- AttemptReleaseObject();
- OnGrabButtonReleased(controllerEvents.SetControllerEvent(ref grabPressed, false));
- }
- protected virtual void CheckControllerAttachPointSet()
- {
- if (controllerAttachPoint == null)
- {
- SetControllerAttachPoint();
- }
- }
- protected virtual void CreateNonTouchingRigidbody()
- {
- if (createRigidBodyWhenNotTouching && grabbedObject == null && interactTouch != null)
- {
- if (!interactTouch.IsRigidBodyForcedActive() && interactTouch.IsRigidBodyActive() != grabPressed)
- {
- interactTouch.ToggleControllerRigidBody(grabPressed);
- }
- }
- }
- protected virtual void CheckPrecognitionGrab()
- {
- if (grabPrecognitionTimer >= Time.time)
- {
- if (GetGrabbableObject() != null)
- {
- AttemptGrabObject();
- if (GetGrabbedObject() != null)
- {
- grabPrecognitionTimer = 0f;
- }
- }
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement