// This is called by the grabber currently grabbing the object
    public void GrabBegin(EVRA_Grabber newGrabber, EVRA_GrabTrigger detectedTrigger)
    {
        // If we're actually being held by another grabber, we prematurely end that grabber's grabbing
        if (currentGrabber != null && currentGrabber != newGrabber)
        {
            currentGrabber.GrabEnd();
        }
        // If our grabbable parent has a rigidbody, we set its kinematic setting to true to prevent collisiosn
        if (grabbableParentRB)
        {
            grabbableParentRB.isKinematic = true;
        }
        // We set grabbable parent as a child of our grabber
        grabbableParent.SetParent(newGrabber.transform);
        // We save a reference to our new grabber
        currentGrabber = newGrabber;

        // If we want to snap, we usually snap based on the clsoest detected trigger (passed on from the grabber).
        // In other words, the grabber has already detected what's the closest trigger. All we need to do is snap our grabbable object relative to that trigger's position on the grabbable object
        if (m_shouldSnap)
        {
            Transform  to = detectedTrigger.transform;
            Quaternion destinationRotation = currentGrabber.transform.rotation * Quaternion.Inverse(to.localRotation) * Quaternion.Euler(45, 0, 0);
            grabbableParent.transform.rotation = destinationRotation;
            Vector3 destinationPosition = currentGrabber.transform.position + (grabbableParent.position - to.position);
            grabbableParent.transform.position = destinationPosition;
        }
    }
 // This one is called under the unique situation that the other grab volume is called in its own GrabEnd() instance.
 // Therefore, we don't need to call `GrabEnd()` with the other hand nor do any snapping
 public void SwitchHand(EVRA_Grabber newGrabber)
 {
     // We set grabbable parent as a child of our grabber
     grabbableParent.SetParent(newGrabber.transform, true);
     // We save a reference to our new grabber
     currentGrabber = newGrabber;
 }
 public void GrabEnd(Vector3 linearVelocity, Vector3 angularVelocity)
 {
     grabbableParent.SetParent(originalWorldParent);
     if (grabbableParentRB)
     {
         grabbableParentRB.isKinematic     = originalKinematicState;
         grabbableParentRB.velocity        = linearVelocity;
         grabbableParentRB.angularVelocity = angularVelocity;
     }
     currentGrabber = null;
 }
    public void AddOtherGrabVolume(EVRA_Grabber other)
    {
        m_OtherGrabVolume = other;

        /*
         * otherGrabVolRelRotation = Quaternion.FromToRotation(other.transform.forward, transform.forward);
         * otherGrabVolRelPosition = other.transform.position - transform.position;
         */
        Quaternion rot = Quaternion.LookRotation(other.transform.position - transform.position);

        otherGrabVolRelRotation = Quaternion.Inverse(rot) * transform.rotation;
    }
 public void GrabEnd()
 {
     grabbableParent.SetParent(originalWorldParent);
     currentGrabber = null;
 }
 public void RemoveOtherGrabVolume()
 {
     m_OtherGrabVolume = null;
 }
    public void GrabEnd()
    {
        EVRA_Grabber otherGrabberRef = m_OtherGrabVolume;

        RemoveOtherGrabVolume();

        if (!m_grabbed)
        {
            return;               // If no objects currently grabbed, end quickly
        }
        // There are two situations:
        // 1) the grabbed object has only one hand grabbing it (aka this one)
        // 2) the grabbed object has two hands grabbing it

        // 1) We need to call `GrabEnd()` with the appropriate linear and angular velocity
        // 2) We need to switch parenting over to the other hand via `SwitchHand()`. To tell if there is another grab volume grabbing the object, we just check if m_OtherGrabVolume is not null

        if (otherGrabberRef)
        {
            // If we have an other grabber ref, then that means that multiple objects are holding the current item.
            // Now, technically, it can be either the initial holder of the item or the rotation ref.
            // If it's the initial holder, then we let go AND transfer possession to the other grab volume
            // If it's just the rotation ref, then we just need to decouple the other grab volume - we don't need to let go of it.
            if (m_grabbed.GrabbableRef.currentGrabber == this)
            {
                //otherGrabberRef.transform.localRotation = Quaternion.Euler(0f,0f,0f);
                m_grabbed.GrabbableRef.SwitchHand(otherGrabberRef);
                //m_grabbed.GrabbableRef.GrabEnd();
            }
            otherGrabberRef.RemoveOtherGrabVolume();
            //if (m_grabbed.GrabbableRef.currentGrabber.grabbed != m_grabbed) m_grabbed.GrabbableRef.currentGrabber.RemoveOtherGrabVolume();
        }
        else
        {
            OVRPose localPose = new OVRPose {
                position = OVRInput.GetLocalControllerPosition(m_CustomGrabber.OVRController), orientation = OVRInput.GetLocalControllerRotation(m_CustomGrabber.OVRController)
            };
            OVRPose trackingSpace   = transform.ToOVRPose() * localPose.Inverse();
            Vector3 linearVelocity  = trackingSpace.orientation * OVRInput.GetLocalControllerVelocity(m_CustomGrabber.OVRController);
            Vector3 angularVelocity = trackingSpace.orientation * OVRInput.GetLocalControllerAngularVelocity(m_CustomGrabber.OVRController);
            angularVelocity *= -1;
            m_grabbed.GrabbableRef.GrabEnd(linearVelocity, angularVelocity);
            //m_grabbed.GrabbableRef.currentGrabber.RemoveOtherGrabVolume();
        }

        /*
         * if (m_grabbed.GrabbableRef.currentGrabber && m_grabbed.GrabbableRef.currentGrabber.OtherGrabVolume) {
         *  if (m_grabbed.GrabbableRef.currentGrabber.grabbed && m_grabbed.GrabbableRef.currentGrabber.grabbed != m_grabbed) m_grabbed.GrabbableRef.currentGrabber.RemoveOtherGrabVolume();
         * }
         * if (m_grabbed.GrabbableRef.currentGrabber == this) {
         *  OVRPose localPose = new OVRPose { position = OVRInput.GetLocalControllerPosition(m_CustomGrabber.OVRController), orientation = OVRInput.GetLocalControllerRotation(m_CustomGrabber.OVRController) };
         *  OVRPose trackingSpace = transform.ToOVRPose() * localPose.Inverse();
         *  Vector3 linearVelocity = trackingSpace.orientation * OVRInput.GetLocalControllerVelocity(m_CustomGrabber.OVRController);
         *  Vector3 angularVelocity = trackingSpace.orientation * OVRInput.GetLocalControllerAngularVelocity(m_CustomGrabber.OVRController);
         *  angularVelocity *= -1;
         *  m_grabbed.GrabbableRef.GrabEnd(linearVelocity,angularVelocity);
         * }
         */
        transform.localRotation = Quaternion.Euler(0f, 0f, 0f);
        m_grabbed = null;
    }