using System;
using Rokid.UXR.Utility;
using UnityEngine;
using UnityEngine.EventSystems;
namespace Rokid.UXR.Interaction
{
///
/// Processing the pose information of the ray
///
public class HeadHandRayPose : BaseRayPose, IHeadHandDriver
{
private RayInteractor rayInteractor;
[SerializeField]
private HandType handType;
[SerializeField, Tooltip("Shoulder position, symmetrically based on neck space")]
private Vector3 shoulder = new Vector3(-0.2f, -0.1f, 0);
[SerializeField, Tooltip("Neck position estimation, calculated based on camera space.")]
private Vector3 neck = new Vector3(0, -0.1f, -0.1f);
[SerializeField, Tooltip("The strength of the influence of palm direction on the ray direction.")]
private float palmForwardInfluencePow = 0f;
[SerializeField, Tooltip("The intensity of ray upward bending.")]
private float upForwardInfluencePow = 0.0f;
private Vector3 shoulderPos;
private Vector3 delta = Vector3.zero;
private bool rayFirstShow = true;
private InteractorType interactorType = InteractorType.Far;
///
/// 颈部位置的tsf
///
private Transform neckTsf;
private Vector3 preWirstPos = Vector3.zero;
private float preCamRotY = 0;
private Transform rayOrigin;
private Vector3 startRayPos;
private Vector3 startRayForward;
private Vector3 preRayPos;
private Vector3 preRayForward;
private Vector3 deltaRayPos;
private Vector3 deltaRayForward;
private Vector3 allDeltaRayPos;
private Vector3 allDeltaRayForward;
private int handFrame = 0;
private int headFrame = 0;
private float noHoverCursorDistance;
protected override void Start()
{
base.Start();
if (rayInteractor == null)
{
rayInteractor = GetComponent();
}
GesEventInput.OnRayPoseUpdate += OnRayPoseUpdate;
neckTsf = new GameObject("neck").transform;
neckTsf.SetParent(transform);
rayOrigin = rayInteractor.GetRayOriginTsf();
noHoverCursorDistance = rayInteractor.NoHoverCursorDistance;
}
private void OnDestroy()
{
GesEventInput.OnRayPoseUpdate -= OnRayPoseUpdate;
}
public void OnChangeHoldHandType(HandType hand)
{
if (hand != HandType.None)
{
handType = hand;
shoulder = handType == HandType.RightHand ? new Vector3(0.2f, -0.1f, 0) : new Vector3(-0.2f, 0.1f, 0);
startRayPos = rayOrigin.position;
startRayForward = rayOrigin.forward;
}
}
public void OnHandPress(HandType hand)
{
if (handFrame > 10)
{
allDeltaRayPos += deltaRayPos;
allDeltaRayForward += deltaRayForward;
rayOrigin.rotation = Quaternion.Slerp(rayOrigin.rotation, Quaternion.FromToRotation(Vector3.forward, startRayForward + allDeltaRayForward), Time.deltaTime * 10);
rayOrigin.position = Vector3.Lerp(rayOrigin.position, startRayPos + allDeltaRayPos, Time.deltaTime * 30);
}
}
public void OnHandRelease()
{
headFrame++;
if (Utils.IsAndroidPlatfrom() && headFrame > 1)
{
rayOrigin.SetPositionAndRotation(MainCameraCache.mainCamera.transform.position + new Vector3(0, 0.05f, 0), Quaternion.FromToRotation(Vector3.forward, MainCameraCache.mainCamera.transform.forward + new Vector3(0, 0.05f, 0)));
}
}
private void OnRayPoseUpdate(HandType hand, Vector3 wrist, Vector3 handCenter, Vector3 pinchCenterOri, Vector3 pinchCenter)
{
if (Utils.IsUnityEditor())
return;
if (hand == handType)
{
float deltaWrist = Vector3.SqrMagnitude(wrist - preWirstPos);
float deltaCamPos = Vector3.SqrMagnitude(MainCameraCache.mainCamera.transform.position - preWirstPos);
neckTsf.position = MainCameraCache.mainCamera.transform.TransformPoint(neck);
neckTsf.rotation = Quaternion.Euler(0, deltaWrist > 0.1f ? MainCameraCache.mainCamera.transform.eulerAngles.y : preCamRotY, 0);
shoulderPos = neckTsf.TransformPoint(shoulder);
preWirstPos = wrist;
preCamRotY = MainCameraCache.mainCamera.transform.eulerAngles.y;
//胳膊朝向
Vector3 armForward = (wrist - shoulderPos).normalized;
//手腕朝向
Vector3 palmForWard = (handCenter - wrist).normalized;
Vector3 curForward = armForward + palmForWard * palmForwardInfluencePow + Vector3.up * upForwardInfluencePow;
Vector3 curPos = pinchCenterOri;
deltaRayForward = curForward - preRayForward;
deltaRayPos = curPos - preRayPos;
preRayForward = curForward;
preRayPos = curPos;
handFrame++;
}
}
public void OnBeforeChangeHoldHandType(HandType hand)
{
if (hand == HandType.None)
{
rayInteractor.NoHoverCursorDistance = noHoverCursorDistance;
handType = HandType.None;
allDeltaRayForward = Vector3.zero;
allDeltaRayPos = Vector3.zero;
handFrame = 0;
headFrame = 0;
}
}
}
}