Skip to content

Commit 8dde5cb

Browse files
committed
fix: Fixed custom icons not being set for generated classes in Unity 2021
AssetPreview.GetMiniThumbnail stopped providing persistent textures, so it can't be used to get a custom texture anymore. .meta file parsing is used instead now.
1 parent fc85fdf commit 8dde5cb

File tree

3 files changed

+86
-23
lines changed

3 files changed

+86
-23
lines changed

Editor/Util/IconFinder.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
namespace GenericUnityObjects.Editor.Util
2+
{
3+
using System;
4+
using System.IO;
5+
using NUnit.Framework;
6+
using UnityEditor;
7+
using UnityEngine;
8+
9+
internal static class IconFinder
10+
{
11+
public static bool TryGetCustomIcon(string genericTypeGUID, out Texture2D customIcon, bool isScriptableObject)
12+
{
13+
customIcon = null;
14+
15+
string assetPath = AssetDatabase.GUIDToAssetPath(genericTypeGUID);
16+
17+
if (string.IsNullOrEmpty(assetPath))
18+
return false;
19+
20+
if (TryGetCustomIcon(assetPath, out customIcon))
21+
return true;
22+
23+
// If generated type inherits from MonoBehaviour, a default script icon must be set, but for scriptable
24+
// objects, it is not the case.
25+
return ! isScriptableObject && TryGetDefaultIconFromMonoBehaviourScript(assetPath, out customIcon);
26+
}
27+
28+
private static bool TryGetDefaultIconFromMonoBehaviourScript(string assetPath, out Texture2D customIcon)
29+
{
30+
var monoScript = AssetDatabase.LoadAssetAtPath<MonoScript>(assetPath);
31+
32+
if (monoScript is null)
33+
{
34+
customIcon = null;
35+
return false;
36+
}
37+
38+
customIcon = AssetPreview.GetMiniThumbnail(monoScript);
39+
return true;
40+
}
41+
42+
private static bool TryGetCustomIcon(string assetPath, out Texture2D customIcon)
43+
{
44+
// Unity doesn't expose any method to get icon guid or Texture2D from MonoScript, so we have to parse the .meta file manually.
45+
// AssetPreview.GetMiniThumbnail returns the icon, but in 2021 it has the DontSave flag and can't be used to set as a custom icon for an asset.
46+
47+
string iconLine = GetIconLine(assetPath);
48+
49+
if (iconLine == null)
50+
{
51+
customIcon = null;
52+
return false;
53+
}
54+
55+
string guid = GetGUIDFromIconLine(iconLine);
56+
string texturePath = AssetDatabase.GUIDToAssetPath(guid);
57+
customIcon = AssetDatabase.LoadAssetAtPath<Texture2D>(texturePath);
58+
Assert.IsNotNull(customIcon);
59+
return true;
60+
}
61+
62+
private static string GetGUIDFromIconLine(string iconLine)
63+
{
64+
int guidIndex = iconLine.IndexOf("guid: ", StringComparison.Ordinal);
65+
return iconLine.Substring(guidIndex + 6, 32);
66+
}
67+
68+
private static string GetIconLine(string assetPath)
69+
{
70+
string[] metaContentLines = File.ReadAllLines($"{assetPath}.meta");
71+
72+
foreach (string line in metaContentLines)
73+
{
74+
if (line.StartsWith(" icon: "))
75+
return line;
76+
}
77+
78+
return null;
79+
}
80+
}
81+
}

Editor/Util/IconFinder.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Editor/Util/IconSetter.cs

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,34 +25,13 @@ public static void AddAssemblyForIconChange(string genericScriptGUID, string ass
2525
if (string.IsNullOrEmpty(genericScriptGUID))
2626
return;
2727

28-
if (TryGetCustomIcon(genericScriptGUID, out Texture2D texture, isScriptableObject))
28+
if (IconFinder.TryGetCustomIcon(genericScriptGUID, out Texture2D texture, isScriptableObject))
2929
Instance.AddAssembly(assemblyGUID, texture);
3030
}
3131

32-
private static bool TryGetCustomIcon(string genericTypeGUID, out Texture2D customIcon, bool isScriptableObject)
33-
{
34-
customIcon = null;
35-
36-
string assetPath = AssetDatabase.GUIDToAssetPath(genericTypeGUID);
37-
38-
if (string.IsNullOrEmpty(assetPath))
39-
return false;
40-
41-
var monoScript = AssetDatabase.LoadAssetAtPath<MonoScript>(assetPath);
42-
43-
if (monoScript is null)
44-
return false;
45-
46-
customIcon = AssetPreview.GetMiniThumbnail(monoScript);
47-
48-
// If generated type inherits from MonoBehaviour, a default script icon must be set, but for scriptable
49-
// objects, it is not the case.
50-
return ! (isScriptableObject && customIcon.name.Contains("cs Script Icon"));
51-
}
52-
5332
private void AddAssembly(string guid, Texture2D texture)
5433
{
55-
if ( ! _dict.TryGetValue(texture, out List<string> guids))
34+
if ( ! _dict.TryGetValue(texture, out var guids))
5635
{
5736
guids = new List<string>();
5837
_dict.Add(texture, guids);

0 commit comments

Comments
 (0)