eye-therapy-2 / Assets / Scripts / Hands / XRHandAttacher.cs
XRHandAttacher.cs
Raw
using System.Collections;
using UnityEngine;
using UnityEngine.XR;
using UnityEngine.XR.Interaction.Toolkit;

public class XRHandAttacher : MonoBehaviour
{
    [SerializeField] private Transform leftHandAttachPoint = null;
    [SerializeField] private Transform rightHandAttachPoint = null;
    [SerializeField] private string animatorBoolName = "Dummy";
    
    //[Header("Rotation")]
    //[SerializeField] private bool allowRotation = false;
    //[Tooltip("Minimal and maximal angle for vertical rotation")]
    //[SerializeField] private Vector2 verticalRotConstraints;
    //[Tooltip("Minimal and maximal angle for horizontal rotation")]
    //[SerializeField] private Vector2 horizontalRotConstraints;
    //[Tooltip("Minimal and maximal angle for side rotation")]
    //[SerializeField] private Vector2 sideRotConstraints;
    //public Transform rotationCenter;

    private float handTravelTime = 0.15f;
    private bool hasTarget = false;
    //private Transform currentHand;
    //private Transform controller;
    //private Transform attach;

    public void OnAttach(SelectEnterEventArgs args)
    {
        var interactor = args.interactor;
        Transform hand = interactor.GetComponent<ActionBasedController>().modelTransform;
        //bool c = interactor.TryGetComponent(out XRController controller);
        if (hand)
        {
            //controller = hand.parent;
            if (rightHandAttachPoint && interactor.name.Contains("Right"))
            {
                hand.parent = rightHandAttachPoint;
                hasTarget = true;
            }
            else if (leftHandAttachPoint /*&& interactor.GetComponent<XRController>().controllerNode == UnityEngine.XR.XRNode.LeftHand*/)
            {
                hand.parent = leftHandAttachPoint;
                hasTarget = true;
            }
            if (hasTarget)
            {
                Animator[] animators = hand.GetComponentsInChildren<Animator>();
                if (animators.Length > 0)
                {
                    animators[0].SetBool("Default", false);
                    animators[0].SetBool(animatorBoolName, true);
                }
                StartCoroutine(SnapHand(hand));
                //currentHand = hand;
                //attach = hand.parent;
            }
        }
    }

    public void OnDetach(SelectExitEventArgs args)
    {
        var interactor = args.interactor;
        hasTarget = false;
        Transform hand = interactor.GetComponent<ActionBasedController>().modelTransform;
        if (hand)
        {
            hand.parent = interactor.transform;
            Animator[] animators = hand.GetComponentsInChildren<Animator>();
            if (animators.Length > 0)
            {
                animators[0].SetBool(animatorBoolName, false);
                animators[0].SetBool("Default", true);
            }
            StartCoroutine(SnapHand(hand));
            //currentHand = null;
            //controller = null;
        }
    }

    private IEnumerator SnapHand(Transform hand)
    {
        //hand.localScale = new Vector3(1 / hand.parent.localScale.x, 1 / hand.parent.localScale.y, 1 / hand.parent.localScale.z);
        Vector3 startPosition = hand.localPosition;
        Quaternion startRotation = hand.localRotation;
        float t = 0f;
        while (t < handTravelTime)
        {
            hand.localPosition = Vector3.Lerp(startPosition, Vector3.zero, t / handTravelTime);
            hand.localRotation = Quaternion.Lerp(startRotation, Quaternion.identity, t / handTravelTime);
            t += Time.deltaTime;
            yield return null;
        }
        hand.localPosition = Vector3.zero;
        hand.localRotation = Quaternion.identity;
    }

//    private void Update()
//    {
//        if (allowRotation && currentHand)
//        {
//            //float y = Mathf.Clamp(controller.eulerAngles.y, attach.eulerAngles.y - 20, attach.eulerAngles.y + 20);
//            //currentHand.rotation = Quaternion.Euler(currentHand.eulerAngles.x, y, currentHand.eulerAngles.z);

//            //currentHand.rotation = Quaternion.Euler(Quaternion.LookRotation(rotationCenter.position - controller.position).eulerAngles + attach.rotation.eulerAngles);
//            //currentHand.position = rotationCenter.position + currentHand.rotation * Vector3.left * (rotationCenter.position - attach.position).magnitude;

//            //currentHand.RotateAround(rotationCenter.position, Vector3.up, (Mathf.Repeat(currentHand.eulerAngles.y, 360f) - Mathf.Repeat(controller.eulerAngles.y, 360f)) * Time.deltaTime);

//            //Quaternion nextRotation = Quaternion.LookRotation(controller.forward, controller.up);
//            //float angleDelta = Quaternion.Angle(currentHand.rotation, nextRotation);
//            //currentHand.RotateAround(rotationCenter.position, controller.up, angleDelta * Time.deltaTime * 0.01f);

//            //Quaternion rotation = Quaternion.AngleAxis(Time.deltaTime, controller.forward);
//            //currentHand.rotation *= rotation;
//            //Vector3 toTarget = (rotationCenter.position - currentHand.position);
//            //Vector3 newOffset = -toTarget - 2 * Time.deltaTime * toTarget.normalized;
//            //transform.position = rotationCenter.position + rotation * newOffset;

//            Quaternion rotation = Quaternion.LookRotation(rotationCenter.position - controller.position);
//            currentHand.localRotation = Quaternion.Euler(new Vector3(0, rotation.eulerAngles.y, 0));
//            currentHand.position = rotationCenter.position + rotation * currentHand.up * (attach.position - rotationCenter.position).magnitude;
//        }
//    }
}