using UnityEngine; using UnityEditor; using UnityEditor.VersionControl; using System; namespace Cinemachine.Editor { /// /// Helper for drawing embedded asset editors /// internal class EmbeddeAssetEditor where T : ScriptableObject { /// /// Create in OnEnable() /// public EmbeddeAssetEditor(string propertyName, UnityEditor.Editor owner) { m_PropertyName = propertyName; m_Owner = owner; m_CreateButtonGUIContent = new GUIContent( "Create Asset", "Create a new shared settings asset"); } /// /// Called after the asset editor is created, in case it needs /// to be customized /// public OnCreateEditorDelegate OnCreateEditor; public delegate void OnCreateEditorDelegate(UnityEditor.Editor editor); /// /// Called when the asset being edited was changed by the user. /// public OnChangedDelegate OnChanged; public delegate void OnChangedDelegate(T obj); /// /// Free the resources in OnDisable() /// public void OnDisable() { DestroyEditor(); m_Owner = null; } /// /// Customize this after creation if you want /// public GUIContent m_CreateButtonGUIContent; private string m_PropertyName; private UnityEditor.Editor m_Editor = null; private UnityEditor.Editor m_Owner = null; const int kIndentOffset = 3; /// /// Call this from OnInspectorGUI. Will draw the asset reference field, and /// the embedded editor, or a Create Asset button, if no asset is set. /// public void DrawEditorCombo( string title, string defaultName, string extension, string message, string showLabel, bool indent) { SerializedProperty property = m_Owner.serializedObject.FindProperty(m_PropertyName); if (m_Editor == null) UpdateEditor(property); if (m_Editor == null) AssetFieldWithCreateButton(property, title, defaultName, extension, message); else { EditorGUILayout.BeginVertical(GUI.skin.box); Rect rect = EditorGUILayout.GetControlRect(true); rect.height = EditorGUIUtility.singleLineHeight; EditorGUI.BeginChangeCheck(); EditorGUI.PropertyField(rect, property); if (EditorGUI.EndChangeCheck()) { m_Owner.serializedObject.ApplyModifiedProperties(); UpdateEditor(property); } if (m_Editor != null) { Rect foldoutRect = new Rect( rect.x - kIndentOffset, rect.y, rect.width + kIndentOffset, rect.height); property.isExpanded = EditorGUI.Foldout( foldoutRect, property.isExpanded, GUIContent.none, true); bool canEditAsset = AssetDatabase.IsOpenForEdit(m_Editor.target, StatusQueryOptions.UseCachedIfPossible); GUI.enabled = canEditAsset; if (property.isExpanded) { EditorGUILayout.Separator(); EditorGUILayout.HelpBox( "This is a shared asset. Changes made here will apply to all users of this asset.", MessageType.Info); EditorGUI.BeginChangeCheck(); if (indent) ++EditorGUI.indentLevel; m_Editor.OnInspectorGUI(); if (indent) --EditorGUI.indentLevel; if (EditorGUI.EndChangeCheck() && (OnChanged != null)) OnChanged(property.objectReferenceValue as T); } GUI.enabled = true; if (m_Editor.target != null) { if (!canEditAsset && GUILayout.Button("Check out")) { Task task = Provider.Checkout(AssetDatabase.GetAssetPath(m_Editor.target), CheckoutMode.Asset); task.Wait(); } } } EditorGUILayout.EndVertical(); } } private void AssetFieldWithCreateButton( SerializedProperty property, string title, string defaultName, string extension, string message) { EditorGUI.BeginChangeCheck(); float hSpace = 5; float buttonWidth = GUI.skin.button.CalcSize(m_CreateButtonGUIContent).x; Rect r = EditorGUILayout.GetControlRect(true); r.width -= buttonWidth + hSpace; EditorGUI.PropertyField(r, property); r.x += r.width + hSpace; r.width = buttonWidth; if (GUI.Button(r, m_CreateButtonGUIContent)) { string newAssetPath = EditorUtility.SaveFilePanelInProject( title, defaultName, extension, message); if (!string.IsNullOrEmpty(newAssetPath)) { T asset = ScriptableObjectUtility.CreateAt(newAssetPath); property.objectReferenceValue = asset; m_Owner.serializedObject.ApplyModifiedProperties(); } } if (EditorGUI.EndChangeCheck()) { m_Owner.serializedObject.ApplyModifiedProperties(); UpdateEditor(property); } } public void DestroyEditor() { if (m_Editor != null) { UnityEngine.Object.DestroyImmediate(m_Editor); m_Editor = null; } } public void UpdateEditor(SerializedProperty property) { var target = property.objectReferenceValue; if (m_Editor != null && m_Editor.target != target) DestroyEditor(); if (target != null) { m_Editor = UnityEditor.Editor.CreateEditor(target); if (OnCreateEditor != null) OnCreateEditor(m_Editor); } } } }