NoiseSettingsPropertyDrawer.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.Collections.Generic;
  4. namespace Cinemachine.Editor
  5. {
  6. [CustomPropertyDrawer(typeof(NoiseSettingsPropertyAttribute))]
  7. internal sealed class NoiseSettingsPropertyDrawer : PropertyDrawer
  8. {
  9. public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label)
  10. {
  11. RebuildProfileList();
  12. float iconSize = rect.height + 4;
  13. rect.width -= iconSize;
  14. int preset = sNoisePresets.IndexOf((NoiseSettings)property.objectReferenceValue);
  15. EditorGUI.showMixedValue = property.hasMultipleDifferentValues;
  16. preset = EditorGUI.Popup(rect, label, preset, sNoisePresetNames);
  17. EditorGUI.showMixedValue = false;
  18. string labelText = label.text;
  19. NoiseSettings newProfile = preset < 0 ? null : sNoisePresets[preset] as NoiseSettings;
  20. if ((NoiseSettings)property.objectReferenceValue != newProfile)
  21. {
  22. property.objectReferenceValue = newProfile;
  23. property.serializedObject.ApplyModifiedProperties();
  24. }
  25. rect.x += rect.width; rect.width = iconSize; rect.height = iconSize; rect.y -= 2;
  26. if (GUI.Button(rect, EditorGUIUtility.IconContent("_Popup"), GUI.skin.label))
  27. {
  28. GenericMenu menu = new GenericMenu();
  29. if (property.objectReferenceValue != null)
  30. {
  31. menu.AddItem(new GUIContent("Edit"), false, ()
  32. => Selection.activeObject = property.objectReferenceValue);
  33. menu.AddItem(new GUIContent("Clone"), false, () =>
  34. {
  35. NoiseSettings pp = CreateProfile(
  36. property, labelText,
  37. (NoiseSettings)property.objectReferenceValue);
  38. if (pp != null)
  39. {
  40. property.objectReferenceValue = pp;
  41. property.serializedObject.ApplyModifiedProperties();
  42. InvalidateProfileList();
  43. }
  44. });
  45. menu.AddItem(new GUIContent("Locate"), false, ()
  46. => EditorGUIUtility.PingObject(property.objectReferenceValue));
  47. }
  48. menu.AddItem(new GUIContent("New"), false, () =>
  49. {
  50. //Undo.RecordObject(Target, "Change Noise Profile");
  51. NoiseSettings pp = CreateProfile(property, labelText, null);
  52. if (pp != null)
  53. {
  54. property.objectReferenceValue = pp;
  55. property.serializedObject.ApplyModifiedProperties();
  56. InvalidateProfileList();
  57. }
  58. });
  59. menu.ShowAsContext();
  60. }
  61. }
  62. static List<ScriptableObject> sNoisePresets;
  63. static GUIContent[] sNoisePresetNames;
  64. static float sLastPresetRebuildTime = 0;
  65. public static void InvalidateProfileList()
  66. {
  67. sNoisePresets = null;
  68. sNoisePresetNames = null;
  69. }
  70. static void RebuildProfileList()
  71. {
  72. if (sLastPresetRebuildTime < Time.realtimeSinceStartup - 5)
  73. InvalidateProfileList();
  74. if (sNoisePresets != null && sNoisePresetNames != null)
  75. return;
  76. sNoisePresets = FindAssetsByType<NoiseSettings>();
  77. #if UNITY_2018_1_OR_NEWER
  78. InspectorUtility.AddAssetsFromPackageSubDirectory(
  79. typeof(NoiseSettings), sNoisePresets, "Presets/Noise");
  80. #endif
  81. sNoisePresets.Insert(0, null);
  82. List<GUIContent> presetNameList = new List<GUIContent>();
  83. foreach (var n in sNoisePresets)
  84. presetNameList.Add(new GUIContent((n == null) ? "(none)" : n.name));
  85. sNoisePresetNames = presetNameList.ToArray();
  86. sLastPresetRebuildTime = Time.realtimeSinceStartup;
  87. }
  88. static List<ScriptableObject> FindAssetsByType<T>() where T : UnityEngine.Object
  89. {
  90. List<ScriptableObject> assets = new List<ScriptableObject>();
  91. string[] guids = AssetDatabase.FindAssets(string.Format("t:{0}", typeof(T)));
  92. for (int i = 0; i < guids.Length; i++)
  93. {
  94. string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]);
  95. ScriptableObject asset = AssetDatabase.LoadAssetAtPath<T>(assetPath) as ScriptableObject;
  96. if (asset != null)
  97. assets.Add(asset);
  98. }
  99. return assets;
  100. }
  101. NoiseSettings CreateProfile(SerializedProperty property, string label, NoiseSettings copyFrom)
  102. {
  103. string path = InspectorUtility.GetVirtualCameraObjectName(property) + " " + label;
  104. path = EditorUtility.SaveFilePanelInProject(
  105. "Create Noise Profile asset", path, "asset",
  106. "This asset will generate a procedural noise signal");
  107. if (!string.IsNullOrEmpty(path))
  108. {
  109. NoiseSettings profile = null;
  110. if (copyFrom != null)
  111. {
  112. string fromPath = AssetDatabase.GetAssetPath(copyFrom);
  113. if (AssetDatabase.CopyAsset(fromPath, path))
  114. {
  115. profile = AssetDatabase.LoadAssetAtPath(
  116. path, typeof(NoiseSettings)) as NoiseSettings;
  117. }
  118. }
  119. else
  120. {
  121. profile = ScriptableObjectUtility.CreateAt(
  122. typeof(NoiseSettings), path) as NoiseSettings;
  123. }
  124. AssetDatabase.SaveAssets();
  125. AssetDatabase.Refresh();
  126. return profile;
  127. }
  128. return null;
  129. }
  130. }
  131. }