Skip to content

Commit fbc6637

Browse files
Collect and dispose resolved model textures
1 parent 3ae8871 commit fbc6637

1 file changed

Lines changed: 35 additions & 12 deletions

File tree

Prowl.Editor/AssetsDatabase/Importers/EditorModelImporter.cs

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.IO;
34

45
using Prowl.Echo;
@@ -94,17 +95,27 @@ private static void ResolveTextures(ModelImportResult data, ImportContext ctx)
9495
string assetsRoot = Project.Current?.AssetsPath ?? "";
9596
if (string.IsNullOrEmpty(assetsRoot)) return;
9697

98+
// A disk-backed texture is loaded once by the model importer but can be referenced by
99+
// multiple material slots (the source file references it once, by index), so collect every
100+
// live texture object that gets replaced by an AssetRef here and dispose each only once,
101+
// after every slot referencing it has been resolved - disposing eagerly per-slot would free
102+
// a texture a later slot still needs to read.
103+
var resolved = new HashSet<Texture2D>();
104+
97105
foreach (var mat in data.Materials)
98106
{
99107
if (mat == null) continue;
100-
ResolveSlot(mat, "_MainTex", modelDir, assetsRoot, db, ctx);
101-
ResolveSlot(mat, "_NormalTex", modelDir, assetsRoot, db, ctx);
102-
ResolveSlot(mat, "_SurfaceTex", modelDir, assetsRoot, db, ctx);
103-
ResolveSlot(mat, "_EmissionTex", modelDir, assetsRoot, db, ctx);
108+
ResolveSlot(mat, "_MainTex", modelDir, assetsRoot, db, ctx, resolved);
109+
ResolveSlot(mat, "_NormalTex", modelDir, assetsRoot, db, ctx, resolved);
110+
ResolveSlot(mat, "_SurfaceTex", modelDir, assetsRoot, db, ctx, resolved);
111+
ResolveSlot(mat, "_EmissionTex", modelDir, assetsRoot, db, ctx, resolved);
104112
}
113+
114+
foreach (var tex in resolved)
115+
tex.Dispose();
105116
}
106117

107-
private static void ResolveSlot(Material mat, string slot, string modelDir, string assetsRoot, EditorAssetDatabase db, ImportContext ctx)
118+
private static void ResolveSlot(Material mat, string slot, string modelDir, string assetsRoot, EditorAssetDatabase db, ImportContext ctx, HashSet<Texture2D> resolved)
108119
{
109120
var tex = mat._properties.GetTexture(slot);
110121
if (tex == null || tex.IsDisposed) return;
@@ -113,16 +124,27 @@ private static void ResolveSlot(Material mat, string slot, string modelDir, stri
113124
if (string.IsNullOrEmpty(texPath)) return;
114125

115126
string? relativePath = null;
116-
if (Path.IsPathRooted(texPath))
127+
try
117128
{
118-
if (texPath.StartsWith(assetsRoot, StringComparison.OrdinalIgnoreCase))
119-
relativePath = Path.GetRelativePath(assetsRoot, texPath).Replace('\\', '/');
129+
if (Path.IsPathRooted(texPath))
130+
{
131+
if (texPath.StartsWith(assetsRoot, StringComparison.OrdinalIgnoreCase))
132+
relativePath = Path.GetRelativePath(assetsRoot, texPath).Replace('\\', '/');
133+
}
134+
else
135+
{
136+
string abs = Path.GetFullPath(Path.Combine(modelDir, texPath));
137+
if (abs.StartsWith(assetsRoot, StringComparison.OrdinalIgnoreCase))
138+
relativePath = Path.GetRelativePath(assetsRoot, abs).Replace('\\', '/');
139+
}
120140
}
121-
else
141+
catch (Exception)
122142
{
123-
string abs = Path.GetFullPath(Path.Combine(modelDir, texPath));
124-
if (abs.StartsWith(assetsRoot, StringComparison.OrdinalIgnoreCase))
125-
relativePath = Path.GetRelativePath(assetsRoot, abs).Replace('\\', '/');
143+
// tex.AssetPath isn't a real filesystem path - e.g. a shared built-in/default texture
144+
// (Texture2D.LoadDefault fallback for an unset material slot) carries a synthetic
145+
// "$Default:Texture/Normal"-style identifier, and the embedded ':' makes Path.GetFullPath
146+
// throw NotSupportedException on Windows. Nothing to resolve; leave the live texture as-is.
147+
return;
126148
}
127149

128150
if (relativePath == null) return;
@@ -135,6 +157,7 @@ private static void ResolveSlot(Material mat, string slot, string modelDir, stri
135157
// At runtime, AssetRef lazy-loads via AssetDatabase.Get().
136158
mat.SetTexture(slot, new AssetRef<Texture2D>(entry.Guid));
137159
ctx.AddDependency(entry.Guid);
160+
resolved.Add(tex);
138161
}
139162

140163
public override EchoObject? DefaultSettings()

0 commit comments

Comments
 (0)