Files
UnrealEngine/Engine/Plugins/Mutable/Source/CustomizableObject/Private/MuCO/CustomizableSkeletalMeshActor.cpp
2025-05-18 13:04:45 +08:00

216 lines
6.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MuCO/CustomizableSkeletalMeshActor.h"
#include "MuCO/CustomizableSkeletalMeshActorPrivate.h"
#include "Components/SkeletalMeshComponent.h"
#include "MuCO/CustomizableSkeletalComponent.h"
#include "MuCO/CustomizableObject.h"
#include "MuCO/CustomizableObjectPrivate.h"
#include "MuCO/CustomizableObjectSystem.h"
#include "MuCO/CustomizableSkeletalComponentPrivate.h"
#include "Engine/SkeletalMesh.h"
#include "MuCO/CustomizableObjectCustomVersion.h"
#include "MuCO/CustomizableObjectPrivate.h"
#include "MuCO/UnrealPortabilityHelpers.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(CustomizableSkeletalMeshActor)
#define LOCTEXT_NAMESPACE "CustomizableObject"
UCustomizableObjectInstance* ACustomizableSkeletalMeshActor::GetInstance()
{
for (const UCustomizableSkeletalComponent* Component : CustomizableSkeletalComponents)
{
if (UCustomizableObjectInstance* COInstance = Component->CustomizableObjectInstance)
{
return COInstance;
}
}
return nullptr;
}
ACustomizableSkeletalMeshActor::ACustomizableSkeletalMeshActor(const FObjectInitializer& Initializer)
{
Private = CreateDefaultSubobject<UCustomizableSkeletalMeshActorPrivate>(TEXT("Private"));
// Old assets used to create the first UCustomizableSkeletalComponent as a Subobject. To be able to deserialize them we need to create it.
// Creating instead an Object instead of a Suobject will not work. Only Component UCustomizableSkeletalComponent 0 is a Subobject.
{
UCustomizableSkeletalComponent* CustomizableSkeletalComponent = CreateDefaultSubobject<UCustomizableSkeletalComponent>(TEXT("CustomizableSkeletalComponent0"));
CustomizableSkeletalComponents.Add(CustomizableSkeletalComponent);
if (USkeletalMeshComponent* SkeletalMeshComp = GetSkeletalMeshComponent())
{
SkeletalMeshComponents.Add(SkeletalMeshComp);
CustomizableSkeletalComponents[0]->AttachToComponent(SkeletalMeshComp, FAttachmentTransformRules::KeepRelativeTransform);
}
}
}
void UCustomizableSkeletalMeshActorPrivate::Init(UCustomizableObjectInstance* Instance)
{
UCustomizableObject* Object = Instance->GetCustomizableObject();
if (!Object)
{
return;
}
for (int32 ObjectComponentIndex = 0; ObjectComponentIndex < Object->GetComponentCount(); ++ObjectComponentIndex)
{
const FName& ComponentName = Object->GetComponentName(ObjectComponentIndex);
const FString ComponentNameString = ComponentName.ToString();
USkeletalMeshComponent* Component;
if (ObjectComponentIndex == 0)
{
Component = GetPublic()->SkeletalMeshComponents[0];
// Renaming the component will make it disappear. Keep it as it is.
}
else
{
const FString SkeletalMeshComponentName = FString::Printf(TEXT("SkeletalMeshComponent %s"), *ComponentNameString);
Component = NewObject<USkeletalMeshComponent>(GetPublic(), USkeletalMeshComponent::StaticClass(), FName(*SkeletalMeshComponentName));
Component->CreationMethod = EComponentCreationMethod::Native;
Component->AttachToComponent(GetPublic()->GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);
Component->RegisterComponent();
}
if (!Component)
{
continue;
}
UCustomizableSkeletalComponent* CustomizableComponent;
if (ObjectComponentIndex == 0)
{
CustomizableComponent = GetPublic()->CustomizableSkeletalComponents[0];
// Renaming the component will make it disappear. Keep it as it is.
}
else
{
const FString CustomizableComponentName = FString::Printf(TEXT("CustomizableSkeletalComponent %s"), *ComponentNameString);
CustomizableComponent = NewObject<UCustomizableSkeletalComponent>(GetPublic(), UCustomizableSkeletalComponent::StaticClass(), FName(CustomizableComponentName));
}
CustomizableComponent->AttachToComponent(Component, FAttachmentTransformRules::KeepRelativeTransform);
CustomizableComponent->CustomizableObjectInstance = Instance;
CustomizableComponent->SetComponentName(ComponentName);
CustomizableComponent->RegisterComponent();
GetPublic()->SkeletalMeshComponents.Add(Component);
GetPublic()->CustomizableSkeletalComponents.Add(CustomizableComponent);
}
Instance->UpdateSkeletalMeshAsync();
}
void ACustomizableSkeletalMeshActor::SetDebugMaterial(UMaterialInterface* InDebugMaterial)
{
if (!InDebugMaterial)
{
return;
}
DebugMaterial = InDebugMaterial;
}
void ACustomizableSkeletalMeshActor::EnableDebugMaterial(bool bEnableDebugMaterial)
{
bRemoveDebugMaterial = bDebugMaterialEnabled && !bEnableDebugMaterial;
bDebugMaterialEnabled = bEnableDebugMaterial;
if (UCustomizableObjectInstance* COInstance = GetInstance())
{
//Bind Instance Update delegate to Actor
COInstance->UpdatedDelegate.AddUniqueDynamic(this, &ACustomizableSkeletalMeshActor::SwitchComponentsMaterials);
SwitchComponentsMaterials(COInstance);
}
}
UCustomizableSkeletalMeshActorPrivate* ACustomizableSkeletalMeshActor::GetPrivate()
{
check(Private);
return Private;
}
const UCustomizableSkeletalMeshActorPrivate* ACustomizableSkeletalMeshActor::GetPrivate() const
{
check(Private);
return Private;
}
void ACustomizableSkeletalMeshActor::SwitchComponentsMaterials(UCustomizableObjectInstance* Instance)
{
if (!DebugMaterial)
{
return;
}
if (bDebugMaterialEnabled || bRemoveDebugMaterial)
{
UCustomizableObjectInstance* COInstance = GetInstance();
if (!COInstance)
{
return;
}
for (int32 ObjectComponentIndex = 0; ObjectComponentIndex < SkeletalMeshComponents.Num(); ++ObjectComponentIndex)
{
int32 NumMaterials = SkeletalMeshComponents[ObjectComponentIndex]->GetNumMaterials();
if (bDebugMaterialEnabled)
{
for (int32 MatIndex = 0; MatIndex < NumMaterials; ++MatIndex)
{
SkeletalMeshComponents[ObjectComponentIndex]->SetMaterial(MatIndex, DebugMaterial);
}
}
else // Remove debugmaterial
{
// check if original materials already overriden
const TArray<TObjectPtr<UMaterialInterface>>* OverrideMaterials = COInstance->GetOverrideMaterials(FCustomizableObjectComponentIndex(ObjectComponentIndex));
const bool bUseOverrideMaterials = COInstance->GetCustomizableObject()->bEnableMeshCache && CVarEnableMeshCache.GetValueOnAnyThread();
if (bUseOverrideMaterials && OverrideMaterials->Num() > 0)
{
for (int32 MatIndex = 0; MatIndex < OverrideMaterials->Num(); ++MatIndex)
{
SkeletalMeshComponents[ObjectComponentIndex]->SetMaterial(MatIndex, (*OverrideMaterials)[MatIndex]);
}
}
else
{
SkeletalMeshComponents[ObjectComponentIndex]->EmptyOverrideMaterials();
}
bRemoveDebugMaterial = false;
}
}
}
}
ACustomizableSkeletalMeshActor* UCustomizableSkeletalMeshActorPrivate::GetPublic()
{
return CastChecked<ACustomizableSkeletalMeshActor>(GetOuter());
}
TArray<TObjectPtr<UCustomizableSkeletalComponent>>& UCustomizableSkeletalMeshActorPrivate::GetComponents()
{
return GetPublic()->CustomizableSkeletalComponents;
}
#undef LOCTEXT_NAMESPACE