ScriptableObjectCreator.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using System;
  4. using Sirenix.OdinInspector.Editor;
  5. using Sirenix.Utilities;
  6. using System.Linq;
  7. using System.IO;
  8. using UnityEditor;
  9. public static class ScriptableObjectCreator
  10. {
  11. public static void ShowDialog<T>(string defaultDestinationPath, Action<T> onScritpableObjectCreated = null)
  12. where T : ScriptableObject
  13. {
  14. var selector = new ScriptableObjectSelector<T>(defaultDestinationPath, onScritpableObjectCreated);
  15. if (selector.SelectionTree.EnumerateTree().Count() == 1)
  16. {
  17. // If there is only one scriptable object to choose from in the selector, then
  18. // we'll automatically select it and confirm the selection.
  19. selector.SelectionTree.EnumerateTree().First().Select();
  20. selector.SelectionTree.Selection.ConfirmSelection();
  21. }
  22. else
  23. {
  24. // Else, we'll open up the selector in a popup and let the user choose.
  25. selector.ShowInPopup(200);
  26. }
  27. }
  28. // Here is the actual ScriptableObjectSelector which inherits from OdinSelector.
  29. // You can learn more about those in the documentation: http://sirenix.net/odininspector/documentation/sirenix/odininspector/editor/odinselector(t)
  30. // This one builds a menu-tree of all types that inherit from T, and when the selection is confirmed, it then prompts the user
  31. // with a dialog to save the newly created scriptable object.
  32. private class ScriptableObjectSelector<T> : OdinSelector<Type> where T : ScriptableObject
  33. {
  34. private Action<T> onScritpableObjectCreated;
  35. private string defaultDestinationPath;
  36. public ScriptableObjectSelector(string defaultDestinationPath, Action<T> onScritpableObjectCreated = null)
  37. {
  38. this.onScritpableObjectCreated = onScritpableObjectCreated;
  39. this.defaultDestinationPath = defaultDestinationPath;
  40. #if UNITY_EDITOR
  41. this.SelectionConfirmed += this.ShowSaveFileDialog;
  42. #endif
  43. }
  44. #if UNITY_EDITOR
  45. protected override void BuildSelectionTree(OdinMenuTree tree)
  46. {
  47. var scriptableObjectTypes = AssemblyUtilities.GetTypes(AssemblyTypeFlags.CustomTypes)
  48. .Where(x => x.IsClass && !x.IsAbstract && x.InheritsFrom(typeof(T)));
  49. tree.Selection.SupportsMultiSelect = false;
  50. tree.Config.DrawSearchToolbar = true;
  51. tree.AddRange(scriptableObjectTypes, x => x.GetNiceName())
  52. .AddThumbnailIcons();
  53. }
  54. #endif
  55. private void ShowSaveFileDialog(IEnumerable<Type> selection)
  56. {
  57. var obj = ScriptableObject.CreateInstance(selection.FirstOrDefault()) as T;
  58. string dest = this.defaultDestinationPath.TrimEnd('/');
  59. if (!Directory.Exists(dest))
  60. {
  61. Directory.CreateDirectory(dest);
  62. #if UNITY_EDITOR
  63. AssetDatabase.Refresh();
  64. #endif
  65. }
  66. #if UNITY_EDITOR
  67. dest = EditorUtility.SaveFilePanel("Save object as", dest, "New " + typeof(T).GetNiceName(), "asset");
  68. #endif
  69. if (!string.IsNullOrEmpty(dest) && PathUtilities.TryMakeRelative(Path.GetDirectoryName(Application.dataPath), dest, out dest))
  70. {
  71. #if UNITY_EDITOR
  72. AssetDatabase.CreateAsset(obj, dest);
  73. AssetDatabase.Refresh();
  74. #endif
  75. if (this.onScritpableObjectCreated != null)
  76. {
  77. this.onScritpableObjectCreated(obj);
  78. }
  79. }
  80. else
  81. {
  82. UnityEngine.Object.DestroyImmediate(obj);
  83. }
  84. }
  85. }
  86. }