SpatialUIElement.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. using EZXR.Glass.Inputs;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using Wheels.Unity;
  6. using EZXR.Glass.Core;
  7. using System;
  8. #if UNITY_EDITOR
  9. using UnityEditor;
  10. #endif
  11. namespace EZXR.Glass.UI
  12. {
  13. [ExecuteInEditMode]
  14. public class SpatialUIElement : MonoBehaviour
  15. {
  16. #region InternalUse
  17. public Transform _visual;
  18. public Transform _mesh;
  19. public TextMesh _text;
  20. public MeshRenderer _meshRenderer;
  21. public MeshRenderer _textRenderer;
  22. public Transform _subElements;
  23. #endregion
  24. public bool interactable = true;
  25. /// <summary>
  26. /// UI的位姿出现类型
  27. /// </summary>
  28. public enum UIPoseType
  29. {
  30. /// <summary>
  31. /// 不对UI的位姿做任何处理
  32. /// </summary>
  33. Free,
  34. /// <summary>
  35. /// 始终朝向头部,位置不变
  36. /// </summary>
  37. FaceToHead,
  38. /// <summary>
  39. /// 与视野平行对齐
  40. /// </summary>
  41. AlignWithView,
  42. /// <summary>
  43. /// 刚性固定到头部,随相机移动和旋转
  44. /// </summary>
  45. FixedToHead,
  46. /// <summary>
  47. /// 超出视野后重置到头部前方,在相机视野外的时候将自己重置到相机前面,且面向相机
  48. /// </summary>
  49. RecenterIfOutOfView,
  50. /// <summary>
  51. /// 绑定在左手小拇指外侧
  52. /// </summary>
  53. LeftPinkySide,
  54. /// <summary>
  55. /// 绑定在右手小拇指外侧
  56. /// </summary>
  57. RightPinkySide,
  58. /// <summary>
  59. /// 绑定在左手手腕上
  60. /// </summary>
  61. OnLeftWrist,
  62. /// <summary>
  63. /// 绑定在右手手腕上
  64. /// </summary>
  65. OnRightWrist,
  66. }
  67. /// <summary>
  68. /// UI的位姿出现类型
  69. /// </summary>
  70. [SerializeField]
  71. protected UIPoseType positionType;
  72. /// <summary>
  73. /// UI的位姿出现类型
  74. /// </summary>
  75. public UIPoseType PositionType
  76. {
  77. get
  78. {
  79. return positionType;
  80. }
  81. set
  82. {
  83. if (positionType == UIPoseType.FixedToHead && value != UIPoseType.FixedToHead)
  84. {
  85. transform.CancelActAsChild();
  86. }
  87. positionType = value;
  88. }
  89. }
  90. public Vector3 size = new Vector3(0.1f, 0.1f, 0.1f);
  91. Vector3 prevSize = Vector3.zero;
  92. ///// <summary>
  93. ///// SharedMaterial
  94. ///// </summary>
  95. //public Material sharedMaterial;
  96. /// <summary>
  97. /// 此实例的Material
  98. /// </summary>
  99. public Material material;
  100. [SerializeField]
  101. private string text = "UI";
  102. /// <summary>
  103. /// UI上显示的文字
  104. /// </summary>
  105. public string Text
  106. {
  107. get
  108. {
  109. return text;
  110. }
  111. set
  112. {
  113. if (string.IsNullOrEmpty(value))
  114. {
  115. _text.gameObject.SetActive(false);
  116. }
  117. else
  118. {
  119. _text.gameObject.SetActive(true);
  120. }
  121. text = value;
  122. _text.text = text;
  123. }
  124. }
  125. [SerializeField]
  126. private Color textColor = Color.white;
  127. /// <summary>
  128. /// Text的颜色
  129. /// </summary>
  130. public Color TextColor
  131. {
  132. get
  133. {
  134. return textColor;
  135. }
  136. set
  137. {
  138. _text.color = value;
  139. }
  140. }
  141. protected MaterialPropertyBlock materialPropertyBlock;
  142. [SerializeField]
  143. private Color color = Color.white;
  144. /// <summary>
  145. /// UI的颜色
  146. /// </summary>
  147. public Color MainColor
  148. {
  149. get
  150. {
  151. return color;
  152. }
  153. set
  154. {
  155. materialPropertyBlock.SetColor("_Color", value);
  156. _meshRenderer.SetPropertyBlock(materialPropertyBlock);
  157. }
  158. }
  159. Color lastColor;
  160. [SerializeField]
  161. private Texture2D texture;
  162. /// <summary>
  163. /// UI的图
  164. /// </summary>
  165. public Texture2D Texture
  166. {
  167. get
  168. {
  169. return texture;
  170. }
  171. set
  172. {
  173. texture = value;
  174. SetMainMaterial();
  175. }
  176. }
  177. /// <summary>
  178. /// UI的叠加顺序
  179. /// </summary>
  180. public int sortingOrder;
  181. /// <summary>
  182. /// UI当前所应用的SpatialUIController.Instance.unitsPerPixel
  183. /// </summary>
  184. public float curUnitsPerPixel = 0.0001f;
  185. public float ratio;
  186. #if UNITY_EDITOR
  187. protected virtual void ReCalculateSize(float newUnitsPerPixel, bool donotReCalSize = true)
  188. {
  189. ratio = newUnitsPerPixel / curUnitsPerPixel;
  190. if (this != null)
  191. {
  192. if (donotReCalSize)
  193. {
  194. size *= (newUnitsPerPixel / curUnitsPerPixel);
  195. }
  196. else
  197. {
  198. if (Texture != null)
  199. {
  200. size = new Vector3(Texture.width * newUnitsPerPixel, Texture.height * newUnitsPerPixel, size.z);
  201. }
  202. }
  203. ////设置UI尺寸
  204. //_mesh.localScale = size;
  205. if (_text != null)
  206. {
  207. _text.transform.localPosition *= ratio;
  208. _text.transform.localScale *= ratio;
  209. }
  210. curUnitsPerPixel = newUnitsPerPixel;
  211. SceneView.RepaintAll();
  212. }
  213. }
  214. #endif
  215. protected virtual void OnValidate()
  216. {
  217. if (prevSize != size)
  218. {
  219. prevSize = size;
  220. transform.parent?.GetComponent<LayoutGroup>()?.ReLayout();
  221. }
  222. }
  223. protected virtual void Awake()
  224. {
  225. gameObject.tag = interactable ? "SpatialUI" : "SpatialUI(NoInteractable)";
  226. if (Application.isPlaying)
  227. {
  228. material = _meshRenderer.material;
  229. materialPropertyBlock = new MaterialPropertyBlock();
  230. _meshRenderer.GetPropertyBlock(materialPropertyBlock);
  231. //设置Material(MaterialPropertyBlock)
  232. SetMainMaterial();
  233. }
  234. else
  235. {
  236. #if UNITY_EDITOR
  237. if (transform.Find("Visual/Text") != null)
  238. {
  239. _text = transform.Find("Visual/Text").GetComponentInChildren<TextMesh>();
  240. }
  241. if (curUnitsPerPixel == 0)
  242. {
  243. curUnitsPerPixel = 0.0001f;
  244. }
  245. Core.PrefabUtility.UnpackPrefabInstance(gameObject);
  246. if (SpatialUIController.Instance == null)
  247. {
  248. Core.PrefabUtility.InstantiatePrefabWithUndoAndSelection(ResourcesManager.Load<GameObject>("SpatialUIController"));
  249. }
  250. if (SpatialUIEventSystem.Instance == null)
  251. {
  252. Core.PrefabUtility.InstantiatePrefabWithUndoAndSelection(ResourcesManager.Load<GameObject>("SpatialUIEventSystem"));
  253. }
  254. SpatialUIController.Instance.ReCalculateAllSize += ReCalculateSize;
  255. materialPropertyBlock = new MaterialPropertyBlock();
  256. _meshRenderer.GetPropertyBlock(materialPropertyBlock);
  257. #endif
  258. }
  259. }
  260. protected virtual void OnEnable()
  261. {
  262. transform.parent?.GetComponent<LayoutGroup>()?.ReLayout();
  263. }
  264. protected virtual void OnDisable()
  265. {
  266. transform.parent?.GetComponent<LayoutGroup>()?.ReLayout();
  267. }
  268. protected virtual void Start()
  269. {
  270. switch (PositionType)
  271. {
  272. case UIPoseType.OnLeftWrist:
  273. //OnWrist的UI初始化的时候应该在视野之外
  274. transform.position = new Vector3(9999, 9999, 9999);
  275. break;
  276. case UIPoseType.FixedToHead:
  277. transform.ActAsChild(SpatialUIController.Instance.leftCamera.transform);
  278. break;
  279. }
  280. }
  281. protected virtual void Update()
  282. {
  283. if (Application.isPlaying)
  284. {
  285. switch (PositionType)
  286. {
  287. case UIPoseType.FaceToHead:
  288. transform.LookAt(SpatialUIController.Instance.leftCamera.transform);
  289. break;
  290. case UIPoseType.AlignWithView:
  291. transform.LookAt(transform.position - SpatialUIController.Instance.leftCamera.transform.forward);
  292. break;
  293. case UIPoseType.RecenterIfOutOfView:
  294. if (!SpatialUIController.Instance.leftCamera.rect.Contains(SpatialUIController.Instance.leftCamera.WorldToViewportPoint(transform.position)) && !SpatialUIController.Instance.rightCamera.rect.Contains(SpatialUIController.Instance.rightCamera.WorldToViewportPoint(transform.position)))
  295. {
  296. transform.position = SpatialUIController.Instance.leftCamera.transform.TransformPoint(new Vector3(0, 0, Vector3.Distance(transform.position, SpatialUIController.Instance.leftCamera.transform.position)));
  297. transform.LookAt(transform.position + SpatialUIController.Instance.leftCamera.transform.forward);
  298. }
  299. break;
  300. case UIPoseType.LeftPinkySide:
  301. NativeSwapManager.Point3 temp = new NativeSwapManager.Point3(ARHandManager.leftHand.GetJointData(HandJointType.Pinky_1).position + ARHandManager.leftHand.GetJointData(HandJointType.Pinky_1).position - ARHandManager.leftHand.GetJointData(HandJointType.Index_1).position);
  302. //NativeSwapManager.filterPoint(ref temp, transform.GetInstanceID());
  303. transform.position = new Vector3(temp.x, temp.y, temp.z);
  304. transform.LookAt(transform.position + ARHandManager.leftHand.palmDirection, ARHandManager.leftHand.palmNormal);
  305. break;
  306. case UIPoseType.OnLeftWrist:
  307. if (ARHandManager.Instance.isActiveAndEnabled && ARHandManager.leftHand != null && ARHandManager.leftHand.Exist)
  308. {
  309. temp = new NativeSwapManager.Point3(ARHandManager.leftHand.GetJointData(HandJointType.Wrist_Middle).position);
  310. //NativeSwapManager.filterPoint(ref temp, transform.GetInstanceID());
  311. Vector3 newPos = new Vector3(temp.x, temp.y, temp.z);
  312. if (Vector3.Distance(newPos, SpatialUIController.Instance.leftCamera.transform.position) > 0.1f)
  313. {
  314. transform.position = newPos + ARHandManager.leftHand.palmDirection.normalized * -0.03f;
  315. transform.LookAt(transform.position + ARHandManager.leftHand.palmNormal, ARHandManager.leftHand.palmDirection.normalized);
  316. }
  317. }
  318. else
  319. {
  320. transform.position = new Vector3(9999, 9999, 9999);
  321. }
  322. break;
  323. }
  324. }
  325. else
  326. {
  327. #if UNITY_EDITOR
  328. //if (SpatialUIController.Instance.unitsPerPixel != curUnitsPerPixel)
  329. //{
  330. // ReCalculateSize(SpatialUIController.Instance.unitsPerPixel, true);
  331. //}
  332. _meshRenderer.sortingOrder = sortingOrder;
  333. if (Selection.activeGameObject != null && Selection.activeGameObject.hideFlags == HideFlags.NotEditable)
  334. {
  335. while (Selection.activeGameObject.transform.parent != null && (Selection.activeGameObject.hideFlags == HideFlags.NotEditable || Selection.activeGameObject.hideFlags == HideFlags.HideInHierarchy))
  336. {
  337. Selection.activeGameObject = Selection.activeGameObject.transform.parent.gameObject;
  338. }
  339. }
  340. _visual = _mesh.parent;
  341. //设置UI尺寸
  342. _mesh.localScale = size;
  343. //确保materialPropertyBlock不为空
  344. if (materialPropertyBlock == null)
  345. {
  346. Awake();
  347. }
  348. //设置Material(MaterialPropertyBlock)
  349. SetMainMaterial();
  350. //_visual.gameObject.hideFlags = HideFlags.HideInHierarchy;
  351. //_mesh.gameObject.hideFlags = HideFlags.NotEditable;
  352. if (_text != null)
  353. {
  354. //_text.transform.hideFlags = HideFlags.HideInHierarchy;
  355. _text.text = Text;
  356. _text.color = textColor;
  357. _text.gameObject.SetActive(!string.IsNullOrEmpty(Text));
  358. if (_textRenderer == null)
  359. {
  360. _textRenderer = _text.GetComponent<MeshRenderer>();
  361. }
  362. _textRenderer.sortingOrder = sortingOrder + 1;
  363. }
  364. #endif
  365. }
  366. }
  367. protected virtual void OnDestroy()
  368. {
  369. if (!Application.isPlaying)
  370. {
  371. #if UNITY_EDITOR
  372. if (SpatialUIController.Instance != null)
  373. {
  374. SpatialUIController.Instance.ReCalculateAllSize -= ReCalculateSize;
  375. }
  376. #endif
  377. }
  378. }
  379. private void SetMainMaterial()
  380. {
  381. //设置UI的bgImage(确保Texture的设定相对于其他的materialPropertyBlock的Set是最前的,因为无法直接SetTexture为null)
  382. //if (bgImage != lastBGImage)
  383. {
  384. if (Texture != null)
  385. {
  386. materialPropertyBlock.SetTexture("_MainTex", Texture);
  387. }
  388. else
  389. {
  390. //重置materialPropertyBlock,因为无法直接SetTexture为null
  391. materialPropertyBlock.Clear();
  392. }
  393. }
  394. //设置UI的颜色
  395. //if (color != lastColor)
  396. {
  397. materialPropertyBlock.SetColor("_Color", color);
  398. lastColor = color;
  399. }
  400. _meshRenderer.SetPropertyBlock(materialPropertyBlock);
  401. }
  402. }
  403. }