SpriteEditorHandles.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. using UnityEngine;
  2. using UnityEvent = UnityEngine.Event;
  3. namespace UnityEditor.U2D.Sprites
  4. {
  5. internal static class SpriteEditorHandles
  6. {
  7. private static Vector2 s_CurrentMousePosition;
  8. private static Vector2 s_DragStartScreenPosition;
  9. private static Vector2 s_DragScreenOffset;
  10. static internal Vector2 PointSlider(Vector2 pos, MouseCursor cursor, GUIStyle dragDot, GUIStyle dragDotActive)
  11. {
  12. int id = GUIUtility.GetControlID("Slider1D".GetHashCode(), FocusType.Keyboard);
  13. Vector2 screenVal = Handles.matrix.MultiplyPoint(pos);
  14. Rect handleScreenPos = new Rect(
  15. screenVal.x - dragDot.fixedWidth * .5f,
  16. screenVal.y - dragDot.fixedHeight * .5f,
  17. dragDot.fixedWidth,
  18. dragDot.fixedHeight
  19. );
  20. var evt = UnityEvent.current;
  21. switch (evt.GetTypeForControl(id))
  22. {
  23. case EventType.Repaint:
  24. if (GUIUtility.hotControl == id)
  25. dragDotActive.Draw(handleScreenPos, GUIContent.none, id);
  26. else
  27. dragDot.Draw(handleScreenPos, GUIContent.none, id);
  28. break;
  29. }
  30. return ScaleSlider(pos, cursor, handleScreenPos);
  31. }
  32. static internal Vector2 ScaleSlider(Vector2 pos, MouseCursor cursor, Rect cursorRect)
  33. {
  34. int id = GUIUtility.GetControlID("Slider1D".GetHashCode(), FocusType.Keyboard);
  35. return ScaleSlider(id, pos, cursor, cursorRect);
  36. }
  37. static private Vector2 ScaleSlider(int id, Vector2 pos, MouseCursor cursor, Rect cursorRect)
  38. {
  39. Vector2 screenVal = Handles.matrix.MultiplyPoint(pos);
  40. var evt = UnityEvent.current;
  41. switch (evt.GetTypeForControl(id))
  42. {
  43. case EventType.MouseDown:
  44. // am I closest to the thingy?
  45. if (evt.button == 0 &&
  46. cursorRect.Contains(UnityEvent.current.mousePosition) &&
  47. !evt.alt)
  48. {
  49. GUIUtility.hotControl = GUIUtility.keyboardControl = id; // Grab mouse focus
  50. s_CurrentMousePosition = evt.mousePosition;
  51. s_DragStartScreenPosition = evt.mousePosition;
  52. s_DragScreenOffset = s_CurrentMousePosition - screenVal;
  53. evt.Use();
  54. EditorGUIUtility.SetWantsMouseJumping(1);
  55. }
  56. break;
  57. case EventType.MouseDrag:
  58. if (GUIUtility.hotControl == id)
  59. {
  60. s_CurrentMousePosition += evt.delta;
  61. Vector2 oldPos = pos;
  62. pos = Handles.inverseMatrix.MultiplyPoint(s_CurrentMousePosition);
  63. if (!Mathf.Approximately((oldPos - pos).magnitude, 0f))
  64. GUI.changed = true;
  65. evt.Use();
  66. }
  67. break;
  68. case EventType.MouseUp:
  69. if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))
  70. {
  71. GUIUtility.hotControl = 0;
  72. evt.Use();
  73. EditorGUIUtility.SetWantsMouseJumping(0);
  74. }
  75. break;
  76. case EventType.KeyDown:
  77. if (GUIUtility.hotControl == id)
  78. {
  79. if (evt.keyCode == KeyCode.Escape)
  80. {
  81. pos = Handles.inverseMatrix.MultiplyPoint(s_DragStartScreenPosition - s_DragScreenOffset);
  82. GUIUtility.hotControl = 0;
  83. GUI.changed = true;
  84. evt.Use();
  85. }
  86. }
  87. break;
  88. case EventType.Repaint:
  89. if (GUIUtility.hotControl == 0 || GUIUtility.hotControl == id)
  90. EditorGUIUtility.AddCursorRect(cursorRect, cursor, id);
  91. break;
  92. }
  93. return pos;
  94. }
  95. static internal Vector2 PivotSlider(Rect sprite, Vector2 pos, GUIStyle pivotDot, GUIStyle pivotDotActive)
  96. {
  97. int id = GUIUtility.GetControlID("Slider1D".GetHashCode(), FocusType.Keyboard);
  98. // Convert from normalized space to texture space
  99. pos = new Vector2(sprite.xMin + sprite.width * pos.x, sprite.yMin + sprite.height * pos.y);
  100. Vector2 screenVal = Handles.matrix.MultiplyPoint(pos);
  101. Rect handleScreenPos = new Rect(
  102. screenVal.x - pivotDot.fixedWidth * .5f,
  103. screenVal.y - pivotDot.fixedHeight * .5f,
  104. pivotDotActive.fixedWidth,
  105. pivotDotActive.fixedHeight
  106. );
  107. var evt = UnityEvent.current;
  108. switch (evt.GetTypeForControl(id))
  109. {
  110. case EventType.MouseDown:
  111. // am I closest to the thingy?
  112. if (evt.button == 0 && handleScreenPos.Contains(UnityEvent.current.mousePosition) && !evt.alt)
  113. {
  114. GUIUtility.hotControl = GUIUtility.keyboardControl = id; // Grab mouse focus
  115. s_CurrentMousePosition = evt.mousePosition;
  116. s_DragStartScreenPosition = evt.mousePosition;
  117. Vector2 rectScreenCenter = Handles.matrix.MultiplyPoint(pos);
  118. s_DragScreenOffset = s_CurrentMousePosition - rectScreenCenter;
  119. evt.Use();
  120. EditorGUIUtility.SetWantsMouseJumping(1);
  121. }
  122. break;
  123. case EventType.MouseDrag:
  124. if (GUIUtility.hotControl == id)
  125. {
  126. s_CurrentMousePosition += evt.delta;
  127. Vector2 oldPos = pos;
  128. Vector3 scrPos = Handles.inverseMatrix.MultiplyPoint(s_CurrentMousePosition - s_DragScreenOffset);
  129. pos = new Vector2(scrPos.x, scrPos.y);
  130. if (!Mathf.Approximately((oldPos - pos).magnitude, 0f))
  131. GUI.changed = true;
  132. evt.Use();
  133. }
  134. break;
  135. case EventType.MouseUp:
  136. if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))
  137. {
  138. GUIUtility.hotControl = 0;
  139. evt.Use();
  140. EditorGUIUtility.SetWantsMouseJumping(0);
  141. }
  142. break;
  143. case EventType.KeyDown:
  144. if (GUIUtility.hotControl == id)
  145. {
  146. if (evt.keyCode == KeyCode.Escape)
  147. {
  148. pos = Handles.inverseMatrix.MultiplyPoint(s_DragStartScreenPosition - s_DragScreenOffset);
  149. GUIUtility.hotControl = 0;
  150. GUI.changed = true;
  151. evt.Use();
  152. }
  153. }
  154. break;
  155. case EventType.Repaint:
  156. EditorGUIUtility.AddCursorRect(handleScreenPos, MouseCursor.Arrow, id);
  157. if (GUIUtility.hotControl == id)
  158. pivotDotActive.Draw(handleScreenPos, GUIContent.none, id);
  159. else
  160. pivotDot.Draw(handleScreenPos, GUIContent.none, id);
  161. break;
  162. }
  163. // Convert from texture space back to normalized space
  164. pos = new Vector2((pos.x - sprite.xMin) / sprite.width, (pos.y - sprite.yMin) / sprite.height);
  165. return pos;
  166. }
  167. static internal Rect SliderRect(Rect pos)
  168. {
  169. int id = GUIUtility.GetControlID("SliderRect".GetHashCode(), FocusType.Keyboard);
  170. var evt = UnityEvent.current;
  171. // SpriteEditorWindow is telling us we got selected and so we fake a mousedown on our Repaint event to get "one-click dragging" going on
  172. if (SpriteEditorWindow.s_OneClickDragStarted && evt.type == EventType.Repaint)
  173. {
  174. HandleSliderRectMouseDown(id, evt, pos);
  175. SpriteEditorWindow.s_OneClickDragStarted = false;
  176. }
  177. switch (evt.GetTypeForControl(id))
  178. {
  179. case EventType.MouseDown:
  180. // am I closest to the thingy?
  181. if (evt.button == 0 && pos.Contains(Handles.inverseMatrix.MultiplyPoint(UnityEvent.current.mousePosition)) && !evt.alt)
  182. {
  183. HandleSliderRectMouseDown(id, evt, pos);
  184. evt.Use();
  185. }
  186. break;
  187. case EventType.MouseDrag:
  188. if (GUIUtility.hotControl == id)
  189. {
  190. s_CurrentMousePosition += evt.delta;
  191. Vector2 oldCenter = pos.center;
  192. pos.center = Handles.inverseMatrix.MultiplyPoint(s_CurrentMousePosition - s_DragScreenOffset);
  193. if (!Mathf.Approximately((oldCenter - pos.center).magnitude, 0f))
  194. GUI.changed = true;
  195. evt.Use();
  196. }
  197. break;
  198. case EventType.MouseUp:
  199. if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))
  200. {
  201. GUIUtility.hotControl = 0;
  202. evt.Use();
  203. EditorGUIUtility.SetWantsMouseJumping(0);
  204. }
  205. break;
  206. case EventType.KeyDown:
  207. if (GUIUtility.hotControl == id)
  208. {
  209. if (evt.keyCode == KeyCode.Escape)
  210. {
  211. pos.center = Handles.inverseMatrix.MultiplyPoint(s_DragStartScreenPosition - s_DragScreenOffset);
  212. GUIUtility.hotControl = 0;
  213. GUI.changed = true;
  214. evt.Use();
  215. }
  216. }
  217. break;
  218. case EventType.Repaint:
  219. Vector2 topleft = Handles.inverseMatrix.MultiplyPoint(new Vector2(pos.xMin, pos.yMin));
  220. Vector2 bottomright = Handles.inverseMatrix.MultiplyPoint(new Vector2(pos.xMax, pos.yMax));
  221. EditorGUIUtility.AddCursorRect(new Rect(topleft.x, topleft.y, bottomright.x - topleft.x, bottomright.y - topleft.y), MouseCursor.Arrow, id);
  222. break;
  223. }
  224. return pos;
  225. }
  226. static internal void HandleSliderRectMouseDown(int id, UnityEvent evt, Rect pos)
  227. {
  228. GUIUtility.hotControl = GUIUtility.keyboardControl = id; // Grab mouse focus
  229. s_CurrentMousePosition = evt.mousePosition;
  230. s_DragStartScreenPosition = evt.mousePosition;
  231. Vector2 rectScreenCenter = Handles.matrix.MultiplyPoint(pos.center);
  232. s_DragScreenOffset = s_CurrentMousePosition - rectScreenCenter;
  233. EditorGUIUtility.SetWantsMouseJumping(1);
  234. }
  235. static int s_RectSelectionID = GUIUtility.GetPermanentControlID();
  236. static internal Rect RectCreator(Rect textureArea, GUIStyle rectStyle)
  237. {
  238. var evt = UnityEvent.current;
  239. Vector2 mousePos = evt.mousePosition;
  240. int id = s_RectSelectionID;
  241. Rect result = new Rect();
  242. switch (evt.GetTypeForControl(id))
  243. {
  244. case EventType.MouseDown:
  245. if (evt.button == 0)
  246. {
  247. GUIUtility.hotControl = id;
  248. // Make sure that the starting position is clamped to inside texture area
  249. s_DragStartScreenPosition = Handles.inverseMatrix.MultiplyPoint(mousePos);
  250. s_DragStartScreenPosition.x = Mathf.Min(Mathf.Max(s_DragStartScreenPosition.x, textureArea.xMin), textureArea.xMax);
  251. s_DragStartScreenPosition.y = Mathf.Min(Mathf.Max(s_DragStartScreenPosition.y, textureArea.yMin), textureArea.yMax);
  252. evt.Use();
  253. }
  254. break;
  255. case EventType.MouseDrag:
  256. if (GUIUtility.hotControl == id)
  257. {
  258. evt.Use();
  259. }
  260. break;
  261. case EventType.Repaint:
  262. {
  263. var startDragPoint = Handles.matrix.MultiplyPoint(s_DragStartScreenPosition);
  264. if (GUIUtility.hotControl == id && ValidRect(startDragPoint, mousePos))
  265. {
  266. // TODO: use rectstyle
  267. //rectStyle.Draw (GetCurrentRect (true, textureWidth, textureHeight, s_DragStartScreenPosition, s_CurrentMousePosition), GUIContent.none, false, false, false, false);
  268. SpriteEditorUtility.BeginLines(Color.green * 1.5f);
  269. SpriteEditorUtility.DrawBox(GetCurrentRect(false, textureArea, startDragPoint, mousePos));
  270. SpriteEditorUtility.EndLines();
  271. }
  272. }
  273. break;
  274. case EventType.MouseUp:
  275. if (GUIUtility.hotControl == id && evt.button == 0)
  276. {
  277. var startDragPoint = Handles.matrix.MultiplyPoint(s_DragStartScreenPosition);
  278. if (ValidRect(startDragPoint, mousePos))
  279. {
  280. result = GetCurrentRect(false, textureArea, startDragPoint, mousePos);
  281. GUI.changed = true;
  282. evt.Use();
  283. }
  284. GUIUtility.hotControl = 0;
  285. }
  286. break;
  287. case EventType.KeyDown:
  288. if (GUIUtility.hotControl == id)
  289. {
  290. if (evt.keyCode == KeyCode.Escape)
  291. {
  292. GUIUtility.hotControl = 0;
  293. GUI.changed = true;
  294. evt.Use();
  295. }
  296. }
  297. break;
  298. }
  299. return result;
  300. }
  301. static internal Rect RectCreator(float textureWidth, float textureHeight, GUIStyle rectStyle)
  302. {
  303. return RectCreator(new Rect(0, 0, textureWidth, textureHeight), rectStyle);
  304. }
  305. static private bool ValidRect(Vector2 startPoint, Vector2 endPoint)
  306. {
  307. return Mathf.Abs((endPoint - startPoint).x) > 5f && Mathf.Abs((endPoint - startPoint).y) > 5f;
  308. }
  309. static private Rect GetCurrentRect(bool screenSpace, Rect clampArea, Vector2 startPoint, Vector2 endPoint)
  310. {
  311. Rect r = EditorGUIExt.FromToRect(Handles.inverseMatrix.MultiplyPoint(startPoint), Handles.inverseMatrix.MultiplyPoint(endPoint));
  312. r = SpriteEditorUtility.ClampedRect(SpriteEditorUtility.RoundToInt(r), clampArea, false);
  313. if (screenSpace)
  314. {
  315. Vector2 topleft = Handles.matrix.MultiplyPoint(new Vector2(r.xMin, r.yMin));
  316. Vector2 bottomright = Handles.matrix.MultiplyPoint(new Vector2(r.xMax, r.yMax));
  317. r = new Rect(topleft.x, topleft.y, bottomright.x - topleft.x, bottomright.y - topleft.y);
  318. }
  319. return r;
  320. }
  321. }
  322. }