eye-therapy-2 / Assets / Scripts / Interactables / XRGrabOffsetInteractable.cs
XRGrabOffsetInteractable.cs
Raw
using UnityEngine;
using UnityEngine.XR;
using UnityEngine.XR.Interaction.Toolkit;

public enum HandInteractionRestriction { None, Left, Right }

public class XRGrabOffsetInteractable : XRGrabInteractable
{
    [SerializeField] private HandInteractionRestriction handInteractionRestriction = HandInteractionRestriction.None;
    [SerializeField] private bool allowOnlyOneHand = false;

    private Vector3 initAttachLocalPosition;
    private Quaternion initAttachLocalRotation;

    void Start()
    {
        if (!attachTransform)
        {
            GameObject grab = new GameObject("Grab Pivot");
            grab.transform.SetParent(transform, false);
            attachTransform = grab.transform;
        }

        initAttachLocalPosition = attachTransform.localPosition;
        initAttachLocalRotation = attachTransform.localRotation;
    }

    protected override void OnSelectEntered(SelectEnterEventArgs args)
    {
        var interactor = args.interactor;
        if (interactor is XRDirectInteractor)
        {
            attachTransform.position = interactor.transform.position;
            attachTransform.rotation = interactor.transform.rotation;
        }
        else
        {
            attachTransform.position = initAttachLocalPosition;
            attachTransform.rotation = initAttachLocalRotation;
        }
        
        if (allowOnlyOneHand)
        {
            if (interactor.GetComponent<XRController>().controllerNode == XRNode.LeftHand)
                handInteractionRestriction = HandInteractionRestriction.Left;
            else if (interactor.GetComponent<XRController>().controllerNode == XRNode.RightHand)
                handInteractionRestriction = HandInteractionRestriction.Right;
        }

        base.OnSelectEntered(args);
    }

    protected override void OnSelectExited(SelectExitEventArgs args)
    {
        if (allowOnlyOneHand) handInteractionRestriction = HandInteractionRestriction.None;

        base.OnSelectExited(args);
    }

    public override bool IsHoverableBy(XRBaseInteractor interactor)
    {
        if (handInteractionRestriction != HandInteractionRestriction.None)
        {
            if ((handInteractionRestriction == HandInteractionRestriction.Left) && (interactor.GetComponent<XRController>().controllerNode != XRNode.LeftHand)) return false;
            if ((handInteractionRestriction == HandInteractionRestriction.Right) && (interactor.GetComponent<XRController>().controllerNode != XRNode.RightHand)) return false;
        }
        return base.IsHoverableBy(interactor);
    }

    public override bool IsSelectableBy(XRBaseInteractor interactor)
    {
        if (handInteractionRestriction != HandInteractionRestriction.None)
        {
            if ((handInteractionRestriction == HandInteractionRestriction.Left) && (interactor.GetComponent<XRController>().controllerNode != XRNode.LeftHand)) return false;
            if ((handInteractionRestriction == HandInteractionRestriction.Right) && (interactor.GetComponent<XRController>().controllerNode != XRNode.RightHand)) return false;
        }
        return base.IsSelectableBy(interactor);
    }

#if UNITY_EDITOR
    private void OnValidate()
    {
        if (allowOnlyOneHand) handInteractionRestriction = HandInteractionRestriction.None;
    }
#endif
}