Finish typename search
This commit is contained in:
@@ -1,62 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "MCPServer.h"
|
||||
#include "MCPHandler.h"
|
||||
#include "MCPFetcher.h"
|
||||
#include "MCPUtils.h"
|
||||
#include "EdGraph/EdGraphNode.h"
|
||||
#include "EdGraphSchema_K2.h"
|
||||
#include "GraphNode_PrintPinType.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UMCP_GraphNode_ListPinTypes : public UObject, public IMCPHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("List every type available in the variable type selector menu, as Category|Item.");
|
||||
}
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
const UEdGraphSchema_K2* Schema = GetDefault<UEdGraphSchema_K2>();
|
||||
TArray<TSharedPtr<UEdGraphSchema_K2::FPinTypeTreeInfo>> TypeTree;
|
||||
Schema->GetVariableTypeTree(TypeTree, ETypeTreeFilter::None);
|
||||
|
||||
for (const TSharedPtr<UEdGraphSchema_K2::FPinTypeTreeInfo>& Root : TypeTree)
|
||||
{
|
||||
PrintTree(Root, FString());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void PrintTree(const TSharedPtr<UEdGraphSchema_K2::FPinTypeTreeInfo>& Node, const FString& Category)
|
||||
{
|
||||
FString Desc = Node->GetDescription().ToString();
|
||||
|
||||
if (!Node->bReadOnly)
|
||||
{
|
||||
UObject *SCO = Node->GetPinTypeNoResolve().PinSubCategoryObject.Get();
|
||||
if (SCO) {
|
||||
UMCPServer::Printf(TEXT("SCO %s %s\n"), *SCO->GetPackage()->GetName(), *SCO->GetName());
|
||||
} else {
|
||||
auto cad = Node->GetCachedAssetData();
|
||||
UMCPServer::Printf(TEXT("CAD %s %s\n"), *cad.PackageName.ToString(), *cad.AssetName.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
FString ChildCategory = FString::Printf(TEXT("%s%s|"), *Category, *Desc);
|
||||
for (const TSharedPtr<UEdGraphSchema_K2::FPinTypeTreeInfo>& Child : Node->Children)
|
||||
{
|
||||
PrintTree(Child, ChildCategory);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "MCPServer.h"
|
||||
#include "MCPHandler.h"
|
||||
#include "MCPTypes.h"
|
||||
#include "MCPUtils.h"
|
||||
#include "AssetRegistry/AssetData.h"
|
||||
#include "AssetRegistry/IAssetRegistry.h"
|
||||
#include "UObject/UObjectIterator.h"
|
||||
#include "StructUtils/UserDefinedStruct.h"
|
||||
#include "Engine/UserDefinedEnum.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "TypeName_Search.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UMCP_TypeName_Search : public UObject, public IMCPHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(meta=(Description="Substring filter for type names"))
|
||||
FString Query;
|
||||
|
||||
UPROPERTY(meta=(Optional, Description="Maximum number of results"))
|
||||
int32 Limit = 100;
|
||||
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("Search for type names usable in pin type specifications. "
|
||||
"Returns short names that can be used with commands like Blueprint_ChangeVariableType.");
|
||||
}
|
||||
|
||||
void TryMatchObject(TSet<UObject*> &Matches, UObject *Obj)
|
||||
{
|
||||
if (!Obj) return;
|
||||
FString Name = Obj->GetName();
|
||||
if (!Name.Contains(Query, ESearchCase::IgnoreCase)) return;
|
||||
Matches.Add(Obj);
|
||||
}
|
||||
|
||||
void TryMatchObjects(TSet<UObject*> &Matches, UClass *Class)
|
||||
{
|
||||
ForEachObjectOfClass(Class, [&](UObject *Obj){
|
||||
if (Matches.Num() == Limit) return;
|
||||
TryMatchObject(Matches, Obj);
|
||||
}, true);
|
||||
}
|
||||
|
||||
void TryMatchAssets(TSet<UObject*> &Matches, UClass *Class)
|
||||
{
|
||||
IAssetRegistry& Registry = *IAssetRegistry::Get();
|
||||
TArray<FAssetData> AssetResults;
|
||||
Registry.GetAssetsByClass(Class->GetClassPathName(), AssetResults, true);
|
||||
for (const FAssetData& Data : AssetResults)
|
||||
{
|
||||
if (Matches.Num() == Limit) return;
|
||||
FString Name = Data.AssetName.ToString();
|
||||
if (!Name.Contains(Query, ESearchCase::IgnoreCase)) continue;
|
||||
UObject *Obj = Data.GetAsset();
|
||||
if (UBlueprint* BP = Cast<UBlueprint>(Obj))
|
||||
Obj = BP->GeneratedClass;
|
||||
TryMatchObject(Matches, Obj);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
TSet<UObject*> Matches;
|
||||
TryMatchObjects(Matches, UScriptStruct::StaticClass());
|
||||
TryMatchObjects(Matches, UClass::StaticClass());
|
||||
TryMatchObjects(Matches, UEnum::StaticClass());
|
||||
TryMatchAssets(Matches, UBlueprint::StaticClass());
|
||||
TryMatchAssets(Matches, UUserDefinedStruct::StaticClass());
|
||||
TryMatchAssets(Matches, UUserDefinedEnum::StaticClass());
|
||||
|
||||
TArray<FString> Results;
|
||||
for (const UObject *Obj : Matches)
|
||||
{
|
||||
const TCHAR *Kind = TEXT("Unknown");
|
||||
if (Cast<UEnum>(Obj))
|
||||
Kind = TEXT("Enum");
|
||||
else if (Cast<UScriptStruct>(Obj))
|
||||
Kind = TEXT("Struct");
|
||||
else if (const UClass* Class = Cast<UClass>(Obj))
|
||||
Kind = Class->IsChildOf(UInterface::StaticClass()) ? TEXT("Interface") : TEXT("Class");
|
||||
Results.Add(FString::Printf(TEXT("%s %s\n"), Kind, *UMCPTypes::TypeToText(Obj)));
|
||||
}
|
||||
Results.Sort();
|
||||
for (const auto &Result : Results)
|
||||
{
|
||||
UMCPServer::Print(Result);
|
||||
}
|
||||
if (Results.Num() == Limit)
|
||||
{
|
||||
UMCPServer::Printf(TEXT("Search limit reached, raise it with Limit=\n"));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -9,13 +9,27 @@
|
||||
// Choose Short Name
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
FString UMCPTypes::GetNameWithoutUnderscoreC(const UObject *Obj)
|
||||
{
|
||||
FString Name = Obj->GetName();
|
||||
if (Name.EndsWith(TEXT("_C")))
|
||||
{
|
||||
if (const UClass* Class = Cast<UClass>(Obj))
|
||||
{
|
||||
if (Class->ClassGeneratedBy != nullptr)
|
||||
Name.LeftChopInline(2);
|
||||
}
|
||||
}
|
||||
return Name;
|
||||
}
|
||||
|
||||
void UMCPTypes::ReserveShortName(FName Name)
|
||||
{
|
||||
FString NameStr = Name.ToString();
|
||||
ShortToPath[NameStr.ToLower()] = TEXT("PRIMITIVE");
|
||||
ShortToPath.Add(NameStr.ToLower(), FString(TEXT("PRIMITIVE")));
|
||||
}
|
||||
|
||||
FString UMCPTypes::ChooseShortName(UObject* Obj)
|
||||
FString UMCPTypes::ChooseShortName(const UObject* Obj)
|
||||
{
|
||||
if (!Cast<UScriptStruct>(Obj) && !Cast<UClass>(Obj) && !Cast<UEnum>(Obj))
|
||||
return FString();
|
||||
@@ -24,8 +38,7 @@ FString UMCPTypes::ChooseShortName(UObject* Obj)
|
||||
FString *OldShort = PathToShort.Find(Path);
|
||||
if (OldShort != nullptr) return *OldShort;
|
||||
|
||||
FString Name = Obj->GetName();
|
||||
if (Name.EndsWith(TEXT("_C"))) Name.LeftChopInline(2);
|
||||
FString Name = GetNameWithoutUnderscoreC(Obj);
|
||||
|
||||
FString Lower = Name.ToLower();
|
||||
if (!ShortToPath.Contains(Lower))
|
||||
@@ -40,7 +53,7 @@ FString UMCPTypes::ChooseShortName(UObject* Obj)
|
||||
FString NumberedLower = FString::Printf(TEXT("%s%d"), *Lower, i);
|
||||
if (!ShortToPath.Contains(NumberedLower))
|
||||
{
|
||||
FString NumberedName = FString::Printf(TEXT("%s%d"), *Name, i);
|
||||
FString NumberedName = FString::Printf(TEXT("%s_%d"), *Name, i);
|
||||
ShortToPath.Add(NumberedLower, Path);
|
||||
PathToShort.Add(Path, NumberedName);
|
||||
return NumberedName;
|
||||
@@ -59,31 +72,34 @@ void UMCPTypes::ChooseShortNames(UPackage* Package)
|
||||
}, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// TypeToText
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
FString UMCPTypes::TypeToTextInner(FName Category, FName SubCategory, UObject* SubCategoryObject)
|
||||
{
|
||||
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 ((Category == UEdGraphSchema_K2::PC_Boolean) ||
|
||||
(Category == UEdGraphSchema_K2::PC_Int) ||
|
||||
(Category == UEdGraphSchema_K2::PC_Int64) ||
|
||||
(Category == UEdGraphSchema_K2::PC_Name) ||
|
||||
(Category == UEdGraphSchema_K2::PC_String) ||
|
||||
(Category == UEdGraphSchema_K2::PC_Text))
|
||||
{
|
||||
return Category.ToString();
|
||||
}
|
||||
|
||||
if (Category == UEdGraphSchema_K2::PC_Real)
|
||||
{
|
||||
if (SubCategory == UEdGraphSchema_K2::PC_Float)
|
||||
return TEXT("float");
|
||||
return TEXT("double");
|
||||
return SubCategory.ToString();
|
||||
}
|
||||
|
||||
if (Category == UEdGraphSchema_K2::PC_Byte)
|
||||
{
|
||||
if (SubCategoryObject)
|
||||
return ChooseShortName(SubCategoryObject);
|
||||
return TEXT("uint8");
|
||||
return Category.ToString();
|
||||
}
|
||||
|
||||
if (Category == UEdGraphSchema_K2::PC_Enum)
|
||||
@@ -155,6 +171,13 @@ FString UMCPTypes::TypeToText(const FProperty *Property)
|
||||
}
|
||||
}
|
||||
|
||||
FString UMCPTypes::TypeToText(const UObject* Obj)
|
||||
{
|
||||
UMCPTypes* Types = GEditor->GetEditorSubsystem<UMCPTypes>();
|
||||
if (!Types) return FString();
|
||||
return Types->ChooseShortName(Obj);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Subsystem lifecycle
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -22,6 +22,10 @@ public:
|
||||
static FString TypeToText(const FEdGraphPinType& PinType);
|
||||
static FString TypeToText(const FProperty *Property);
|
||||
|
||||
// Get the short name for a UClass, UScriptStruct, or UEnum.
|
||||
// Returns empty string if the object is not one of those types.
|
||||
static FString TypeToText(const UObject* Obj);
|
||||
|
||||
// Try to parse a type. If there's a problem, returns an error
|
||||
// message. If all goes well, returns empty string.
|
||||
static FString TryTextToType(const FString& Text, FEdGraphPinType& OutPinType);
|
||||
@@ -35,6 +39,10 @@ private:
|
||||
|
||||
bool ResolvePath(const FString &Name, const FString &Path, FEdGraphPinType &OutType);
|
||||
|
||||
// Get the object's name, not including the _C generated
|
||||
// by the blueprint compiler for generated classes.
|
||||
static FString GetNameWithoutUnderscoreC(const UObject *Obj);
|
||||
|
||||
// Reserve the short name for a primitive type.
|
||||
// The value stored in the map is just "PRIMITIVE".
|
||||
void ReserveShortName(FName Name);
|
||||
@@ -43,7 +51,7 @@ private:
|
||||
// choose the same name for two classes. If the object already has
|
||||
// a short name, return it. If it's not a class, struct, enum, or
|
||||
// interface, return empty string.
|
||||
FString ChooseShortName(UObject* Obj);
|
||||
FString ChooseShortName(const UObject* Obj);
|
||||
|
||||
// Choose short names for every type in the package.
|
||||
void ChooseShortNames(UPackage* Package);
|
||||
|
||||
@@ -185,3 +185,4 @@ private:
|
||||
static void AppendNumericSuffix(FString &Name, int32 N);
|
||||
static FString SetPropertyFromJson(void* Container, FProperty* Prop, const FString& FieldName, const FJsonObject* Json);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user