(Fix) Vider les materiaux surcharges au changement de mesh

Passer du corps A au corps B donnait une silhouette feminine peinte avec la
peau et les abdominaux du modele masculin.

OverrideMaterials appartient au COMPOSANT et pas au mesh : SetSkeletalMeshAsset
remplace l'asset sans y toucher, donc le MID derive de MI_BodyA_a restait colle
a l'element 0. Le symptome trompe, parce que le mesh, lui, avait bien change --
seule sa peau ne suivait pas.

SetPartMesh() vide les overrides avant d'assigner, et rend la main sans rien
faire quand le mesh est deja le bon : un changement de couleur seul continue
ainsi de reutiliser les MID en place au lieu de tout reconstruire.

Vaut pour toutes les pieces, pas seulement le corps -- changer de tete ou de
coiffure donnait le meme symptome.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-08 20:02:02 +02:00
parent 5970db0512
commit e8e128457a
2 changed files with 33 additions and 4 deletions
@@ -246,7 +246,7 @@ void UCharacterAppearanceComponent::RebuildMeshes(const FCharacterBodySet& BodyS
if (BodySet.BodyMeshes.Num() > 0 && BodySet.BodyMeshes[0]) if (BodySet.BodyMeshes.Num() > 0 && BodySet.BodyMeshes[0])
{ {
TargetMesh->SetSkeletalMeshAsset(BodySet.BodyMeshes[0]); SetPartMesh(TargetMesh, BodySet.BodyMeshes[0]);
} }
if (BodySet.AnimClass) if (BodySet.AnimClass)
@@ -267,7 +267,7 @@ void UCharacterAppearanceComponent::RebuildMeshes(const FCharacterBodySet& BodyS
if (USkeletalMeshComponent* Segment = ExtraBodyComponents[i]) if (USkeletalMeshComponent* Segment = ExtraBodyComponents[i])
{ {
Segment->SetSkeletalMeshAsset(BodySet.BodyMeshes[i + 1]); SetPartMesh(Segment, BodySet.BodyMeshes[i + 1]);
} }
} }
@@ -278,7 +278,7 @@ void UCharacterAppearanceComponent::RebuildMeshes(const FCharacterBodySet& BodyS
{ {
if (USkeletalMeshComponent* Segment = ExtraBodyComponents[i]) if (USkeletalMeshComponent* Segment = ExtraBodyComponents[i])
{ {
Segment->SetSkeletalMeshAsset(nullptr); SetPartMesh(Segment, nullptr);
} }
} }
@@ -305,7 +305,7 @@ void UCharacterAppearanceComponent::RebuildMeshes(const FCharacterBodySet& BodyS
if (USkeletalMeshComponent* PartComponent = EnsurePartComponent(Category)) if (USkeletalMeshComponent* PartComponent = EnsurePartComponent(Category))
{ {
PartComponent->SetSkeletalMeshAsset(Mesh); SetPartMesh(PartComponent, Mesh);
} }
}; };
@@ -432,6 +432,26 @@ void UCharacterAppearanceComponent::ApplyColors(const FCharacterBodySet& BodySet
} }
} }
void UCharacterAppearanceComponent::SetPartMesh(USkeletalMeshComponent* MeshComponent, USkeletalMesh* NewMesh)
{
if (!MeshComponent || MeshComponent->GetSkeletalMeshAsset() == NewMesh)
{
// Rien a faire, et surtout : on ne jette pas les MID en place pour
// rien. ApplyColors les reutilise, c'est ce qui rend le changement de
// couleur seul aussi bon marche.
return;
}
// LE point du montage a ne pas oublier : les materiaux surcharges d'un
// composant vivent dans OverrideMaterials, un tableau qui lui appartient et
// que changer de mesh ne touche PAS. Sans ce vidage, passer du corps A au
// corps B garde le MID derive de MI_BodyA_a sur l'element 0 -- on obtient
// une silhouette feminine peinte avec la peau et les abdominaux du modele
// masculin. Le symptome trompe, parce que le mesh, lui, a bien change.
MeshComponent->EmptyOverrideMaterials();
MeshComponent->SetSkeletalMeshAsset(NewMesh);
}
void UCharacterAppearanceComponent::TintAllElements(USkeletalMeshComponent* MeshComponent, FName Parameter, const FLinearColor& Color) void UCharacterAppearanceComponent::TintAllElements(USkeletalMeshComponent* MeshComponent, FName Parameter, const FLinearColor& Color)
{ {
if (!MeshComponent || Parameter.IsNone() || !MeshComponent->GetSkeletalMeshAsset()) if (!MeshComponent || Parameter.IsNone() || !MeshComponent->GetSkeletalMeshAsset())
@@ -133,6 +133,15 @@ private:
void ApplyColors(const FCharacterBodySet& BodySet); void ApplyColors(const FCharacterBodySet& BodySet);
/** Pose un parametre vectoriel sur TOUS les elements d'un mesh. */ /** Pose un parametre vectoriel sur TOUS les elements d'un mesh. */
/**
* Assigne un mesh a un composant en vidant d'abord ses materiaux surcharges.
*
* Indispensable : OverrideMaterials appartient au COMPOSANT, pas au mesh, et
* survit donc a un changement d'asset. Sans ce vidage, le corps B garderait
* la peau du corps A.
*/
static void SetPartMesh(USkeletalMeshComponent* MeshComponent, USkeletalMesh* NewMesh);
static void TintAllElements(USkeletalMeshComponent* MeshComponent, FName Parameter, const FLinearColor& Color); static void TintAllElements(USkeletalMeshComponent* MeshComponent, FName Parameter, const FLinearColor& Color);
/** Le mesh porteur, leader de tous les autres. */ /** Le mesh porteur, leader de tous les autres. */