173 lines
6.5 KiB
C#
173 lines
6.5 KiB
C#
|
using UnityEngine;
|
||
|
using UnityEditor;
|
||
|
using UnityEditor.VersionControl;
|
||
|
using System;
|
||
|
|
||
|
namespace Cinemachine.Editor
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Helper for drawing embedded asset editors
|
||
|
/// </summary>
|
||
|
internal class EmbeddeAssetEditor<T> where T : ScriptableObject
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Create in OnEnable()
|
||
|
/// </summary>
|
||
|
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");
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Called after the asset editor is created, in case it needs
|
||
|
/// to be customized
|
||
|
/// </summary>
|
||
|
public OnCreateEditorDelegate OnCreateEditor;
|
||
|
public delegate void OnCreateEditorDelegate(UnityEditor.Editor editor);
|
||
|
|
||
|
/// <summary>
|
||
|
/// Called when the asset being edited was changed by the user.
|
||
|
/// </summary>
|
||
|
public OnChangedDelegate OnChanged;
|
||
|
public delegate void OnChangedDelegate(T obj);
|
||
|
|
||
|
/// <summary>
|
||
|
/// Free the resources in OnDisable()
|
||
|
/// </summary>
|
||
|
public void OnDisable()
|
||
|
{
|
||
|
DestroyEditor();
|
||
|
m_Owner = null;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Customize this after creation if you want
|
||
|
/// </summary>
|
||
|
public GUIContent m_CreateButtonGUIContent;
|
||
|
|
||
|
private string m_PropertyName;
|
||
|
private UnityEditor.Editor m_Editor = null;
|
||
|
private UnityEditor.Editor m_Owner = null;
|
||
|
|
||
|
const int kIndentOffset = 3;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Call this from OnInspectorGUI. Will draw the asset reference field, and
|
||
|
/// the embedded editor, or a Create Asset button, if no asset is set.
|
||
|
/// </summary>
|
||
|
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<T>(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);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|