Forked from FreyaHolmer/ScriptableObjectSpawner.cs
Last active
January 8, 2020 06:52
-
-
Save vicenterusso/e70c4db0d1ba2af9817df51e75d5c7dd to your computer and use it in GitHub Desktop.
ScriptableObject asset spawner for Unity with search capabilities
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Adds a menu item for easy creation of your ScriptableObject types | |
// Usage: Right click in project view -> Create -> ScriptableObject... -> Select your type | |
// It will land in the root of your assets folder with the same name as your class | |
// Freya Holmér - [email protected] | |
// | |
// Added search capabilities by [email protected] | |
using System; | |
using UnityEngine; | |
using UnityEditor; | |
using System.Reflection; | |
using System.Linq; | |
using System.IO; | |
using Object = UnityEngine.Object; | |
public class ScriptableObjectSpawner : EditorWindow { | |
// Config | |
const bool CLOSE_AFTER_SPAWNING = true; | |
const bool SELECT_AFTER_SPAWN = true; | |
// Variables | |
string[] m_TypeNames; | |
string[] m_TypeNS; // Namespaces | |
string[] m_AssemblyNames; | |
System.Type[] m_Types; | |
GUIStyle m_LeftAlignedButtonStyle; | |
Vector2 m_ScrollViewPos; | |
string m_filter = ""; | |
// Window spawning | |
[MenuItem( "Assets/Create/ScriptableObject..." )] | |
static void Init() { | |
ScriptableObjectSpawner window = (ScriptableObjectSpawner)EditorWindow.GetWindow( typeof( ScriptableObjectSpawner ), true ); | |
window.title = "Select a type..."; | |
window.Center(); | |
} | |
// Center on screen | |
void Center(){ | |
Rect scPos = this.position; | |
scPos.center = new Vector2(Screen.currentResolution.width, Screen.currentResolution.height) / 2; | |
this.position = scPos; | |
} | |
// Interface | |
void OnGUI() { | |
GUILayout.BeginHorizontal(); | |
{ | |
GUILayout.BeginVertical(); | |
{ | |
GUILayout.Space(8); | |
GUILayout.Label("Search type:"); | |
m_filter = GUILayout.TextField(m_filter); | |
GUILayout.Space(4); | |
} | |
GUILayout.EndVertical(); | |
} | |
GUILayout.EndHorizontal(); | |
GUILayout.Space(4); | |
if( m_TypeNames == null || m_Types == null || m_LeftAlignedButtonStyle == null ) | |
Reload(); | |
m_ScrollViewPos = EditorGUILayout.BeginScrollView( m_ScrollViewPos ); | |
float halfWidth = ( Screen.width / 2 ) - 13; | |
for( int i = 0; i < m_Types.Length; i++ ) { | |
if(m_filter != "" && m_TypeNames[i].IndexOf(m_filter, StringComparison.OrdinalIgnoreCase) < 0 && | |
(m_TypeNS[i] == null || m_TypeNS[i].IndexOf(m_filter, StringComparison.OrdinalIgnoreCase) < 0)) | |
continue; | |
GUILayout.BeginHorizontal(); | |
if( GUILayout.Button( m_TypeNames[i], m_LeftAlignedButtonStyle, GUILayout.Width( halfWidth ) ) ) { | |
ScriptableObject so = ScriptableObject.CreateInstance( m_Types[i] ); | |
AssetDatabase.CreateAsset( so, GetUniqueAssetPath( m_Types[i] ) ); | |
if( SELECT_AFTER_SPAWN ) | |
Selection.objects = new Object[] { so }; | |
EditorGUIUtility.PingObject( so ); | |
if( CLOSE_AFTER_SPAWNING ) | |
Close(); | |
} | |
var labelPrefix = m_TypeNS[i] != null ? m_TypeNS[i] + " / " : ""; | |
GUILayout.Label( labelPrefix + m_AssemblyNames[i], GUILayout.Width( halfWidth ) ); | |
GUILayout.EndHorizontal(); | |
} | |
EditorGUILayout.EndScrollView(); | |
} | |
// Reload data and recache arrays | |
void Reload() { | |
Assembly[] asms = System.AppDomain.CurrentDomain.GetAssemblies().Where( x => x.FullName.StartsWith( "Assembly-CSharp" ) ).ToArray(); | |
m_Types = asms.SelectMany( x => x.GetTypes().Where( type => type.IsSubclassOf( typeof( ScriptableObject ) ) && !type.IsSubclassOf( typeof( Editor ) ) && !type.IsSubclassOf( typeof( EditorWindow ) ) ) ).OrderBy( x => x.Name ).ToArray(); | |
m_TypeNames = m_Types.Select( x => x.Name ).ToArray(); | |
m_TypeNS = m_Types.Select( x => x.Namespace ).ToArray(); | |
m_AssemblyNames = m_Types.Select( x => x.Assembly.FullName.Split( ',' )[0] ).ToArray(); | |
m_LeftAlignedButtonStyle = new GUIStyle( GUI.skin.button ); | |
m_LeftAlignedButtonStyle.alignment = TextAnchor.MiddleLeft; | |
} | |
// Used to make sure names are incremental, eg. MyObject, MyObject_2, MyObject_3 | |
string GetUniqueAssetPath( System.Type type ) { | |
string typeName = type.Name; | |
string folder = GetAssetFolder(); | |
string path = folder + typeName + ".asset"; | |
if( AssetDatabase.LoadAssetAtPath( path, type ) == null ) | |
return path; | |
int i = 2; | |
do { | |
path = folder + typeName + "_" + i + ".asset"; | |
i++; | |
} while( AssetDatabase.LoadAssetAtPath( path, type ) != null ); | |
return path; | |
} | |
// Get the folder to create the asset in | |
string GetAssetFolder(){ | |
Object[] selection = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets); | |
if( selection != null && selection.Length > 0 ){ // If any assets are selected | |
for(int i=0;i<selection.Length;i++){ // Search for a folder | |
string path = AssetDatabase.GetAssetPath(selection[i]); | |
if(Directory.Exists(Application.dataPath.Substring(0,Application.dataPath.Length-6) + path)){ | |
return path + "/"; | |
} | |
} | |
return Path.GetDirectoryName( AssetDatabase.GetAssetPath(selection[0])) + "/"; // If no folder was found, grab the first object's directory | |
} | |
return "Assets/"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment