Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

Commit e9181df

Browse files
committed
A serializable Texture2D wrapper to fix icon loading
Fixes #18 Texture2D objects get thrown away by Unity even though they're serialized, because Unity wants to be very conservative about the things it keeps in memory, and games can load large amounts of textures during play mode which Unity clears up. This means that it also throws away all the textures we load, so we lose all the icons. This adds a class that decomposes Texture2D into separate fields that Unity won't throw away, so we can recreate textures on demand whenever we detect that it has thrown the texture away.
1 parent c477ef6 commit e9181df

File tree

2 files changed

+76
-20
lines changed

2 files changed

+76
-20
lines changed

src/UnityExtension/Assets/Editor/GitHub.Unity/Misc/Utility.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,40 @@
77

88
namespace GitHub.Unity
99
{
10+
[Serializable]
11+
public class SerializableTexture2D
12+
{
13+
[SerializeField] private byte[] bytes;
14+
[SerializeField] private int height;
15+
[SerializeField] private int width;
16+
[SerializeField] private TextureFormat format;
17+
[SerializeField] private bool mipmap;
18+
[SerializeField] private Texture2D texture;
19+
20+
public Texture2D Texture
21+
{
22+
get
23+
{
24+
if (texture == null)
25+
{
26+
texture = new Texture2D(width, height, format, mipmap);
27+
texture.LoadRawTextureData(bytes);
28+
texture.Apply();
29+
}
30+
return texture;
31+
}
32+
set
33+
{
34+
texture = value;
35+
bytes = value.GetRawTextureData();
36+
height = value.height;
37+
width = value.width;
38+
format = value.format;
39+
mipmap = value.mipmapCount > 1;
40+
}
41+
}
42+
}
43+
1044
class Utility : ScriptableObject
1145
{
1246
public static Texture2D GetIcon(string filename, string filename2x = "")

src/UnityExtension/Assets/Editor/GitHub.Unity/UI/TreeControl.cs

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,33 @@ namespace GitHub.Unity
1111
[Serializable]
1212
public class Tree
1313
{
14-
[SerializeField] private List<TreeNode> nodes = new List<TreeNode>();
15-
[SerializeField] private TreeNode selectedNode = null;
16-
[SerializeField] private TreeNode activeNode = null;
1714
[SerializeField] public float ItemHeight = EditorGUIUtility.singleLineHeight;
1815
[SerializeField] public float ItemSpacing = EditorGUIUtility.standardVerticalSpacing;
1916
[SerializeField] public float Indentation = 12f;
2017
[SerializeField] public Rect Margin = new Rect();
2118
[SerializeField] public Rect Padding = new Rect();
22-
[SerializeField] private List<string> foldersKeys = new List<string>();
23-
[SerializeField] public Texture2D ActiveNodeIcon;
24-
[SerializeField] public Texture2D NodeIcon;
25-
[SerializeField] public Texture2D FolderIcon;
26-
[SerializeField] public Texture2D RootFolderIcon;
19+
20+
[SerializeField] private SerializableTexture2D activeNodeIcon = new SerializableTexture2D();
21+
public Texture2D ActiveNodeIcon { get { return activeNodeIcon.Texture; } set { activeNodeIcon.Texture = value; } }
22+
23+
[SerializeField] private SerializableTexture2D nodeIcon = new SerializableTexture2D();
24+
public Texture2D NodeIcon { get { return nodeIcon.Texture; } set { nodeIcon.Texture = value; } }
25+
26+
[SerializeField] private SerializableTexture2D folderIcon = new SerializableTexture2D();
27+
public Texture2D FolderIcon { get { return folderIcon.Texture; } set { folderIcon.Texture = value; } }
28+
29+
[SerializeField] private SerializableTexture2D rootFolderIcon = new SerializableTexture2D();
30+
public Texture2D RootFolderIcon { get { return rootFolderIcon.Texture; } set { rootFolderIcon.Texture = value; } }
31+
2732
[SerializeField] public GUIStyle FolderStyle;
2833
[SerializeField] public GUIStyle TreeNodeStyle;
2934
[SerializeField] public GUIStyle ActiveTreeNodeStyle;
3035

36+
[SerializeField] private List<TreeNode> nodes = new List<TreeNode>();
37+
[SerializeField] private TreeNode selectedNode = null;
38+
[SerializeField] private TreeNode activeNode = null;
39+
[SerializeField] private List<string> foldersKeys = new List<string>();
40+
3141
[NonSerialized] private Stack<bool> indents = new Stack<bool>();
3242
[NonSerialized] private Hashtable folders;
3343

@@ -105,20 +115,10 @@ public void Load(IEnumerable<ITreeData> data, string title)
105115
if (node.IsActive)
106116
{
107117
activeNode = node;
108-
node.Icon = ActiveNodeIcon;
109-
}
110-
else if (node.IsFolder)
111-
{
112-
if (node.Level == 1)
113-
node.Icon = RootFolderIcon;
114-
else
115-
node.Icon = FolderIcon;
116-
}
117-
else
118-
{
119-
node.Icon = NodeIcon;
120118
}
121119

120+
ResetNodeIcons(node);
121+
122122
node.Load();
123123

124124
nodes.Add(node);
@@ -142,6 +142,7 @@ public Rect Render(Rect rect, Vector2 scroll, Action<TreeNode> singleClick = nul
142142
rect = new Rect(0f, rect.y, rect.width, ItemHeight);
143143

144144
var titleNode = nodes[0];
145+
ResetNodeIcons(titleNode);
145146
bool selectionChanged = titleNode.Render(rect, 0f, selectedNode == titleNode, FolderStyle, TreeNodeStyle, ActiveTreeNodeStyle);
146147

147148
if (selectionChanged)
@@ -159,6 +160,7 @@ public Rect Render(Rect rect, Vector2 scroll, Action<TreeNode> singleClick = nul
159160
for (; i < nodes.Count; i++)
160161
{
161162
var node = nodes[i];
163+
ResetNodeIcons(node);
162164

163165
if (node.Level > level && !node.IsHidden)
164166
{
@@ -374,6 +376,26 @@ private void Unindent()
374376
{
375377
indents.Pop();
376378
}
379+
380+
private void ResetNodeIcons(TreeNode node)
381+
{
382+
if (node.IsActive)
383+
{
384+
node.Icon = ActiveNodeIcon;
385+
}
386+
else if (node.IsFolder)
387+
{
388+
if (node.Level == 1)
389+
node.Icon = RootFolderIcon;
390+
else
391+
node.Icon = FolderIcon;
392+
}
393+
else
394+
{
395+
node.Icon = NodeIcon;
396+
}
397+
node.Load();
398+
}
377399
}
378400

379401
[Serializable]

0 commit comments

Comments
 (0)