using System.IO; using System.Linq; using System.Collections.Generic; using UnityEditor; namespace UnityAtoms.Editor { /// /// Postprocessor that processes all scripts using the EditorIcon attribute and assigns the matching icon guid (matching the icon query name) to the script's meta. It's a very simple solution (and very hacky), but works really great. /// public class EditorIconPostProcessor : AssetPostprocessor { /// /// Called when new assets are imported, deleted or moved. /// /// Imported assets. /// Deleted assets. /// Moved assets. /// Moved from asset paths. static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) { var metaChangedForAssets = new List(); foreach (string assetPath in importedAssets) { // NOTE: Below is not working since it's not compiled at this point // We therefore need to do some string manipulations... // var script = AssetDatabase.LoadAssetAtPath(assetPath); // var type = script?.GetClass(); var metaPath = $"{assetPath}.meta"; if (File.Exists(assetPath) && File.Exists(metaPath) && assetPath.EndsWith(".cs")) { // Hack, hack, hack away.... var scriptText = File.ReadAllText(assetPath); var containsEditorIconAttr = scriptText.Contains("[EditorIcon("); if (containsEditorIconAttr) { // Extract icon name from attribute // We are assuming that template strings are not used var attrIconNameStartIndex = scriptText.IndexOf("[EditorIcon(") + 13; var attrIconNameLength = scriptText.IndexOf("\")", attrIconNameStartIndex) - attrIconNameStartIndex; var iconName = scriptText.Substring(attrIconNameStartIndex, attrIconNameLength); // Find guid based on icon name from attr var iconGuids = AssetDatabase.FindAssets($"{iconName} t:texture2D"); var iconGuidsList = iconGuids.ToList(); var guid = iconGuidsList.FirstOrDefault(); if (!string.IsNullOrEmpty(guid)) { // Read meta for script var scriptMetaTextLines = File.ReadAllLines(metaPath); var metaIconLine = $"icon: {{fileID: 2800000, guid: {guid}, type: 3}}"; for (var i = 0; i < scriptMetaTextLines.Length; ++i) { var line = scriptMetaTextLines[i]; // Find icon line if (line.Contains("icon: ") && !line.Contains(metaIconLine)) { var indexIconKeyName = line.IndexOf("icon: "); var indexAfterClosingBrace = line.IndexOf("}", indexIconKeyName) + 1; var newLine = line.Replace(line.Substring(indexIconKeyName, indexAfterClosingBrace - indexIconKeyName), metaIconLine); scriptMetaTextLines[i] = newLine; File.WriteAllLines(metaPath, scriptMetaTextLines); metaChangedForAssets.Add(assetPath); break; } } } } } } // We need to reimport all assets where the meta was changed if (metaChangedForAssets.Count > 0) { foreach (var assetPath in metaChangedForAssets) { AssetDatabase.ImportAsset(assetPath); } } } } }