RotateUseHandle.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System.Runtime.InteropServices;
  4. using UnityEngine;
  5. namespace EZXR.Glass.Inputs
  6. {
  7. [RequireComponent(typeof(HandInfo))]
  8. public class RotateUseHandle : MonoBehaviour
  9. {
  10. HandInfo handInfo;
  11. TransformWithBounds transformUseBounds;
  12. /// <summary>
  13. /// 射线上次射击到的Collider,用于将射线结果转化成OnTriggerStay和OnTriggerExit
  14. /// </summary>
  15. Collider lastRayCastResult = null;
  16. //public LayerMask layerMask;
  17. /// <summary>
  18. /// 要被旋转的目标物体
  19. /// </summary>
  20. Transform target;
  21. /// <summary>
  22. /// 当前控制的是哪个旋转手柄
  23. /// </summary>
  24. Transform curHandle;
  25. /// <summary>
  26. /// 旋转手柄被捏住一瞬间的手柄的position
  27. /// </summary>
  28. Vector3 curHandlePos;
  29. /// <summary>
  30. /// 旋转手柄被捏住一瞬间,手柄与射线起始点的偏移量
  31. /// </summary>
  32. Vector3 offset;
  33. /// <summary>
  34. /// 旋转手柄被捏住一瞬间的localRotation
  35. /// </summary>
  36. Quaternion curTargetRotation;
  37. /// <summary>
  38. /// 用户是否捏合了手指(等于按住鼠标)
  39. /// </summary>
  40. bool press;
  41. /// <summary>
  42. /// 抓取状态,0为没有手进入此物体的Trigger区域,1为手已经进入了Trigger区域(待抓取),2为已经被左手抓起来了
  43. /// </summary>
  44. int grabState;
  45. /// <summary>
  46. /// 当前握住的手柄所在平面的法线
  47. /// </summary>
  48. Vector3 normal;
  49. /// <summary>
  50. /// 目标物体中心到射线发射点的向量在手柄所在平面的投影向量
  51. /// </summary>
  52. Vector3 projectedPos;
  53. /// <summary>
  54. /// 用于计算手柄所在平面所需要的另外一个点,连同物体中心点这三个点才能组成一个平面
  55. /// </summary>
  56. Vector3 anotherPoint;
  57. // Start is called before the first frame update
  58. void Start()
  59. {
  60. handInfo = GetComponent<HandInfo>();
  61. //用于得到当前手的射线检测的结果
  62. handInfo.Event_GetRayCastResult += OnRayCastHit;
  63. }
  64. private void OnDisable()
  65. {
  66. grabState = 0;
  67. if (curHandle != null)
  68. {
  69. curHandle.GetComponent<Renderer>().material.color = Color.white;
  70. curHandle = null;
  71. }
  72. target = null;
  73. }
  74. // Update is called once per frame
  75. void Update()
  76. {
  77. switch (grabState)
  78. {
  79. case 1:
  80. if (handInfo.isPinching)
  81. {
  82. curHandlePos = curHandle.position;
  83. //算出旋转手柄被捏住一瞬间,手柄与射线起始点的偏移量
  84. offset = curHandle.position - handInfo.rayPoint_Start;
  85. curTargetRotation = target.localRotation;
  86. //得到当前手柄与target以及同轴面上另外一个手柄所在平面的法线
  87. normal = GetPlaneNormal();
  88. grabState = 2;
  89. }
  90. break;
  91. case 2:
  92. if (handInfo.isPinching)
  93. {
  94. //算出手柄的实时位置,要加上刚被握住时候的偏移量
  95. NativeSwapManager.Point3 temp = new NativeSwapManager.Point3(handInfo.rayPoint_Start + offset);
  96. NativeSwapManager.filterPoint(ref temp, curHandle.GetInstanceID());
  97. projectedPos = target.position + Vector3.ProjectOnPlane(new Vector3(temp.x, temp.y, temp.z) - target.position, normal);
  98. target.localRotation = Quaternion.FromToRotation(curHandlePos - target.position, projectedPos - target.position) * curTargetRotation;
  99. }
  100. else
  101. {
  102. grabState = 0;
  103. curHandle.GetComponent<Renderer>().material.color = Color.white;
  104. curHandle = null;
  105. target = null;
  106. }
  107. break;
  108. }
  109. }
  110. //private void OnDrawGizmos()
  111. //{
  112. // Gizmos.DrawCube(anotherPoint, Vector3.one * 0.05f);
  113. // if (target != null)
  114. // {
  115. // Gizmos.DrawLine(target.position, curHandlePos);
  116. // Gizmos.DrawLine(target.position, target.position + normal);
  117. // Gizmos.DrawLine(target.position, projectedPos);
  118. // }
  119. //}
  120. /// <summary>
  121. /// 获得射线检测结果,转化成OnTriggerStay和OnTriggerExit
  122. /// </summary>
  123. public void OnRayCastHit(Collider other, bool isUI)
  124. {
  125. if (enabled)
  126. {
  127. //触发和OnTriggerExit基本一致的逻辑
  128. if (lastRayCastResult != other)
  129. {
  130. if (lastRayCastResult != null)
  131. {
  132. //OnTriggerExit(lastRayCastResult);
  133. if (!handInfo.isPinching)
  134. {
  135. if (other != null && other.tag == "SpatialHandler" && lastRayCastResult.name == "RotateHandle(Clone)")
  136. {
  137. grabState = 0;
  138. if (curHandle != null)
  139. {
  140. curHandle.GetComponent<Renderer>().material.color = Color.white;
  141. }
  142. curHandle = null;
  143. target = null;
  144. }
  145. }
  146. }
  147. lastRayCastResult = other;
  148. }
  149. //触发和OnTriggerStay基本一致的逻辑
  150. if (other != null)
  151. {
  152. if (!handInfo.isPinching && !handInfo.IsCloseContacting)
  153. {
  154. if (other.tag == "SpatialHandler" && other.name == "RotateHandle(Clone)")
  155. {
  156. grabState = 1;
  157. curHandle = other.transform;
  158. curHandle.GetComponent<Renderer>().material.color = Color.red;
  159. //设置要被旋转的目标物体
  160. target = other.transform.parent;
  161. transformUseBounds = target.GetComponent<TransformWithBounds>();
  162. }
  163. }
  164. }
  165. }
  166. }
  167. public void ForOnTriggerEnter(Collider other)
  168. {
  169. ForOnTriggerStay(other);
  170. }
  171. public void ForOnTriggerStay(Collider other)
  172. {
  173. if (enabled && other.name == "RotateHandle(Clone)")
  174. {
  175. grabState = 1;
  176. curHandle = other.transform;
  177. curHandle.GetComponent<Renderer>().material.color = Color.red;
  178. //设置要被旋转的目标物体
  179. target = other.transform.parent;
  180. transformUseBounds = target.GetComponent<TransformWithBounds>();
  181. }
  182. }
  183. public void ForOnTriggerExit(Collider other)
  184. {
  185. if (enabled && other.name == "RotateHandle(Clone)")
  186. {
  187. grabState = 0;
  188. curHandle.GetComponent<Renderer>().material.color = Color.white;
  189. curHandle = null;
  190. target = null;
  191. }
  192. }
  193. /// <summary>
  194. /// 得到当前手柄与target以及同轴面上另外一个手柄所在平面的法线
  195. /// </summary>
  196. /// <returns></returns>
  197. Vector3 GetPlaneNormal()
  198. {
  199. bool gotIt = false;
  200. anotherPoint = Vector3.zero;
  201. for (int i = 0; i < transformUseBounds.rotate_X.Length; i++)
  202. {
  203. if (transformUseBounds.rotate_X[i] == curHandle)
  204. {
  205. gotIt = true;
  206. if (i < 3)
  207. {
  208. anotherPoint = transformUseBounds.rotate_X[i + 1].position;
  209. }
  210. else
  211. {
  212. anotherPoint = transformUseBounds.rotate_X[i - 1].position;
  213. }
  214. }
  215. }
  216. if (!gotIt)
  217. {
  218. for (int i = 0; i < transformUseBounds.rotate_Y.Length; i++)
  219. {
  220. if (transformUseBounds.rotate_Y[i] == curHandle)
  221. {
  222. gotIt = true;
  223. if (i < 3)
  224. {
  225. anotherPoint = transformUseBounds.rotate_Y[i + 1].position;
  226. }
  227. else
  228. {
  229. anotherPoint = transformUseBounds.rotate_Y[i - 1].position;
  230. }
  231. }
  232. }
  233. }
  234. if (!gotIt)
  235. {
  236. for (int i = 0; i < transformUseBounds.rotate_Z.Length; i++)
  237. {
  238. if (transformUseBounds.rotate_Z[i] == curHandle)
  239. {
  240. gotIt = true;
  241. if (i < 3)
  242. {
  243. anotherPoint = transformUseBounds.rotate_Z[i + 1].position;
  244. }
  245. else
  246. {
  247. anotherPoint = transformUseBounds.rotate_Z[i - 1].position;
  248. }
  249. }
  250. }
  251. }
  252. if (gotIt)
  253. {
  254. return Vector3.Cross(curHandlePos - target.position, anotherPoint - target.position);
  255. }
  256. else
  257. {
  258. return anotherPoint;
  259. }
  260. }
  261. }
  262. }