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

165 lines
4.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "UnloadedBlueprintData.h"
#include "ClassViewerNode.h"
#include "Engine/BlueprintGeneratedClass.h"
#include "HAL/PlatformCrt.h"
#include "UObject/Class.h"
#include "UObject/Object.h"
#include "UObject/WeakObjectPtrTemplates.h"
FUnloadedBlueprintData::FUnloadedBlueprintData(TWeakPtr<FClassViewerNode> InClassViewerNode)
: ClassViewerNode(InClassViewerNode)
{
}
bool FUnloadedBlueprintData::HasAnyClassFlags( uint32 InFlagsToCheck ) const
{
return (ClassFlags & InFlagsToCheck) != 0;
}
bool FUnloadedBlueprintData::HasAllClassFlags( uint32 InFlagsToCheck ) const
{
return ((ClassFlags & InFlagsToCheck) == InFlagsToCheck);
}
void FUnloadedBlueprintData::SetClassFlags(uint32 InFlags)
{
ClassFlags = InFlags;
}
bool FUnloadedBlueprintData::IsChildOf(const UClass* InClass) const
{
TSharedPtr<FClassViewerNode> CurrentNode = ClassViewerNode.Pin()->GetParentNode();
// Keep going through parents till you find an invalid.
while (CurrentNode.IsValid())
{
if (CurrentNode->Class.Get() == InClass)
{
return true;
}
CurrentNode = CurrentNode->GetParentNode();
}
return false;
}
bool FUnloadedBlueprintData::ImplementsInterface(const UClass* InInterface) const
{
FString InterfacePath = InInterface->GetPathName();
// Does this blueprint implement the interface directly?
for (const FString& DirectlyImplementedInterface : ImplementedInterfaces)
{
if (DirectlyImplementedInterface == InterfacePath)
{
return true;
}
}
// If not, does a parent class implement the interface?
TSharedPtr<FClassViewerNode> CurrentNode = ClassViewerNode.Pin()->GetParentNode();
while (CurrentNode.IsValid())
{
if (CurrentNode->Class.IsValid() && CurrentNode->Class->ImplementsInterface(InInterface))
{
return true;
}
else if (CurrentNode->UnloadedBlueprintData.IsValid() && CurrentNode->UnloadedBlueprintData->ImplementsInterface(InInterface))
{
return true;
}
CurrentNode = CurrentNode->GetParentNode();
}
return false;
}
bool FUnloadedBlueprintData::IsA(const UClass* InClass) const
{
// Unloaded blueprints will always return true for IsA(UBlueprintGeneratedClass::StaticClass). With that in mind, even though we do not have the exact class, we can use that knowledge as a basis for a check.
return ((UObject*)UBlueprintGeneratedClass::StaticClass())->IsA(InClass);
}
const UClass* FUnloadedBlueprintData::GetClassWithin() const
{
TSharedPtr<FClassViewerNode> CurrentNode = ClassViewerNode.Pin()->GetParentNode();
while (CurrentNode.IsValid())
{
// The class field will be invalid for unloaded classes.
// However, it should be valid once we've hit a loaded class or a Native class.
// Assuming BP cannot change ClassWithin data, this should be safe.
if (CurrentNode->Class.IsValid())
{
return CurrentNode->Class->ClassWithin;
}
CurrentNode = CurrentNode->GetParentNode();
}
return nullptr;
}
const UClass* FUnloadedBlueprintData::GetNativeParent() const
{
TSharedPtr<FClassViewerNode> CurrentNode = ClassViewerNode.Pin()->GetParentNode();
while (CurrentNode.IsValid())
{
// The class field will be invalid for unloaded classes.
// However, it should be valid once we've hit a loaded class or a Native class.
// Assuming BP cannot change ClassWithin data, this should be safe.
if (CurrentNode->Class.IsValid() && CurrentNode->Class->HasAnyClassFlags(CLASS_Native))
{
return CurrentNode->Class.Get();
}
CurrentNode = CurrentNode->GetParentNode();
}
return nullptr;
}
TSharedPtr<FString> FUnloadedBlueprintData::GetClassName() const
{
if (ClassViewerNode.IsValid())
{
return ClassViewerNode.Pin()->GetClassName();
}
return TSharedPtr<FString>();
}
FName FUnloadedBlueprintData::GetClassPath() const
{
if (ClassViewerNode.IsValid())
{
return FName(*ClassViewerNode.Pin()->ClassPath.ToString());
}
return FName();
}
FTopLevelAssetPath FUnloadedBlueprintData::GetClassPathName() const
{
if (ClassViewerNode.IsValid())
{
return ClassViewerNode.Pin()->ClassPath;
}
return FTopLevelAssetPath();
}
const TWeakPtr<FClassViewerNode>& FUnloadedBlueprintData::GetClassViewerNode() const
{
return ClassViewerNode;
}
void FUnloadedBlueprintData::AddImplementedInterface(const FString& InterfaceName)
{
ImplementedInterfaces.Add(InterfaceName);
}