Skip to content

Commit

Permalink
feat(Interaction): add ability to utilise secondary controller grab
Browse files Browse the repository at this point in the history
  > **Breaking Changes**

The `Is Swappable` parameter has now been removed from the interactable
object and is replaced with a new `Secondary Controller Grab Action`
that at the moment performs the same concept of either:

 * No action: When the second controller grabs the item doesn't swap.
 * Swap controller: When the second controller grabs the item swaps
 to the new controller hand.

The Interactable Object now also tracks the grab of both controllers,
the first controller to grab is considered holding the object and
the second controller to grab is considered to be influencing the
object or to have a specific action.
  • Loading branch information
thestonefox committed Nov 2, 2016
1 parent b6e7b72 commit 7961fbe
Show file tree
Hide file tree
Showing 4 changed files with 263 additions and 102 deletions.
2 changes: 1 addition & 1 deletion Assets/VRTK/Editor/VRTK_InteractableObjectEditor.cs
Expand Up @@ -81,7 +81,7 @@ public override void OnInspectorGUI()
EditorGUI.indentLevel++;

EditorGUILayout.PropertyField(serializedObject.FindProperty("validDrop"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("isSwappable"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("secondaryGrabAction"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("holdButtonToGrab"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("grabOverrideButton"));

Expand Down
148 changes: 93 additions & 55 deletions Assets/VRTK/Scripts/VRTK_InteractGrab.cs
Expand Up @@ -51,6 +51,7 @@ public class VRTK_InteractGrab : MonoBehaviour

private Joint controllerAttachJoint;
private GameObject grabbedObject = null;
private bool influencingGrabbedObject = false;
private bool updatedHideControllerOnGrab = false;
private VRTK_InteractTouch interactTouch;
private VRTK_ControllerActions controllerActions;
Expand Down Expand Up @@ -87,7 +88,7 @@ public void ForceRelease()
}
else
{
ReleaseObject(false);
UngrabInteractedObject(false);
}
}

Expand Down Expand Up @@ -196,7 +197,8 @@ private void SetControllerAttachPoint()

private bool IsObjectGrabbable(GameObject obj)
{
return (interactTouch.IsObjectInteractable(obj) && obj.GetComponent<VRTK_InteractableObject>().isGrabbable);
var objScript = obj.GetComponent<VRTK_InteractableObject>();
return (interactTouch.IsObjectInteractable(obj) && objScript && (objScript.isGrabbable || objScript.PerformSecondaryAction()));
}

private bool IsObjectHoldOnGrab(GameObject obj)
Expand Down Expand Up @@ -347,12 +349,15 @@ private void ThrowReleasedObject(Rigidbody rb, float objectThrowMultiplier)

private bool GrabInteractedObject()
{
if (controllerAttachJoint == null && grabbedObject == null && IsObjectGrabbable(interactTouch.GetTouchedObject()))
if (controllerAttachJoint == null)
{
InitGrabbedObject();
if (grabbedObject)
{
SnapObjectToGrabToController(grabbedObject);
if (!influencingGrabbedObject)
{
SnapObjectToGrabToController(grabbedObject);
}
return true;
}
}
Expand All @@ -361,30 +366,23 @@ private bool GrabInteractedObject()

private bool GrabTrackedObject()
{
if (grabbedObject == null && IsObjectGrabbable(interactTouch.GetTouchedObject()))
InitGrabbedObject();
if (grabbedObject)
{
InitGrabbedObject();
if (grabbedObject)
if (!influencingGrabbedObject)
{
var objectScript = grabbedObject.GetComponent<VRTK_InteractableObject>();
objectScript.SetGrabbedSnapHandle(GetSnapHandle(objectScript));
return true;
}
return true;
}
return false;
}

private bool GrabClimbObject()
{
if (grabbedObject == null && IsObjectGrabbable(interactTouch.GetTouchedObject()))
{
InitGrabbedObject();
if (grabbedObject)
{
return true;
}
}
return false;
InitGrabbedObject();
return (grabbedObject ? true : false);
}

private void InitGrabbedObject()
Expand All @@ -394,37 +392,68 @@ private void InitGrabbedObject()
{
var grabbedObjectScript = grabbedObject.GetComponent<VRTK_InteractableObject>();

if (!grabbedObjectScript.IsValidInteractableController(gameObject, grabbedObjectScript.allowedGrabControllers))
if (!grabbedObjectScript.IsGrabbed() || grabbedObjectScript.IsSwappable())
{
grabbedObject = null;
interactTouch.ForceStopTouching();
return;
InitPrimaryGrab(grabbedObjectScript);
}
else
{
InitSecondaryGrab(grabbedObjectScript);
}

OnControllerGrabInteractableObject(interactTouch.SetControllerInteractEvent(grabbedObject));
updatedHideControllerOnGrab = grabbedObjectScript.CheckHideMode(hideControllerOnGrab, grabbedObjectScript.hideControllerOnGrab);

grabbedObjectScript.SaveCurrentState();
grabbedObjectScript.Grabbed(gameObject);
grabbedObjectScript.ZeroVelocity();
grabbedObjectScript.ToggleHighlight(false);
grabbedObjectScript.ToggleKinematic(false);
OnControllerGrabInteractableObject(interactTouch.SetControllerInteractEvent(grabbedObject));
}

//Pause collisions (if allowed on object) for a moment whilst sorting out position to prevent clipping issues
grabbedObjectScript.PauseCollisions();
if (updatedHideControllerOnGrab)
{
Invoke("HideController", hideControllerDelay);
}
}

if (grabbedObjectScript.grabAttachMechanic == VRTK_InteractableObject.GrabAttachType.Child_Of_Controller)
private void InitPrimaryGrab(VRTK_InteractableObject currentGrabbedObject)
{
if (!currentGrabbedObject.IsValidInteractableController(gameObject, currentGrabbedObject.allowedGrabControllers))
{
grabbedObject = null;
if (currentGrabbedObject.IsGrabbed(gameObject))
{
grabbedObjectScript.ToggleKinematic(true);
interactTouch.ForceStopTouching();
}
updatedHideControllerOnGrab = grabbedObjectScript.CheckHideMode(hideControllerOnGrab, grabbedObjectScript.hideControllerOnGrab);
return;
}

if (updatedHideControllerOnGrab)
influencingGrabbedObject = false;
currentGrabbedObject.SaveCurrentState();
currentGrabbedObject.Grabbed(gameObject);
currentGrabbedObject.ZeroVelocity();
currentGrabbedObject.ToggleHighlight(false);
currentGrabbedObject.ToggleKinematic(false);

//Pause collisions (if allowed on object) for a moment whilst sorting out position to prevent clipping issues
currentGrabbedObject.PauseCollisions();

if (currentGrabbedObject.grabAttachMechanic == VRTK_InteractableObject.GrabAttachType.Child_Of_Controller)
{
Invoke("HideController", hideControllerDelay);
currentGrabbedObject.ToggleKinematic(true);
}
}

private void InitSecondaryGrab(VRTK_InteractableObject currentGrabbedObject)
{
if (!currentGrabbedObject.IsValidInteractableController(gameObject, currentGrabbedObject.allowedGrabControllers))
{
grabbedObject = null;
influencingGrabbedObject = false;
currentGrabbedObject.Ungrabbed(gameObject);
return;
}

influencingGrabbedObject = true;
currentGrabbedObject.Grabbed(gameObject);
}

private void HideController()
{
if (grabbedObject != null)
Expand All @@ -436,7 +465,7 @@ private void HideController()

private void UngrabInteractedObject(bool withThrow)
{
if (grabbedObject != null)
if (grabbedObject != null && !influencingGrabbedObject)
{
Rigidbody releasedObjectRigidBody = ReleaseGrabbedObjectFromController(withThrow);
if (withThrow)
Expand Down Expand Up @@ -465,7 +494,6 @@ private void UngrabClimbObject()

private void InitUngrabbedObject()
{
OnControllerUngrabInteractableObject(interactTouch.SetControllerInteractEvent(grabbedObject));
if (grabbedObject != null)
{
grabbedObject.GetComponent<VRTK_InteractableObject>().Ungrabbed(gameObject);
Expand All @@ -478,14 +506,15 @@ private void InitUngrabbedObject()
controllerVisibilityState = true;
}

if (!influencingGrabbedObject)
{
interactTouch.ForceStopTouching();
}
influencingGrabbedObject = false;

OnControllerUngrabInteractableObject(interactTouch.SetControllerInteractEvent(grabbedObject));
grabEnabledState = 0;
grabbedObject = null;
interactTouch.ForceStopTouching();
}

private void ReleaseObject(bool withThrow)
{
UngrabInteractedObject(withThrow);
}

private GameObject GetGrabbableObject()
Expand Down Expand Up @@ -513,18 +542,11 @@ private void AttemptGrabObject()
{
IncrementGrabState();
var initialGrabAttempt = false;
var objectToGrabScript = objectToGrab.GetComponent<VRTK_InteractableObject>();

if (objectToGrab.GetComponent<VRTK_InteractableObject>().AttachIsTrackObject())
{
initialGrabAttempt = GrabTrackedObject();
}
else if (objectToGrab.GetComponent<VRTK_InteractableObject>().AttachIsClimbObject())
{
initialGrabAttempt = GrabClimbObject();
}
else
if (grabbedObject == null && IsObjectGrabbable(interactTouch.GetTouchedObject()))
{
initialGrabAttempt = GrabInteractedObject();
initialGrabAttempt = CheckGrabAttempt(objectToGrabScript);
}

undroppableGrabbedObject = (grabbedObject && grabbedObject.GetComponent<VRTK_InteractableObject>() && !grabbedObject.GetComponent<VRTK_InteractableObject>().IsDroppable() ? grabbedObject : null);
Expand All @@ -544,6 +566,20 @@ private void AttemptGrabObject()
}
}

private bool CheckGrabAttempt(VRTK_InteractableObject objectToGrab)
{
if (objectToGrab.AttachIsTrackObject())
{
return GrabTrackedObject();
}
else if (objectToGrab.AttachIsClimbObject())
{
return GrabClimbObject();
}

return GrabInteractedObject();
}

private bool CanRelease()
{
return (grabbedObject && grabbedObject.GetComponent<VRTK_InteractableObject>().IsDroppable());
Expand All @@ -553,17 +589,19 @@ private void AttemptReleaseObject()
{
if (CanRelease() && (IsObjectHoldOnGrab(grabbedObject) || grabEnabledState >= 2))
{
if (grabbedObject.GetComponent<VRTK_InteractableObject>().AttachIsUnthrowableObject())
var grabbedObjectScript = grabbedObject.GetComponent<VRTK_InteractableObject>();

if (grabbedObjectScript.AttachIsUnthrowableObject())
{
UngrabTrackedObject();
}
else if (grabbedObject.GetComponent<VRTK_InteractableObject>().AttachIsClimbObject())
else if (grabbedObjectScript.AttachIsClimbObject())
{
UngrabClimbObject();
}
else
{
ReleaseObject(true);
UngrabInteractedObject(true);
}
}
}
Expand Down

0 comments on commit 7961fbe

Please sign in to comment.