Moving to use of global MCPServer
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "MCPFetcher.h"
|
||||
#include "MCPServer.h"
|
||||
#include "MCPUtils.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "EdGraph/EdGraph.h"
|
||||
@@ -14,10 +15,12 @@
|
||||
#include "Engine/LevelScriptBlueprint.h"
|
||||
#include "Subsystems/AssetEditorSubsystem.h"
|
||||
|
||||
MCPFetcher& MCPFetcher::SetError(const FString& Msg)
|
||||
void MCPFetcher::SetObj(UObject* InObj) { UMCPServer::AddTouchedObject(InObj); Obj = InObj; ResultPin = nullptr; }
|
||||
void MCPFetcher::SetPin(UEdGraphPin* InPin) { ResultPin = InPin; Obj = nullptr; }
|
||||
|
||||
MCPFetcher& MCPFetcher::SetError()
|
||||
{
|
||||
bError = true;
|
||||
ErrorCB.SetError(Msg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -25,22 +28,22 @@ MCPFetcher& MCPFetcher::TypeMismatch(const TCHAR* Walker, const TCHAR* Expected)
|
||||
{
|
||||
bError = true;
|
||||
if (ResultPin)
|
||||
ErrorCB.SetError(FString::Printf(TEXT("Input to '%s' is a pin, expected %s"), Walker, Expected));
|
||||
UMCPServer::Printf(TEXT("ERROR: Input to '%s' is a pin, expected %s\n"), Walker, Expected);
|
||||
else if (Obj)
|
||||
ErrorCB.SetError(FString::Printf(TEXT("Input to '%s' is %s, expected %s"), Walker, *Obj->GetClass()->GetName(), Expected));
|
||||
UMCPServer::Printf(TEXT("ERROR: Input to '%s' is %s, expected %s\n"), Walker, *Obj->GetClass()->GetName(), Expected);
|
||||
else
|
||||
ErrorCB.SetError(FString::Printf(TEXT("Input to '%s' is null, expected %s"), Walker, Expected));
|
||||
UMCPServer::Printf(TEXT("ERROR: Input to '%s' is null, expected %s\n"), Walker, Expected);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const TArray<MCPFetcher::FWalker>& MCPFetcher::GetWalkerTable()
|
||||
{
|
||||
static const TArray<FWalker> Table = {
|
||||
{ TEXT("graph"), TEXT("Find a named UEdGraph (blank name for material graphs)"), &MCPFetcher::Graph },
|
||||
{ TEXT("node"), TEXT("Find a named UEdGraphNode within a graph or blueprint"), &MCPFetcher::Node },
|
||||
{ TEXT("pin"), TEXT("Find a named UEdGraphPin on a node"), &MCPFetcher::Pin },
|
||||
{ TEXT("component"), TEXT("Find a named component in a Blueprint's SCS"), &MCPFetcher::Component },
|
||||
{ TEXT("levelblueprint"), TEXT("Get the level blueprint from a UWorld"), &MCPFetcher::LevelBlueprint },
|
||||
static TArray<FWalker> Table = {
|
||||
{ TEXT("graph"), TEXT("Find a named UEdGraph (blank name for material graphs)"), &MCPFetcher::Graph },
|
||||
{ TEXT("node"), TEXT("Find a named UEdGraphNode within a graph or blueprint"), &MCPFetcher::Node },
|
||||
{ TEXT("pin"), TEXT("Find a named UEdGraphPin on a node"), &MCPFetcher::Pin },
|
||||
{ TEXT("component"), TEXT("Find a named component in a Blueprint's SCS"), &MCPFetcher::Component },
|
||||
{ TEXT("levelblueprint"), TEXT("Get the level blueprint from a UWorld"), &MCPFetcher::LevelBlueprint },
|
||||
};
|
||||
return Table;
|
||||
}
|
||||
@@ -53,8 +56,8 @@ MCPFetcher& MCPFetcher::Walk(const FString& Path)
|
||||
Path.ParseIntoArray(Segments, TEXT(","));
|
||||
if (Segments.Num() == 0)
|
||||
{
|
||||
SetError(TEXT("Empty path"));
|
||||
return *this;
|
||||
UMCPServer::Print(TEXT("ERROR: Empty path\n"));
|
||||
return SetError();
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < Segments.Num(); i++)
|
||||
@@ -73,8 +76,8 @@ MCPFetcher& MCPFetcher::Walk(const FString& Path)
|
||||
const FWalker* W = GetWalker(Key);
|
||||
if (!W)
|
||||
{
|
||||
SetError(FString::Printf(TEXT("Unknown path step '%s'"), *Key));
|
||||
return *this;
|
||||
UMCPServer::Printf(TEXT("ERROR: Unknown path step '%s'\n"), *Key);
|
||||
return SetError();
|
||||
}
|
||||
(this->*W->Func)(Value);
|
||||
if (bError) return *this;
|
||||
@@ -87,18 +90,27 @@ MCPFetcher& MCPFetcher::Asset(const FString& PackagePath)
|
||||
{
|
||||
SetObj(LoadObject<UObject>(nullptr, *PackagePath));
|
||||
if (!Obj)
|
||||
return SetError(FString::Printf(TEXT("Could not load asset '%s'"), *PackagePath));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Could not load asset '%s'\n"), *PackagePath);
|
||||
return SetError();
|
||||
}
|
||||
|
||||
OriginalAsset = Obj;
|
||||
|
||||
// Open the editor for this asset (or bring it to front if already open).
|
||||
UAssetEditorSubsystem* Sub = GEditor->GetEditorSubsystem<UAssetEditorSubsystem>();
|
||||
if (!Sub || !Sub->OpenEditorForAsset(Obj))
|
||||
return SetError(FString::Printf(TEXT("Could not open editor for '%s'"), *PackagePath));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Could not open editor for '%s'\n"), *PackagePath);
|
||||
return SetError();
|
||||
}
|
||||
|
||||
Editor = Sub->FindEditorForAsset(OriginalAsset, false);
|
||||
if (!Editor)
|
||||
return SetError(FString::Printf(TEXT("Could not find editor instance for '%s'"), *PackagePath));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Could not find editor instance for '%s'\n"), *PackagePath);
|
||||
return SetError();
|
||||
}
|
||||
|
||||
// If this is a material, use the editor's transient copy.
|
||||
if (UMaterial* Mat = ::Cast<UMaterial>(Obj))
|
||||
@@ -114,9 +126,10 @@ bool MCPFetcher::CheckAssetIsA(UClass* StaticClass)
|
||||
if (bError) return false;
|
||||
if (!OriginalAsset || !OriginalAsset->IsA(StaticClass))
|
||||
{
|
||||
SetError(FString::Printf(TEXT("Asset is %s, expected %s"),
|
||||
UMCPServer::Printf(TEXT("ERROR: Asset is %s, expected %s\n"),
|
||||
OriginalAsset ? *OriginalAsset->GetClass()->GetName() : TEXT("null"),
|
||||
*StaticClass->GetName()));
|
||||
*StaticClass->GetName());
|
||||
SetError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -126,7 +139,7 @@ const MCPFetcher::FWalker* MCPFetcher::GetWalker(const FString& Key)
|
||||
{
|
||||
for (const FWalker& W : GetWalkerTable())
|
||||
{
|
||||
if (StrEq(Key, W.Key))
|
||||
if (Key.Equals(W.Key, ESearchCase::IgnoreCase))
|
||||
return &W;
|
||||
}
|
||||
return nullptr;
|
||||
@@ -140,10 +153,16 @@ MCPFetcher& MCPFetcher::Graph(const FString& Value)
|
||||
if (UMaterial* Mat = ::Cast<UMaterial>(Obj))
|
||||
{
|
||||
if (!Value.IsEmpty())
|
||||
return SetError(FString::Printf(TEXT("Materials do not have named graphs (got '%s')"), *Value));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Materials do not have named graphs (got '%s')\n"), *Value);
|
||||
return SetError();
|
||||
}
|
||||
MCPUtils::EnsureMaterialGraph(Mat);
|
||||
if (!Mat->MaterialGraph)
|
||||
return SetError(FString::Printf(TEXT("Material '%s' has no material graph"), *Mat->GetName()));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Material '%s' has no material graph\n"), *Mat->GetName());
|
||||
return SetError();
|
||||
}
|
||||
SetObj(Mat->MaterialGraph);
|
||||
return *this;
|
||||
}
|
||||
@@ -154,9 +173,15 @@ MCPFetcher& MCPFetcher::Graph(const FString& Value)
|
||||
|
||||
TArray<UEdGraph*> Matches = MCPUtils::AllGraphsNamed(BP, Value);
|
||||
if (Matches.Num() == 0)
|
||||
return SetError(FString::Printf(TEXT("Graph '%s' not found in %s"), *Value, *BP->GetName()));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Graph '%s' not found in %s\n"), *Value, *BP->GetName());
|
||||
return SetError();
|
||||
}
|
||||
if (Matches.Num() > 1)
|
||||
return SetError(FString::Printf(TEXT("Ambiguous graph '%s' in %s — %d matches"), *Value, *BP->GetName(), Matches.Num()));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Ambiguous graph '%s' in %s — %d matches\n"), *Value, *BP->GetName(), Matches.Num());
|
||||
return SetError();
|
||||
}
|
||||
|
||||
SetObj(Matches[0]);
|
||||
return *this;
|
||||
@@ -175,11 +200,17 @@ MCPFetcher& MCPFetcher::Node(const FString& Value)
|
||||
if (!N || !MCPUtils::Identifies(Value, N))
|
||||
continue;
|
||||
if (Found)
|
||||
return SetError(FString::Printf(TEXT("Ambiguous node '%s' in graph %s"), *Value, *G->GetName()));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Ambiguous node '%s' in graph %s\n"), *Value, *G->GetName());
|
||||
return SetError();
|
||||
}
|
||||
Found = N;
|
||||
}
|
||||
if (!Found)
|
||||
return SetError(FString::Printf(TEXT("Node '%s' not found in graph %s"), *Value, *G->GetName()));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Node '%s' not found in graph %s\n"), *Value, *G->GetName());
|
||||
return SetError();
|
||||
}
|
||||
SetObj(Found);
|
||||
return *this;
|
||||
}
|
||||
@@ -195,12 +226,18 @@ MCPFetcher& MCPFetcher::Node(const FString& Value)
|
||||
if (!N || !MCPUtils::Identifies(Value, N))
|
||||
continue;
|
||||
if (Found)
|
||||
return SetError(FString::Printf(TEXT("Ambiguous node '%s' in %s"), *Value, *BP->GetName()));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Ambiguous node '%s' in %s\n"), *Value, *BP->GetName());
|
||||
return SetError();
|
||||
}
|
||||
Found = N;
|
||||
}
|
||||
}
|
||||
if (!Found)
|
||||
return SetError(FString::Printf(TEXT("Node '%s' not found in %s"), *Value, *BP->GetName()));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Node '%s' not found in %s\n"), *Value, *BP->GetName());
|
||||
return SetError();
|
||||
}
|
||||
SetObj(Found);
|
||||
return *this;
|
||||
}
|
||||
@@ -221,13 +258,19 @@ MCPFetcher& MCPFetcher::Pin(const FString& Value)
|
||||
if (!MCPUtils::Identifies(Value, P))
|
||||
continue;
|
||||
if (Found)
|
||||
return SetError(FString::Printf(TEXT("Ambiguous pin '%s' on node %s"),
|
||||
*Value, *MCPUtils::FormatName(N)));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Ambiguous pin '%s' on node %s\n"),
|
||||
*Value, *MCPUtils::FormatName(N));
|
||||
return SetError();
|
||||
}
|
||||
Found = P;
|
||||
}
|
||||
if (!Found)
|
||||
return SetError(FString::Printf(TEXT("Pin '%s' not found on node %s"),
|
||||
*Value, *MCPUtils::FormatName(N)));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Pin '%s' not found on node %s\n"),
|
||||
*Value, *MCPUtils::FormatName(N));
|
||||
return SetError();
|
||||
}
|
||||
|
||||
SetPin(Found);
|
||||
return *this;
|
||||
@@ -243,7 +286,10 @@ MCPFetcher& MCPFetcher::Component(const FString& Value)
|
||||
|
||||
USimpleConstructionScript* SCS = BP->SimpleConstructionScript;
|
||||
if (!SCS)
|
||||
return SetError(FString::Printf(TEXT("Blueprint %s has no SimpleConstructionScript (not an Actor Blueprint)"), *BP->GetName()));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Blueprint %s has no SimpleConstructionScript (not an Actor Blueprint)\n"), *BP->GetName());
|
||||
return SetError();
|
||||
}
|
||||
|
||||
FName SearchName(*Value);
|
||||
for (USCS_Node* SCSNode : SCS->GetAllNodes())
|
||||
@@ -255,7 +301,8 @@ MCPFetcher& MCPFetcher::Component(const FString& Value)
|
||||
}
|
||||
}
|
||||
|
||||
return SetError(FString::Printf(TEXT("Component '%s' not found in %s"), *Value, *BP->GetName()));
|
||||
UMCPServer::Printf(TEXT("ERROR: Component '%s' not found in %s\n"), *Value, *BP->GetName());
|
||||
return SetError();
|
||||
}
|
||||
|
||||
MCPFetcher& MCPFetcher::LevelBlueprint(const FString& Value)
|
||||
@@ -267,11 +314,17 @@ MCPFetcher& MCPFetcher::LevelBlueprint(const FString& Value)
|
||||
return TypeMismatch(TEXT("levelblueprint"), TEXT("World"));
|
||||
|
||||
if (!World->PersistentLevel)
|
||||
return SetError(TEXT("World has no PersistentLevel"));
|
||||
{
|
||||
UMCPServer::Print(TEXT("ERROR: World has no PersistentLevel\n"));
|
||||
return SetError();
|
||||
}
|
||||
|
||||
ULevelScriptBlueprint* LevelBP = World->PersistentLevel->GetLevelScriptBlueprint(true);
|
||||
if (!LevelBP)
|
||||
return SetError(TEXT("World has no level blueprint"));
|
||||
{
|
||||
UMCPServer::Print(TEXT("ERROR: World has no level blueprint\n"));
|
||||
return SetError();
|
||||
}
|
||||
|
||||
SetObj(LevelBP);
|
||||
return *this;
|
||||
@@ -281,12 +334,18 @@ MCPFetcher& MCPFetcher::Template()
|
||||
{
|
||||
if (bError) return *this;
|
||||
if (!Obj)
|
||||
return SetError(TEXT("Template: object is null"));
|
||||
{
|
||||
UMCPServer::Print(TEXT("ERROR: Template: object is null\n"));
|
||||
return SetError();
|
||||
}
|
||||
|
||||
if (UBlueprint* BP = ::Cast<UBlueprint>(Obj))
|
||||
{
|
||||
if (!BP->GeneratedClass)
|
||||
return SetError(FString::Printf(TEXT("Blueprint '%s' has no GeneratedClass"), *Obj->GetName()));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: Blueprint '%s' has no GeneratedClass\n"), *Obj->GetName());
|
||||
return SetError();
|
||||
}
|
||||
SetObj(BP->GeneratedClass->GetDefaultObject());
|
||||
return *this;
|
||||
}
|
||||
@@ -303,10 +362,16 @@ MCPFetcher& MCPFetcher::ToBlueprint()
|
||||
if (UWorld* World = ::Cast<UWorld>(Obj))
|
||||
{
|
||||
if (!World->PersistentLevel)
|
||||
return SetError(TEXT("ToBlueprint: World has no PersistentLevel"));
|
||||
{
|
||||
UMCPServer::Print(TEXT("ERROR: ToBlueprint: World has no PersistentLevel\n"));
|
||||
return SetError();
|
||||
}
|
||||
ULevelScriptBlueprint* LevelBP = World->PersistentLevel->GetLevelScriptBlueprint(true);
|
||||
if (!LevelBP)
|
||||
return SetError(TEXT("ToBlueprint: World has no level blueprint"));
|
||||
{
|
||||
UMCPServer::Print(TEXT("ERROR: ToBlueprint: World has no level blueprint\n"));
|
||||
return SetError();
|
||||
}
|
||||
SetObj(LevelBP);
|
||||
return *this;
|
||||
}
|
||||
@@ -323,11 +388,13 @@ MCPFetcher& MCPFetcher::ToGraph()
|
||||
{
|
||||
MCPUtils::EnsureMaterialGraph(Mat);
|
||||
if (!Mat->MaterialGraph)
|
||||
return SetError(FString::Printf(TEXT("ToGraph: Material '%s' has no material graph"), *Mat->GetName()));
|
||||
{
|
||||
UMCPServer::Printf(TEXT("ERROR: ToGraph: Material '%s' has no material graph\n"), *Mat->GetName());
|
||||
return SetError();
|
||||
}
|
||||
SetObj(Mat->MaterialGraph);
|
||||
return *this;
|
||||
}
|
||||
|
||||
return TypeMismatch(TEXT("ToGraph"), TEXT("Graph or Material"));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user