using UnityEditor; using System; using System.Collections.Generic; using Cinemachine.Utility; using System.Linq.Expressions; namespace Cinemachine.Editor { /// /// A convenience base class for making inspector editors. /// /// The class we're editing public class BaseEditor : UnityEditor.Editor where T : class { /// /// The target object, cast as the same class as the object being edited /// protected T Target { get { return target as T; } } /// /// Return the Serialized property for a field, and exclude it from being automatically /// displayed in the inspector. Call this when you need to provide a custom UX for a field. /// /// Magic experssion code /// Call format is FindAndExcludeProperty(x => x.myField) /// The serialized property for the field protected SerializedProperty FindAndExcludeProperty(Expression> expr) { SerializedProperty p = FindProperty(expr); ExcludeProperty(p.name); return p; } /// /// Return the Serialized property for a field. /// /// Magic experssion code /// Call format is FindProperty(x => x.myField) /// The serialized property for the field protected SerializedProperty FindProperty(Expression> expr) { return serializedObject.FindProperty(FieldPath(expr)); } /// /// Magic code to get the string name of a field. Will not build if the field name changes. /// /// Magic experssion code /// Call format is FieldPath(x => x.myField) /// The string name of the field protected string FieldPath(Expression> expr) { return ReflectionHelpers.GetFieldPath(expr); } /// Obsolete, do not use. Use the overload, which is more performant /// List of property names to exclude protected virtual List GetExcludedPropertiesInInspector() { return mExcluded; } /// Get the property names to exclude in the inspector. /// Add the names to this list protected virtual void GetExcludedPropertiesInInspector(List excluded) { excluded.Add("m_Script"); } /// /// Exclude a property from automatic inclusion in the inspector /// when DrawRemainingPropertiesInInspector() is called /// /// The property to exclude protected void ExcludeProperty(string propertyName) { mExcluded.Add(propertyName); } /// Check whenther a property is in the excluded list /// The property to check /// True if property is excluded from automatic inclusion in the inspector /// when DrawRemainingPropertiesInInspector() is called protected bool IsPropertyExcluded(string propertyName) { return mExcluded.Contains(propertyName); } /// /// Draw the inspector /// public override void OnInspectorGUI() { BeginInspector(); DrawRemainingPropertiesInInspector(); } List mExcluded = new List(); /// /// Clients should call this at the start of OnInspectorGUI. /// Updates the serialized object and Sets up for excluded properties. /// protected virtual void BeginInspector() { serializedObject.Update(); mExcluded.Clear(); GetExcludedPropertiesInInspector(mExcluded); } /// /// Draw a property in the inspector, if it is not excluded. /// Property is marked as drawn, so will not be drawn again /// by DrawRemainingPropertiesInInspector() /// /// The property to draw protected virtual void DrawPropertyInInspector(SerializedProperty p) { if (!IsPropertyExcluded(p.name)) { EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(p); if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties(); ExcludeProperty(p.name); } } /// /// Draw all remaining unexcluded undrawn properties in the inspector. /// protected void DrawRemainingPropertiesInInspector() { EditorGUI.BeginChangeCheck(); DrawPropertiesExcluding(serializedObject, mExcluded.ToArray()); if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties(); } } }