BaseEditor.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. using UnityEditor;
  2. using System;
  3. using System.Collections.Generic;
  4. using Cinemachine.Utility;
  5. using System.Linq.Expressions;
  6. namespace Cinemachine.Editor
  7. {
  8. /// <summary>
  9. /// A convenience base class for making inspector editors.
  10. /// </summary>
  11. /// <typeparam name="T">The class we're editing</typeparam>
  12. public class BaseEditor<T> : UnityEditor.Editor where T : class
  13. {
  14. /// <summary>
  15. /// The target object, cast as the same class as the object being edited
  16. /// </summary>
  17. protected T Target { get { return target as T; } }
  18. /// <summary>
  19. /// Return the Serialized property for a field, and exclude it from being automatically
  20. /// displayed in the inspector. Call this when you need to provide a custom UX for a field.
  21. /// </summary>
  22. /// <typeparam name="TValue">Magic experssion code</typeparam>
  23. /// <param name="expr">Call format is FindAndExcludeProperty(x => x.myField)</param>
  24. /// <returns>The serialized property for the field</returns>
  25. protected SerializedProperty FindAndExcludeProperty<TValue>(Expression<Func<T, TValue>> expr)
  26. {
  27. SerializedProperty p = FindProperty(expr);
  28. ExcludeProperty(p.name);
  29. return p;
  30. }
  31. /// <summary>
  32. /// Return the Serialized property for a field.
  33. /// </summary>
  34. /// <typeparam name="TValue">Magic experssion code</typeparam>
  35. /// <param name="expr">Call format is FindProperty(x => x.myField)</param>
  36. /// <returns>The serialized property for the field</returns>
  37. protected SerializedProperty FindProperty<TValue>(Expression<Func<T, TValue>> expr)
  38. {
  39. return serializedObject.FindProperty(FieldPath(expr));
  40. }
  41. /// <summary>
  42. /// Magic code to get the string name of a field. Will not build if the field name changes.
  43. /// </summary>
  44. /// <typeparam name="TValue">Magic experssion code</typeparam>
  45. /// <param name="expr">Call format is FieldPath(x => x.myField)</param>
  46. /// <returns>The string name of the field</returns>
  47. protected string FieldPath<TValue>(Expression<Func<T, TValue>> expr)
  48. {
  49. return ReflectionHelpers.GetFieldPath(expr);
  50. }
  51. /// <summary>Obsolete, do not use. Use the overload, which is more performant</summary>
  52. /// <returns>List of property names to exclude</returns>
  53. protected virtual List<string> GetExcludedPropertiesInInspector() { return mExcluded; }
  54. /// <summary>Get the property names to exclude in the inspector.</summary>
  55. /// <param name="excluded">Add the names to this list</param>
  56. protected virtual void GetExcludedPropertiesInInspector(List<string> excluded)
  57. {
  58. excluded.Add("m_Script");
  59. }
  60. /// <summary>
  61. /// Exclude a property from automatic inclusion in the inspector
  62. /// when DrawRemainingPropertiesInInspector() is called
  63. /// </summary>
  64. /// <param name="propertyName">The property to exclude</param>
  65. protected void ExcludeProperty(string propertyName)
  66. {
  67. mExcluded.Add(propertyName);
  68. }
  69. /// <summary>Check whenther a property is in the excluded list</summary>
  70. /// <param name="propertyName">The property to check</param>
  71. /// <returns>True if property is excluded from automatic inclusion in the inspector
  72. /// when DrawRemainingPropertiesInInspector() is called</returns>
  73. protected bool IsPropertyExcluded(string propertyName)
  74. {
  75. return mExcluded.Contains(propertyName);
  76. }
  77. /// <summary>
  78. /// Draw the inspector
  79. /// </summary>
  80. public override void OnInspectorGUI()
  81. {
  82. BeginInspector();
  83. DrawRemainingPropertiesInInspector();
  84. }
  85. List<string> mExcluded = new List<string>();
  86. /// <summary>
  87. /// Clients should call this at the start of OnInspectorGUI.
  88. /// Updates the serialized object and Sets up for excluded properties.
  89. /// </summary>
  90. protected virtual void BeginInspector()
  91. {
  92. serializedObject.Update();
  93. mExcluded.Clear();
  94. GetExcludedPropertiesInInspector(mExcluded);
  95. }
  96. /// <summary>
  97. /// Draw a property in the inspector, if it is not excluded.
  98. /// Property is marked as drawn, so will not be drawn again
  99. /// by DrawRemainingPropertiesInInspector()
  100. /// </summary>
  101. /// <param name="p">The property to draw</param>
  102. protected virtual void DrawPropertyInInspector(SerializedProperty p)
  103. {
  104. if (!IsPropertyExcluded(p.name))
  105. {
  106. EditorGUI.BeginChangeCheck();
  107. EditorGUILayout.PropertyField(p);
  108. if (EditorGUI.EndChangeCheck())
  109. serializedObject.ApplyModifiedProperties();
  110. ExcludeProperty(p.name);
  111. }
  112. }
  113. /// <summary>
  114. /// Draw all remaining unexcluded undrawn properties in the inspector.
  115. /// </summary>
  116. protected void DrawRemainingPropertiesInInspector()
  117. {
  118. EditorGUI.BeginChangeCheck();
  119. DrawPropertiesExcluding(serializedObject, mExcluded.ToArray());
  120. if (EditorGUI.EndChangeCheck())
  121. serializedObject.ApplyModifiedProperties();
  122. }
  123. }
  124. }