| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- using UnityEngine;
- using UnityEditor;
- using System;
- using Cinemachine.Utility;
- using System.Linq;
- using System.Collections.Generic;
- namespace Cinemachine.Editor
- {
- [CustomPropertyDrawer(typeof(CinemachineEmbeddedAssetPropertyAttribute))]
- internal sealed class EmbeddedAssetPropertyDrawer : PropertyDrawer
- {
- const float vSpace = 2;
- const float kIndentAmount = 15;
- const float kBoxMargin = 3;
- float HelpBoxHeight { get { return EditorGUIUtility.singleLineHeight * 2.5f; } }
- bool mExpanded = false;
- bool WarnIfNull
- {
- get
- {
- var attr = attribute as CinemachineEmbeddedAssetPropertyAttribute;
- return attr == null ? false : attr.WarnIfNull;
- }
- }
- float HeaderHeight { get { return EditorGUIUtility.singleLineHeight * 1.5f; } }
- float DrawHeader(Rect rect, string text)
- {
- float delta = HeaderHeight - EditorGUIUtility.singleLineHeight;
- rect.y += delta; rect.height -= delta;
- EditorGUI.LabelField(rect, new GUIContent(text), EditorStyles.boldLabel);
- return HeaderHeight;
- }
- string HeaderText(SerializedProperty property)
- {
- var attrs = property.serializedObject.targetObject.GetType()
- .GetCustomAttributes(typeof(HeaderAttribute), false);
- if (attrs != null && attrs.Length > 0)
- return ((HeaderAttribute)attrs[0]).header;
- return null;
- }
- bool AssetHasCustomEditor(SerializedProperty property)
- {
- ScriptableObject asset = property.objectReferenceValue as ScriptableObject;
- if (asset != null)
- return ActiveEditorTracker.HasCustomEditor(asset);
- return false;
- }
- public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
- {
- bool hasCustomEditor = AssetHasCustomEditor(property);
- float height = base.GetPropertyHeight(property, label);
- height += + 2 * (kBoxMargin + vSpace);
- if (mExpanded && !hasCustomEditor)
- {
- height += HelpBoxHeight + kBoxMargin;
- ScriptableObject asset = property.objectReferenceValue as ScriptableObject;
- if (asset != null)
- {
- SerializedObject so = new SerializedObject(asset);
- var prop = so.GetIterator();
- prop.NextVisible(true);
- do
- {
- if (prop.name == "m_Script")
- continue;
- string header = HeaderText(prop);
- if (header != null)
- height += HeaderHeight + vSpace;
- height += EditorGUI.GetPropertyHeight(prop, false) + vSpace;
- }
- while (prop.NextVisible(prop.isExpanded));
- height += kBoxMargin;
- }
- }
- return height;
- }
- public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label)
- {
- bool hasCustomEditor = AssetHasCustomEditor(property);
- rect.y += vSpace; rect.height -= 2 * vSpace;
- GUI.Box(rect, GUIContent.none, GUI.skin.box);
- rect.y += kBoxMargin;
- rect.height = EditorGUIUtility.singleLineHeight;
- EditorGUIUtility.labelWidth -= kBoxMargin;
- AssetFieldWithCreateButton(
- new Rect(rect.x + kBoxMargin, rect.y, rect.width - 2 * kBoxMargin, rect.height),
- property, WarnIfNull,
- property.serializedObject.targetObject.name + " " + label.text);
- ScriptableObject asset = property.objectReferenceValue as ScriptableObject;
- if (asset != null && !hasCustomEditor)
- {
- mExpanded = EditorGUI.Foldout(rect, mExpanded, GUIContent.none, true);
- if (mExpanded)
- {
- rect.y += rect.height + kBoxMargin + vSpace;
- rect.x += kIndentAmount + kBoxMargin;
- rect.width -= kIndentAmount + 2 * kBoxMargin;
- EditorGUIUtility.labelWidth -= kIndentAmount;
- EditorGUI.HelpBox(
- new Rect(rect.x, rect.y, rect.width, HelpBoxHeight),
- "This is a shared asset.\n"
- + "Changes made here will apply to all users of this asset",
- MessageType.Info);
- rect.y += HelpBoxHeight + kBoxMargin;
- SerializedObject so = new SerializedObject(property.objectReferenceValue);
- var prop = so.GetIterator();
- prop.NextVisible(true);
- var indent = EditorGUI.indentLevel;
- do
- {
- if (prop.name == "m_Script")
- continue;
- string header = HeaderText(prop);
- if (header != null)
- {
- DrawHeader(rect, header);
- rect.y += HeaderHeight + vSpace;
- rect.height -= HeaderHeight + vSpace;
- }
- rect.height = EditorGUI.GetPropertyHeight(prop, false);
- EditorGUI.indentLevel = indent + prop.depth;
- EditorGUI.PropertyField(rect, prop);
- rect.y += rect.height + vSpace;
- } while (prop.NextVisible(prop.isExpanded));
- if (GUI.changed)
- so.ApplyModifiedProperties();
- }
- EditorGUIUtility.labelWidth += kIndentAmount;
- }
- EditorGUIUtility.labelWidth += kBoxMargin;
- }
- Type EmbeddedAssetType(SerializedProperty property)
- {
- Type type = property.serializedObject.targetObject.GetType();
- var a = property.propertyPath.Split('.');
- for (int i = 0; i < a.Length; ++i)
- type = type.GetField(a[i],
- System.Reflection.BindingFlags.Public
- | System.Reflection.BindingFlags.NonPublic
- | System.Reflection.BindingFlags.Instance).FieldType;
- return type;
- }
- Type[] mAssetTypes = null;
- List<ScriptableObject> mAssetPresets;
- GUIContent[] mAssetPresetNames;
- void RebuildPresetList()
- {
- if (mAssetPresets != null && mAssetPresetNames != null)
- return;
- mAssetPresets = new List<ScriptableObject>();
- #if UNITY_2018_1_OR_NEWER
- if (mAssetTypes != null)
- {
- for (int i = 0; i < mAssetTypes.Length; ++i)
- InspectorUtility.AddAssetsFromPackageSubDirectory(
- mAssetTypes[i], mAssetPresets, "Presets/Noise");
- }
- #endif
- List<GUIContent> presetNameList = new List<GUIContent>();
- foreach (var n in mAssetPresets)
- presetNameList.Add(new GUIContent("Presets/" + n.name));
- mAssetPresetNames = presetNameList.ToArray();
- }
- void AssetFieldWithCreateButton(
- Rect r, SerializedProperty property, bool warnIfNull, string defaultName)
- {
- // Collect all the eligible asset types
- Type type = EmbeddedAssetType(property);
- if (mAssetTypes == null)
- mAssetTypes = ReflectionHelpers.GetTypesInAllDependentAssemblies(
- (Type t) => type.IsAssignableFrom(t) && !t.IsAbstract).ToArray();
- float iconSize = r.height + 4;
- r.width -= iconSize;
- GUIContent label = new GUIContent(property.displayName, property.tooltip);
- if (warnIfNull && property.objectReferenceValue == null)
- label.image = EditorGUIUtility.IconContent("console.warnicon.sml").image;
- EditorGUI.PropertyField(r, property, label);
- r.x += r.width; r.width = iconSize; r.height = iconSize;
- if (GUI.Button(r, EditorGUIUtility.IconContent("_Popup"), GUI.skin.label))
- {
- GenericMenu menu = new GenericMenu();
- if (property.objectReferenceValue != null)
- {
- menu.AddItem(new GUIContent("Edit"), false, ()
- => Selection.activeObject = property.objectReferenceValue);
- menu.AddItem(new GUIContent("Clone"), false, () =>
- {
- ScriptableObject copyFrom = property.objectReferenceValue as ScriptableObject;
- if (copyFrom != null)
- {
- string title = "Create New " + copyFrom.GetType().Name + " asset";
- ScriptableObject asset = CreateAsset(
- copyFrom.GetType(), copyFrom, defaultName, title);
- if (asset != null)
- {
- property.objectReferenceValue = asset;
- property.serializedObject.ApplyModifiedProperties();
- }
- }
- });
- menu.AddItem(new GUIContent("Locate"), false, ()
- => EditorGUIUtility.PingObject(property.objectReferenceValue));
- }
- RebuildPresetList();
- int i = 0;
- foreach (var a in mAssetPresets)
- {
- menu.AddItem(mAssetPresetNames[i++], false, () =>
- {
- property.objectReferenceValue = a;
- property.serializedObject.ApplyModifiedProperties();
- });
- }
- foreach (var t in mAssetTypes)
- {
- menu.AddItem(new GUIContent("New " + InspectorUtility.NicifyClassName(t.Name)), false, () =>
- {
- string title = "Create New " + t.Name + " asset";
- ScriptableObject asset = CreateAsset(t, null, defaultName, title);
- if (asset != null)
- {
- property.objectReferenceValue = asset;
- property.serializedObject.ApplyModifiedProperties();
- }
- });
- }
- menu.ShowAsContext();
- }
- }
- ScriptableObject CreateAsset(
- Type assetType, ScriptableObject copyFrom, string defaultName, string dialogTitle)
- {
- ScriptableObject asset = null;
- string path = EditorUtility.SaveFilePanelInProject(
- dialogTitle, defaultName, "asset", string.Empty);
- if (!string.IsNullOrEmpty(path))
- {
- if (copyFrom != null)
- {
- string fromPath = AssetDatabase.GetAssetPath(copyFrom);
- if (AssetDatabase.CopyAsset(fromPath, path))
- asset = AssetDatabase.LoadAssetAtPath(path, assetType) as ScriptableObject;
- }
- else
- {
- asset = ScriptableObjectUtility.CreateAt(assetType, path);
- }
- AssetDatabase.SaveAssets();
- AssetDatabase.Refresh();
- }
- return asset;
- }
- }
- }
|