|
|
|
@ -3,65 +3,132 @@
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
{ |
|
|
|
|
internal static partial class FungusEditorResources |
|
|
|
|
[CustomEditor(typeof(FungusEditorResources))] |
|
|
|
|
internal class FungusEditorResourcesInspector : Editor |
|
|
|
|
{ |
|
|
|
|
private static Dictionary<string, Texture2D> textures = new Dictionary<string, Texture2D>(); |
|
|
|
|
private static readonly string editorResourcesFolderName = "\"EditorResources\""; |
|
|
|
|
|
|
|
|
|
static FungusEditorResources() |
|
|
|
|
public override void OnInspectorGUI() |
|
|
|
|
{ |
|
|
|
|
LoadTexturesFromNames(); |
|
|
|
|
if (serializedObject.FindProperty("updateOnReloadScripts").boolValue) |
|
|
|
|
{ |
|
|
|
|
GUILayout.Label("Updating..."); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
if (GUILayout.Button("Sync with EditorResources folder")) |
|
|
|
|
{ |
|
|
|
|
FungusEditorResources.GenerateResourcesScript(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
DrawDefaultInspector(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static void LoadTexturesFromNames() |
|
|
|
|
// Handle reimporting all assets |
|
|
|
|
internal class EditorResourcesPostProcessor : AssetPostprocessor |
|
|
|
|
{ |
|
|
|
|
private static void OnPostprocessAllAssets(string[] importedAssets, string[] _, string[] __, string[] ___) |
|
|
|
|
{ |
|
|
|
|
var baseDirectories = AssetDatabase.FindAssets(editorResourcesFolderName).Select( |
|
|
|
|
guid => AssetDatabase.GUIDToAssetPath(guid) |
|
|
|
|
).ToArray(); |
|
|
|
|
|
|
|
|
|
foreach (var name in resourceNames) |
|
|
|
|
foreach (var path in importedAssets) |
|
|
|
|
{ |
|
|
|
|
LoadTexturesFromGUIDs(AssetDatabase.FindAssets(name + " t:Texture2D", baseDirectories)); |
|
|
|
|
if (path.EndsWith("FungusEditorResources.asset")) |
|
|
|
|
{ |
|
|
|
|
var asset = AssetDatabase.LoadAssetAtPath(path, typeof(FungusEditorResources)) as FungusEditorResources; |
|
|
|
|
if (asset != null) |
|
|
|
|
{ |
|
|
|
|
FungusEditorResources.UpdateTextureReferences(asset); |
|
|
|
|
AssetDatabase.SaveAssets(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static void LoadAllTexturesInFolder() |
|
|
|
|
internal partial class FungusEditorResources : ScriptableObject |
|
|
|
|
{ |
|
|
|
|
[Serializable] |
|
|
|
|
internal class EditorTexture |
|
|
|
|
{ |
|
|
|
|
var rootGuid = AssetDatabase.FindAssets(editorResourcesFolderName)[0]; |
|
|
|
|
var root = AssetDatabase.GUIDToAssetPath(rootGuid); |
|
|
|
|
LoadTexturesFromGUIDs(AssetDatabase.FindAssets("t:Texture2D", new [] { root })); |
|
|
|
|
[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 void LoadTexturesFromGUIDs(string[] guids) |
|
|
|
|
{ |
|
|
|
|
var paths = guids.Select(guid => AssetDatabase.GUIDToAssetPath(guid)).OrderBy(path => path.ToLower().Contains("/pro/")); |
|
|
|
|
private static FungusEditorResources instance; |
|
|
|
|
private static readonly string editorResourcesFolderName = "\"EditorResources\""; |
|
|
|
|
[SerializeField] [HideInInspector] private bool updateOnReloadScripts = false; |
|
|
|
|
|
|
|
|
|
foreach (var path in paths) |
|
|
|
|
internal static FungusEditorResources Instance |
|
|
|
|
{ |
|
|
|
|
get |
|
|
|
|
{ |
|
|
|
|
if (path.ToLower().Contains("/pro/") && !EditorGUIUtility.isProSkin) |
|
|
|
|
if (instance == null) |
|
|
|
|
{ |
|
|
|
|
return; |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
var texture = AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D; |
|
|
|
|
textures[texture.name] = texture; |
|
|
|
|
|
|
|
|
|
return instance; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[MenuItem("Tools/Fungus/Utilities/Update Editor Resources Script")] |
|
|
|
|
private static void GenerateResourcesScript() |
|
|
|
|
private static string GetRootFolder() |
|
|
|
|
{ |
|
|
|
|
var rootGuid = AssetDatabase.FindAssets(editorResourcesFolderName)[0]; |
|
|
|
|
return AssetDatabase.GUIDToAssetPath(rootGuid); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
internal static void GenerateResourcesScript() |
|
|
|
|
{ |
|
|
|
|
textures.Clear(); |
|
|
|
|
LoadAllTexturesInFolder(); |
|
|
|
|
// Get all unique filenames |
|
|
|
|
var textureNames = new HashSet<string>(); |
|
|
|
|
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 guid = AssetDatabase.FindAssets("FungusEditorResources t:MonoScript")[0]; |
|
|
|
|
var relativePath = AssetDatabase.GUIDToAssetPath(guid).Replace("FungusEditorResources.cs", "FungusEditorResourcesGenerated.cs"); |
|
|
|
|
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)) |
|
|
|
@ -73,43 +140,83 @@ namespace Fungus.EditorUtils
|
|
|
|
|
writer.WriteLine(""); |
|
|
|
|
writer.WriteLine("namespace Fungus.EditorUtils"); |
|
|
|
|
writer.WriteLine("{"); |
|
|
|
|
writer.WriteLine(" internal static partial class FungusEditorResources"); |
|
|
|
|
writer.WriteLine(" internal partial class FungusEditorResources : ScriptableObject"); |
|
|
|
|
writer.WriteLine(" {"); |
|
|
|
|
writer.WriteLine(" private static readonly string[] resourceNames = new [] {"); |
|
|
|
|
|
|
|
|
|
foreach (var pair in textures) |
|
|
|
|
foreach (var name in textureNames) |
|
|
|
|
{ |
|
|
|
|
writer.WriteLine(" \"" + pair.Key + "\","); |
|
|
|
|
writer.WriteLine(" [SerializeField] private EditorTexture " + name + ";"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
writer.WriteLine(" };"); |
|
|
|
|
writer.WriteLine(""); |
|
|
|
|
|
|
|
|
|
foreach (var pair in textures) |
|
|
|
|
foreach (var name in textureNames) |
|
|
|
|
{ |
|
|
|
|
var name = pair.Key; |
|
|
|
|
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 GetTexture(\"" + name + "\"); } }"); |
|
|
|
|
writer.WriteLine(" public static Texture2D " + pascalCase + " { get { return Instance." + name + ".Texture2D; } }"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
writer.WriteLine(" }"); |
|
|
|
|
writer.WriteLine("}"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Instance.updateOnReloadScripts = true; |
|
|
|
|
AssetDatabase.ImportAsset(relativePath); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static Texture2D GetTexture(string name) |
|
|
|
|
[DidReloadScripts] |
|
|
|
|
private static void OnDidReloadScripts() |
|
|
|
|
{ |
|
|
|
|
Texture2D texture; |
|
|
|
|
if (!textures.TryGetValue(name, out texture)) |
|
|
|
|
if (Instance.updateOnReloadScripts) |
|
|
|
|
{ |
|
|
|
|
Debug.LogWarning("Texture \"" + name + "\" not found!"); |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
serializedObject.FindProperty("updateOnReloadScripts").boolValue = false; |
|
|
|
|
|
|
|
|
|
return texture; |
|
|
|
|
// 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 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|