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

PivotTool.cs 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. using System;
  2. using UnityEditor.U2D.Layout;
  3. using UnityEditor.U2D.Common;
  4. using UnityEngine;
  5. using UnityEngine.UIElements;
  6. namespace UnityEditor.U2D.Animation
  7. {
  8. internal class PivotInspectorPanel : VisualElement
  9. {
  10. EnumField m_PivotAlignment;
  11. Vector2Field m_PivotPosition;
  12. public class CustomUxmlFactory : UxmlFactory<PivotInspectorPanel, UxmlTraits> { }
  13. internal static PivotInspectorPanel CreateFromUxml()
  14. {
  15. var visualTree = ResourceLoader.Load<VisualTreeAsset>("SkinningModule/PivotInspectorPanel.uxml");
  16. var ve = (PivotInspectorPanel)visualTree.CloneTree().Q("PivotInspectorPanel");
  17. ve.styleSheets.Add(ResourceLoader.Load<StyleSheet>("SkinningModule/PivotInspectorPanelStyle.uss"));
  18. if (EditorGUIUtility.isProSkin)
  19. ve.AddToClassList("Dark");
  20. ve.LocalizeTextInChildren();
  21. ve.BindElements();
  22. return ve;
  23. }
  24. private void BindElements()
  25. {
  26. m_PivotPosition = this.Q<Vector2Field>("PivotPositionField");
  27. m_PivotAlignment = this.Q<EnumField>("pivotField");
  28. m_PivotAlignment.Init(SpriteAlignment.Center);
  29. m_PivotAlignment.label = TextContent.pivot;
  30. }
  31. public EnumField pivotAlignment
  32. {
  33. get => m_PivotAlignment;
  34. set => m_PivotAlignment = value;
  35. }
  36. public Vector2Field pivotPosition
  37. {
  38. get => m_PivotPosition;
  39. set => m_PivotPosition = value;
  40. }
  41. }
  42. internal class PivotTool : SkeletonToolWrapper
  43. {
  44. static class Styles
  45. {
  46. public static GUIStyle pivotdotactive = "U2D.pivotDotActive";
  47. public static GUIStyle pivotdot = "U2D.pivotDot";
  48. }
  49. Vector2 m_Pivot = Vector2.zero;
  50. Vector2 m_CurrentMousePosition;
  51. Vector2 m_DragScreenOffset;
  52. Vector2 m_DragStartScreenPosition;
  53. SpriteCache m_LastSelectedSprite;
  54. PivotInspectorPanel m_InspectorPanel;
  55. int m_SlideHashCode = "PivotTool_Slider1D".GetHashCode();
  56. readonly Rect k_PivotNormalizedRect = Rect.MinMaxRect(0, 0, 1, 1);
  57. Rect m_PivotRect = Rect.zero;
  58. static bool CanSelectWhileInPivotTool() => false;
  59. public override void Initialize(LayoutOverlay layout)
  60. {
  61. base.Initialize(layout);
  62. m_InspectorPanel = PivotInspectorPanel.CreateFromUxml();
  63. layout.rightOverlay.Add(m_InspectorPanel);
  64. m_InspectorPanel.SetHiddenFromLayout(true);
  65. m_InspectorPanel.pivotAlignment.RegisterValueChangedCallback(PivotAlignmentValueChange);
  66. m_InspectorPanel.pivotPosition.RegisterValueChangedCallback(PivotPositionValueChange);
  67. }
  68. void PivotAlignmentValueChange(ChangeEvent<Enum> evt)
  69. {
  70. m_Pivot = GetPivotPoint((SpriteAlignment)m_InspectorPanel.pivotAlignment.value, m_Pivot);
  71. m_InspectorPanel.pivotPosition.SetValueWithoutNotify(m_Pivot);
  72. UpdateCharacterPivot();
  73. }
  74. void PivotPositionValueChange(ChangeEvent<Vector2> evt)
  75. {
  76. m_Pivot = m_InspectorPanel.pivotPosition.value;
  77. m_InspectorPanel.pivotAlignment.SetValueWithoutNotify(SpriteAlignment.Custom);
  78. UpdateCharacterPivot();
  79. }
  80. protected override void OnGUI()
  81. {
  82. base.OnGUI();
  83. var pivot = PivotSlider(m_PivotRect, m_Pivot, Styles.pivotdot, Styles.pivotdotactive);
  84. if (m_Pivot != pivot)
  85. {
  86. UpdateViewFields();
  87. m_Pivot = pivot;
  88. UpdateCharacterPivot();
  89. }
  90. }
  91. void UpdateCharacterPivot()
  92. {
  93. using (skinningCache.UndoScope(TextContent.pivotChanged))
  94. {
  95. skinningCache.character.pivot = m_Pivot;
  96. skinningCache.events.pivotChange.Invoke();
  97. }
  98. }
  99. protected override void OnActivate()
  100. {
  101. if (skinningCache.hasCharacter)
  102. {
  103. base.OnActivate();
  104. m_PivotRect = new Rect(0, 0, skinningCache.character.dimension.x, skinningCache.character.dimension.y);
  105. m_LastSelectedSprite = skinningCache.selectedSprite;
  106. m_InspectorPanel.SetHiddenFromLayout(false);
  107. m_Pivot = skinningCache.character.pivot;
  108. UpdateViewFields();
  109. skinningCache.selectionTool.CanSelect += CanSelectWhileInPivotTool;
  110. skinningCache.selectedSprite = null;
  111. }
  112. else
  113. {
  114. m_InspectorPanel.SetHiddenFromLayout(true);
  115. }
  116. }
  117. void UpdateViewFields()
  118. {
  119. SpriteAlignment alignment;
  120. TranslatePivotPoint(m_Pivot, out alignment);
  121. m_InspectorPanel.pivotAlignment.SetValueWithoutNotify(alignment);
  122. m_InspectorPanel.pivotPosition.SetValueWithoutNotify(m_Pivot);
  123. }
  124. protected override void OnDeactivate()
  125. {
  126. if (skinningCache.hasCharacter)
  127. {
  128. base.OnDeactivate();
  129. m_InspectorPanel.SetHiddenFromLayout(true);
  130. skinningCache.selectionTool.CanSelect -= CanSelectWhileInPivotTool;
  131. if (isActive)
  132. skinningCache.selectedSprite = m_LastSelectedSprite;
  133. }
  134. }
  135. void TranslatePivotPoint(Vector2 pivot, out SpriteAlignment alignment)
  136. {
  137. if (new Vector2(k_PivotNormalizedRect.xMin, k_PivotNormalizedRect.yMax) == pivot)
  138. alignment = SpriteAlignment.TopLeft;
  139. else if(new Vector2(k_PivotNormalizedRect.center.x, k_PivotNormalizedRect.yMax) == pivot)
  140. alignment = SpriteAlignment.TopCenter;
  141. else if(new Vector2(k_PivotNormalizedRect.xMax, k_PivotNormalizedRect.yMax) == pivot)
  142. alignment = SpriteAlignment.TopRight;
  143. else if(new Vector2(k_PivotNormalizedRect.xMin, k_PivotNormalizedRect.center.y) == pivot)
  144. alignment = SpriteAlignment.LeftCenter;
  145. else if(new Vector2(k_PivotNormalizedRect.center.x, k_PivotNormalizedRect.center.y) == pivot)
  146. alignment = SpriteAlignment.Center;
  147. else if(new Vector2(k_PivotNormalizedRect.xMax, k_PivotNormalizedRect.center.y) == pivot)
  148. alignment = SpriteAlignment.RightCenter;
  149. else if(new Vector2(k_PivotNormalizedRect.xMin, k_PivotNormalizedRect.yMin) == pivot)
  150. alignment = SpriteAlignment.BottomLeft;
  151. else if(new Vector2(k_PivotNormalizedRect.center.x, k_PivotNormalizedRect.yMin) == pivot)
  152. alignment = SpriteAlignment.BottomCenter;
  153. else if(new Vector2(k_PivotNormalizedRect.xMax, k_PivotNormalizedRect.yMin) == pivot)
  154. alignment = SpriteAlignment.BottomRight;
  155. else
  156. alignment = SpriteAlignment.Custom;
  157. }
  158. Vector2 GetPivotPoint(SpriteAlignment alignment, Vector2 customPivot)
  159. {
  160. switch (alignment)
  161. {
  162. case SpriteAlignment.TopLeft:
  163. return new Vector2(k_PivotNormalizedRect.xMin, k_PivotNormalizedRect.yMax);
  164. case SpriteAlignment.TopCenter:
  165. return new Vector2(k_PivotNormalizedRect.center.x, k_PivotNormalizedRect.yMax);
  166. case SpriteAlignment.TopRight:
  167. return new Vector2(k_PivotNormalizedRect.xMax, k_PivotNormalizedRect.yMax);
  168. case SpriteAlignment.LeftCenter:
  169. return new Vector2(k_PivotNormalizedRect.xMin, k_PivotNormalizedRect.center.y);
  170. case SpriteAlignment.Center:
  171. return new Vector2(k_PivotNormalizedRect.center.x, k_PivotNormalizedRect.center.y);
  172. case SpriteAlignment.RightCenter:
  173. return new Vector2(k_PivotNormalizedRect.xMax, k_PivotNormalizedRect.center.y);
  174. case SpriteAlignment.BottomLeft:
  175. return new Vector2(k_PivotNormalizedRect.xMin, k_PivotNormalizedRect.yMin);
  176. case SpriteAlignment.BottomCenter:
  177. return new Vector2(k_PivotNormalizedRect.center.x, k_PivotNormalizedRect.yMin);
  178. case SpriteAlignment.BottomRight:
  179. return new Vector2(k_PivotNormalizedRect.xMax, k_PivotNormalizedRect.yMin);
  180. case SpriteAlignment.Custom:
  181. return new Vector2(customPivot.x * k_PivotNormalizedRect.width, customPivot.y * k_PivotNormalizedRect.height);
  182. }
  183. return Vector2.zero;
  184. }
  185. Vector2 PivotSlider(Rect sprite, Vector2 pos, GUIStyle pivotDot, GUIStyle pivotDotActive)
  186. {
  187. int id = GUIUtility.GetControlID(m_SlideHashCode, FocusType.Keyboard);
  188. // Convert from normalized space to texture space
  189. pos = new Vector2(sprite.xMin + sprite.width * pos.x, sprite.yMin + sprite.height * pos.y);
  190. Vector2 screenVal = Handles.matrix.MultiplyPoint(pos);
  191. Rect handleScreenPos = new Rect(
  192. screenVal.x - pivotDot.fixedWidth * .5f,
  193. screenVal.y - pivotDot.fixedHeight * .5f,
  194. pivotDotActive.fixedWidth,
  195. pivotDotActive.fixedHeight
  196. );
  197. var evt = Event.current;
  198. switch (evt.GetTypeForControl(id))
  199. {
  200. case EventType.MouseDown:
  201. // am I closest to the thingy?
  202. if (evt.button == 0 && handleScreenPos.Contains(Event.current.mousePosition) && !evt.alt)
  203. {
  204. GUIUtility.hotControl = GUIUtility.keyboardControl = id; // Grab mouse focus
  205. m_CurrentMousePosition = evt.mousePosition;
  206. m_DragStartScreenPosition = evt.mousePosition;
  207. Vector2 rectScreenCenter = Handles.matrix.MultiplyPoint(pos);
  208. m_DragScreenOffset = m_CurrentMousePosition - rectScreenCenter;
  209. evt.Use();
  210. EditorGUIUtility.SetWantsMouseJumping(1);
  211. }
  212. break;
  213. case EventType.MouseDrag:
  214. if (GUIUtility.hotControl == id)
  215. {
  216. m_CurrentMousePosition += evt.delta;
  217. Vector2 oldPos = pos;
  218. Vector3 scrPos = Handles.inverseMatrix.MultiplyPoint(m_CurrentMousePosition - m_DragScreenOffset);
  219. pos = new Vector2(scrPos.x, scrPos.y);
  220. if (!Mathf.Approximately((oldPos - pos).magnitude, 0f))
  221. GUI.changed = true;
  222. evt.Use();
  223. }
  224. break;
  225. case EventType.MouseUp:
  226. if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))
  227. {
  228. GUIUtility.hotControl = 0;
  229. evt.Use();
  230. EditorGUIUtility.SetWantsMouseJumping(0);
  231. }
  232. break;
  233. case EventType.KeyDown:
  234. if (GUIUtility.hotControl == id)
  235. {
  236. if (evt.keyCode == KeyCode.Escape)
  237. {
  238. pos = Handles.inverseMatrix.MultiplyPoint(m_DragStartScreenPosition - m_DragScreenOffset);
  239. GUIUtility.hotControl = 0;
  240. GUI.changed = true;
  241. evt.Use();
  242. }
  243. }
  244. break;
  245. case EventType.Repaint:
  246. EditorGUIUtility.AddCursorRect(handleScreenPos, MouseCursor.Arrow, id);
  247. if (GUIUtility.hotControl == id)
  248. pivotDotActive.Draw(handleScreenPos, GUIContent.none, id);
  249. else
  250. pivotDot.Draw(handleScreenPos, GUIContent.none, id);
  251. break;
  252. }
  253. // Convert from texture space back to normalized space
  254. pos = new Vector2((pos.x - sprite.xMin) / sprite.width, (pos.y - sprite.yMin) / sprite.height);
  255. return pos;
  256. }
  257. }
  258. }