|
|
|
|
@@ -1,140 +1,166 @@
|
|
|
|
|
#include "MCPTypes.h"
|
|
|
|
|
#include "Editor.h"
|
|
|
|
|
#include "EdGraphSchema_K2.h"
|
|
|
|
|
#include "UObject/UObjectIterator.h"
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// Helper: format a UField name with module prefix if not in /Script/Engine.
|
|
|
|
|
// Choose Short Name
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
static FString FormatFieldName(UField* Field, const FString& TypePrefix)
|
|
|
|
|
FString UMCPTypes::ChooseShortName(UObject* Obj)
|
|
|
|
|
{
|
|
|
|
|
// Package name is /Script/ModuleName
|
|
|
|
|
FString ModuleName = Field->GetOutermost()->GetName().Mid(8);
|
|
|
|
|
if (!Cast<UScriptStruct>(Obj) && !Cast<UClass>(Obj) && !Cast<UEnum>(Obj))
|
|
|
|
|
return FString();
|
|
|
|
|
|
|
|
|
|
FString Name = TypePrefix + Field->GetName();
|
|
|
|
|
if (ModuleName != TEXT("Engine"))
|
|
|
|
|
return ModuleName + TEXT("::") + Name;
|
|
|
|
|
return Name;
|
|
|
|
|
FString Path = Obj->GetPathName();
|
|
|
|
|
FString *OldShort = PathToShort.Find(Path);
|
|
|
|
|
if (OldShort != nullptr) return *OldShort;
|
|
|
|
|
|
|
|
|
|
FString Name = Obj->GetName();
|
|
|
|
|
if (Name.EndsWith(TEXT("_C"))) Name.LeftChopInline(2);
|
|
|
|
|
|
|
|
|
|
FString Lower = Name.ToLower();
|
|
|
|
|
if (!ShortToPath.Contains(Lower))
|
|
|
|
|
{
|
|
|
|
|
ShortToPath.Add(Lower, Path);
|
|
|
|
|
PathToShort.Add(Path, Name);
|
|
|
|
|
return Name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int32 i = 2; ; ++i)
|
|
|
|
|
{
|
|
|
|
|
FString NumberedLower = FString::Printf(TEXT("%s%d"), *Lower, i);
|
|
|
|
|
if (!ShortToPath.Contains(NumberedLower))
|
|
|
|
|
{
|
|
|
|
|
FString NumberedName = FString::Printf(TEXT("%s%d"), *Name, i);
|
|
|
|
|
ShortToPath.Add(NumberedLower, Path);
|
|
|
|
|
PathToShort.Add(Path, NumberedName);
|
|
|
|
|
return NumberedName;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FString FormatClassName(UClass* Class)
|
|
|
|
|
void UMCPTypes::ChooseShortNames(UPackage* Package)
|
|
|
|
|
{
|
|
|
|
|
FString Prefix = Class->IsChildOf(AActor::StaticClass()) ? TEXT("A") : TEXT("U");
|
|
|
|
|
return FormatFieldName(Class, Prefix);
|
|
|
|
|
}
|
|
|
|
|
if (Package == nullptr) return;
|
|
|
|
|
|
|
|
|
|
static FString FormatStructName(UScriptStruct* Struct)
|
|
|
|
|
{
|
|
|
|
|
return FormatFieldName(Struct, TEXT("F"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FString FormatEnumName(UEnum* Enum)
|
|
|
|
|
{
|
|
|
|
|
return FormatFieldName(Enum, TEXT("E"));
|
|
|
|
|
ForEachObjectWithPackage(Package, [&](UObject* Obj)
|
|
|
|
|
{
|
|
|
|
|
ChooseShortName(Obj);
|
|
|
|
|
return true;
|
|
|
|
|
}, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// TypeToText
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
static FString TerminalToText(const FEdGraphPinType& PinType)
|
|
|
|
|
FString UMCPTypes::TypeToTextInner(FName Category, FName SubCategory, UObject* SubCategoryObject)
|
|
|
|
|
{
|
|
|
|
|
const FName& Cat = PinType.PinCategory;
|
|
|
|
|
UObject* SubObj = PinType.PinSubCategoryObject.Get();
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_Boolean) return TEXT("bool");
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_Int) return TEXT("int32");
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_Int64) return TEXT("int64");
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_Name) return TEXT("Name");
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_String) return TEXT("String");
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_Text) return TEXT("Text");
|
|
|
|
|
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_Boolean) return TEXT("bool");
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_Int) return TEXT("int32");
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_Int64) return TEXT("int64");
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_Name) return TEXT("FName");
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_String) return TEXT("FString");
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_Text) return TEXT("FText");
|
|
|
|
|
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_Real)
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_Real)
|
|
|
|
|
{
|
|
|
|
|
if (PinType.PinSubCategory == UEdGraphSchema_K2::PC_Float)
|
|
|
|
|
if (SubCategory == UEdGraphSchema_K2::PC_Float)
|
|
|
|
|
return TEXT("float");
|
|
|
|
|
return TEXT("double");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_Byte)
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_Byte)
|
|
|
|
|
{
|
|
|
|
|
if (UEnum* Enum = Cast<UEnum>(SubObj))
|
|
|
|
|
return FormatEnumName(Enum);
|
|
|
|
|
if (SubCategoryObject)
|
|
|
|
|
return ChooseShortName(SubCategoryObject);
|
|
|
|
|
return TEXT("uint8");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_Enum)
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_Enum)
|
|
|
|
|
{
|
|
|
|
|
if (UEnum* Enum = Cast<UEnum>(SubObj))
|
|
|
|
|
return FormatEnumName(Enum);
|
|
|
|
|
return TEXT("uint8");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_Struct)
|
|
|
|
|
{
|
|
|
|
|
if (UScriptStruct* Struct = Cast<UScriptStruct>(SubObj))
|
|
|
|
|
return FormatStructName(Struct);
|
|
|
|
|
if (SubCategoryObject)
|
|
|
|
|
return ChooseShortName(SubCategoryObject);
|
|
|
|
|
return FString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_Object)
|
|
|
|
|
if (SubCategoryObject)
|
|
|
|
|
{
|
|
|
|
|
if (UClass* Class = Cast<UClass>(SubObj))
|
|
|
|
|
return FormatClassName(Class) + TEXT("*");
|
|
|
|
|
return FString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_Class)
|
|
|
|
|
{
|
|
|
|
|
if (UClass* Class = Cast<UClass>(SubObj))
|
|
|
|
|
return FString::Printf(TEXT("TSubclassOf<%s>"), *FormatClassName(Class));
|
|
|
|
|
return FString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_SoftObject)
|
|
|
|
|
{
|
|
|
|
|
if (UClass* Class = Cast<UClass>(SubObj))
|
|
|
|
|
return FString::Printf(TEXT("TSoftObjectPtr<%s>"), *FormatClassName(Class));
|
|
|
|
|
return FString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_SoftClass)
|
|
|
|
|
{
|
|
|
|
|
if (UClass* Class = Cast<UClass>(SubObj))
|
|
|
|
|
return FString::Printf(TEXT("TSoftClassPtr<%s>"), *FormatClassName(Class));
|
|
|
|
|
return FString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Cat == UEdGraphSchema_K2::PC_Interface)
|
|
|
|
|
{
|
|
|
|
|
if (UClass* Class = Cast<UClass>(SubObj))
|
|
|
|
|
return FString::Printf(TEXT("TScriptInterface<%s>"), *FormatClassName(Class));
|
|
|
|
|
return FString();
|
|
|
|
|
FString Short = ChooseShortName(SubCategoryObject);
|
|
|
|
|
if (Short.IsEmpty()) return FString();
|
|
|
|
|
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_Struct)
|
|
|
|
|
return Short;
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_Object)
|
|
|
|
|
return Short;
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_Class)
|
|
|
|
|
return FString::Printf(TEXT("Class<%s>"), *Short);
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_SoftObject)
|
|
|
|
|
return FString::Printf(TEXT("Soft<%s>"), *Short);
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_SoftClass)
|
|
|
|
|
return FString::Printf(TEXT("SoftClass<%s>"), *Short);
|
|
|
|
|
if (Category == UEdGraphSchema_K2::PC_Interface)
|
|
|
|
|
return Short;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FString MCPTypes::TypeToText(const FEdGraphPinType& PinType)
|
|
|
|
|
FString UMCPTypes::TypeToText(const FEdGraphPinType& PinType)
|
|
|
|
|
{
|
|
|
|
|
FString Inner = TerminalToText(PinType);
|
|
|
|
|
UMCPTypes* Types = GEditor->GetEditorSubsystem<UMCPTypes>();
|
|
|
|
|
if (!Types) return FString();
|
|
|
|
|
|
|
|
|
|
FString Inner = Types->TypeToTextInner(PinType.PinCategory, PinType.PinSubCategory, PinType.PinSubCategoryObject.Get());
|
|
|
|
|
if (Inner.IsEmpty())
|
|
|
|
|
return FString();
|
|
|
|
|
|
|
|
|
|
if (PinType.IsArray())
|
|
|
|
|
return FString::Printf(TEXT("TArray<%s>"), *Inner);
|
|
|
|
|
return FString::Printf(TEXT("Array<%s>"), *Inner);
|
|
|
|
|
if (PinType.IsSet())
|
|
|
|
|
return FString::Printf(TEXT("TSet<%s>"), *Inner);
|
|
|
|
|
return FString::Printf(TEXT("Set<%s>"), *Inner);
|
|
|
|
|
if (PinType.IsMap())
|
|
|
|
|
{
|
|
|
|
|
FEdGraphPinType ValueType;
|
|
|
|
|
ValueType.PinCategory = PinType.PinValueType.TerminalCategory;
|
|
|
|
|
ValueType.PinSubCategory = PinType.PinValueType.TerminalSubCategory;
|
|
|
|
|
ValueType.PinSubCategoryObject = PinType.PinValueType.TerminalSubCategoryObject;
|
|
|
|
|
FString ValueInner = TerminalToText(ValueType);
|
|
|
|
|
FString ValueInner = Types->TypeToTextInner(
|
|
|
|
|
PinType.PinValueType.TerminalCategory,
|
|
|
|
|
PinType.PinValueType.TerminalSubCategory,
|
|
|
|
|
PinType.PinValueType.TerminalSubCategoryObject.Get());
|
|
|
|
|
if (ValueInner.IsEmpty())
|
|
|
|
|
return FString();
|
|
|
|
|
return FString::Printf(TEXT("TMap<%s, %s>"), *Inner, *ValueInner);
|
|
|
|
|
return FString::Printf(TEXT("Map<%s, %s>"), *Inner, *ValueInner);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Inner;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// Subsystem lifecycle
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void UMCPTypes::Initialize(FSubsystemCollectionBase& Collection)
|
|
|
|
|
{
|
|
|
|
|
Super::Initialize(Collection);
|
|
|
|
|
|
|
|
|
|
// Collect all packages and sort by name for stable short-name assignment.
|
|
|
|
|
TArray<UPackage*> Packages;
|
|
|
|
|
for (TObjectIterator<UPackage> It; It; ++It)
|
|
|
|
|
Packages.Add(*It);
|
|
|
|
|
Packages.Sort([](const UPackage& A, const UPackage& B) { return A.GetName() < B.GetName(); });
|
|
|
|
|
|
|
|
|
|
// Scan priority packages first, then everything else in sorted order.
|
|
|
|
|
ChooseShortNames(FindPackage(nullptr, TEXT("/Script/CoreUObject")));
|
|
|
|
|
ChooseShortNames(FindPackage(nullptr, TEXT("/Script/Engine")));
|
|
|
|
|
ChooseShortNames(FindPackage(nullptr, TEXT("/Script/Integration")));
|
|
|
|
|
|
|
|
|
|
for (UPackage* Pkg : Packages)
|
|
|
|
|
ChooseShortNames(Pkg);
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogTemp, Display, TEXT("MCPTypes: Registered %d types"), ShortToPath.Num());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UMCPTypes::Deinitialize()
|
|
|
|
|
{
|
|
|
|
|
Super::Deinitialize();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|