diff --git a/Source/Engine/Level/Actors/AnimatedModel.cpp b/Source/Engine/Level/Actors/AnimatedModel.cpp index dae5f281f..373278885 100644 --- a/Source/Engine/Level/Actors/AnimatedModel.cpp +++ b/Source/Engine/Level/Actors/AnimatedModel.cpp @@ -898,6 +898,23 @@ void AnimatedModel::Deserialize(DeserializeStream& stream, ISerializeModifier* m DrawModes |= DrawPass::GlobalSurfaceAtlas; } +MaterialBase* AnimatedModel::GetMaterial(int32 entryIndex) +{ + if (SkinnedModel) + SkinnedModel->WaitForLoaded(); + else + return nullptr; + CHECK_RETURN(entryIndex >= 0 && entryIndex < Entries.Count(), nullptr); + MaterialBase* material = Entries[entryIndex].Material.Get(); + if (!material) + { + material = SkinnedModel->MaterialSlots[entryIndex].Material.Get(); + if (!material) + material = GPUDevice::Instance->GetDefaultMaterial(); + } + return material; +} + 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 33f206580..2693f573d 100644 --- a/Source/Engine/Level/Actors/AnimatedModel.h +++ b/Source/Engine/Level/Actors/AnimatedModel.h @@ -373,6 +373,7 @@ public: bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override; void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; + MaterialBase* GetMaterial(int32 entryIndex) 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; void OnDeleteObject() override; diff --git a/Source/Engine/Level/Actors/ModelInstanceActor.cpp b/Source/Engine/Level/Actors/ModelInstanceActor.cpp index 0c1879d83..03b873864 100644 --- a/Source/Engine/Level/Actors/ModelInstanceActor.cpp +++ b/Source/Engine/Level/Actors/ModelInstanceActor.cpp @@ -39,10 +39,9 @@ void ModelInstanceActor::SetMaterial(int32 entryIndex, MaterialBase* material) MaterialInstance* ModelInstanceActor::CreateAndSetVirtualMaterialInstance(int32 entryIndex) { WaitForModelLoad(); - CHECK_RETURN(entryIndex >= 0 && entryIndex < Entries.Count(), nullptr); - auto material = Entries[entryIndex].Material.Get(); + MaterialBase* material = GetMaterial(entryIndex); CHECK_RETURN(material && !material->WaitForLoaded(), nullptr); - const auto result = material->CreateVirtualInstance(); + MaterialInstance* result = material->CreateVirtualInstance(); Entries[entryIndex].Material = result; if (_sceneRenderingKey != -1) GetSceneRendering()->UpdateActor(this, _sceneRenderingKey); diff --git a/Source/Engine/Level/Actors/ModelInstanceActor.h b/Source/Engine/Level/Actors/ModelInstanceActor.h index 825b64c23..1dfd5c0e0 100644 --- a/Source/Engine/Level/Actors/ModelInstanceActor.h +++ b/Source/Engine/Level/Actors/ModelInstanceActor.h @@ -35,6 +35,12 @@ public: /// API_PROPERTY() void SetEntries(const Array& value); + /// + /// Gets the material used to draw the meshes which are assigned to that slot (set in Entries or model's default). + /// + /// The material slot entry index. + API_FUNCTION(Sealed) virtual MaterialBase* GetMaterial(int32 entryIndex) = 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 08dc5ddea..843bf6076 100644 --- a/Source/Engine/Level/Actors/SplineModel.cpp +++ b/Source/Engine/Level/Actors/SplineModel.cpp @@ -341,6 +341,23 @@ void SplineModel::OnParentChanged() OnSplineUpdated(); } +MaterialBase* SplineModel::GetMaterial(int32 entryIndex) +{ + if (Model) + Model->WaitForLoaded(); + else + return nullptr; + CHECK_RETURN(entryIndex >= 0 && entryIndex < Entries.Count(), nullptr); + MaterialBase* material = Entries[entryIndex].Material.Get(); + if (!material) + { + material = Model->MaterialSlots[entryIndex].Material.Get(); + if (!material) + material = GPUDevice::Instance->GetDefaultDeformableMaterial(); + } + return material; +} + bool SplineModel::HasContentLoaded() const { return (Model == nullptr || Model->IsLoaded()) && Entries.HasContentLoaded(); diff --git a/Source/Engine/Level/Actors/SplineModel.h b/Source/Engine/Level/Actors/SplineModel.h index 50864d7b7..87f39699c 100644 --- a/Source/Engine/Level/Actors/SplineModel.h +++ b/Source/Engine/Level/Actors/SplineModel.h @@ -115,6 +115,7 @@ public: void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void OnParentChanged() override; + MaterialBase* GetMaterial(int32 entryIndex) override; protected: // [ModelInstanceActor] diff --git a/Source/Engine/Level/Actors/StaticModel.cpp b/Source/Engine/Level/Actors/StaticModel.cpp index 3eb3b6012..778f24d65 100644 --- a/Source/Engine/Level/Actors/StaticModel.cpp +++ b/Source/Engine/Level/Actors/StaticModel.cpp @@ -535,6 +535,23 @@ void StaticModel::Deserialize(DeserializeStream& stream, ISerializeModifier* mod } } +MaterialBase* StaticModel::GetMaterial(int32 entryIndex) +{ + if (Model) + Model->WaitForLoaded(); + else + return nullptr; + CHECK_RETURN(entryIndex >= 0 && entryIndex < Entries.Count(), nullptr); + MaterialBase* material = Entries[entryIndex].Material.Get(); + if (!material) + { + material = Model->MaterialSlots[entryIndex].Material.Get(); + if (!material) + material = GPUDevice::Instance->GetDefaultMaterial(); + } + return material; +} + 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 af3aa53c0..06fbdd874 100644 --- a/Source/Engine/Level/Actors/StaticModel.h +++ b/Source/Engine/Level/Actors/StaticModel.h @@ -121,7 +121,7 @@ public: /// The zero-based mesh index. /// The LOD index. /// Material or null if not assigned. - API_FUNCTION() MaterialBase* GetMaterial(int32 meshIndex, int32 lodIndex = 0) const; + API_FUNCTION() MaterialBase* GetMaterial(int32 meshIndex, int32 lodIndex) const; /// /// Gets the color of the painter vertex (this model instance). @@ -166,6 +166,7 @@ public: bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override; void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; + MaterialBase* GetMaterial(int32 entryIndex) 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;