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
|
// 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)
|
void UMCPTypes::ReserveShortName(FName Name)
|
||||||
{
|
{
|
||||||
FString NameStr = Name.ToString();
|
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))
|
if (!Cast<UScriptStruct>(Obj) && !Cast<UClass>(Obj) && !Cast<UEnum>(Obj))
|
||||||
return FString();
|
return FString();
|
||||||
@@ -24,8 +38,7 @@ FString UMCPTypes::ChooseShortName(UObject* Obj)
|
|||||||
FString *OldShort = PathToShort.Find(Path);
|
FString *OldShort = PathToShort.Find(Path);
|
||||||
if (OldShort != nullptr) return *OldShort;
|
if (OldShort != nullptr) return *OldShort;
|
||||||
|
|
||||||
FString Name = Obj->GetName();
|
FString Name = GetNameWithoutUnderscoreC(Obj);
|
||||||
if (Name.EndsWith(TEXT("_C"))) Name.LeftChopInline(2);
|
|
||||||
|
|
||||||
FString Lower = Name.ToLower();
|
FString Lower = Name.ToLower();
|
||||||
if (!ShortToPath.Contains(Lower))
|
if (!ShortToPath.Contains(Lower))
|
||||||
@@ -40,7 +53,7 @@ FString UMCPTypes::ChooseShortName(UObject* Obj)
|
|||||||
FString NumberedLower = FString::Printf(TEXT("%s%d"), *Lower, i);
|
FString NumberedLower = FString::Printf(TEXT("%s%d"), *Lower, i);
|
||||||
if (!ShortToPath.Contains(NumberedLower))
|
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);
|
ShortToPath.Add(NumberedLower, Path);
|
||||||
PathToShort.Add(Path, NumberedName);
|
PathToShort.Add(Path, NumberedName);
|
||||||
return NumberedName;
|
return NumberedName;
|
||||||
@@ -59,31 +72,34 @@ void UMCPTypes::ChooseShortNames(UPackage* Package)
|
|||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// TypeToText
|
// TypeToText
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
FString UMCPTypes::TypeToTextInner(FName Category, FName SubCategory, UObject* SubCategoryObject)
|
FString UMCPTypes::TypeToTextInner(FName Category, FName SubCategory, UObject* SubCategoryObject)
|
||||||
{
|
{
|
||||||
if (Category == UEdGraphSchema_K2::PC_Boolean) return TEXT("bool");
|
if ((Category == UEdGraphSchema_K2::PC_Boolean) ||
|
||||||
if (Category == UEdGraphSchema_K2::PC_Int) return TEXT("int32");
|
(Category == UEdGraphSchema_K2::PC_Int) ||
|
||||||
if (Category == UEdGraphSchema_K2::PC_Int64) return TEXT("int64");
|
(Category == UEdGraphSchema_K2::PC_Int64) ||
|
||||||
if (Category == UEdGraphSchema_K2::PC_Name) return TEXT("Name");
|
(Category == UEdGraphSchema_K2::PC_Name) ||
|
||||||
if (Category == UEdGraphSchema_K2::PC_String) return TEXT("String");
|
(Category == UEdGraphSchema_K2::PC_String) ||
|
||||||
if (Category == UEdGraphSchema_K2::PC_Text) return TEXT("Text");
|
(Category == UEdGraphSchema_K2::PC_Text))
|
||||||
|
{
|
||||||
|
return Category.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
if (Category == UEdGraphSchema_K2::PC_Real)
|
if (Category == UEdGraphSchema_K2::PC_Real)
|
||||||
{
|
{
|
||||||
if (SubCategory == UEdGraphSchema_K2::PC_Float)
|
return SubCategory.ToString();
|
||||||
return TEXT("float");
|
|
||||||
return TEXT("double");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Category == UEdGraphSchema_K2::PC_Byte)
|
if (Category == UEdGraphSchema_K2::PC_Byte)
|
||||||
{
|
{
|
||||||
if (SubCategoryObject)
|
if (SubCategoryObject)
|
||||||
return ChooseShortName(SubCategoryObject);
|
return ChooseShortName(SubCategoryObject);
|
||||||
return TEXT("uint8");
|
return Category.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Category == UEdGraphSchema_K2::PC_Enum)
|
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
|
// Subsystem lifecycle
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ public:
|
|||||||
static FString TypeToText(const FEdGraphPinType& PinType);
|
static FString TypeToText(const FEdGraphPinType& PinType);
|
||||||
static FString TypeToText(const FProperty *Property);
|
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
|
// Try to parse a type. If there's a problem, returns an error
|
||||||
// message. If all goes well, returns empty string.
|
// message. If all goes well, returns empty string.
|
||||||
static FString TryTextToType(const FString& Text, FEdGraphPinType& OutPinType);
|
static FString TryTextToType(const FString& Text, FEdGraphPinType& OutPinType);
|
||||||
@@ -35,6 +39,10 @@ private:
|
|||||||
|
|
||||||
bool ResolvePath(const FString &Name, const FString &Path, FEdGraphPinType &OutType);
|
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.
|
// Reserve the short name for a primitive type.
|
||||||
// The value stored in the map is just "PRIMITIVE".
|
// The value stored in the map is just "PRIMITIVE".
|
||||||
void ReserveShortName(FName Name);
|
void ReserveShortName(FName Name);
|
||||||
@@ -43,7 +51,7 @@ private:
|
|||||||
// choose the same name for two classes. If the object already has
|
// 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
|
// a short name, return it. If it's not a class, struct, enum, or
|
||||||
// interface, return empty string.
|
// interface, return empty string.
|
||||||
FString ChooseShortName(UObject* Obj);
|
FString ChooseShortName(const UObject* Obj);
|
||||||
|
|
||||||
// Choose short names for every type in the package.
|
// Choose short names for every type in the package.
|
||||||
void ChooseShortNames(UPackage* Package);
|
void ChooseShortNames(UPackage* Package);
|
||||||
|
|||||||
@@ -185,3 +185,4 @@ private:
|
|||||||
static void AppendNumericSuffix(FString &Name, int32 N);
|
static void AppendNumericSuffix(FString &Name, int32 N);
|
||||||
static FString SetPropertyFromJson(void* Container, FProperty* Prop, const FString& FieldName, const FJsonObject* Json);
|
static FString SetPropertyFromJson(void* Container, FProperty* Prop, const FString& FieldName, const FJsonObject* Json);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user