Fix drawing editor thumbnails when texture used by asset is using dynamic streaming

This commit is contained in:
2026-04-19 22:37:58 +02:00
parent 8553785397
commit 635ef0ad66
12 changed files with 36 additions and 42 deletions
@@ -47,8 +47,6 @@ namespace FlaxEditor.Content
_preview = new CubeTexturePreview(false);
InitAssetPreview(_preview);
}
// TODO: disable streaming for asset during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
@@ -50,16 +50,12 @@ namespace FlaxEditor.Content
Offsets = Margin.Zero,
};
}
// TODO: disable streaming for asset during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
public override bool CanDrawThumbnail(ThumbnailRequest request)
{
// Check if asset is streamed enough
var asset = (IESProfile)request.Asset;
return asset.ResidentMipLevels >= Mathf.Max(1, (int)(asset.MipLevels * ThumbnailsModule.MinimumRequiredResourcesQuality));
return ThumbnailsModule.HasMinimumQuality((IESProfile)request.Asset);
}
/// <inheritdoc />
@@ -55,8 +55,6 @@ namespace FlaxEditor.Content
_preview = new MaterialPreview(false);
InitAssetPreview(_preview);
}
// TODO: disable streaming for dependant assets during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
@@ -99,8 +99,6 @@ namespace FlaxEditor.Content
_preview = new MaterialPreview(false);
InitAssetPreview(_preview);
}
// TODO: disable streaming for dependant assets during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
@@ -78,8 +78,6 @@ namespace FlaxEditor.Content
};
InitAssetPreview(_preview);
}
// TODO: disable streaming for asset during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
+1 -2
View File
@@ -113,8 +113,6 @@ namespace FlaxEditor.Content
_preview = new PrefabPreview(false);
InitAssetPreview(_preview);
}
// TODO: disable streaming for asset during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
@@ -125,6 +123,7 @@ namespace FlaxEditor.Content
// Check if asset is streamed enough
var asset = (Prefab)request.Asset;
// TODO: check all prefab actors to have loaded resources (models/textures/etc.)
return asset.IsLoaded;
}
@@ -101,8 +101,6 @@ namespace FlaxEditor.Content
_preview = new AnimatedModelPreview(false);
InitAssetPreview(_preview);
}
// TODO: disable streaming for asset during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
@@ -50,16 +50,12 @@ namespace FlaxEditor.Content
Offsets = Margin.Zero,
};
}
// TODO: disable streaming for asset during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
public override bool CanDrawThumbnail(ThumbnailRequest request)
{
// Check if asset is streamed enough
var asset = (SpriteAtlas)request.Asset;
return asset.ResidentMipLevels >= Mathf.Max(1, (int)(asset.MipLevels * ThumbnailsModule.MinimumRequiredResourcesQuality));
return ThumbnailsModule.HasMinimumQuality((SpriteAtlas)request.Asset);
}
/// <inheritdoc />
@@ -50,8 +50,6 @@ namespace FlaxEditor.Content
Offsets = Margin.Zero,
};
}
// TODO: disable streaming for asset during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
@@ -122,39 +122,43 @@ namespace FlaxEditor.Content.Thumbnails
internal static bool HasMinimumQuality(TextureBase asset)
{
// Don't block thumbnails queue when texture fails to stream in (eg. unsupported format)
if (asset.HasStreamingError)
return true; // Don't block thumbnails queue when texture fails to stream in (eg. unsupported format)
return true;
// Check if enough mip levels are loaded
var mipLevels = asset.MipLevels;
var minMipLevels = Mathf.Min(mipLevels, 7);
return asset.IsLoaded && asset.ResidentMipLevels >= Mathf.Max(minMipLevels, (int)(mipLevels * MinimumRequiredResourcesQuality));
if (asset.IsLoaded && asset.ResidentMipLevels >= Mathf.Max(minMipLevels, (int)(mipLevels * MinimumRequiredResourcesQuality)))
return true;
// Inform streaming about resource usage to stream it in for the thumbnail
asset.SetStreamingVisible();
return false;
}
internal static bool HasMinimumQuality(Model asset)
internal static bool HasMinimumQuality(ModelBase asset)
{
if (!asset.IsLoaded)
return false;
var lods = asset.LODs.Length;
var lods = asset.LODsCount;
var slots = asset.MaterialSlots;
foreach (var slot in slots)
{
if (slot.Material && !HasMinimumQuality(slot.Material))
return false;
}
return asset.LoadedLODs >= Mathf.Max(1, (int)(lods * MinimumRequiredResourcesQuality));
}
internal static bool HasMinimumQuality(SkinnedModel asset)
{
var lods = asset.LODs.Length;
if (asset.IsLoaded && lods == 0)
return true; // Skeleton-only model
var slots = asset.MaterialSlots;
// Check if all materials are loaded (incl. dependent resources)
foreach (var slot in slots)
{
if (slot.Material && !HasMinimumQuality(slot.Material))
return false;
}
return asset.LoadedLODs >= Mathf.Max(1, (int)(lods * MinimumRequiredResourcesQuality));
// Check if enough LODs are loaded
if (asset.LoadedLODs >= Mathf.Max(1, (int)(lods * MinimumRequiredResourcesQuality)))
return true;
// TODO: impl SetStreamingVisible for models similar to textures (ModelsStreamingHandler needs to use it)
return false;
}
internal static bool HasMinimumQuality(MaterialBase asset)
@@ -302,6 +302,12 @@ bool TextureBase::HasStreamingError() const
return _texture.Streaming.Error;
}
void TextureBase::SetStreamingVisible() const
{
if (_texture.GetTexture())
_texture.GetTexture()->LastRenderTime = Platform::GetTimeSeconds();
}
BytesContainer TextureBase::GetMipData(int32 mipIndex, int32& rowPitch, int32& slicePitch)
{
BytesContainer result;
@@ -153,6 +153,11 @@ public:
/// </summary>
API_PROPERTY() bool HasStreamingError() const;
/// <summary>
/// Sets the texture as visible this frame to inform streaming about usage which will stream boost its priority for the streaming.
/// </summary>
API_FUNCTION() void SetStreamingVisible() const;
public:
/// <summary>
/// Gets the mip data.