This commit is contained in:
2026-03-16 04:56:25 -04:00
parent 81abf87305
commit 46ea58423b
4 changed files with 119 additions and 4 deletions

Binary file not shown.

View File

@@ -31,7 +31,8 @@ public class BlueprintMCP : ModuleRules
"AnimGraphRuntime", "AnimGraphRuntime",
"RHI", "RHI",
"Slate", "Slate",
"SlateCore" "SlateCore",
"ToolMenus"
}); });
} }
} }

View File

@@ -0,0 +1,104 @@
#pragma once
#include "CoreMinimal.h"
#include "MCPHandler.h"
#include "MCPFetcher.h"
#include "MCPUtils.h"
#include "MCPServer.h"
#include "EdGraph/EdGraphNode.h"
#include "EdGraph/EdGraphSchema.h"
#include "ToolMenus.h"
#include "GraphNode_ShowMenu.generated.h"
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
UCLASS()
class UMCP_GraphNode_ShowMenu : public UObject, public IMCPHandler
{
GENERATED_BODY()
public:
UPROPERTY(meta=(Description="Target node"))
FString Node;
virtual FString GetDescription() const override
{
return TEXT("Show context menu actions available for a node and its pins.");
}
virtual void Handle() override
{
MCPFetcher F;
UEdGraphNode* FoundNode = F.Walk(Node).Cast<UEdGraphNode>();
if (!FoundNode) return;
UEdGraph* Graph = FoundNode->GetGraph();
if (!Graph) return;
const UEdGraphSchema* Schema = Graph->GetSchema();
if (!Schema) return;
// Print actions for the node itself (no pin).
PrintActions(FoundNode, Graph, Schema, nullptr);
// Print actions for each pin.
for (UEdGraphPin* Pin : FoundNode->Pins)
{
PrintActions(FoundNode, Graph, Schema, Pin);
}
}
private:
void PrintMenu(UToolMenu* Menu, const TCHAR* Header)
{
bool bAnyEntries = false;
for (const FToolMenuSection& Section : Menu->Sections)
{
for (const FToolMenuEntry& Entry : Section.Blocks)
{
FText Label = Entry.Label.Get();
if (Label.IsEmpty())
continue;
// Check if this is a command-based entry or a direct action.
TSharedPtr<const FUICommandList> OutCommandList;
bool bIsCommand = (Entry.GetActionForCommand(FToolMenuContext(), OutCommandList) != nullptr)
|| OutCommandList.IsValid();
if (!bAnyEntries)
UMCPServer::Printf(TEXT(" %s:\n"), Header);
if (bIsCommand)
UMCPServer::Printf(TEXT(" %s (command)\n"), *Label.ToString());
else
UMCPServer::Printf(TEXT(" %s\n"), *Label.ToString());
bAnyEntries = true;
}
}
}
void PrintActions(UEdGraphNode* FoundNode, UEdGraph* Graph, const UEdGraphSchema* Schema, const UEdGraphPin* Pin)
{
UGraphNodeContextMenuContext* Context = NewObject<UGraphNodeContextMenuContext>();
Context->Init(Graph, FoundNode, Pin, false);
// Print header.
if (Pin)
UMCPServer::Printf(TEXT("\nPin: %s\n"), *MCPUtils::FormatName(Pin));
else
UMCPServer::Printf(TEXT("Node: %s\n"), *MCPUtils::FormatName(FoundNode));
// Gather and print node-level actions.
UToolMenu* NodeMenu = NewObject<UToolMenu>();
FoundNode->GetNodeContextMenuActions(NodeMenu, Context);
PrintMenu(NodeMenu, TEXT("Node Actions"));
// Gather and print schema-level actions.
UToolMenu* SchemaMenu = NewObject<UToolMenu>();
Schema->GetContextMenuActions(SchemaMenu, Context);
PrintMenu(SchemaMenu, TEXT("Schema Actions"));
}
};

View File

@@ -43,8 +43,18 @@ void FBPVarEditor::Dump()
bool FBPVarEditor::ApplyJson(const FJsonObject* Json) bool FBPVarEditor::ApplyJson(const FJsonObject* Json)
{ {
LoadFlags();
bool bHasDefault = Json->HasField(TEXT("DefaultValue")); bool bHasDefault = Json->HasField(TEXT("DefaultValue"));
bool bHasType = Json->HasField(TEXT("VarType"));
if (bHasDefault && bHasType)
{
UMCPServer::Print(TEXT(
"ERROR: Cannot set VarType and DefaultValue in the same call.\n"
"Change the type first, then recompile the blueprint,\n"
"then set the default.\n"));
return false;
}
LoadFlags();
TArray<MCPProperty> Props = MergedProperties(); TArray<MCPProperty> Props = MergedProperties();
if (!MCPJson::PopulateFromJson(Props, Json, true)) if (!MCPJson::PopulateFromJson(Props, Json, true))