using System.Collections.Generic; using UnityEngine; using System; using Sirenix.OdinInspector.Editor; using Sirenix.Utilities; using System.Linq; using System.IO; using UnityEditor; public static class ScriptableObjectCreator { public static void ShowDialog(string defaultDestinationPath, Action onScritpableObjectCreated = null) where T : ScriptableObject { var selector = new ScriptableObjectSelector(defaultDestinationPath, onScritpableObjectCreated); if (selector.SelectionTree.EnumerateTree().Count() == 1) { // If there is only one scriptable object to choose from in the selector, then // we'll automatically select it and confirm the selection. selector.SelectionTree.EnumerateTree().First().Select(); selector.SelectionTree.Selection.ConfirmSelection(); } else { // Else, we'll open up the selector in a popup and let the user choose. selector.ShowInPopup(200); } } // Here is the actual ScriptableObjectSelector which inherits from OdinSelector. // You can learn more about those in the documentation: http://sirenix.net/odininspector/documentation/sirenix/odininspector/editor/odinselector(t) // This one builds a menu-tree of all types that inherit from T, and when the selection is confirmed, it then prompts the user // with a dialog to save the newly created scriptable object. private class ScriptableObjectSelector : OdinSelector where T : ScriptableObject { private Action onScritpableObjectCreated; private string defaultDestinationPath; public ScriptableObjectSelector(string defaultDestinationPath, Action onScritpableObjectCreated = null) { this.onScritpableObjectCreated = onScritpableObjectCreated; this.defaultDestinationPath = defaultDestinationPath; #if UNITY_EDITOR this.SelectionConfirmed += this.ShowSaveFileDialog; #endif } #if UNITY_EDITOR protected override void BuildSelectionTree(OdinMenuTree tree) { var scriptableObjectTypes = AssemblyUtilities.GetTypes(AssemblyTypeFlags.CustomTypes) .Where(x => x.IsClass && !x.IsAbstract && x.InheritsFrom(typeof(T))); tree.Selection.SupportsMultiSelect = false; tree.Config.DrawSearchToolbar = true; tree.AddRange(scriptableObjectTypes, x => x.GetNiceName()) .AddThumbnailIcons(); } #endif private void ShowSaveFileDialog(IEnumerable selection) { var obj = ScriptableObject.CreateInstance(selection.FirstOrDefault()) as T; string dest = this.defaultDestinationPath.TrimEnd('/'); if (!Directory.Exists(dest)) { Directory.CreateDirectory(dest); #if UNITY_EDITOR AssetDatabase.Refresh(); #endif } #if UNITY_EDITOR dest = EditorUtility.SaveFilePanel("Save object as", dest, "New " + typeof(T).GetNiceName(), "asset"); #endif if (!string.IsNullOrEmpty(dest) && PathUtilities.TryMakeRelative(Path.GetDirectoryName(Application.dataPath), dest, out dest)) { #if UNITY_EDITOR AssetDatabase.CreateAsset(obj, dest); AssetDatabase.Refresh(); #endif if (this.onScritpableObjectCreated != null) { this.onScritpableObjectCreated(obj); } } else { UnityEngine.Object.DestroyImmediate(obj); } } } }