CurvedLayoutGroup.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using EZXR.Glass.SixDof;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.TestTools;
  6. namespace EZXR.Glass.UI
  7. {
  8. [ExecuteInEditMode]
  9. public class CurvedLayoutGroup : LayoutGroup
  10. {
  11. /// <summary>
  12. /// 扇形区域的半径
  13. /// </summary>
  14. public float radius = 3;
  15. float prevRadius;
  16. /// <summary>
  17. /// 每个物体之间的间隔角度
  18. /// </summary>
  19. public float angle = 60f;
  20. float prevAngle;
  21. List<SpatialUIElement> children = new List<SpatialUIElement>();
  22. float prevChildCount;
  23. Vector3 prevSize;
  24. public override void OnValidate()
  25. {
  26. if (!Application.isPlaying)
  27. {
  28. base.OnValidate();
  29. GetSpatialUIElement();
  30. if (radius != prevRadius || angle != prevAngle || spatialUIElement.size != prevSize || (children != null && children.Count != prevChildCount))
  31. {
  32. prevRadius = radius;
  33. prevAngle = angle;
  34. prevSize = spatialUIElement.size;
  35. prevChildCount = children.Count;
  36. needReLayout = true;
  37. }
  38. }
  39. }
  40. private void OnDisable()
  41. {
  42. children = null;
  43. }
  44. // Update is called once per frame
  45. void Update()
  46. {
  47. if (startLayout)
  48. {
  49. if (needReLayout)
  50. {
  51. needReLayout = false;
  52. if (transform.childCount > 0)
  53. {
  54. children = new List<SpatialUIElement>();
  55. for (int i = 0; i < transform.childCount; i++)
  56. {
  57. SpatialUIElement temp = transform.GetChild(i).GetComponent<SpatialUIElement>();
  58. if (temp != null && temp.gameObject.activeInHierarchy)
  59. {
  60. children.Add(temp);
  61. }
  62. }
  63. prevRadius = radius;
  64. prevAngle = angle;
  65. // 从相机的位置和朝向获取扇形的起始角度
  66. Quaternion sectorRotation = Quaternion.LookRotation(Vector3.ProjectOnPlane(HMDPoseTracker.Instance.leftCamera.transform.forward, Vector3.up), Vector3.up);
  67. Quaternion startRotation = Quaternion.AngleAxis(-angle * (children.Count - 1) / 2f, Vector3.up) * sectorRotation;
  68. for (int i = 0; i < children.Count; i++)
  69. {
  70. if (children[i] != null)
  71. {
  72. // 计算当前物体的旋转
  73. Quaternion currentRotation = startRotation * Quaternion.AngleAxis(angle * i, Vector3.up);
  74. // 计算当前物体的位置
  75. children[i].transform.position = currentRotation * (Vector3.forward * radius) + HMDPoseTracker.Instance.leftCamera.transform.position;
  76. children[i].transform.LookAt(HMDPoseTracker.Instance.leftCamera.transform);
  77. }
  78. }
  79. }
  80. else
  81. {
  82. children = null;
  83. }
  84. }
  85. }
  86. }
  87. }
  88. }