// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus). // It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE) using UnityEngine; using UnityEditor; using UnityEditor.Callbacks; using System; using System.IO; using System.Linq; using System.Collections.Generic; #if UNITY_5_0 || UNITY_5_1 using System.Reflection; #endif namespace Fungus.EditorUtils { [CustomEditor(typeof(FungusEditorResources))] internal class FungusEditorResourcesInspector : Editor { public override void OnInspectorGUI() { if (serializedObject.FindProperty("updateOnReloadScripts").boolValue) { GUILayout.Label("Updating..."); } else { if (GUILayout.Button("Sync with EditorResources folder")) { FungusEditorResources.GenerateResourcesScript(); } DrawDefaultInspector(); } } } internal class EditorResourcesPostProcessor : AssetPostprocessor { private static void OnPostprocessAllAssets(string[] importedAssets, string[] _, string[] __, string[] ___) { foreach (var path in importedAssets) { if (path.EndsWith("FungusEditorResources.asset")) { var asset = AssetDatabase.LoadAssetAtPath(path, typeof(FungusEditorResources)) as FungusEditorResources; if (asset != null) { FungusEditorResources.UpdateTextureReferences(asset); AssetDatabase.SaveAssets(); return; } } } } } internal partial class FungusEditorResources : ScriptableObject { [Serializable] internal class EditorTexture { [SerializeField] private Texture2D free; [SerializeField] private Texture2D pro; public Texture2D Texture2D { get { return EditorGUIUtility.isProSkin && pro != null ? pro : free; } } public EditorTexture(Texture2D free, Texture2D pro) { this.free = free; this.pro = pro; } } private static FungusEditorResources instance; private static readonly string editorResourcesFolderName = "\"EditorResources\""; [SerializeField] [HideInInspector] private bool updateOnReloadScripts = false; internal static FungusEditorResources Instance { get { if (instance == null) { var guids = AssetDatabase.FindAssets("FungusEditorResources t:FungusEditorResources"); if (guids.Length == 0) { instance = ScriptableObject.CreateInstance(typeof(FungusEditorResources)) as FungusEditorResources; AssetDatabase.CreateAsset(instance, GetRootFolder() + "/FungusEditorResources.asset"); } else { if (guids.Length > 1) { Debug.LogWarning("Multiple FungusEditorResources assets found!"); } var path = AssetDatabase.GUIDToAssetPath(guids[0]); instance = AssetDatabase.LoadAssetAtPath(path, typeof(FungusEditorResources)) as FungusEditorResources; } } return instance; } } private static string GetRootFolder() { var rootGuid = AssetDatabase.FindAssets(editorResourcesFolderName)[0]; return AssetDatabase.GUIDToAssetPath(rootGuid); } internal static void GenerateResourcesScript() { // Get all unique filenames var textureNames = new HashSet(); var guids = AssetDatabase.FindAssets("t:Texture2D", new [] { GetRootFolder() }); var paths = guids.Select(guid => AssetDatabase.GUIDToAssetPath(guid)); foreach (var path in paths) { textureNames.Add(Path.GetFileNameWithoutExtension(path)); } var scriptGuid = AssetDatabase.FindAssets("FungusEditorResources t:MonoScript")[0]; var relativePath = AssetDatabase.GUIDToAssetPath(scriptGuid).Replace("FungusEditorResources.cs", "FungusEditorResourcesGenerated.cs"); var absolutePath = Application.dataPath + relativePath.Substring("Assets".Length); using (var writer = new StreamWriter(absolutePath)) { writer.WriteLine("// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus)."); writer.WriteLine("// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)"); writer.WriteLine(""); writer.WriteLine("using UnityEngine;"); writer.WriteLine(""); writer.WriteLine("namespace Fungus.EditorUtils"); writer.WriteLine("{"); writer.WriteLine(" internal partial class FungusEditorResources : ScriptableObject"); writer.WriteLine(" {"); foreach (var name in textureNames) { writer.WriteLine(" [SerializeField] private EditorTexture " + name + ";"); } writer.WriteLine(""); foreach (var name in textureNames) { var pascalCase = string.Join("", name.Split(new [] { '_' }, StringSplitOptions.RemoveEmptyEntries).Select( s => s.Substring(0, 1).ToUpper() + s.Substring(1)).ToArray() ); writer.WriteLine(" public static Texture2D " + pascalCase + " { get { return Instance." + name + ".Texture2D; } }"); } writer.WriteLine(" }"); writer.WriteLine("}"); } Instance.updateOnReloadScripts = true; AssetDatabase.ImportAsset(relativePath); } [DidReloadScripts] private static void OnDidReloadScripts() { if (Instance.updateOnReloadScripts) { UpdateTextureReferences(Instance); } } internal static void UpdateTextureReferences(FungusEditorResources instance) { // Iterate through all fields in instance and set texture references var serializedObject = new SerializedObject(instance); var prop = serializedObject.GetIterator(); var rootFolder = new [] { GetRootFolder() }; prop.NextVisible(true); while (prop.NextVisible(false)) { if (prop.propertyType == SerializedPropertyType.Generic) { var guids = AssetDatabase.FindAssets(prop.name + " t:Texture2D", rootFolder); var paths = guids.Select(guid => AssetDatabase.GUIDToAssetPath(guid)).Where( path => path.Contains(prop.name + ".") ); foreach (var path in paths) { var texture = AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D; if (path.ToLower().Contains("/pro/")) { prop.FindPropertyRelative("pro").objectReferenceValue = texture; } else { prop.FindPropertyRelative("free").objectReferenceValue = texture; } } } } instance.updateOnReloadScripts = false; // The ApplyModifiedPropertiesWithoutUndo() function wasn't documented until Unity 5.2 #if UNITY_5_0 || UNITY_5_1 var flags = BindingFlags.Instance | BindingFlags.NonPublic; var applyMethod = typeof(SerializedObject).GetMethod("ApplyModifiedPropertiesWithoutUndo", flags); applyMethod.Invoke(serializedObject, null); #else serializedObject.ApplyModifiedPropertiesWithoutUndo(); #endif } } }