Inspector.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.Collections;
  4. namespace RootMotion {
  5. /*
  6. * Inspector contains helper methods for creating undoable custom inspectors with enforced layout, tooltips and styling
  7. * */
  8. public class Inspector {
  9. #region InspectorGUI tools
  10. public const int indent = 16;
  11. public delegate void DrawArrayElement(SerializedProperty prop, bool editHierarchy);
  12. public delegate void DrawArrayElementLabel(SerializedProperty prop, bool editHierarchy);
  13. public delegate void OnAddToArray(SerializedProperty prop);
  14. private static string arrayName;
  15. private static SerializedProperty property;
  16. private static SerializedProperty element;
  17. public static string GetArrayName(SerializedProperty array, string emptyName, string propertyName = "") {
  18. if (array.arraySize < 1) return emptyName;
  19. property = propertyName == ""? array.GetArrayElementAtIndex(0): array.GetArrayElementAtIndex(0).FindPropertyRelative(propertyName);
  20. return GetObjectReferenceName(property, emptyName);
  21. }
  22. public static string GetObjectReferenceName(SerializedProperty prop, string emptyName) {
  23. if (prop.objectReferenceValue == null) return emptyName;
  24. return prop.objectReferenceValue.name;
  25. }
  26. public static void AddArray(SerializedProperty prop, GUIContent guiContent, bool editHierarchy, bool changeOrder, DrawArrayElement drawArrayElement = null, OnAddToArray onAddToArray = null, DrawArrayElementLabel drawArrayElementLabel = null, bool showHeading = true) {
  27. int resetIndent = EditorGUI.indentLevel;
  28. // Array heading
  29. if (showHeading) {
  30. GUILayout.BeginHorizontal();
  31. GUILayout.Space(EditorGUI.indentLevel * indent);
  32. if (drawArrayElement == null) {
  33. GUILayout.Label(guiContent.text + " (" + prop.arraySize.ToString() + ")", GUILayout.Width(150));
  34. } else {
  35. EditorGUILayout.PropertyField(prop, new GUIContent(guiContent.text + " (" + prop.arraySize.ToString() + ")", string.Empty), false, GUILayout.Width(150));
  36. }
  37. GUILayout.EndHorizontal();
  38. }
  39. int deleteIndex = -1;
  40. if (drawArrayElement == null || !showHeading) prop.isExpanded = true;
  41. // Draw Array elements
  42. if (prop.isExpanded) {
  43. for(int i = 0; i < prop.arraySize; i++) {
  44. GUILayout.BeginHorizontal(); // Main
  45. GUILayout.Space(((EditorGUI.indentLevel + 1) * indent));
  46. GUILayout.BeginVertical();
  47. element = prop.GetArrayElementAtIndex(i);
  48. // Label
  49. GUILayout.BeginHorizontal();
  50. if (editHierarchy && GUILayout.Button(new GUIContent("-", "Remove"), changeOrder? EditorStyles.miniButtonLeft: EditorStyles.miniButton, GUILayout.Width(20))){
  51. deleteIndex = i;
  52. }
  53. if (changeOrder) {
  54. if (GUILayout.Button(new GUIContent("<", "Move up"), editHierarchy? EditorStyles.miniButtonMid: EditorStyles.miniButtonLeft, GUILayout.Width(20))) {
  55. int moveTo = i == 0? prop.arraySize - 1: i - 1;
  56. prop.MoveArrayElement(i, moveTo);
  57. prop.isExpanded = true;
  58. }
  59. if (GUILayout.Button(new GUIContent(">", "Move down"), EditorStyles.miniButtonRight, GUILayout.Width(20))) {
  60. int moveTo = i == prop.arraySize - 1? 0: i + 1;
  61. prop.MoveArrayElement(i, moveTo);
  62. prop.isExpanded = true;
  63. }
  64. }
  65. // Calling the DrawArrayElementLabel delegate
  66. if (drawArrayElementLabel != null) {
  67. drawArrayElementLabel(element, editHierarchy);
  68. }
  69. GUILayout.EndHorizontal(); // End Label
  70. // Array Element
  71. GUILayout.BeginVertical();
  72. if (element.isExpanded && drawArrayElement != null) {
  73. drawArrayElement(element, editHierarchy);
  74. }
  75. GUILayout.EndVertical();
  76. GUILayout.Space(5);
  77. GUILayout.EndVertical(); // End Style
  78. GUILayout.EndHorizontal(); // End Main
  79. }
  80. // Deleting array elements
  81. if (deleteIndex != -1) prop.DeleteArrayElementAtIndex(deleteIndex);
  82. // Adding array elements
  83. GUILayout.BeginHorizontal();
  84. GUILayout.Space(((EditorGUI.indentLevel + 1) * indent) + 4);
  85. GUILayout.BeginVertical();
  86. if (editHierarchy && GUILayout.Button(new GUIContent("+", "Add"), EditorStyles.miniButton, GUILayout.Width(20))) {
  87. prop.arraySize ++;
  88. if (onAddToArray != null) onAddToArray(prop.GetArrayElementAtIndex(prop.arraySize - 1));
  89. }
  90. GUILayout.EndVertical();
  91. GUILayout.EndHorizontal();
  92. }
  93. EditorGUI.indentLevel = resetIndent;
  94. }
  95. public static void AddContent(SerializedContent content, bool addChildren = false, params GUILayoutOption[] options) {
  96. EditorGUILayout.PropertyField(content.prop, content.guiContent, addChildren, options);
  97. }
  98. public static void AddClampedFloat(SerializedContent content, float min = 0f, float max = 1f, params GUILayoutOption[] options) {
  99. AddClampedFloat(content.prop, content.guiContent, min, max, options);
  100. }
  101. public static void AddClampedInt(SerializedContent content, int min = int.MinValue, int max = int.MaxValue, params GUILayoutOption[] options) {
  102. AddClampedInt(content.prop, content.guiContent, min, max, options);
  103. }
  104. public static void AddClampedFloat(SerializedProperty prop, GUIContent guiContent, float min = 0f, float max = 1f, params GUILayoutOption[] options) {
  105. EditorGUILayout.PropertyField(prop, guiContent, options);
  106. prop.floatValue = Mathf.Clamp(prop.floatValue, min, max);
  107. }
  108. public static void AddClampedInt(SerializedProperty prop, GUIContent guiContent, int min = int.MinValue, int max = int.MaxValue, params GUILayoutOption[] options) {
  109. EditorGUILayout.PropertyField(prop, guiContent, options);
  110. prop.intValue = Mathf.Clamp(prop.intValue, min, max);
  111. }
  112. public static void AddObjectReference(SerializedProperty prop, GUIContent guiContent, bool editHierarchy, int labelWidth, bool alignToEdge = true) {
  113. if (alignToEdge) GUILayout.BeginHorizontal();
  114. EditorGUILayout.LabelField(guiContent, GUILayout.MinWidth(labelWidth));
  115. if (editHierarchy) {
  116. EditorGUILayout.PropertyField(prop, GUIContent.none);
  117. } else {
  118. UnityEngine.Object obj = prop.objectReferenceValue;
  119. EditorGUILayout.LabelField(new GUIContent(obj != null? obj.name: "None"));
  120. }
  121. if (alignToEdge) GUILayout.EndHorizontal();
  122. }
  123. public static void AddObjectReference(SerializedProperty prop, GUIContent guiContent, bool editHierarchy, int labelWidth, int propWidth, bool alignToEdge = true) {
  124. //if (alignToEdge) GUILayout.BeginHorizontal();
  125. EditorGUILayout.LabelField(guiContent, GUILayout.Width(labelWidth));
  126. if (editHierarchy) {
  127. EditorGUILayout.PropertyField(prop, GUIContent.none, GUILayout.Width(propWidth));
  128. } else {
  129. UnityEngine.Object obj = prop.objectReferenceValue;
  130. EditorGUILayout.LabelField(new GUIContent(obj != null? obj.name: "None"), GUILayout.Width(propWidth));
  131. }
  132. //if (alignToEdge) GUILayout.EndHorizontal();
  133. }
  134. #endregion InspectorGUI tools
  135. #region SceneGUI tools
  136. public static bool Button(string name, string toolTip, Object undoObject, params GUILayoutOption[] options) {
  137. bool button = GUILayout.Button(new GUIContent(name, toolTip), options);
  138. if (button && !Application.isPlaying) Undo.RecordObject(undoObject, name);
  139. return button;
  140. }
  141. public static Object AddObject(Object input, string name, string toolTip, System.Type type, bool allowSceneObjects, Object undoObject, params GUILayoutOption[] options) {
  142. Object newValue = EditorGUILayout.ObjectField(new GUIContent(name, toolTip), input, type, allowSceneObjects, options);
  143. return RecordObject(input, newValue, name, undoObject);
  144. }
  145. public static System.Enum AddEnum(System.Enum input, string name, string toolTip, Object undoObject, params GUILayoutOption[] options) {
  146. System.Enum newValue = EditorGUILayout.EnumPopup(new GUIContent(name, toolTip), input, options);
  147. if (newValue.ToString() != input.ToString() && !Application.isPlaying) Undo.RecordObject(undoObject, name);
  148. return newValue;
  149. }
  150. public static void AddHorizontalSlider(ref float input, float leftValue, float rightValue, string name, string toolTip, Object undoObject, int labelWidth, int minWidth) {
  151. EditorGUILayout.BeginHorizontal();
  152. GUILayout.Label(new GUIContent(name, toolTip), GUILayout.Width(labelWidth));
  153. input = RecordObjectFloat(input, GUILayout.HorizontalSlider(input, leftValue, rightValue, GUILayout.MinWidth(minWidth)), name, undoObject);
  154. input = Mathf.Clamp(RecordObjectFloat(input, EditorGUILayout.FloatField(string.Empty, input, GUILayout.Width(75)), name, undoObject), leftValue, rightValue);
  155. EditorGUILayout.EndHorizontal();
  156. }
  157. public static void AddFloat(ref float input, string name, string toolTip, Object undoObject, float min = -Mathf.Infinity, float max = Mathf.Infinity, params GUILayoutOption[] options) {
  158. input = Mathf.Clamp(RecordObjectFloat(input, EditorGUILayout.FloatField(new GUIContent(name, toolTip), input, options), name, undoObject), min, max);
  159. }
  160. public static void AddInt(ref int input, string name, string toolTip, Object undoObject, int min = -int.MaxValue, int max = int.MaxValue, params GUILayoutOption[] options) {
  161. input = Mathf.Clamp((int)RecordObjectFloat((float)input, (float)EditorGUILayout.IntField(new GUIContent(name, toolTip), input, options), name, undoObject), min, max);
  162. }
  163. public static void AddBool(ref bool input, string name, string toolTip, Object undoObject) {
  164. bool newValue = EditorGUILayout.Toggle(new GUIContent(name, toolTip), input);
  165. if (newValue != input && !Application.isPlaying) {
  166. Undo.RecordObject(undoObject, name);
  167. }
  168. input = newValue;
  169. }
  170. public static void AddVector3(ref Vector3 input, string name, Object undoObject, params GUILayoutOption[] options) {
  171. Vector3 newValue = EditorGUILayout.Vector3Field(name, input, options);
  172. if (newValue != input && !Application.isPlaying) {
  173. Undo.RecordObject(undoObject, name);
  174. }
  175. input = newValue;
  176. }
  177. private static float RecordObjectFloat(float input, float newValue, string name, Object undoObject) {
  178. if (newValue != input && !Application.isPlaying) Undo.RecordObject(undoObject, name);
  179. return newValue;
  180. }
  181. private static Object RecordObject(Object input, Object newValue, string name, Object undoObject) {
  182. if (newValue != input && !Application.isPlaying) Undo.RecordObject(undoObject, name);
  183. return newValue;
  184. }
  185. #endregion SceneGUI tools
  186. #region Platform dependent
  187. public static void SphereCap(int controlID, Vector3 position, Quaternion rotation, float size) {
  188. #if UNITY_5_6_OR_NEWER
  189. Handles.SphereHandleCap(controlID, position, rotation, size, EventType.Repaint);
  190. #else
  191. Handles.SphereCap(controlID, position, rotation, size);
  192. #endif
  193. }
  194. public static void CubeCap(int controlID, Vector3 position, Quaternion rotation, float size) {
  195. #if UNITY_5_6_OR_NEWER
  196. Handles.CubeHandleCap(controlID, position, rotation, size, EventType.Repaint);
  197. #else
  198. Handles.CubeCap(controlID, position, rotation, size);
  199. #endif
  200. }
  201. public static void ConeCap(int controlID, Vector3 position, Quaternion rotation, float size) {
  202. #if UNITY_5_6_OR_NEWER
  203. Handles.ConeHandleCap(controlID, position, rotation, size, EventType.Repaint);
  204. #else
  205. Handles.ConeCap(controlID, position, rotation, size);
  206. #endif
  207. }
  208. public static void ArrowCap(int controlID, Vector3 position, Quaternion rotation, float size) {
  209. #if UNITY_5_6_OR_NEWER
  210. Handles.ArrowHandleCap(controlID, position, rotation, size, EventType.Repaint);
  211. #else
  212. Handles.ArrowCap(controlID, position, rotation, size);
  213. #endif
  214. }
  215. public static void CircleCap(int controlID, Vector3 position, Quaternion rotation, float size) {
  216. #if UNITY_5_6_OR_NEWER
  217. Handles.CircleHandleCap(controlID, position, rotation, size, EventType.Repaint);
  218. #else
  219. Handles.CircleCap(controlID, position, rotation, size);
  220. #endif
  221. }
  222. public static void DotCap(int controlID, Vector3 position, Quaternion rotation, float size) {
  223. #if UNITY_5_6_OR_NEWER
  224. Handles.DotHandleCap(controlID, position, rotation, size, EventType.Repaint);
  225. #else
  226. Handles.DotCap(controlID, position, rotation, size);
  227. #endif
  228. }
  229. public static bool DotButton(Vector3 position, Quaternion direction, float size, float pickSize) {
  230. #if UNITY_5_6_OR_NEWER
  231. return Handles.Button(position, direction, size, pickSize, Handles.DotHandleCap);
  232. #else
  233. return Handles.Button(position, direction, size, pickSize, Handles.DotCap);
  234. #endif
  235. }
  236. public static bool SphereButton(Vector3 position, Quaternion direction, float size, float pickSize) {
  237. #if UNITY_5_6_OR_NEWER
  238. return Handles.Button(position, direction, size, pickSize, Handles.SphereHandleCap);
  239. #else
  240. return Handles.Button(position, direction, size, pickSize, Handles.SphereCap);
  241. #endif
  242. }
  243. public static float ScaleValueHandleSphere(float value, Vector3 position, Quaternion rotation, float size, float snap) {
  244. #if UNITY_5_6_OR_NEWER
  245. return Handles.ScaleValueHandle(value, position, rotation, size, Handles.SphereHandleCap, snap);
  246. #else
  247. return Handles.ScaleValueHandle(value, position, rotation, size, Handles.SphereCap, snap);
  248. #endif
  249. }
  250. #endregion Platform dependent
  251. }
  252. }