General refactoring

This commit is contained in:
2026-03-13 02:09:19 -04:00
parent 39fc8c6af8
commit a3247b451e
7 changed files with 87 additions and 228 deletions

View File

@@ -12,38 +12,6 @@
#include "K2Node_FunctionEntry.h"
#include "MaterialGraph/MaterialGraphNode.h"
static FString WrapText(const FString& Text, int32 ColLimit, const FString& Prefix)
{
FString Clean = Text;
Clean.ReplaceInline(TEXT("\r\n"), TEXT("\n"));
TArray<FString> Words;
Clean.ParseIntoArrayWS(Words);
TStringBuilder<1024> Result;
int32 Col = 0;
for (const FString& Word : Words)
{
if (Col > 0 && Col + 1 + Word.Len() > ColLimit)
{
Result.Append(TEXT("\n"));
Col = 0;
}
if (Col == 0)
{
Result.Append(Prefix);
Col = Prefix.Len();
}
else
{
Result.Append(TEXT(" "));
Col += 1;
}
Result.Append(Word);
Col += Word.Len();
}
return Result.ToString();
}
FlxBlueprintExporter::FlxBlueprintExporter(UEdGraph* InGraph)
: Graph(InGraph)
{
@@ -347,7 +315,7 @@ void FlxBlueprintExporter::EmitDetails()
if (Node->IsA<UK2Node_Knot>()) continue;
if (Node->IsA<UEdGraphNode_Comment>()) continue;
if (Node->IsA<UK2Node_VariableGet>()) continue;
Details.Appendf(TEXT("details %s\n"), *MCPUtils::FormatName(Node));
Details.Appendf(TEXT("\ndetails %s\n"), *MCPUtils::FormatName(Node));
Details.Appendf(TEXT(" pos %d, %d\n"), Node->NodePosX, Node->NodePosY);
EmitMaterialProperties(Node, Details, false);
@@ -369,7 +337,7 @@ void FlxBlueprintExporter::EmitComments()
Output.Appendf(TEXT("\ncomment %s:\n"), *MCPUtils::FormatName(CommentNode));
// Emit wrapped, indented body.
Output.Append(WrapText(CommentNode->NodeComment, 70, TEXT(" - ")));
Output.Append(MCPUtils::WrapText(CommentNode->NodeComment, 70, TEXT(" - ")));
Output.Append(TEXT("\n"));
// Find contained nodes.

View File

@@ -258,7 +258,9 @@ TStatId UMCPServer::GetStatId() const
FString UMCPServer::HandleRequest(const FString& Line)
{
// Turn the request string into a JSON tree.
TSharedPtr<FJsonObject> Request = MCPUtils::ParseBodyJson(Line);
TSharedPtr<FJsonObject> Request;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Line);
FJsonSerializer::Deserialize(Reader, Request);
if (!Request.IsValid())
{
return TEXT("Request is not valid JSON");
@@ -415,6 +417,6 @@ void UMCPServer::BuildMCPHandlerRegistry()
{
for (UClass* Class : MCPUtils::CollectHandlerClasses())
{
MCPHandlerRegistry.FindOrAdd(MCPUtils::GetToolName(Class)) = Class;
MCPHandlerRegistry.FindOrAdd(MCPUtils::GetHandlerName(Class)) = Class;
}
}

View File

@@ -295,63 +295,63 @@ FString MCPUtils::FormatNodeTitle(const UEdGraphNode *Node)
// JSON helpers
// ============================================================
TSharedPtr<FJsonObject> MCPUtils::ParseBodyJson(const FString& Body)
// ============================================================
// Text formatting
// ============================================================
FString MCPUtils::WrapText(const FString& Text, int32 ColLimit, const FString& Prefix)
{
TSharedPtr<FJsonObject> JsonObj;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Body);
FJsonSerializer::Deserialize(Reader, JsonObj);
return JsonObj;
}
FString Clean = Text;
Clean.ReplaceInline(TEXT("\r\n"), TEXT("\n"));
TArray<FString> Words;
Clean.ParseIntoArrayWS(Words);
FString MCPUtils::UrlDecode(const FString& EncodedString)
{
FString Result;
Result.Reserve(EncodedString.Len());
for (int32 i = 0; i < EncodedString.Len(); ++i)
TStringBuilder<1024> Result;
int32 Col = 0;
for (const FString& Word : Words)
{
TCHAR C = EncodedString[i];
if (C == TEXT('+'))
if (Col > 0 && Col + 1 + Word.Len() > ColLimit)
{
Result += TEXT(' ');
Result.Append(TEXT("\n"));
Col = 0;
}
else if (C == TEXT('%') && i + 2 < EncodedString.Len())
if (Col == 0)
{
FString HexStr = EncodedString.Mid(i + 1, 2);
int32 HexVal = 0;
bool bValid = true;
for (TCHAR H : HexStr)
{
HexVal <<= 4;
if (H >= TEXT('0') && H <= TEXT('9'))
HexVal += H - TEXT('0');
else if (H >= TEXT('a') && H <= TEXT('f'))
HexVal += 10 + H - TEXT('a');
else if (H >= TEXT('A') && H <= TEXT('F'))
HexVal += 10 + H - TEXT('A');
else
{
bValid = false;
break;
}
}
if (bValid)
{
Result += (TCHAR)HexVal;
i += 2;
}
else
{
Result += C;
}
Result.Append(Prefix);
Col = Prefix.Len();
}
else
{
Result += C;
Result.Append(TEXT(" "));
Col += 1;
}
Result.Append(Word);
Col += Word.Len();
}
return Result;
return Result.ToString();
}
// ============================================================
// Enum helpers
// ============================================================
FString MCPUtils::EnumToString(UEnum* Enum, int64 Value, const FString& Prefix)
{
FString Full = Enum->GetNameStringByValue(Value);
if (!Prefix.IsEmpty() && Full.StartsWith(Prefix))
return Full.Mid(Prefix.Len());
return Full;
}
bool MCPUtils::StringToEnum(UEnum* Enum, const FString& Str, int64& OutValue, MCPErrorCallback Error, const FString& Prefix)
{
OutValue = Enum->GetValueByNameString(Prefix + Str);
if (OutValue == INDEX_NONE)
{
Error.SetError(FString::Printf(TEXT("Invalid value '%s' for %s"), *Str, *Enum->GetName()));
return false;
}
return true;
}
// ============================================================
@@ -382,37 +382,6 @@ TArray<UEdGraphNode*> MCPUtils::AllNodes(UBlueprint* BP)
return Nodes;
}
TArray<TSharedPtr<FJsonValue>> MCPUtils::AllGraphNamesJson(UBlueprint* BP)
{
TArray<TSharedPtr<FJsonValue>> Result;
for (UEdGraph* Graph : AllGraphs(BP))
Result.Add(MakeShared<FJsonValueString>(FormatName(Graph)));
return Result;
}
UEdGraphNode* MCPUtils::FindNodeByGuid(
UBlueprint* BP, const FString& GuidString, UEdGraph** OutGraph)
{
FGuid TargetGuid;
FGuid::Parse(GuidString, TargetGuid);
TArray<UEdGraph*> AllGraphs;
BP->GetAllGraphs(AllGraphs);
for (UEdGraph* Graph : AllGraphs)
{
for (UEdGraphNode* Node : Graph->Nodes)
{
if (Node && Node->NodeGuid == TargetGuid)
{
if (OutGraph) *OutGraph = Graph;
return Node;
}
}
}
return nullptr;
}
bool MCPUtils::SaveBlueprintPackage(UBlueprint* BP)
{
UPackage* Package = BP->GetPackage();
@@ -946,12 +915,6 @@ void MCPUtils::FormatMaterialParameter(FStringBuilderBase& Result, const FMateri
}
}
bool MCPUtils::SaveMaterialPackage(UMaterial* Material)
{
if (!Material) return false;
return SaveGenericPackage(Material);
}
bool MCPUtils::SaveGenericPackage(UObject* Asset)
{
if (!Asset) return false;
@@ -1339,15 +1302,15 @@ TArray<UClass*> MCPUtils::CollectHandlerClasses()
if (!Class->ImplementsInterface(UMCPHandler::StaticClass())) continue;
Result.Add(Class);
}
Result.Sort([](UClass& A, UClass& B) { return GetToolName(&A) < GetToolName(&B); });
Result.Sort([](UClass& A, UClass& B) { return GetHandlerName(&A) < GetHandlerName(&B); });
return Result;
}
// ============================================================
// GetToolName — derive tool name from handler class name
// GetHandlerName — derive tool name from handler class name
// ============================================================
FString MCPUtils::GetToolName(UClass* HandlerClass)
FString MCPUtils::GetHandlerName(UClass* HandlerClass)
{
FString Name = HandlerClass->GetName();
// Strip "MCP_" prefix
@@ -1361,10 +1324,10 @@ FString MCPUtils::GetToolName(UClass* HandlerClass)
}
// ============================================================
// GetToolGroup — derive group name from handler class name
// GetHandlerGroup — derive group name from handler class name
// ============================================================
FString MCPUtils::GetToolGroup(UClass* HandlerClass)
FString MCPUtils::GetHandlerGroup(UClass* HandlerClass)
{
FString Name = HandlerClass->GetName();
// Strip "MCP_" prefix
@@ -1400,28 +1363,6 @@ FString MCPUtils::FormatPropertyType(FProperty* Prop)
// GetTemplate
// ============================================================
UObject* MCPUtils::GetTemplate(UObject* Obj, MCPErrorCallback Error)
{
if (!Obj)
{
Error.SetError(TEXT("Object is null"));
return nullptr;
}
// Blueprint → operate on the Class Default Object.
if (UBlueprint* BP = Cast<UBlueprint>(Obj))
{
if (!BP->GeneratedClass)
{
Error.SetError(FString::Printf(TEXT("Blueprint '%s' has no GeneratedClass"), *Obj->GetName()));
return nullptr;
}
return BP->GeneratedClass->GetDefaultObject();
}
return Obj;
}
// ============================================================
// FindPropertyByName
// ============================================================
@@ -1525,7 +1466,11 @@ void MCPUtils::FormatCommandHelp(UClass* HandlerClass, FStringBuilderBase& Resul
const IMCPHandler* Handler = Cast<IMCPHandler>(HandlerClass->GetDefaultObject());
if (!Handler) return;
FString ToolName = GetToolName(HandlerClass);
FString ToolName = GetHandlerName(HandlerClass);
Result.Append(TEXT("\n"));
Result.Append(WrapText(Handler->GetDescription(), 80, TEXT("// ")));
Result.Append(TEXT("\n"));
// Command signature line
Result.Append(ToolName);
@@ -1540,8 +1485,7 @@ void MCPUtils::FormatCommandHelp(UClass* HandlerClass, FStringBuilderBase& Resul
}
Result.Append(TEXT(")\n"));
// Description and parameter details
Result.Appendf(TEXT(" %s\n"), *Handler->GetDescription());
// parameter details
for (TFieldIterator<FProperty> PropIt(HandlerClass, EFieldIterationFlags::None); PropIt; ++PropIt)
{
FProperty* Prop = *PropIt;