Files
UnrealEngine/Engine/Source/Editor/UnrealEd/Private/ComponentAssetBroker.cpp
2025-05-18 13:04:45 +08:00

396 lines
10 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "ComponentAssetBroker.h"
#include "GameFramework/Actor.h"
#include "Engine/Blueprint.h"
#include "Components/StaticMeshComponent.h"
#include "Engine/SkeletalMesh.h"
#include "Components/SkeletalMeshComponent.h"
#include "Particles/ParticleSystem.h"
#include "Components/AudioComponent.h"
#include "Particles/ParticleSystemComponent.h"
#include "Engine/StaticMesh.h"
#include "Sound/SoundBase.h"
#include "Components/ChildActorComponent.h"
//////////////////////////////////////////////////////////////////////////
// FStaticMeshComponentBroker
class FStaticMeshComponentBroker : public IComponentAssetBroker
{
public:
UClass* GetSupportedAssetClass() override
{
return UStaticMesh::StaticClass();
}
virtual bool AssignAssetToComponent(UActorComponent* InComponent, UObject* InAsset) override
{
if (UStaticMeshComponent* StaticMeshComp = Cast<UStaticMeshComponent>(InComponent))
{
UStaticMesh* StaticMesh = Cast<UStaticMesh>(InAsset);
if ((StaticMesh != NULL) || (InAsset == NULL))
{
StaticMeshComp->SetStaticMesh(StaticMesh);
return true;
}
}
return false;
}
virtual UObject* GetAssetFromComponent(UActorComponent* InComponent) override
{
if (UStaticMeshComponent* StaticMeshComp = Cast<UStaticMeshComponent>(InComponent))
{
return StaticMeshComp->GetStaticMesh();
}
return NULL;
}
};
//////////////////////////////////////////////////////////////////////////
// FSkeletalMeshComponentBroker
class FSkeletalMeshComponentBroker : public IComponentAssetBroker
{
public:
UClass* GetSupportedAssetClass() override
{
return USkeletalMesh::StaticClass();
}
virtual bool AssignAssetToComponent(UActorComponent* InComponent, UObject* InAsset) override
{
if (USkeletalMeshComponent* SkeletalComp = Cast<USkeletalMeshComponent>(InComponent))
{
USkeletalMesh* SkeletalMesh = Cast<USkeletalMesh>(InAsset);
if ((SkeletalMesh != NULL) || (InAsset == NULL))
{
SkeletalComp->SetSkeletalMesh(SkeletalMesh);
return true;
}
}
return false;
}
virtual UObject* GetAssetFromComponent(UActorComponent* InComponent) override
{
if (USkeletalMeshComponent* SkelMeshComp = Cast<USkeletalMeshComponent>(InComponent))
{
return SkelMeshComp->GetSkeletalMeshAsset();
}
return NULL;
}
};
//////////////////////////////////////////////////////////////////////////
// FParticleSystemComponentBroker
class FParticleSystemComponentBroker : public IComponentAssetBroker
{
public:
UClass* GetSupportedAssetClass() override
{
return UParticleSystem::StaticClass();
}
virtual bool AssignAssetToComponent(UActorComponent* InComponent, UObject* InAsset) override
{
if (UParticleSystemComponent* ParticleComp = Cast<UParticleSystemComponent>(InComponent))
{
UParticleSystem* ParticleSystem = Cast<UParticleSystem>(InAsset);
if ((ParticleSystem != NULL) || (InAsset == NULL))
{
ParticleComp->SetTemplate(ParticleSystem);
return true;
}
}
return false;
}
virtual UObject* GetAssetFromComponent(UActorComponent* InComponent) override
{
if (UParticleSystemComponent* ParticleComp = Cast<UParticleSystemComponent>(InComponent))
{
return ParticleComp->Template;
}
return NULL;
}
};
//////////////////////////////////////////////////////////////////////////
// FChildActorComponentBroker
class FChildActorComponentBroker : public IComponentAssetBroker
{
public:
UClass* GetSupportedAssetClass() override
{
return UBlueprint::StaticClass();
}
virtual bool AssignAssetToComponent(UActorComponent* InComponent, UObject* InAsset) override
{
if (UChildActorComponent* ChildActorComp = Cast<UChildActorComponent>(InComponent))
{
UClass* Class = Cast<UClass>(InAsset);
if (Class == nullptr)
{
if (UBlueprint* BP = Cast<UBlueprint>(InAsset))
{
Class = *(BP->GeneratedClass);
}
}
if (Class && Class->IsChildOf<AActor>())
{
ChildActorComp->SetChildActorClass(Class);
return true;
}
}
return false;
}
virtual UObject* GetAssetFromComponent(UActorComponent* InComponent) override
{
if (UChildActorComponent* ChildActorComp = Cast<UChildActorComponent>(InComponent))
{
return UBlueprint::GetBlueprintFromClass(*(ChildActorComp->GetChildActorClass()));
}
return NULL;
}
};
//////////////////////////////////////////////////////////////////////////
// FComponentAssetBrokerageage statics
TMap<UClass*, FComponentClassList> FComponentAssetBrokerage::AssetToComponentClassMap;
TMap< TSubclassOf<UActorComponent>, TSharedPtr<IComponentAssetBroker> > FComponentAssetBrokerage::ComponentToBrokerMap;
TMap< UClass*, TArray< TSharedPtr<IComponentAssetBroker> > > FComponentAssetBrokerage::AssetToBrokerMap;
bool FComponentAssetBrokerage::bInitializedBuiltinMap = false;
bool FComponentAssetBrokerage::bShutSystemDown = false;
//////////////////////////////////////////////////////////////////////////
// FComponentAssetBrokerageage
/** Find set of components that support this asset */
FComponentClassList FComponentAssetBrokerage::GetComponentsForAsset(const UObject* InAsset)
{
InitializeMap();
FComponentClassList OutClasses;
if (InAsset != NULL)
{
for (UClass* Class = InAsset->GetClass(); Class != UObject::StaticClass(); Class = Class->GetSuperClass())
{
if (FComponentClassList* pTypesForClass = AssetToComponentClassMap.Find(Class))
{
OutClasses.Append(*pTypesForClass);
}
}
}
return OutClasses;
}
TSubclassOf<UActorComponent> FComponentAssetBrokerage::GetPrimaryComponentForAsset(UClass* InAssetClass)
{
InitializeMap();
if (InAssetClass != NULL)
{
for (UClass* Class = InAssetClass; Class != UObject::StaticClass(); Class = Class->GetSuperClass())
{
if (FComponentClassList* pTypesForClass = AssetToComponentClassMap.Find(Class))
{
if (pTypesForClass->Num() > 0)
{
return (*pTypesForClass)[0];
}
}
}
}
return NULL;
}
/** Assign the assigned asset to the supplied component */
bool FComponentAssetBrokerage::AssignAssetToComponent(UActorComponent* InComponent, UObject* InAsset)
{
InitializeMap();
if (InComponent != NULL)
{
TSharedPtr<IComponentAssetBroker> Broker = FindBrokerByComponentType(InComponent->GetClass());
if (Broker.IsValid())
{
return Broker->AssignAssetToComponent(InComponent, InAsset);
}
}
return false;
}
UObject* FComponentAssetBrokerage::GetAssetFromComponent(UActorComponent* InComponent)
{
InitializeMap();
if (InComponent != NULL)
{
TSharedPtr<IComponentAssetBroker> Broker = FindBrokerByComponentType(InComponent->GetClass());
if (Broker.IsValid())
{
return Broker->GetAssetFromComponent(InComponent);
}
}
return NULL;
}
/** See if this component supports assets of any type */
bool FComponentAssetBrokerage::SupportsAssets(UActorComponent* InComponent)
{
InitializeMap();
if (InComponent == NULL)
{
return false;
}
else
{
TSharedPtr<IComponentAssetBroker> Broker = FindBrokerByComponentType(InComponent->GetClass());
return Broker.IsValid();
}
}
void FComponentAssetBrokerage::PRIVATE_ShutdownBrokerage()
{
check(!bShutSystemDown);
bShutSystemDown = true;
AssetToComponentClassMap.Empty();
AssetToBrokerMap.Empty();
ComponentToBrokerMap.Empty();
}
void FComponentAssetBrokerage::InitializeMap()
{
check(!bShutSystemDown);
if (!bInitializedBuiltinMap)
{
bInitializedBuiltinMap = true;
RegisterBroker(MakeShareable(new FStaticMeshComponentBroker), UStaticMeshComponent::StaticClass(), true, true);
RegisterBroker(MakeShareable(new FSkeletalMeshComponentBroker), USkeletalMeshComponent::StaticClass(), true, true);
RegisterBroker(MakeShareable(new FParticleSystemComponentBroker), UParticleSystemComponent::StaticClass(), true, true);
RegisterBroker(MakeShareable(new FChildActorComponentBroker), UChildActorComponent::StaticClass(), true, false);
}
}
void FComponentAssetBrokerage::RegisterBroker(TSharedPtr<IComponentAssetBroker> Broker, TSubclassOf<UActorComponent> InComponentClass, bool bSetAsPrimary, bool bMapComponentForAssets)
{
InitializeMap();
check(Broker.IsValid());
UClass* AssetClass = Broker->GetSupportedAssetClass();
check((AssetClass != NULL) && (AssetClass != UObject::StaticClass()));
checkf(!ComponentToBrokerMap.Contains(InComponentClass), TEXT("Component class already has a registered broker; you have to chain them yourself."));
ComponentToBrokerMap.Add(InComponentClass, Broker);
if (bSetAsPrimary)
{
AssetToBrokerMap.FindOrAdd(AssetClass).Insert(Broker, 0);
}
else
{
AssetToBrokerMap.FindOrAdd(AssetClass).Add(Broker);
}
if (bMapComponentForAssets)
{
FComponentClassList& ValidComponentTypes = AssetToComponentClassMap.FindOrAdd(AssetClass);
if (bSetAsPrimary)
{
ValidComponentTypes.Insert(InComponentClass, 0);
}
else
{
ValidComponentTypes.Add(InComponentClass);
}
}
}
void FComponentAssetBrokerage::UnregisterBroker(TSharedPtr<IComponentAssetBroker> Broker)
{
UClass* AssetClass = Broker->GetSupportedAssetClass();
if (TArray< TSharedPtr<IComponentAssetBroker> >* pBrokerList = AssetToBrokerMap.Find(AssetClass))
{
pBrokerList->Remove(Broker);
}
if (FComponentClassList* pTypesForClass = AssetToComponentClassMap.Find(AssetClass))
{
for (auto ComponentTypeIt = ComponentToBrokerMap.CreateIterator(); ComponentTypeIt; ++ComponentTypeIt)
{
TSubclassOf<UActorComponent> ComponentClass = ComponentTypeIt.Key();
if (ComponentTypeIt.Value() == Broker)
{
ComponentTypeIt.RemoveCurrent();
pTypesForClass->Remove(ComponentClass);
}
}
if (pTypesForClass->Num() == 0)
{
AssetToComponentClassMap.Remove(AssetClass);
}
}
}
TSharedPtr<IComponentAssetBroker> FComponentAssetBrokerage::FindBrokerByComponentType(TSubclassOf<UActorComponent> InComponentClass)
{
InitializeMap();
return ComponentToBrokerMap.FindRef(InComponentClass);
}
TSharedPtr<IComponentAssetBroker> FComponentAssetBrokerage::FindBrokerByAssetType(UClass* InAssetClass)
{
InitializeMap();
TArray< TSharedPtr<IComponentAssetBroker> >* pBrokerList = AssetToBrokerMap.Find(InAssetClass);
return ((pBrokerList != NULL) && (pBrokerList->Num() > 0)) ? (*pBrokerList)[0] : NULL;
}
TArray<UClass*> FComponentAssetBrokerage::GetSupportedAssets(UClass* InFilterComponentClass)
{
InitializeMap();
TArray< UClass* > SupportedAssets;
for (auto ComponentTypeIt = ComponentToBrokerMap.CreateIterator(); ComponentTypeIt; ++ComponentTypeIt)
{
TSubclassOf<UActorComponent> Component = ComponentTypeIt.Key();
if(InFilterComponentClass == NULL || Component->IsChildOf(InFilterComponentClass))
{
SupportedAssets.Add(ComponentTypeIt.Value()->GetSupportedAssetClass());
}
}
return SupportedAssets;
}