Нет описания
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

WeightPainterPanel.cs 10.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEditor.U2D.Common;
  4. using UnityEngine;
  5. using UnityEngine.UIElements;
  6. namespace UnityEditor.U2D.Animation
  7. {
  8. #if ENABLE_UXML_SERIALIZED_DATA
  9. [UxmlElement]
  10. #endif
  11. internal partial class WeightPainterPanel : VisualElement
  12. {
  13. #if ENABLE_UXML_TRAITS
  14. public class WeightPainterPanelFactory : UxmlFactory<WeightPainterPanel, WeightPainterPanelUxmlTraits> {}
  15. public class WeightPainterPanelUxmlTraits : UxmlTraits {}
  16. #endif
  17. public static readonly string kNone = "None";
  18. private WeightPainterMode m_PaintMode;
  19. private EnumField m_ModeField;
  20. private Toggle m_NormalizeToggle;
  21. private IntegerField m_HardnessField;
  22. private IntegerField m_StepField;
  23. private IntegerField m_SizeField;
  24. private FloatField m_AmountField;
  25. private Slider m_AmountSlider;
  26. private VisualElement m_BonePopupContainer;
  27. private PopupField<string> m_BonePopup;
  28. private bool m_SliderActive = false;
  29. private WeightInspectorIMGUIPanel m_WeightInspectorPanel;
  30. private UnityEngine.UIElements.PopupWindow m_PopupWindow;
  31. public event Action<int> bonePopupChanged = (s) => {};
  32. public event Action sliderStarted = () => {};
  33. public event Action<float> sliderChanged = (s) => {};
  34. public event Action sliderEnded = () => {};
  35. public event Action weightsChanged = () => {};
  36. public WeightPainterMode paintMode
  37. {
  38. get { return m_PaintMode; }
  39. set
  40. {
  41. if (value == m_PaintMode)
  42. return;
  43. m_PaintMode = value;
  44. if (m_PaintMode == WeightPainterMode.Brush)
  45. {
  46. RemoveFromClassList("SliderMode");
  47. AddToClassList("BrushMode");
  48. }
  49. else
  50. {
  51. RemoveFromClassList("BrushMode");
  52. AddToClassList("SliderMode");
  53. }
  54. }
  55. }
  56. public string title
  57. {
  58. set { m_PopupWindow.text = value; }
  59. }
  60. public WeightEditorMode mode
  61. {
  62. get { return (WeightEditorMode)m_ModeField.value; }
  63. set { m_ModeField.value = value; }
  64. }
  65. public int boneIndex
  66. {
  67. get { return m_BonePopup.index - 1; }
  68. }
  69. public int size
  70. {
  71. get { return m_SizeField.value; }
  72. set { m_SizeField.value = value; }
  73. }
  74. public int hardness
  75. {
  76. get { return m_HardnessField.value; }
  77. set { m_HardnessField.value = value; }
  78. }
  79. public int step
  80. {
  81. get { return m_StepField.value; }
  82. set { m_StepField.value = value; }
  83. }
  84. public bool normalize
  85. {
  86. get { return m_NormalizeToggle.value; }
  87. set { m_NormalizeToggle.value = value; }
  88. }
  89. public float amount
  90. {
  91. get { return m_AmountField.value; }
  92. set { m_AmountField.value = value; }
  93. }
  94. public WeightPainterPanel()
  95. {
  96. styleSheets.Add(ResourceLoader.Load<StyleSheet>("SkinningModule/WeightPainterPanelStyle.uss"));
  97. if (EditorGUIUtility.isProSkin)
  98. AddToClassList("Dark");
  99. paintMode = WeightPainterMode.Brush;
  100. AddToClassList("BrushMode");
  101. RegisterCallback<MouseDownEvent>((e) => { e.StopPropagation(); });
  102. RegisterCallback<MouseUpEvent>((e) => { e.StopPropagation(); });
  103. }
  104. public void BindElements()
  105. {
  106. m_ModeField = this.Q<EnumField>("ModeField");
  107. m_BonePopupContainer = this.Q<VisualElement>("BoneEnumPopup");
  108. m_NormalizeToggle = this.Q<Toggle>("NormalizeToggle");
  109. m_SizeField = this.Q<IntegerField>("SizeField");
  110. m_HardnessField = this.Q<IntegerField>("HardnessField");
  111. m_StepField = this.Q<IntegerField>("StepField");
  112. m_AmountSlider = this.Q<Slider>("AmountSlider");
  113. m_AmountField = this.Q<FloatField>("AmountField");
  114. m_AmountField.isDelayed = true;
  115. m_WeightInspectorPanel = this.Q<WeightInspectorIMGUIPanel>("WeightsInspector");
  116. m_PopupWindow = this.Q<UnityEngine.UIElements.PopupWindow>();
  117. LinkSliderToIntegerField(this.Q<Slider>("HardnessSlider"), m_HardnessField);
  118. LinkSliderToIntegerField(this.Q<Slider>("StepSlider"), m_StepField);
  119. m_ModeField.RegisterValueChangedCallback((evt) =>
  120. {
  121. SetupMode();
  122. });
  123. m_AmountSlider.RegisterValueChangedCallback((evt) =>
  124. {
  125. if (!evt.Equals(m_AmountField.value))
  126. m_AmountField.value = (float)Math.Round((double)evt.newValue, 2);
  127. if (m_SliderActive)
  128. sliderChanged?.Invoke(m_AmountField.value);
  129. });
  130. m_AmountSlider.RegisterCallback<MouseCaptureEvent>(evt =>
  131. {
  132. m_SliderActive = true;
  133. sliderStarted?.Invoke();
  134. }, TrickleDown.TrickleDown);
  135. m_AmountSlider.RegisterCallback<MouseCaptureOutEvent>(evt =>
  136. {
  137. m_SliderActive = false;
  138. sliderEnded?.Invoke();
  139. m_AmountSlider.value = 0;
  140. }, TrickleDown.TrickleDown);
  141. m_AmountField.RegisterValueChangedCallback((evt) =>
  142. {
  143. var newValue = Mathf.Clamp(evt.newValue, m_AmountSlider.lowValue, m_AmountSlider.highValue);
  144. if (focusController.focusedElement == m_AmountField && !newValue.Equals(m_AmountSlider.value))
  145. {
  146. sliderStarted();
  147. sliderChanged(newValue);
  148. sliderEnded();
  149. Focus();
  150. m_AmountField.value = 0f;
  151. m_AmountSlider.value = 0f;
  152. }
  153. });
  154. m_WeightInspectorPanel.weightsChanged += () => weightsChanged();
  155. }
  156. public void SetActive(bool active)
  157. {
  158. this.Q("Amount").SetEnabled(active);
  159. }
  160. private void SetupMode()
  161. {
  162. var boneElement = this.Q<VisualElement>("Bone");
  163. boneElement.SetHiddenFromLayout(mode == WeightEditorMode.Smooth);
  164. SetupAmountSlider();
  165. }
  166. private void SetupAmountSlider()
  167. {
  168. if (paintMode == WeightPainterMode.Slider)
  169. {
  170. if (mode == WeightEditorMode.Smooth)
  171. {
  172. m_AmountSlider.lowValue = 0.0f;
  173. m_AmountSlider.highValue = 8.0f;
  174. }
  175. else
  176. {
  177. m_AmountSlider.lowValue = -1.0f;
  178. m_AmountSlider.highValue = 1.0f;
  179. }
  180. }
  181. }
  182. private void LinkSliderToIntegerField(Slider slider, IntegerField field)
  183. {
  184. slider.RegisterValueChangedCallback((evt) =>
  185. {
  186. if (!evt.newValue.Equals(field.value))
  187. field.value = Mathf.RoundToInt(evt.newValue);
  188. });
  189. field.RegisterValueChangedCallback((evt) =>
  190. {
  191. if (!evt.newValue.Equals((int)slider.value))
  192. slider.value = evt.newValue;
  193. });
  194. }
  195. public void UpdateWeightInspector(BaseSpriteMeshData spriteMeshData, string[] boneNames, ISelection<int> selection, ICacheUndo cacheUndo)
  196. {
  197. m_WeightInspectorPanel.weightInspector.spriteMeshData = spriteMeshData;
  198. m_WeightInspectorPanel.weightInspector.boneNames = ModuleUtility.ToGUIContentArray(boneNames);
  199. m_WeightInspectorPanel.weightInspector.selection = selection;
  200. m_WeightInspectorPanel.weightInspector.cacheUndo = cacheUndo;
  201. }
  202. public void UpdatePanel(string[] boneNames)
  203. {
  204. SetupMode();
  205. UpdateBonePopup(boneNames);
  206. }
  207. private void UpdateBonePopup(string[] names)
  208. {
  209. VisualElement boneElement = null;
  210. if (m_ModeField != null && mode == WeightEditorMode.Smooth)
  211. {
  212. boneElement = this.Q<VisualElement>("Bone");
  213. boneElement.SetHiddenFromLayout(false);
  214. }
  215. if (m_BonePopup != null)
  216. {
  217. m_BonePopupContainer.Remove(m_BonePopup);
  218. }
  219. m_BonePopup = new PopupField<string>(new List<string>(names), 0);
  220. m_BonePopup.name = "BonePopupField";
  221. m_BonePopup.label = TextContent.bone;
  222. m_BonePopup.tooltip = TextContent.boneToolTip;
  223. m_BonePopup.RegisterValueChangedCallback((evt) =>
  224. {
  225. bonePopupChanged(boneIndex);
  226. });
  227. m_BonePopupContainer.Add(m_BonePopup);
  228. if (boneElement != null)
  229. {
  230. boneElement.SetHiddenFromLayout(true);
  231. }
  232. }
  233. internal void SetBoneSelectionByName(string boneName)
  234. {
  235. if (m_BonePopup != null)
  236. m_BonePopup.value = boneName;
  237. }
  238. public static WeightPainterPanel GenerateFromUXML()
  239. {
  240. var visualTree = ResourceLoader.Load<VisualTreeAsset>("SkinningModule/WeightPainterPanel.uxml");
  241. var clone = visualTree.CloneTree().Q<WeightPainterPanel>("WeightPainterPanel");
  242. clone.LocalizeTextInChildren();
  243. // EnumField can only get type of Enum from the current running assembly when defined through UXML
  244. // Manually create the EnumField here
  245. var mode = clone.Q<VisualElement>("Mode");
  246. var modeField = new EnumField(WeightEditorMode.AddAndSubtract);
  247. modeField.name = "ModeField";
  248. modeField.label = TextContent.mode;
  249. modeField.tooltip = TextContent.modeTooltip;
  250. mode.Add(modeField);
  251. clone.BindElements();
  252. return clone;
  253. }
  254. }
  255. }