Unity Udexreal开发插件包
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

884 lines
37 KiB

using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.Events;
using DG.Tweening;
using UnityEngine.Windows;
using static UDE_HAND_INTERACTION.HandInteractionSetting;
using static UDE_HAND_INTERACTION.InteractableObject;
namespace UDE_HAND_INTERACTION
{
public class HandInteractor : MonoBehaviour
{
[HideInInspector]
public FingerInteractData FingerInteractData;
[HideInInspector]
public HandDriver HandDriver { get; private set; }
private List<float> JointList;
[SerializeField, Space]
private UnityEvent WhenHandInteract;
[SerializeField]
private UnityEvent WhenHandDisable;
private bool SeparateFinger;
[HideInInspector]
public float ActiveRange;
[HideInInspector]
public float ActiveIntense;
[HideInInspector]
public InteractType interactType;
[HideInInspector]
public KeyCode ShortCutKeyCode;
private Vector3 RegularTransferPosition = Vector3.zero;
private List<Finger> Fingers = new();
private List<Vector3> FixedPoseAngle = new();
[HideInInspector]
public List<Quaternion> OriginalAngle;
[HideInInspector]
public List<Transform> Joints;
public enum Handness
{
Left,
Right
}
[HideInInspector]
public Handness handness;
[HideInInspector]
public Transform TipTrans;
[HideInInspector]
public InteractableObject InteractObject{ get; private set; }
[HideInInspector]
public InteractableObject ContactObject;
[HideInInspector]
public HandInteraction ChosenPose { get; private set; }
private Dictionary<InteractableObject, Collider> TriggerObjects = new();
private bool[] ActiveCnt;
[HideInInspector]
public bool InActive { private set; get; } = false;
private bool[] OnceAvtive = new bool[5] { true, true, true, true, true };
private float[] ActiveClock = new float[5] { 0, 0, 0, 0, 0 };
private bool OnceDisable = true;
private bool UpdateCheckResult = false;
private bool TriggerEnterCheck = false;
private InteractableObject RemoveOperation;
private bool FollowJointInClone = false;
private HandInteractor CloneTarget;
private SkinnedMeshRenderer HandSkinnedMeshRenderer;
public Transform DetectArea { get; private set; }
private LineRenderer lineRender;
private List<Vector3> UsedLine = new();
private float CurveHighest = 0;
public Vector3 CurveHighestVec { get; private set; } = Vector3.zero;
private Ray[] DetectRays;
private RaycastHit[] raycastHits = new RaycastHit[6];
private Dictionary<InteractableObject, float> RayDetectedTarget = new Dictionary<InteractableObject, float>();
private InteractableObject RayTargetObj;
private InteractableObject AreaObject;
private StaticPoseDetector staticPoseDetector => transform.parent?.GetComponentInChildren<StaticPoseDetector>();
private List<HandStaticPose> staticPoses;
private List<Vector3> FullAngleList;
void Awake()
{
HandDriver = GetComponentInChildren<HandDriver>();
if (HandDriver.Hand == HandDriver.HandType.Right)
{
handness = Handness.Right;
}
else
{
handness = Handness.Left;
}
}
void Start()
{
OriginalAngle = new()
{
HandDriver.Thumb1.localRotation,
HandDriver.Thumb2.localRotation,
HandDriver.Thumb3.localRotation,
HandDriver.Index1.localRotation,
HandDriver.Index2.localRotation,
HandDriver.Index3.localRotation,
HandDriver.Middle1.localRotation,
HandDriver.Middle2.localRotation,
HandDriver.Middle3.localRotation,
HandDriver.Ring1.localRotation,
HandDriver.Ring2.localRotation,
HandDriver.Ring3.localRotation,
HandDriver.Pinky1.localRotation,
HandDriver.Pinky2.localRotation,
HandDriver.Pinky3.localRotation,
};
ActiveCnt = new bool[5] { false, false, false, false, false };
//ActiveRange = FingerInteractData.ActiveRange;
ShortCutKeyCode = FingerInteractData.ShortcutKeyCode;
DetectArea = transform.Find("DetectArea");
HandSkinnedMeshRenderer = transform.GetComponentInChildren<SkinnedMeshRenderer>();
lineRender = DetectArea.TryGetComponent<LineRenderer>(out var line) ? line : null;
staticPoses = (handness == Handness.Left) ? staticPoseDetector?.LeftPoses : staticPoseDetector?.RightPoses;
}
private void OnTriggerEnter(Collider other)
{
Transform obj = other.transform;
if (obj.TryGetComponent<InteractableObject>(out var _))
{
TriggerEnterCheck = !UpdateCheckResult;
return;
}
while (obj.parent != null)
{
obj = obj.parent;
if (obj.TryGetComponent<InteractableObject>(out var _))
{
TriggerEnterCheck = !UpdateCheckResult;
return;
}
}
}
private void OnTriggerStay(Collider other)
{
Transform trans = other.transform;
InteractableObject obj = null;
if (trans.TryGetComponent<InteractableObject>(out var _obj))
{
obj = _obj;
}
while (trans.parent != null)
{
trans = trans.parent;
if (trans.TryGetComponent<InteractableObject>(out var __obj))
{
obj = __obj;
}
}
if (obj == null) return;
ContactObject = obj;
if (!TriggerEnterCheck)
{
TriggerEnterCheck = !UpdateCheckResult;
}
InteractableObject selected = InteractObject;
bool ActivePermission = false;
if (!InActive)
{
if (!TriggerObjects.ContainsKey(obj) && !FollowJointInClone)
{
TriggerObjects.Add(obj, other);
}
int Priority = int.MaxValue;
List<InteractableObject> DeleteList = new();
foreach(var (interact_object, collider) in TriggerObjects)
{
if (collider != null && Vector3.Distance(collider.ClosestPoint(transform.Find("DetectArea").position), transform.Find("DetectArea").position) > ActiveRange)
{
DeleteList.Add(interact_object);
continue;
}
if (interact_object != null && interact_object.InteractPriority < Priority)
{
Priority = interact_object.InteractPriority;
selected = interact_object;
}
}
foreach(var del in DeleteList)
{
TriggerObjects.Remove(del);
}
if (selected == null) return;
if (selected.objectFollowType == ObjectFollowType.NoPose)
{
ChosenPose = null;
var SettingData = selected.GetComponentInChildren<HandInteractionSetting>();
Fingers = new()
{
new Finger("Thumb", SettingData.Thumb, SettingData.ThumbIntense),
new Finger("Index", SettingData.Index, SettingData.IndexIntense),
new Finger("Middle", SettingData.Middle, SettingData.MiddleIntense),
new Finger("Ring", SettingData.Ring, SettingData.RingIntense),
new Finger("Pinky", SettingData.Pinky, SettingData.PinkyIntense),
};
SeparateFinger = SettingData.SeparateFinger;
ActiveIntense = SettingData.ActiveIntense;
interactType = SettingData.interactType;
ActivePermission = ActiveChecker();
}
else
{
var SortedDict = GetFairInteractableDict(selected);
ChosenPose = SortedDict.Values.FirstOrDefault();
foreach (HandInteraction interact in SortedDict.Values)
{
var SettingData = interact.GetComponent<HandInteractionSetting>();
Fingers = new()
{
new Finger("Thumb", SettingData.Thumb, SettingData.ThumbIntense),
new Finger("Index", SettingData.Index, SettingData.IndexIntense),
new Finger("Middle", SettingData.Middle, SettingData.MiddleIntense),
new Finger("Ring", SettingData.Ring, SettingData.RingIntense),
new Finger("Pinky", SettingData.Pinky, SettingData.PinkyIntense),
};
SeparateFinger = SettingData.SeparateFinger;
ActiveIntense = SettingData.ActiveIntense;
interactType = SettingData.interactType;
if (ActiveChecker())
{
ChosenPose = interact;
ActivePermission = true;
break;
}
}
}
if (ChosenPose != null && ChosenPose.TryGetComponent<RegularShapeFit>(out var _regular))
{
CalCloestPoint(TipTrans.position, _regular.RealStart, _regular.RealEnd, _regular.TipDist);
}
else
{
RegularTransferPosition = Vector3.zero;
}
var FingerSet = ChosenPose?.HandPose.FingersFreedom;
FixedPoseAngle = new();
for (int i = 0; i < 15; ++i)
{
if (ChosenPose != null && selected.objectFollowType != ObjectFollowType.NoPose && (FingerSet == null || FingerSet[i / 3] != JointFreedom.Free))
{
FixedPoseAngle.Add((OriginalAngle[i] * ChosenPose.HandPose.JointRotations[i]).eulerAngles);
}
else
{
FixedPoseAngle.Add(Vector3.zero);
}
}
}
//Debug.Log(selected.name + "/" + ActivePermission + " " + TriggerEnterCheck + !InActive + !selected.IsFollow);
selected.interactableObjectOutline?.EnableWithHand((int)handness, !selected.IsFollow);
AreaObject = selected;
if (ActivePermission && TriggerEnterCheck && !InActive && (!selected.IsFollow || ChosenPose.GetComponent<HandInteractionSetting>().OperationInsideObject))
{
InteractObject = selected;
selected.HandActive(gameObject, ChosenPose, RegularTransferPosition);
if (ChosenPose != null && ChosenPose.TryGetComponent<FingerUseInteraction>(out var script))
{
script.ResetInteraction();
}
InActive = true;
Debug.Log($"Active Hand : {handness}, Active Object: {selected.name}, Interaction Pose: {ChosenPose?.name}");
WhenHandInteract.Invoke();
}
}
private void OnTriggerExit(Collider other)
{
Transform trans = other.transform;
InteractableObject obj = null;
AreaObject = null;
if (trans.TryGetComponent<InteractableObject>(out var _obj))
{
obj = _obj;
}
while (trans.parent != null && obj == null)
{
trans = trans.parent;
if (trans.TryGetComponent<InteractableObject>(out var __obj))
{
obj = __obj;
}
}
if (obj == null) return;
obj.interactableObjectOutline?.EnableWithHand((int)handness, false);
TriggerObjects.Remove(obj);
if (ChosenPose != null && ChosenPose.GetComponent<HandInteractionSetting>().OperationInsideObject && InActive)
{
RemoveOperation = obj;
return;
}
if (InteractObject == obj && !InteractObject.IsFollow)
{
WhenHandDisable.Invoke();
TriggerEnterCheck = false;
InteractObject = null;
ChosenPose = null;
RegularTransferPosition = Vector3.zero;
obj.HandDisable((Handedness)handness);
Fingers.Clear();
}
}
void Update()
{
if (gameObject.name.Contains("("))
{
return;
}
if (UnityEngine.Input.GetKeyDown(ShortCutKeyCode))
{
RecordInteractionButton();
}
JointList = new()
{
Math.Abs(HandDriver.thumb3.z),
Math.Abs(HandDriver.index2.z),
Math.Abs(HandDriver.middle2.z),
Math.Abs(HandDriver.ring2.z),
Math.Abs(HandDriver.pinky2.z),
};
RayDetect();
if (Fingers.Count != 5)
{
Fingers = new() { new(""), new(""), new(""), new(""), new("") };
interactType = InteractType.AllFingers;
}
int Index = 0;
foreach (var finger in Fingers)
{
ActiveCnt[Index] = false;
if (SeparateFinger && finger.IsActive && JointList[Index] >= finger.MaxAngle * finger.Threshold)
{
ActiveCnt[Index] = true;
}
else if (!SeparateFinger && JointList[Index] >= finger.MaxAngle * ActiveIntense)
{
ActiveCnt[Index] = true;
}
Index++;
}
Joints = new()
{
HandDriver.Thumb1,
HandDriver.Thumb2,
HandDriver.Thumb3,
HandDriver.Index1,
HandDriver.Index2,
HandDriver.Index3,
HandDriver.Middle1,
HandDriver.Middle2,
HandDriver.Middle3,
HandDriver.Ring1,
HandDriver.Ring2,
HandDriver.Ring3,
HandDriver.Pinky1,
HandDriver.Pinky2,
HandDriver.Pinky3,
};
FullAngleList = new()
{
HandDriver.thumb1,
HandDriver.thumb2,
HandDriver.thumb3,
HandDriver.index1,
HandDriver.index2,
HandDriver.index3,
HandDriver.middle1,
HandDriver.middle2,
HandDriver.middle3,
HandDriver.ring1,
HandDriver.ring2,
HandDriver.ring3,
HandDriver.pinky1,
HandDriver.pinky2,
HandDriver.pinky3,
};
PoseDetect();
//Debug.Log(ActiveCnt + "//" + InActive);
if (!ActiveChecker(true)) InActive = false;
if (InteractObject == null && RayTargetObj == null) return;
if(RayTargetObj != null && InteractObject == null)
{
InteractObject = RayTargetObj;
InActive = ActiveChecker();
if(AreaObject == null || AreaObject == RayTargetObj)
{
RayTargetObj.interactableObjectOutline?.EnableWithHand((int)handness, !InActive);
}
}
if(AreaObject != null && AreaObject != RayTargetObj)
{
InteractObject = AreaObject;
}
if (InActive)
{
InteractObject.HandActive(gameObject, ChosenPose, RegularTransferPosition);
for (int i = 0; i < 5; ++i)
{
if (ChosenPose == null) break;
ActiveClock[i] += Time.deltaTime;
bool TempActive = (SeparateFinger && JointList[i] >= Fingers[i].MaxAngle * Fingers[i].Threshold) ||
(!SeparateFinger && JointList[i] >= Fingers[i].MaxAngle * ActiveIntense);
switch ((int)ChosenPose.HandPose.FingersFreedom[i])
{
case 1:
if (OnceAvtive[i])
{
for (int j = 3 * i; j < 3 * (i + 1); ++j)
{
Joints[j].DOLocalRotate(FixedPoseAngle[j], 0.4f, RotateMode.Fast);
}
OnceAvtive[i] = false;
ActiveClock[i] = 0;
}
else if (ActiveClock[i] >= 0.39f)
{
for (int j = 3 * i; j < 3 * (i + 1); ++j)
{
Joints[j].DOLocalRotate(FixedPoseAngle[j], 0f, RotateMode.Fast);
}
}
break;
case 2:
if (OnceAvtive[i] && TempActive)
{
for (int j = 3 * i; j < 3 * (i + 1); ++j)
{
Joints[j].DOLocalRotate(FixedPoseAngle[j], 0.4f, RotateMode.Fast);
}
OnceAvtive[i] = false;
ActiveClock[i] = 0;
}
else if (ActiveClock[i] >= 0.39f && TempActive)
{
for (int j = 3 * i; j < 3 * (i + 1); ++j)
{
Joints[j].DOLocalRotate(FixedPoseAngle[j], 0f, RotateMode.Fast);
}
}
break;
case 3:
var UseInteraction = ChosenPose.GetComponent<FingerUseInteraction>();
float rate = JointList[i] / Fingers[i].MaxAngle;
if (TempActive)
{
var UsePoseAngle = UseInteraction.FingerConfig((rate - Fingers[i].Threshold) / (1 - Fingers[i].Threshold), i);
for (int j = 3 * i, k = 0; j < 3 * (i + 1); ++j)
{
Joints[j].DOLocalRotate((OriginalAngle[j] * UsePoseAngle[k++]).eulerAngles, 0.05f, RotateMode.Fast);
}
}
break;
}
}
}
if (!InActive)
{
InteractObject.HandDisable((Handedness)handness);
if (RemoveOperation != null)
{
TriggerObjects.Clear();
InteractObject = null;
WhenHandDisable.Invoke();
ChosenPose = null;
RemoveOperation = null;
}
RegularTransferPosition = Vector3.zero;
//OnceAvtive = true;
for (int i = 0; i < 5; ++i)
{
OnceAvtive[i] = true;
}
if (OnceDisable)
{
for (int i = 0; i < 15; ++i)
{
if (FixedPoseAngle[i] != Vector3.zero)
{
//Joints[i].DOLocalRotate(Joints[i].localEulerAngles, 0.3f, RotateMode.Fast);
}
}
//OnceDisable = false;
}
}
//move from late update
if (FollowJointInClone && GameObject.Find("Network Manager") != null)
{
for (int i = 0; i < CloneTarget.Joints.Count; ++i)
{
CloneTarget.Joints[i].DOLocalRotate(Joints[i].localEulerAngles, 0f);
}
}
}
private bool ActiveChecker(bool IsUpdate = false)
{
bool[] ActiveCheck = new bool[2] { false, true };
if(ActiveCnt == null)
{
ActiveCnt = new bool[5];
}
bool res = false;
for (int i = 0; i < 5; ++i)
{
if (Fingers[i].IsActive != SeparateFinger) continue;
if (interactType == InteractType.AnyFinger)
{
ActiveCheck[0] |= ActiveCnt[i];
res = ActiveCheck[0];
}
else if (interactType == InteractType.AllFingers)
{
ActiveCheck[1] &= ActiveCnt[i];
res = ActiveCheck[1];
}
}
if (IsUpdate) UpdateCheckResult = res;
return res;
}
private Dictionary<float, HandInteraction> GetFairInteractableDict(InteractableObject obj)
{
Dictionary<float, HandInteraction> InteractableList = new();
foreach (var interact in obj.HandInteractions)
{
if ((int)interact.handness == (int)handness)
{
float distance = Vector3.Distance(interact.transform.GetChild(0).position, TipTrans.position);
float RotationDistance = Quaternion.Angle(transform.rotation, interact.transform.rotation);
if (interact.TryGetComponent<RegularShapeFit>(out var regular))
{
distance = CalCloestPoint(TipTrans.position, regular.RealStart, regular.RealEnd, regular.TipDist);
}
InteractableList[distance * RotationDistance] = interact;
}
}
return InteractableList.OrderBy(item => item.Key).ToDictionary(item => item.Key, item => item.Value);
}
private float CalCloestPoint(Vector3 handPoint, Vector3 lineStart, Vector3 lineEnd, float radius)
{
Vector3 lineDirection = lineEnd - lineStart;
float lineLength = lineDirection.magnitude;
lineDirection.Normalize();
Vector3 CenterPoint = lineStart + Vector3.Project(handPoint - lineStart, lineDirection);
if ((CenterPoint - lineStart).magnitude > lineLength || (CenterPoint - lineEnd).magnitude > lineLength)
{
CenterPoint = (CenterPoint - lineStart).magnitude > lineLength ? lineEnd : lineStart;
RegularTransferPosition = CenterPoint;
return CloestDirectionOnCircle(CenterPoint, handPoint, handPoint + lineDirection, radius);
}
else
{
RegularTransferPosition = CenterPoint;
return (handPoint - CenterPoint).magnitude - radius;
}
}
private float CloestDirectionOnCircle(Vector3 point, Vector3 lineStart, Vector3 lineEnd, float radius)
{
Vector3 lineDir = lineEnd - lineStart;
Vector3 pontDir = point - lineStart;
float Dot = Vector3.Dot(pontDir, lineDir);
Vector3 centerToEdge = (pontDir - Dot * lineDir.normalized).normalized * radius;
return (pontDir + centerToEdge).magnitude;
}
public void HandVisionControl(bool IsShow, HandInteractor clone)
{
HandSkinnedMeshRenderer.gameObject.SetActive(IsShow);
FollowJointInClone = !IsShow;
CloneTarget = clone;
}
public void ForceActive(InteractableObject newObj, HandInteraction newInteraction)
{
TriggerObjects = new();
InteractObject?.HandDisable((Handedness)handness);
if (newObj != null)
{
TriggerObjects.Add(newObj, null);
}
InteractObject = newObj;
ChosenPose = newInteraction;
InteractObject?.HandActive(gameObject, ChosenPose, Vector3.zero);
}
void PoseDetect()
{
if (staticPoses == null || staticPoses.Count == 0) return;
foreach(var pose in staticPoses)
{
List<Quaternion> PoseRot = pose._handPose.JointRotations.ToList();
bool Judge = true;
Judge &= (!pose.ConsiderWrist || Quaternion.Angle(transform.rotation, pose.transform.rotation) <= 30);
if (Judge)
{
for (int i = 0; i < FullAngleList.Count; ++i)
{
var TotalCheck = Quaternion.Angle(Quaternion.Euler(FullAngleList[i]), PoseRot[i]) <= 25;
if (!TotalCheck)
{
var regularPose = RegularAngle(PoseRot[i].eulerAngles);
TotalCheck = Math.Abs(FullAngleList[i].x - regularPose.x) <= 10 &&
Math.Abs(FullAngleList[i].y - regularPose.y) <= 10 &&
Math.Abs(FullAngleList[i].z - regularPose.z) <= 10;
}
Judge &= TotalCheck;
}
}
pose.IsPoseDetected(Judge);
}
}
void RayDetect()
{
if (lineRender == null) return;
int sign = handness == Handness.Left ? 1 : -1;
DetectRays = new Ray[6]
{
new Ray(DetectArea.position, DetectArea.forward),
new Ray(DetectArea.position, DetectArea.forward + sign * DetectArea.right),
new Ray(DetectArea.position, sign * DetectArea.right),
new Ray(DetectArea.position, sign * DetectArea.right - DetectArea.forward),
new Ray(DetectArea.position, sign * DetectArea.right + (float)Math.Sqrt(3) * DetectArea.up),
new Ray(DetectArea.position, sign * DetectArea.right - (float)Math.Sqrt(3) * DetectArea.up)
};
RayDetectedTarget.Clear();
for (int i = 0; i < DetectRays.Length; ++i)
{
if (Physics.Raycast(DetectRays[i], out raycastHits[i]) && raycastHits[i].collider.gameObject.TryGetComponent<InteractableObject>(out var interactableObject))
{
float Dist = Vector3.Distance(DetectArea.position, interactableObject.transform.position);
if (interactableObject.objectFollowType != ObjectFollowType.Distance || Dist > interactableObject.TrackingDistance || interactableObject.IsFollow) continue;
if (RayDetectedTarget.ContainsKey(interactableObject))
{
RayDetectedTarget[interactableObject] = Math.Min(RayDetectedTarget[interactableObject], Dist);
}
else
{
RayDetectedTarget[interactableObject] = Dist;
}
}
}
int priority = 99;
if(RayTargetObj != null && RayTargetObj != AreaObject)
{
RayTargetObj.interactableObjectOutline?.EnableWithHand((int)handness, false);
}
if (RayTargetObj == InteractObject && !InActive) InteractObject = null;
RayTargetObj = null;
foreach (InteractableObject obj in RayDetectedTarget.Keys)
{
if (priority > obj.InteractPriority)
{
priority = obj.InteractPriority;
RayTargetObj = obj;
}
else if (priority == obj.InteractPriority && RayDetectedTarget[obj] < RayDetectedTarget[RayTargetObj])
{
RayTargetObj = obj;
}
}
UsedLine.Clear();
if (RayTargetObj != null && !InActive && AreaObject == null)
{
var SortedDict = GetFairInteractableDict(RayTargetObj);
ChosenPose = SortedDict.Values.FirstOrDefault();
var SettingData = ChosenPose.GetComponent<HandInteractionSetting>();
Fingers = new()
{
new Finger("Thumb", SettingData.Thumb, SettingData.ThumbIntense),
new Finger("Index", SettingData.Index, SettingData.IndexIntense),
new Finger("Middle", SettingData.Middle, SettingData.MiddleIntense),
new Finger("Ring", SettingData.Ring, SettingData.RingIntense),
new Finger("Pinky", SettingData.Pinky, SettingData.PinkyIntense),
};
SeparateFinger = SettingData.SeparateFinger;
ActiveIntense = SettingData.ActiveIntense;
interactType = SettingData.interactType;
if (ChosenPose.TryGetComponent<RegularShapeFit>(out var _regular))
{
CalCloestPoint(TipTrans.position, _regular.RealStart, _regular.RealEnd, _regular.TipDist);
}
else
{
RegularTransferPosition = Vector3.zero;
}
var FingerSet = ChosenPose.HandPose.FingersFreedom;
FixedPoseAngle = new();
for (int i = 0; i < 15; ++i)
{
if (ChosenPose != null && RayTargetObj.objectFollowType != ObjectFollowType.NoPose && (FingerSet == null || FingerSet[i / 3] != JointFreedom.Free))
{
FixedPoseAngle.Add((OriginalAngle[i] * ChosenPose.HandPose.JointRotations[i]).eulerAngles);
}
else
{
FixedPoseAngle.Add(Vector3.zero);
}
}
Vector3 HandToObj = RayTargetObj.transform.position - DetectArea.position;
float Distance = HandToObj.magnitude;
Vector3 project = Vector3.Project(DetectArea.forward, HandToObj);
Vector3 normal = (DetectArea.forward - project).normalized;
float MaxAngle = (float)Math.Atan(0.6 / Distance);
float CurAngle = Vector3.Angle(DetectArea.forward, HandToObj);
for (int i = 0; i <= 100; ++i)
{
float x = (Distance / 100) * i;
float y = 0;
if (CurAngle <= MaxAngle)
{
y = -(float)Math.Tan(CurAngle) / Distance * (float)Math.Pow(x, 2) + (float)Math.Tan(CurAngle) * x;
}
else
{
y = (-0.6f) / (float)Math.Pow(Distance, 2) * (float)Math.Pow(x, 2) + 0.6f / Distance * x;
}
Vector3 newPos = DetectArea.position + HandToObj.normalized * x + normal * y;
CurveHighest = Math.Max(y, CurveHighest);
if (i >= 15 && i <=96)
{
UsedLine.Add(newPos);
}
}
CurveHighestVec = normal * CurveHighest;
}
lineRender.positionCount = UsedLine.Count;
lineRender.SetPositions(UsedLine.ToArray());
}
Vector3 RegularAngle(Vector3 euler)
{
var X = Math.Abs(euler.x) > 180 ? Math.Sign(euler.x) == 1 ? euler.x - 360 : euler.x + 360 : euler.x;
var Y = Math.Abs(euler.y) > 180 ? Math.Sign(euler.y) == 1 ? euler.y - 360 : euler.y + 360 : euler.y;
var Z = Math.Abs(euler.z) > 180 ? Math.Sign(euler.z) == 1 ? euler.z - 360 : euler.z + 360 : euler.z;
return new Vector3(X, Y, Z);
}
public void RecordInteractionButton()
{
if (ContactObject == null)
{
Debug.LogError("Not In Runtime or Interaction Area!");
return;
}
#if UNITY_EDITOR
GameObject virtualHand = ContactObject.DefaultVirtualHand;
var RecordedTarget = Instantiate(virtualHand, ContactObject.transform);
var interaction = RecordedTarget.GetComponent<HandInteraction>();
interaction._relativeTo = ContactObject.transform;
interaction._handPose = new()
{
Handedness = (Handedness)handness,
JointRotations = new Quaternion[15]
{
Quaternion.Inverse(OriginalAngle[0]) * Joints[0].localRotation,
Quaternion.Inverse(OriginalAngle[1]) * Joints[1].localRotation,
Quaternion.Inverse(OriginalAngle[2]) * Joints[2].localRotation,
Quaternion.Inverse(OriginalAngle[3]) * Joints[3].localRotation,
Quaternion.Inverse(OriginalAngle[4]) * Joints[4].localRotation,
Quaternion.Inverse(OriginalAngle[5]) * Joints[5].localRotation,
Quaternion.Inverse(OriginalAngle[6]) * Joints[6].localRotation,
Quaternion.Inverse(OriginalAngle[7]) * Joints[7].localRotation,
Quaternion.Inverse(OriginalAngle[8]) * Joints[8].localRotation,
Quaternion.Inverse(OriginalAngle[9]) * Joints[9].localRotation,
Quaternion.Inverse(OriginalAngle[10]) * Joints[10].localRotation,
Quaternion.Inverse(OriginalAngle[11]) * Joints[11].localRotation,
Quaternion.Inverse(OriginalAngle[12]) * Joints[12].localRotation,
Quaternion.Inverse(OriginalAngle[13]) * Joints[13].localRotation,
Quaternion.Inverse(OriginalAngle[14]) * Joints[14].localRotation,
}
};
RecordedTarget.transform.position = transform.position;
if (!Directory.Exists(Application.dataPath + "/SDK/Interaction SDK/TempVirtual"))
{
Directory.CreateDirectory(Application.dataPath + "/SDK/Interaction SDK/TempVirtual");
}
string PrefabName = "RecordedInteraction";
int index = 1;
while (Directory.Exists(Application.dataPath + $"/SDK/Interaction SDK/TempVirtual/{PrefabName}.prefab"))
{
PrefabName = "RecordedInteraction" + index++;
}
PrefabUtility.SaveAsPrefabAsset(RecordedTarget, Application.dataPath + $"/SDK/Interaction SDK/TempVirtual/{PrefabName}.prefab");
#endif
}
public void RecordStaticPoseButton()
{
#if UNITY_EDITOR
GameObject virtualHand = new GameObject(name + "NewStaticPose");
virtualHand.transform.SetParent(staticPoseDetector.transform);
var staticPose = virtualHand.AddComponent<HandStaticPose>();
Quaternion[] Target = new Quaternion[15];
if(OriginalAngle.Count == 0)
{
for(int i = 0; i < 15; ++i)
{
Target[i] = Quaternion.identity;
}
}
else
{
for (int i = 0; i < 15; ++i)
{
Target[i] = Quaternion.Inverse(OriginalAngle[i]) * Joints[i].localRotation;
}
}
staticPose._handPose = new()
{
Handedness = (Handedness)handness,
JointRotations = Target
};
virtualHand.transform.position = transform.position;
if (!Directory.Exists(Application.dataPath + "/SDK/Interaction SDK/TempVirtual"))
{
Directory.CreateDirectory(Application.dataPath + "/SDK/Interaction SDK/TempVirtual");
}
string PrefabName = virtualHand.name;
int index = 1;
while (File.Exists(Application.dataPath + $"/SDK/Interaction SDK/TempVirtual/{PrefabName}.prefab"))
{
PrefabName = virtualHand.name + index++;
}
PrefabUtility.SaveAsPrefabAsset(virtualHand, Application.dataPath + $"/SDK/Interaction SDK/TempVirtual/{PrefabName}.prefab");
#endif
}
}
}