暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

DisplacableRectHandles.cs 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. using System;
  2. using System.Reflection;
  3. using UnityEngine;
  4. namespace UnityEditor.Rendering.Universal
  5. {
  6. // Copy of UnityEditor.Rendering.HighDefinition.DisplacableRectHandles
  7. class DisplacableRectHandles
  8. {
  9. const float k_HandleSizeCoef = 0.05f;
  10. enum NamedEdge { Right, Top, Left, Bottom, None }
  11. int[] m_ControlIDs = new int[4] { 0, 0, 0, 0 };
  12. Color m_MonochromeHandleColor;
  13. Color m_WireframeColor;
  14. Color m_WireframeColorBehind;
  15. /// <summary>The position of the center of the box in Handle.matrix space. On plane z=0.</summary>
  16. public Vector2 center { get; set; }
  17. /// <summary>The size of the box in Handle.matrix space. On plane z=0.</summary>
  18. public Vector2 size { get; set; }
  19. //Note: Handles.Slider not allow to use a specific ControlID.
  20. //Thus Slider1D is used (with reflection)
  21. static Type k_Slider1D = Type.GetType("UnityEditorInternal.Slider1D, UnityEditor");
  22. static MethodInfo k_Slider1D_Do = k_Slider1D
  23. .GetMethod(
  24. "Do",
  25. BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public,
  26. null,
  27. CallingConventions.Any,
  28. new[] { typeof(int), typeof(Vector3), typeof(Vector3), typeof(float), typeof(Handles.CapFunction), typeof(float) },
  29. null);
  30. static void Slider1D(int controlID, ref Vector3 handlePosition, Vector3 handleOrientation, float snapScale)
  31. {
  32. handlePosition = (Vector3)k_Slider1D_Do.Invoke(null, new object[]
  33. {
  34. controlID,
  35. handlePosition,
  36. handleOrientation,
  37. HandleUtility.GetHandleSize(handlePosition) * k_HandleSizeCoef,
  38. new Handles.CapFunction(Handles.DotHandleCap),
  39. snapScale
  40. });
  41. }
  42. /// <summary>The baseColor used to draw the rect.</summary>
  43. public Color baseColor
  44. {
  45. get { return m_MonochromeHandleColor; }
  46. set
  47. {
  48. m_MonochromeHandleColor = GizmoUtility.GetHandleColor(value);
  49. m_WireframeColor = GizmoUtility.GetWireframeColor(value);
  50. m_WireframeColorBehind = GizmoUtility.GetWireframeColorBehindObjects(value);
  51. }
  52. }
  53. public DisplacableRectHandles(Color baseColor)
  54. {
  55. this.baseColor = baseColor;
  56. }
  57. /// <summary>Draw the rect.</summary>
  58. public void DrawRect(bool dottedLine = false, float thickness = .0f, float screenSpaceSize = 5f)
  59. {
  60. Vector2 start = center - size * .5f;
  61. Vector3[] positions = new Vector3[]
  62. {
  63. start,
  64. start + size * Vector2.right,
  65. start + size,
  66. start + size * Vector2.up
  67. };
  68. Vector3[] edges = new Vector3[]
  69. {
  70. positions[0], positions[1],
  71. positions[1], positions[2],
  72. positions[2], positions[3],
  73. positions[3], positions[0],
  74. };
  75. void Draw()
  76. {
  77. if (dottedLine)
  78. Handles.DrawDottedLines(edges, screenSpaceSize);
  79. else
  80. {
  81. Handles.DrawLine(positions[0], positions[1], thickness);
  82. Handles.DrawLine(positions[1], positions[2], thickness);
  83. Handles.DrawLine(positions[2], positions[3], thickness);
  84. Handles.DrawLine(positions[3], positions[0], thickness);
  85. }
  86. }
  87. Color previousColor = Handles.color;
  88. Handles.color = m_WireframeColor;
  89. Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual;
  90. Draw();
  91. Handles.color = m_WireframeColorBehind;
  92. Handles.zTest = UnityEngine.Rendering.CompareFunction.Greater;
  93. Draw();
  94. Handles.zTest = UnityEngine.Rendering.CompareFunction.Always;
  95. Handles.color = previousColor;
  96. }
  97. NamedEdge DrawSliders(ref Vector3 leftPosition, ref Vector3 rightPosition, ref Vector3 topPosition, ref Vector3 bottomPosition)
  98. {
  99. NamedEdge theChangedEdge = NamedEdge.None;
  100. using (new Handles.DrawingScope(m_MonochromeHandleColor))
  101. {
  102. EditorGUI.BeginChangeCheck();
  103. Slider1D(m_ControlIDs[(int)NamedEdge.Left], ref leftPosition, Vector3.left, EditorSnapSettings.scale);
  104. if (EditorGUI.EndChangeCheck())
  105. theChangedEdge = NamedEdge.Left;
  106. EditorGUI.BeginChangeCheck();
  107. Slider1D(m_ControlIDs[(int)NamedEdge.Right], ref rightPosition, Vector3.right, EditorSnapSettings.scale);
  108. if (EditorGUI.EndChangeCheck())
  109. theChangedEdge = NamedEdge.Right;
  110. EditorGUI.BeginChangeCheck();
  111. Slider1D(m_ControlIDs[(int)NamedEdge.Top], ref topPosition, Vector3.up, EditorSnapSettings.scale);
  112. if (EditorGUI.EndChangeCheck())
  113. theChangedEdge = NamedEdge.Top;
  114. EditorGUI.BeginChangeCheck();
  115. Slider1D(m_ControlIDs[(int)NamedEdge.Bottom], ref bottomPosition, Vector3.down, EditorSnapSettings.scale);
  116. if (EditorGUI.EndChangeCheck())
  117. theChangedEdge = NamedEdge.Bottom;
  118. }
  119. return theChangedEdge;
  120. }
  121. void EnsureEdgeFacesOutsideForHomothety(NamedEdge theChangedEdge, ref Vector3 leftPosition, ref Vector3 rightPosition, ref Vector3 topPosition, ref Vector3 bottomPosition)
  122. {
  123. switch (theChangedEdge)
  124. {
  125. case NamedEdge.Left:
  126. if (rightPosition.x < leftPosition.x)
  127. leftPosition.x = rightPosition.x;
  128. if (topPosition.y < bottomPosition.y)
  129. topPosition.y = bottomPosition.y = center.y;
  130. break;
  131. case NamedEdge.Right:
  132. if (rightPosition.x < leftPosition.x)
  133. rightPosition.x = leftPosition.x;
  134. if (topPosition.y < bottomPosition.y)
  135. topPosition.y = bottomPosition.y = center.y;
  136. break;
  137. case NamedEdge.Top:
  138. if (topPosition.y < bottomPosition.y)
  139. topPosition.y = bottomPosition.y;
  140. if (rightPosition.x < leftPosition.x)
  141. rightPosition.x = leftPosition.x = center.x;
  142. break;
  143. case NamedEdge.Bottom:
  144. if (topPosition.y < bottomPosition.y)
  145. bottomPosition.y = topPosition.y;
  146. if (rightPosition.x < leftPosition.x)
  147. rightPosition.x = leftPosition.x = center.x;
  148. break;
  149. }
  150. }
  151. void EnsureEdgeFacesOutsideForSymetry(NamedEdge theChangedEdge, ref Vector3 leftPosition, ref Vector3 rightPosition, ref Vector3 topPosition, ref Vector3 bottomPosition)
  152. {
  153. switch (theChangedEdge)
  154. {
  155. case NamedEdge.Left:
  156. case NamedEdge.Right:
  157. if (rightPosition.x < leftPosition.x)
  158. rightPosition.x = leftPosition.x = center.x;
  159. break;
  160. case NamedEdge.Top:
  161. case NamedEdge.Bottom:
  162. if (topPosition.y < bottomPosition.y)
  163. topPosition.y = bottomPosition.y = center.y;
  164. break;
  165. }
  166. }
  167. void EnsureEdgeFacesOutsideForOtherTransformation(ref Vector2 max, ref Vector2 min)
  168. {
  169. for (int axis = 0; axis < 2; ++axis)
  170. {
  171. if (min[axis] > max[axis])
  172. {
  173. // Control IDs in m_ControlIDs[0-1] are for positive axes
  174. if (GUIUtility.hotControl == m_ControlIDs[axis])
  175. max[axis] = min[axis];
  176. else
  177. min[axis] = max[axis];
  178. }
  179. }
  180. }
  181. /// <summary>Draw the manipulable handles</summary>
  182. public void DrawHandle()
  183. {
  184. Event evt = Event.current;
  185. bool useHomothety = evt.shift;
  186. bool useSymetry = evt.alt || evt.command;
  187. // Note: snapping is handled natively on ctrl for each Slider1D
  188. for (int i = 0, count = m_ControlIDs.Length; i < count; ++i)
  189. m_ControlIDs[i] = GUIUtility.GetControlID("DisplacableRectHandles".GetHashCode() + i, FocusType.Passive);
  190. Vector3 leftPosition = center + size.x * .5f * Vector2.left;
  191. Vector3 rightPosition = center + size.x * .5f * Vector2.right;
  192. Vector3 topPosition = center + size.y * .5f * Vector2.up;
  193. Vector3 bottomPosition = center + size.y * .5f * Vector2.down;
  194. var theChangedEdge = NamedEdge.None;
  195. EditorGUI.BeginChangeCheck();
  196. theChangedEdge = DrawSliders(ref leftPosition, ref rightPosition, ref topPosition, ref bottomPosition);
  197. if (EditorGUI.EndChangeCheck())
  198. {
  199. float delta = 0f;
  200. switch (theChangedEdge)
  201. {
  202. case NamedEdge.Left: delta = ((Vector2)leftPosition - center - size.x * .5f * Vector2.left).x; break;
  203. case NamedEdge.Right: delta = -((Vector2)rightPosition - center - size.x * .5f * Vector2.right).x; break;
  204. case NamedEdge.Top: delta = -((Vector2)topPosition - center - size.y * .5f * Vector2.up).y; break;
  205. case NamedEdge.Bottom: delta = ((Vector2)bottomPosition - center - size.y * .5f * Vector2.down).y; break;
  206. }
  207. if (useHomothety && useSymetry)
  208. {
  209. var tempSize = size - Vector2.one * delta;
  210. //ensure that the rect edges are still facing outside
  211. for (int axis = 0; axis < 3; ++axis)
  212. {
  213. if (tempSize[axis] < 0)
  214. {
  215. delta += tempSize[axis];
  216. tempSize = size - Vector2.one * delta;
  217. }
  218. }
  219. size = tempSize;
  220. }
  221. else
  222. {
  223. if (useSymetry)
  224. {
  225. switch (theChangedEdge)
  226. {
  227. case NamedEdge.Left: rightPosition.x -= delta; break;
  228. case NamedEdge.Right: leftPosition.x += delta; break;
  229. case NamedEdge.Top: bottomPosition.y += delta; break;
  230. case NamedEdge.Bottom: topPosition.y -= delta; break;
  231. }
  232. EnsureEdgeFacesOutsideForSymetry(theChangedEdge, ref leftPosition, ref rightPosition, ref topPosition, ref bottomPosition);
  233. }
  234. if (useHomothety)
  235. {
  236. float halfDelta = delta * 0.5f;
  237. switch (theChangedEdge)
  238. {
  239. case NamedEdge.Left:
  240. case NamedEdge.Right:
  241. bottomPosition.y += halfDelta;
  242. topPosition.y -= halfDelta;
  243. break;
  244. case NamedEdge.Top:
  245. case NamedEdge.Bottom:
  246. rightPosition.x -= halfDelta;
  247. leftPosition.x += halfDelta;
  248. break;
  249. }
  250. EnsureEdgeFacesOutsideForHomothety(theChangedEdge, ref leftPosition, ref rightPosition, ref topPosition, ref bottomPosition);
  251. }
  252. var max = new Vector2(rightPosition.x, topPosition.y);
  253. var min = new Vector2(leftPosition.x, bottomPosition.y);
  254. if (!useSymetry && !useHomothety)
  255. EnsureEdgeFacesOutsideForOtherTransformation(ref max, ref min);
  256. center = (max + min) * .5f;
  257. size = max - min;
  258. }
  259. }
  260. }
  261. }
  262. }