VFXConeGizmos.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using UnityEngine;
  6. using UnityEngine.VFX;
  7. namespace UnityEditor.VFX
  8. {
  9. [VFXGizmo(typeof(TCone))]
  10. class VFXConeGizmo : VFXSpaceableGizmo<TCone>
  11. {
  12. IProperty<Vector3> m_CenterProperty;
  13. IProperty<Vector3> m_AnglesProperty;
  14. IProperty<Vector3> m_ScaleProperty;
  15. IProperty<float> m_BaseRadiusProperty;
  16. IProperty<float> m_TopRadiusProperty;
  17. IProperty<float> m_HeightProperty;
  18. public override void RegisterEditableMembers(IContext context)
  19. {
  20. m_CenterProperty = context.RegisterProperty<Vector3>("transform.position");
  21. m_AnglesProperty = context.RegisterProperty<Vector3>("transform.angles");
  22. m_ScaleProperty = context.RegisterProperty<Vector3>("transform.scale");
  23. m_BaseRadiusProperty = context.RegisterProperty<float>("baseRadius");
  24. m_TopRadiusProperty = context.RegisterProperty<float>("topRadius");
  25. m_HeightProperty = context.RegisterProperty<float>("height");
  26. }
  27. float topRadiusScreen;
  28. float baseRadiusScreen;
  29. bool m_Dragging;
  30. public struct Extremities
  31. {
  32. public void Build(float baseRadius, float topRadius, float height)
  33. {
  34. topCap = height * Vector3.up;
  35. bottomCap = Vector3.zero;
  36. if (extremities == null)
  37. extremities = new List<Vector3>(8);
  38. extremities.Clear();
  39. extremities.Add(topCap + Vector3.forward * topRadius);
  40. extremities.Add(topCap - Vector3.forward * topRadius);
  41. extremities.Add(topCap + Vector3.left * topRadius);
  42. extremities.Add(topCap - Vector3.left * topRadius);
  43. extremities.Add(bottomCap + Vector3.forward * baseRadius);
  44. extremities.Add(bottomCap - Vector3.forward * baseRadius);
  45. extremities.Add(bottomCap + Vector3.left * baseRadius);
  46. extremities.Add(bottomCap - Vector3.left * baseRadius);
  47. visibleCount = 4;
  48. }
  49. public void Build(float baseRadius, float topRadius, float height, float degArc)
  50. {
  51. topCap = height * Vector3.up;
  52. bottomCap = Vector3.zero;
  53. int count = 4;
  54. visibleCount = Mathf.CeilToInt(degArc / 90);
  55. if (visibleCount <= 0)
  56. {
  57. visibleCount = 1;
  58. }
  59. if (extremities == null)
  60. extremities = new List<Vector3>(8);
  61. extremities.Clear();
  62. extremities.Add(topCap + Vector3.forward * topRadius);
  63. if (count > 1)
  64. {
  65. extremities.Add(topCap - Vector3.left * topRadius);
  66. if (count > 2)
  67. {
  68. extremities.Add(topCap - Vector3.forward * topRadius);
  69. if (count > 3)
  70. {
  71. extremities.Add(topCap + Vector3.left * topRadius);
  72. }
  73. }
  74. }
  75. extremities.Add(bottomCap + Vector3.forward * baseRadius);
  76. if (count > 1)
  77. {
  78. extremities.Add(bottomCap - Vector3.left * baseRadius);
  79. if (count > 2)
  80. {
  81. extremities.Add(bottomCap - Vector3.forward * baseRadius);
  82. if (count > 3)
  83. {
  84. extremities.Add(bottomCap + Vector3.left * baseRadius);
  85. }
  86. }
  87. }
  88. }
  89. public Vector3 topCap;
  90. public Vector3 bottomCap;
  91. public List<Vector3> extremities;
  92. public int visibleCount;
  93. }
  94. private static readonly int[] s_ExtremitiesNames =
  95. {
  96. "VFX_DrawCone_Cap_0".GetHashCode(),
  97. "VFX_DrawCone_Cap_1".GetHashCode(),
  98. "VFX_DrawCone_Cap_2".GetHashCode(),
  99. "VFX_DrawCone_Cap_3".GetHashCode(),
  100. "VFX_DrawCone_Cap_4".GetHashCode(),
  101. "VFX_DrawCone_Cap_5".GetHashCode(),
  102. "VFX_DrawCone_Cap_6".GetHashCode(),
  103. "VFX_DrawCone_Cap_7".GetHashCode(),
  104. };
  105. private static readonly int s_HeightCapName = "VFX_DrawCone_HeightCap".GetHashCode();
  106. public static void DrawCone(VFXGizmo gizmo, TCone cone, ref Extremities extremities, IProperty<Vector3> centerProperty, IProperty<Vector3> anglesProperty, IProperty<Vector3> scaleProperty, IProperty<float> baseRadiusProperty, IProperty<float> topRadiusProperty, IProperty<float> heightProperty, float baseRadiusScreen, float topRadiusScreen)
  107. {
  108. var center = cone.transform.position;
  109. var scale = cone.transform.scale;
  110. var angles = cone.transform.angles;
  111. var baseRadius = cone.baseRadius;
  112. var topRadius = cone.topRadius;
  113. var height = cone.height;
  114. gizmo.PositionGizmo(center, angles, centerProperty, false);
  115. gizmo.RotationGizmo(center, angles, anglesProperty, false);
  116. gizmo.ScaleGizmo(center, angles, scale, scaleProperty, false);
  117. using (new Handles.DrawingScope(Handles.matrix * cone.transform))
  118. {
  119. if (baseRadiusScreen > 2 && baseRadiusProperty.isEditable)
  120. {
  121. for (int i = extremities.extremities.Count / 2; i < extremities.extremities.Count && (i - extremities.extremities.Count / 2) < extremities.visibleCount; ++i)
  122. {
  123. EditorGUI.BeginChangeCheck();
  124. var pos = extremities.extremities[i];
  125. var result = Handles.Slider(s_ExtremitiesNames[i], pos, pos - extremities.bottomCap, handleSize * HandleUtility.GetHandleSize(pos), CustomCubeHandleCap, 0);
  126. if (EditorGUI.EndChangeCheck())
  127. {
  128. baseRadiusProperty.SetValue(result.magnitude);
  129. }
  130. }
  131. }
  132. if (topRadiusScreen > 2 && topRadiusProperty.isEditable)
  133. {
  134. for (int i = 0; i < extremities.extremities.Count / 2 && i < extremities.visibleCount; ++i)
  135. {
  136. EditorGUI.BeginChangeCheck();
  137. var pos = extremities.extremities[i];
  138. var dir = pos - extremities.topCap;
  139. var result = Handles.Slider(s_ExtremitiesNames[i], pos, dir, handleSize * HandleUtility.GetHandleSize(pos), CustomCubeHandleCap, 0);
  140. if (EditorGUI.EndChangeCheck())
  141. topRadiusProperty.SetValue((result - extremities.topCap).magnitude);
  142. }
  143. }
  144. if (heightProperty.isEditable)
  145. {
  146. EditorGUI.BeginChangeCheck();
  147. var result = Handles.Slider(s_HeightCapName, extremities.topCap, Vector3.up, handleSize * HandleUtility.GetHandleSize(extremities.topCap), CustomCubeHandleCap, 0);
  148. if (EditorGUI.EndChangeCheck())
  149. heightProperty.SetValue(result.magnitude);
  150. }
  151. }
  152. }
  153. Extremities extremities;
  154. public override void OnDrawSpacedGizmo(TCone cone)
  155. {
  156. extremities.Build(cone.baseRadius, cone.topRadius, cone.height);
  157. if (Event.current != null && Event.current.type == EventType.MouseDown)
  158. {
  159. m_Dragging = true;
  160. }
  161. if (Event.current != null && Event.current.type == EventType.MouseUp)
  162. {
  163. m_Dragging = false;
  164. }
  165. if (!m_Dragging)
  166. {
  167. topRadiusScreen = (HandleUtility.WorldToGUIPoint(extremities.topCap) - HandleUtility.WorldToGUIPoint(extremities.topCap + Vector3.forward * cone.topRadius)).magnitude;
  168. baseRadiusScreen = (HandleUtility.WorldToGUIPoint(extremities.bottomCap) - HandleUtility.WorldToGUIPoint(extremities.bottomCap + Vector3.forward * cone.baseRadius)).magnitude;
  169. }
  170. using (new Handles.DrawingScope(Handles.matrix * cone.transform))
  171. {
  172. Handles.DrawWireDisc(extremities.topCap, Vector3.up, cone.topRadius);
  173. Handles.DrawWireDisc(extremities.bottomCap, Vector3.up, cone.baseRadius);
  174. for (int i = 0; i < extremities.extremities.Count / 2; ++i)
  175. {
  176. Handles.DrawLine(extremities.extremities[i], extremities.extremities[i + extremities.extremities.Count / 2]);
  177. }
  178. }
  179. DrawCone(this, cone, ref extremities, m_CenterProperty, m_AnglesProperty, m_ScaleProperty, m_BaseRadiusProperty, m_TopRadiusProperty, m_HeightProperty, baseRadiusScreen, topRadiusScreen);
  180. }
  181. static public Bounds GetBoundsFromCone(TCone cone)
  182. {
  183. var baseScale = new Vector3(Mathf.Max(cone.baseRadius, cone.topRadius), Mathf.Max(cone.baseRadius, cone.topRadius), cone.height);
  184. baseScale.x *= cone.transform.scale.x;
  185. baseScale.y *= cone.transform.scale.y;
  186. baseScale.z *= cone.transform.scale.z;
  187. return new Bounds(cone.transform.position, baseScale);
  188. }
  189. public override Bounds OnGetSpacedGizmoBounds(TCone value)
  190. {
  191. return GetBoundsFromCone(value);
  192. }
  193. }
  194. [VFXGizmo(typeof(TArcCone))]
  195. class VFXTArcConeGizmo : VFXSpaceableGizmo<TArcCone>
  196. {
  197. IProperty<Vector3> m_CenterProperty;
  198. IProperty<Vector3> m_AnglesProperty;
  199. IProperty<Vector3> m_ScaleProperty;
  200. IProperty<float> m_baseRadiusProperty;
  201. IProperty<float> m_topRadiusProperty;
  202. IProperty<float> m_HeightProperty;
  203. IProperty<float> m_ArcProperty;
  204. public override void RegisterEditableMembers(IContext context)
  205. {
  206. m_CenterProperty = context.RegisterProperty<Vector3>("cone.transform.position");
  207. m_AnglesProperty = context.RegisterProperty<Vector3>("cone.transform.angles");
  208. m_ScaleProperty = context.RegisterProperty<Vector3>("cone.transform.scale");
  209. m_baseRadiusProperty = context.RegisterProperty<float>("cone.baseRadius");
  210. m_topRadiusProperty = context.RegisterProperty<float>("cone.topRadius");
  211. m_HeightProperty = context.RegisterProperty<float>("cone.height");
  212. m_ArcProperty = context.RegisterProperty<float>("arc");
  213. }
  214. VFXConeGizmo.Extremities extremities;
  215. bool m_Dragging;
  216. float topRadiusScreen;
  217. float baseRadiusScreen;
  218. public override void OnDrawSpacedGizmo(TArcCone arcCone)
  219. {
  220. var arc = arcCone.arc * Mathf.Rad2Deg;
  221. extremities.Build(arcCone.cone.baseRadius, arcCone.cone.topRadius, arcCone.cone.height, arc);
  222. var arcDirection = Quaternion.AngleAxis(arc, Vector3.up) * Vector3.forward;
  223. if (Event.current != null && Event.current.type == EventType.MouseDown)
  224. {
  225. m_Dragging = true;
  226. }
  227. if (Event.current != null && Event.current.type == EventType.MouseUp)
  228. {
  229. m_Dragging = false;
  230. }
  231. if (!m_Dragging)
  232. {
  233. topRadiusScreen = (HandleUtility.WorldToGUIPoint(extremities.topCap) - HandleUtility.WorldToGUIPoint(extremities.topCap + Vector3.forward * arcCone.cone.topRadius)).magnitude;
  234. baseRadiusScreen = (HandleUtility.WorldToGUIPoint(extremities.bottomCap) - HandleUtility.WorldToGUIPoint(extremities.bottomCap + Vector3.forward * arcCone.cone.baseRadius)).magnitude;
  235. }
  236. using (new Handles.DrawingScope(Handles.matrix * arcCone.cone.transform))
  237. {
  238. if (topRadiusScreen > 2)
  239. Handles.DrawWireArc(extremities.topCap, Vector3.up, Vector3.forward, arc, arcCone.cone.topRadius);
  240. if (baseRadiusScreen > 2)
  241. Handles.DrawWireArc(extremities.bottomCap, Vector3.up, Vector3.forward, arc, arcCone.cone.baseRadius);
  242. for (int i = 0; i < extremities.extremities.Count / 2 && i < extremities.visibleCount; ++i)
  243. {
  244. Handles.DrawLine(extremities.extremities[i], extremities.extremities[i + extremities.extremities.Count / 2]);
  245. }
  246. Handles.DrawLine(extremities.topCap, extremities.extremities[0]);
  247. Handles.DrawLine(extremities.bottomCap, extremities.extremities[extremities.extremities.Count / 2]);
  248. Handles.DrawLine(extremities.topCap, extremities.topCap + arcDirection * arcCone.cone.topRadius);
  249. Handles.DrawLine(extremities.bottomCap, arcDirection * arcCone.cone.baseRadius);
  250. Handles.DrawLine(arcDirection * arcCone.cone.baseRadius, extremities.topCap + arcDirection * arcCone.cone.topRadius);
  251. var radius = arcCone.cone.baseRadius > arcCone.cone.topRadius ? arcCone.cone.baseRadius : arcCone.cone.topRadius;
  252. var center = arcCone.cone.baseRadius > arcCone.cone.topRadius ? Vector3.zero : extremities.topCap;
  253. if (radius != 0)
  254. ArcGizmo(center, radius, arc, m_ArcProperty, Quaternion.identity);
  255. }
  256. VFXConeGizmo.DrawCone(this, arcCone.cone, ref extremities, m_CenterProperty, m_AnglesProperty, m_ScaleProperty, m_baseRadiusProperty, m_topRadiusProperty, m_HeightProperty, baseRadiusScreen, topRadiusScreen);
  257. }
  258. public override Bounds OnGetSpacedGizmoBounds(TArcCone value)
  259. {
  260. return VFXConeGizmo.GetBoundsFromCone(value.cone);
  261. }
  262. }
  263. }