diff --git a/Source/Editor/Content/Proxy/PrefabProxy.cs b/Source/Editor/Content/Proxy/PrefabProxy.cs
index c01fc9ebf..0fb247605 100644
--- a/Source/Editor/Content/Proxy/PrefabProxy.cs
+++ b/Source/Editor/Content/Proxy/PrefabProxy.cs
@@ -122,9 +122,7 @@ namespace FlaxEditor.Content
return false;
// 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;
+ return ThumbnailsModule.HasMinimumQuality((Prefab)request.Asset);
}
private void Prepare(Actor actor, ref BoundingBox bounds)
diff --git a/Source/Editor/Content/Thumbnails/ThumbnailsModule.cs b/Source/Editor/Content/Thumbnails/ThumbnailsModule.cs
index 75ab79c4d..dbc970b05 100644
--- a/Source/Editor/Content/Thumbnails/ThumbnailsModule.cs
+++ b/Source/Editor/Content/Thumbnails/ThumbnailsModule.cs
@@ -181,6 +181,14 @@ namespace FlaxEditor.Content.Thumbnails
return baseMaterial == null || HasMinimumQualityInternal(baseMaterial);
}
+ internal static bool HasMinimumQuality(Prefab asset)
+ {
+ if (!asset.IsLoaded)
+ return false;
+ var defaultInstance = asset.GetDefaultInstance();
+ return defaultInstance == null || HasMinimumQualityInternal(defaultInstance);
+ }
+
private static bool HasMinimumQualityInternal(MaterialBase asset)
{
if (!asset.IsLoaded)
@@ -194,6 +202,43 @@ namespace FlaxEditor.Content.Thumbnails
return true;
}
+ private static bool HasMinimumQualityInternal(Actor actor)
+ {
+ if (!actor.IsActive)
+ return true;
+
+ if (actor is ModelInstanceActor modelInstance)
+ {
+ var model = modelInstance.GetModel();
+ if (model && !HasMinimumQuality(model))
+ return false;
+ var slots = modelInstance.MaterialSlots;
+ foreach (var slot in slots)
+ {
+ if (slot.Material && !HasMinimumQuality(slot.Material))
+ return false;
+ }
+ }
+ if (actor is SpriteRender spriteRender)
+ {
+ if (spriteRender.Material && !HasMinimumQuality(spriteRender.Material))
+ return false;
+ }
+ if (actor is TextRender textRender)
+ {
+ if (textRender.Material && !HasMinimumQuality(textRender.Material))
+ return false;
+ }
+
+ for (int i = 0; i < actor.ChildrenCount; i++)
+ {
+ if (!HasMinimumQualityInternal(actor.GetChild(i)))
+ return false;
+ }
+
+ return true;
+ }
+
#region IContentItemOwner
///
diff --git a/Source/Engine/Level/Actors/AnimatedModel.cpp b/Source/Engine/Level/Actors/AnimatedModel.cpp
index 1f441b6b0..ce106dc83 100644
--- a/Source/Engine/Level/Actors/AnimatedModel.cpp
+++ b/Source/Engine/Level/Actors/AnimatedModel.cpp
@@ -1332,6 +1332,11 @@ MaterialBase* AnimatedModel::GetMaterial(int32 entryIndex)
return material;
}
+ModelBase* AnimatedModel::GetModel()
+{
+ return SkinnedModel.Get();
+}
+
bool AnimatedModel::IntersectsEntry(int32 entryIndex, const Ray& ray, Real& distance, Vector3& normal)
{
auto model = SkinnedModel.Get();
diff --git a/Source/Engine/Level/Actors/AnimatedModel.h b/Source/Engine/Level/Actors/AnimatedModel.h
index f9182d115..5e549e4a8 100644
--- a/Source/Engine/Level/Actors/AnimatedModel.h
+++ b/Source/Engine/Level/Actors/AnimatedModel.h
@@ -476,6 +476,7 @@ public:
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
const Span GetMaterialSlots() const override;
MaterialBase* GetMaterial(int32 entryIndex) override;
+ ModelBase* GetModel() override;
bool IntersectsEntry(int32 entryIndex, const Ray& ray, Real& distance, Vector3& normal) override;
bool IntersectsEntry(const Ray& ray, Real& distance, Vector3& normal, int32& entryIndex) override;
bool GetMeshData(const MeshReference& ref, MeshBufferType type, BytesContainer& result, int32& count, GPUVertexLayout** layout) const override;
diff --git a/Source/Engine/Level/Actors/ModelInstanceActor.h b/Source/Engine/Level/Actors/ModelInstanceActor.h
index d553d132a..05b6c7f91 100644
--- a/Source/Engine/Level/Actors/ModelInstanceActor.h
+++ b/Source/Engine/Level/Actors/ModelInstanceActor.h
@@ -66,6 +66,11 @@ public:
/// The material slot entry index.
API_FUNCTION(Sealed) virtual MaterialBase* GetMaterial(int32 entryIndex) = 0;
+ ///
+ /// Gets the model (base class).
+ ///
+ API_FUNCTION(Sealed) virtual ModelBase* GetModel() = 0;
+
///
/// Sets the material to the entry slot. Can be used to override the material of the meshes using this slot.
///
diff --git a/Source/Engine/Level/Actors/SplineModel.cpp b/Source/Engine/Level/Actors/SplineModel.cpp
index 42b2dc620..0da4a3d70 100644
--- a/Source/Engine/Level/Actors/SplineModel.cpp
+++ b/Source/Engine/Level/Actors/SplineModel.cpp
@@ -367,6 +367,11 @@ MaterialBase* SplineModel::GetMaterial(int32 entryIndex)
return material;
}
+ModelBase* SplineModel::GetModel()
+{
+ return Model.Get();
+}
+
void SplineModel::UpdateBounds()
{
OnSplineUpdated();
diff --git a/Source/Engine/Level/Actors/SplineModel.h b/Source/Engine/Level/Actors/SplineModel.h
index a63d4f721..a9b105a8e 100644
--- a/Source/Engine/Level/Actors/SplineModel.h
+++ b/Source/Engine/Level/Actors/SplineModel.h
@@ -117,6 +117,7 @@ public:
void OnParentChanged() override;
const Span GetMaterialSlots() const override;
MaterialBase* GetMaterial(int32 entryIndex) override;
+ ModelBase* GetModel() override;
void UpdateBounds() override;
protected:
diff --git a/Source/Engine/Level/Actors/StaticModel.cpp b/Source/Engine/Level/Actors/StaticModel.cpp
index fad068bf0..1fba1ba2e 100644
--- a/Source/Engine/Level/Actors/StaticModel.cpp
+++ b/Source/Engine/Level/Actors/StaticModel.cpp
@@ -599,6 +599,11 @@ MaterialBase* StaticModel::GetMaterial(int32 entryIndex)
return material;
}
+ModelBase* StaticModel::GetModel()
+{
+ return Model.Get();
+}
+
bool StaticModel::IntersectsEntry(int32 entryIndex, const Ray& ray, Real& distance, Vector3& normal)
{
auto model = Model.Get();
diff --git a/Source/Engine/Level/Actors/StaticModel.h b/Source/Engine/Level/Actors/StaticModel.h
index 063638e14..3a8c391f6 100644
--- a/Source/Engine/Level/Actors/StaticModel.h
+++ b/Source/Engine/Level/Actors/StaticModel.h
@@ -178,6 +178,7 @@ public:
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
const Span GetMaterialSlots() const override;
MaterialBase* GetMaterial(int32 entryIndex) override;
+ ModelBase* GetModel() override;
bool IntersectsEntry(int32 entryIndex, const Ray& ray, Real& distance, Vector3& normal) override;
bool IntersectsEntry(const Ray& ray, Real& distance, Vector3& normal, int32& entryIndex) override;
bool GetMeshData(const MeshReference& ref, MeshBufferType type, BytesContainer& result, int32& count, GPUVertexLayout** layout) const override;