using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine; namespace EZXR.Glass.Inputs { [RequireComponent(typeof(HandInfo))] public class RotateUseHandle : MonoBehaviour { HandInfo handInfo; TransformWithBounds transformUseBounds; /// /// 射线上次射击到的Collider,用于将射线结果转化成OnTriggerStay和OnTriggerExit /// Collider lastRayCastResult = null; //public LayerMask layerMask; /// /// 要被旋转的目标物体 /// Transform target; /// /// 当前控制的是哪个旋转手柄 /// Transform curHandle; /// /// 旋转手柄被捏住一瞬间的手柄的position /// Vector3 curHandlePos; /// /// 旋转手柄被捏住一瞬间,手柄与射线起始点的偏移量 /// Vector3 offset; /// /// 旋转手柄被捏住一瞬间的localRotation /// Quaternion curTargetRotation; /// /// 用户是否捏合了手指(等于按住鼠标) /// bool press; /// /// 抓取状态,0为没有手进入此物体的Trigger区域,1为手已经进入了Trigger区域(待抓取),2为已经被左手抓起来了 /// int grabState; /// /// 当前握住的手柄所在平面的法线 /// Vector3 normal; /// /// 目标物体中心到射线发射点的向量在手柄所在平面的投影向量 /// Vector3 projectedPos; /// /// 用于计算手柄所在平面所需要的另外一个点,连同物体中心点这三个点才能组成一个平面 /// Vector3 anotherPoint; // Start is called before the first frame update void Start() { handInfo = GetComponent(); //用于得到当前手的射线检测的结果 handInfo.Event_GetRayCastResult += OnRayCastHit; } private void OnDisable() { grabState = 0; if (curHandle != null) { curHandle.GetComponent().material.color = Color.white; curHandle = null; } target = null; } // Update is called once per frame void Update() { switch (grabState) { case 1: if (handInfo.isPinching) { curHandlePos = curHandle.position; //算出旋转手柄被捏住一瞬间,手柄与射线起始点的偏移量 offset = curHandle.position - handInfo.rayPoint_Start; curTargetRotation = target.localRotation; //得到当前手柄与target以及同轴面上另外一个手柄所在平面的法线 normal = GetPlaneNormal(); grabState = 2; } break; case 2: if (handInfo.isPinching) { //算出手柄的实时位置,要加上刚被握住时候的偏移量 NativeSwapManager.Point3 temp = new NativeSwapManager.Point3(handInfo.rayPoint_Start + offset); NativeSwapManager.filterPoint(ref temp, curHandle.GetInstanceID()); projectedPos = target.position + Vector3.ProjectOnPlane(new Vector3(temp.x, temp.y, temp.z) - target.position, normal); target.localRotation = Quaternion.FromToRotation(curHandlePos - target.position, projectedPos - target.position) * curTargetRotation; } else { grabState = 0; curHandle.GetComponent().material.color = Color.white; curHandle = null; target = null; } break; } } //private void OnDrawGizmos() //{ // Gizmos.DrawCube(anotherPoint, Vector3.one * 0.05f); // if (target != null) // { // Gizmos.DrawLine(target.position, curHandlePos); // Gizmos.DrawLine(target.position, target.position + normal); // Gizmos.DrawLine(target.position, projectedPos); // } //} /// /// 获得射线检测结果,转化成OnTriggerStay和OnTriggerExit /// public void OnRayCastHit(Collider other, bool isUI) { if (enabled) { //触发和OnTriggerExit基本一致的逻辑 if (lastRayCastResult != other) { if (lastRayCastResult != null) { //OnTriggerExit(lastRayCastResult); if (!handInfo.isPinching) { if (other != null && other.tag == "SpatialHandler" && lastRayCastResult.name == "RotateHandle(Clone)") { grabState = 0; if (curHandle != null) { curHandle.GetComponent().material.color = Color.white; } curHandle = null; target = null; } } } lastRayCastResult = other; } //触发和OnTriggerStay基本一致的逻辑 if (other != null) { if (!handInfo.isPinching && !handInfo.IsCloseContacting) { if (other.tag == "SpatialHandler" && other.name == "RotateHandle(Clone)") { grabState = 1; curHandle = other.transform; curHandle.GetComponent().material.color = Color.red; //设置要被旋转的目标物体 target = other.transform.parent; transformUseBounds = target.GetComponent(); } } } } } public void ForOnTriggerEnter(Collider other) { ForOnTriggerStay(other); } public void ForOnTriggerStay(Collider other) { if (enabled && other.name == "RotateHandle(Clone)") { grabState = 1; curHandle = other.transform; curHandle.GetComponent().material.color = Color.red; //设置要被旋转的目标物体 target = other.transform.parent; transformUseBounds = target.GetComponent(); } } public void ForOnTriggerExit(Collider other) { if (enabled && other.name == "RotateHandle(Clone)") { grabState = 0; curHandle.GetComponent().material.color = Color.white; curHandle = null; target = null; } } /// /// 得到当前手柄与target以及同轴面上另外一个手柄所在平面的法线 /// /// Vector3 GetPlaneNormal() { bool gotIt = false; anotherPoint = Vector3.zero; for (int i = 0; i < transformUseBounds.rotate_X.Length; i++) { if (transformUseBounds.rotate_X[i] == curHandle) { gotIt = true; if (i < 3) { anotherPoint = transformUseBounds.rotate_X[i + 1].position; } else { anotherPoint = transformUseBounds.rotate_X[i - 1].position; } } } if (!gotIt) { for (int i = 0; i < transformUseBounds.rotate_Y.Length; i++) { if (transformUseBounds.rotate_Y[i] == curHandle) { gotIt = true; if (i < 3) { anotherPoint = transformUseBounds.rotate_Y[i + 1].position; } else { anotherPoint = transformUseBounds.rotate_Y[i - 1].position; } } } } if (!gotIt) { for (int i = 0; i < transformUseBounds.rotate_Z.Length; i++) { if (transformUseBounds.rotate_Z[i] == curHandle) { gotIt = true; if (i < 3) { anotherPoint = transformUseBounds.rotate_Z[i + 1].position; } else { anotherPoint = transformUseBounds.rotate_Z[i - 1].position; } } } } if (gotIt) { return Vector3.Cross(curHandlePos - target.position, anotherPoint - target.position); } else { return anotherPoint; } } } }