From 6b21fb9674e6313b56f2a2c344517a06473777c6 Mon Sep 17 00:00:00 2001 From: jyelon Date: Sun, 15 Mar 2026 02:53:25 -0400 Subject: [PATCH] Good type-to-text routine in MCP --- Content/Tangibles/TAN_Character.uasset | 4 +- .../Blueprint_ChangeFunctionParameterType.h | 3 +- .../Handlers/Blueprint_ChangeVariableType.h | 7 +- .../BlueprintMCP/Handlers/Blueprint_Dump.h | 3 +- .../Handlers/Blueprint_ListEventDispatchers.h | 3 +- .../Handlers/GraphNode_PrintPinType.h | 8 +- .../Private/BlueprintExporter.cpp | 5 +- .../Source/BlueprintMCP/Private/MCPAssets.cpp | 1 - .../Source/BlueprintMCP/Private/MCPServer.cpp | 6 + .../Source/BlueprintMCP/Private/MCPTypes.cpp | 200 ++++++++++-------- .../Source/BlueprintMCP/Private/MCPUtils.cpp | 15 -- .../Source/BlueprintMCP/Public/MCPTypes.h | 43 ++-- .../Source/BlueprintMCP/Public/MCPUtils.h | 2 - Source/Integration/Tangible.cpp | 2 +- 14 files changed, 171 insertions(+), 131 deletions(-) diff --git a/Content/Tangibles/TAN_Character.uasset b/Content/Tangibles/TAN_Character.uasset index fe08bcdf..1420fe51 100644 --- a/Content/Tangibles/TAN_Character.uasset +++ b/Content/Tangibles/TAN_Character.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06a10b11ff76bacafd20aed5b54ffbd8ef6c1471ac411c5f56bddd617be1a913 -size 371974 +oid sha256:45e83f34d7dd667c2baee9497235404cadf505821373862d355f791ad4181241 +size 375635 diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_ChangeFunctionParameterType.h b/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_ChangeFunctionParameterType.h index 0ea3c3ae..724ab904 100644 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_ChangeFunctionParameterType.h +++ b/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_ChangeFunctionParameterType.h @@ -5,6 +5,7 @@ #include "MCPFetcher.h" #include "MCPUtils.h" #include "MCPServer.h" +#include "MCPTypes.h" #include "Engine/Blueprint.h" #include "EdGraph/EdGraph.h" #include "EdGraph/EdGraphPin.h" @@ -153,7 +154,7 @@ public: bool bSaved = MCPUtils::SaveBlueprintPackage(BP); UMCPServer::Printf(TEXT("Changed '%s' to %s. Save %s.\n"), - *ParamName, *MCPUtils::FormatPinType(NewPinType), + *ParamName, *UMCPTypes::TypeToText(NewPinType), bSaved ? TEXT("succeeded") : TEXT("failed")); } }; diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_ChangeVariableType.h b/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_ChangeVariableType.h index 47e6c9ae..f88d650f 100644 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_ChangeVariableType.h +++ b/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_ChangeVariableType.h @@ -2,6 +2,7 @@ #include "CoreMinimal.h" #include "MCPServer.h" +#include "MCPTypes.h" #include "MCPHandler.h" #include "MCPFetcher.h" #include "MCPUtils.h" @@ -116,8 +117,8 @@ public: { UMCPServer::Printf(TEXT("Dry run: would change %s from %s to %s\n"), *MCPUtils::FormatName(*Found), - *MCPUtils::FormatPinType(Found->VarType), - *MCPUtils::FormatPinType(NewPinType)); + *UMCPTypes::TypeToText(Found->VarType), + *UMCPTypes::TypeToText(NewPinType)); if (bHasAffected) { UMCPServer::Print(TEXT("Affected nodes:\n")); @@ -133,7 +134,7 @@ public: bool bSaved = MCPUtils::SaveBlueprintPackage(BP); UMCPServer::Printf(TEXT("Changed %s to %s.%s\n"), *MCPUtils::FormatName(*Found), - *MCPUtils::FormatPinType(NewPinType), + *UMCPTypes::TypeToText(NewPinType), bSaved ? TEXT("") : TEXT(" WARNING: save failed.")); if (bHasAffected) diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_Dump.h b/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_Dump.h index 0d420429..f0acfb6e 100644 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_Dump.h +++ b/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_Dump.h @@ -2,6 +2,7 @@ #include "CoreMinimal.h" #include "MCPServer.h" +#include "MCPTypes.h" #include "MCPHandler.h" #include "MCPFetcher.h" #include "MCPUtils.h" @@ -65,7 +66,7 @@ public: for (const FBPVariableDescription& V : BP->NewVariables) { UMCPServer::Printf(TEXT(" %s %s"), - *MCPUtils::FormatPinType(V.VarType), + *UMCPTypes::TypeToText(V.VarType), *MCPUtils::FormatName(V)); if (!V.DefaultValue.IsEmpty()) UMCPServer::Printf(TEXT(" = %s"), *V.DefaultValue); diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_ListEventDispatchers.h b/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_ListEventDispatchers.h index ef54aad5..bedb67bf 100644 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_ListEventDispatchers.h +++ b/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/Blueprint_ListEventDispatchers.h @@ -2,6 +2,7 @@ #include "CoreMinimal.h" #include "MCPServer.h" +#include "MCPTypes.h" #include "MCPHandler.h" #include "MCPFetcher.h" #include "MCPUtils.h" @@ -57,7 +58,7 @@ public: if (!bFirst) UMCPServer::Print(TEXT(", ")); bFirst = false; UMCPServer::Printf(TEXT("%s %s"), - *MCPUtils::FormatPinType(PinInfo->PinType), + *UMCPTypes::TypeToText(PinInfo->PinType), *PinInfo->PinName.ToString()); } break; // only need the first entry node diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/GraphNode_PrintPinType.h b/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/GraphNode_PrintPinType.h index 73ce197f..43b90e72 100644 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/GraphNode_PrintPinType.h +++ b/Plugins/BlueprintMCP/Source/BlueprintMCP/Handlers/GraphNode_PrintPinType.h @@ -45,8 +45,12 @@ private: if (!Node->bReadOnly) { UObject *SCO = Node->GetPinTypeNoResolve().PinSubCategoryObject.Get(); - FString Path = SCO ? SCO->GetPathName() : *Node->GetCachedAssetData().GetObjectPathString(); - UMCPServer::Printf(TEXT("%s%s --- %s\n"), *Category, *Desc, *Path); + 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); diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/BlueprintExporter.cpp b/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/BlueprintExporter.cpp index 391adfbb..3ccc4a27 100644 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/BlueprintExporter.cpp +++ b/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/BlueprintExporter.cpp @@ -1,4 +1,5 @@ #include "BlueprintExporter.h" +#include "MCPTypes.h" #include "MCPUtils.h" #include "Engine/Blueprint.h" #include "EdGraph/EdGraph.h" @@ -211,7 +212,7 @@ void FlxBlueprintExporter::EmitNode(UEdGraphNode* Node) if (Pin->bHidden) continue; Output.Appendf(TEXT(" input %s %s = %s\n"), - *MCPUtils::FormatPinType(Pin), + *UMCPTypes::TypeToText(Pin->PinType), *MCPUtils::FormatName(Pin), *FormatPinSource(Pin)); } @@ -290,7 +291,7 @@ void FlxBlueprintExporter::EmitLocalVariables() { FString Default = Var.DefaultValue.IsEmpty() ? TEXT("") : Var.DefaultValue; Output.Appendf(TEXT("local %s %s = %s\n"), - *MCPUtils::FormatPinType(Var.VarType), + *UMCPTypes::TypeToText(Var.VarType), *MCPUtils::FormatName(Var), *Default); } diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPAssets.cpp b/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPAssets.cpp index fa8ee6a5..aff8ac5e 100644 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPAssets.cpp +++ b/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPAssets.cpp @@ -57,7 +57,6 @@ bool MCPAssetsBase::Info() // Query the asset registry IAssetRegistry& AR = FModuleManager::LoadModuleChecked("AssetRegistry").Get(); - while (AR.IsLoadingAssets()) FPlatformProcess::Sleep(0.1f); TArray Candidates; AR.GetAssets(ConfigureFilter(), Candidates); diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPServer.cpp b/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPServer.cpp index 4ea42b77..66fcf856 100644 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPServer.cpp +++ b/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPServer.cpp @@ -398,6 +398,12 @@ void UMCPServer::ClientThreadFunc(UMCPServer* Server, TSharedPtr("AssetRegistry").Get(); + while (AR.IsLoadingAssets()) FPlatformProcess::Sleep(0.25f); + } + // Enqueue the line for game-thread processing TSharedPtr Msg = MakeShared(); Msg->Line = Line; diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPTypes.cpp b/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPTypes.cpp index c1c15d14..71d9e648 100644 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPTypes.cpp +++ b/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPTypes.cpp @@ -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(Obj) && !Cast(Obj) && !Cast(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(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(SubObj)) - return FormatEnumName(Enum); - return TEXT("uint8"); - } - - if (Cat == UEdGraphSchema_K2::PC_Struct) - { - if (UScriptStruct* Struct = Cast(SubObj)) - return FormatStructName(Struct); + if (SubCategoryObject) + return ChooseShortName(SubCategoryObject); return FString(); } - if (Cat == UEdGraphSchema_K2::PC_Object) + if (SubCategoryObject) { - if (UClass* Class = Cast(SubObj)) - return FormatClassName(Class) + TEXT("*"); - return FString(); - } - - if (Cat == UEdGraphSchema_K2::PC_Class) - { - if (UClass* Class = Cast(SubObj)) - return FString::Printf(TEXT("TSubclassOf<%s>"), *FormatClassName(Class)); - return FString(); - } - - if (Cat == UEdGraphSchema_K2::PC_SoftObject) - { - if (UClass* Class = Cast(SubObj)) - return FString::Printf(TEXT("TSoftObjectPtr<%s>"), *FormatClassName(Class)); - return FString(); - } - - if (Cat == UEdGraphSchema_K2::PC_SoftClass) - { - if (UClass* Class = Cast(SubObj)) - return FString::Printf(TEXT("TSoftClassPtr<%s>"), *FormatClassName(Class)); - return FString(); - } - - if (Cat == UEdGraphSchema_K2::PC_Interface) - { - if (UClass* Class = Cast(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(); + 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 Packages; + for (TObjectIterator 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(); +} + diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPUtils.cpp b/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPUtils.cpp index ea056ff7..8ff1c769 100644 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPUtils.cpp +++ b/Plugins/BlueprintMCP/Source/BlueprintMCP/Private/MCPUtils.cpp @@ -251,21 +251,6 @@ bool MCPUtils::Identifies(const FString &Name, const UEdGraphNode* Node) // Formatting other things // ============================================================ -FString MCPUtils::FormatPinType(const FEdGraphPinType& PinType) -{ - if (UObject* SubObj = PinType.PinSubCategoryObject.Get()) - { - return SubObj->GetName(); - } - FString Type = PinType.PinCategory.ToString(); - Type[0] = FChar::ToUpper(Type[0]); - return Type; -} - -FString MCPUtils::FormatPinType(UEdGraphPin* Pin) -{ - return FormatPinType(Pin->PinType); -} FString MCPUtils::FormatNodeTitle(const UEdGraphNode *Node) { diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Public/MCPTypes.h b/Plugins/BlueprintMCP/Source/BlueprintMCP/Public/MCPTypes.h index 9513df51..5bf3088a 100644 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Public/MCPTypes.h +++ b/Plugins/BlueprintMCP/Source/BlueprintMCP/Public/MCPTypes.h @@ -1,10 +1,12 @@ #pragma once #include "CoreMinimal.h" +#include "EditorSubsystem.h" #include "EdGraph/EdGraphPin.h" +#include "MCPTypes.generated.h" // --------------------------------------------------------------------------- -// MCPTypes — converts between FEdGraphPinType and a concise C++-like string. +// UMCPTypes — converts between FEdGraphPinType and a concise C++-like string. // // The text format mirrors GetCPPType where possible: // bool, uint8, int32, int64, float, double, FName, FString, FText @@ -20,27 +22,42 @@ // TypeToText and TextToType are inverses of each other. // --------------------------------------------------------------------------- - - - - - -class MCPTypes +UCLASS() +class UMCPTypes : public UEditorSubsystem { + GENERATED_BODY() + public: - // Convert an FEdGraphPinType to a concise string. - // Returns empty string on failure. - FString TypeToText(const FEdGraphPinType& PinType); + virtual void Initialize(FSubsystemCollectionBase& Collection) override; + virtual void Deinitialize() override; + + // Convert a pin type to a type string. Returns empty string on failure. + static FString TypeToText(const FEdGraphPinType& PinType); // Convert a concise string back to an FEdGraphPinType. // Returns true on success. Prints error via UMCPServer on failure. - bool TextToType(const FString& Text, FEdGraphPinType& OutPinType); + static bool TextToType(const FString& Text, FEdGraphPinType& OutPinType); // Same as TextToType, but does not print an error message on failure. - bool TryTextToType(const FString& Text, FEdGraphPinType& OutPinType); + static bool TryTextToType(const FString& Text, FEdGraphPinType& OutPinType); private: + FString TypeToTextInner(FName Category, FName SubCategory, UObject* SubCategoryObject); + + // Chooses a short name for the specified type, making sure not to + // 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); + + // Choose short names for every type in the package. + void ChooseShortNames(UPackage* Package); + + // Short name registry: bidirectional mapping between short names and full paths. + TMap ShortToPath; // e.g. "vector" -> "/Script/CoreUObject.Vector" + TMap PathToShort; // e.g. "/Script/CoreUObject.Vector" -> "Vector" + + // Parser state (used by TextToType) TArray Tokens; int32 Cursor = 0; - }; diff --git a/Plugins/BlueprintMCP/Source/BlueprintMCP/Public/MCPUtils.h b/Plugins/BlueprintMCP/Source/BlueprintMCP/Public/MCPUtils.h index 3fd1316b..092ff322 100644 --- a/Plugins/BlueprintMCP/Source/BlueprintMCP/Public/MCPUtils.h +++ b/Plugins/BlueprintMCP/Source/BlueprintMCP/Public/MCPUtils.h @@ -93,8 +93,6 @@ public: //////////////////////////////////////////////////////// - static FString FormatPinType(const FEdGraphPinType& PinType); - static FString FormatPinType(UEdGraphPin* Pin); static FString FormatNodeTitle(const UEdGraphNode *Node); // ----- Enum helpers ----- diff --git a/Source/Integration/Tangible.cpp b/Source/Integration/Tangible.cpp index 3081f63d..c598ad38 100644 --- a/Source/Integration/Tangible.cpp +++ b/Source/Integration/Tangible.cpp @@ -266,7 +266,7 @@ bool UlxTangible::AnimationStepIsFinished(AActor *target, const FlxAnimationStep UlxScriptedAnimations *UlxTangible::GetScriptedAnimations(AActor *Target) { - UlxTangible *tan = GetActorTangibleOrLog(Target); + UlxTangible *tan = GetActorTangibleQuiet(Target); if (tan == nullptr) return nullptr; if (tan->ScriptedAnimations == nullptr) {