More work on Blueprint_Dump
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"blueprint-mcp": {
|
"ue-wingman": {
|
||||||
"command": "python3",
|
"command": "python3",
|
||||||
"args": ["tools/mcp-bridge.py"]
|
"args": ["tools/mcp-bridge.py"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
UCLASS(meta=(Group="Unclassified"))
|
UCLASS()
|
||||||
class UMCPHandler_AddMaterialExpression : public UObject, public IMCPHandler
|
class UMCPHandler_AddMaterialExpression : public UObject, public IMCPHandler
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "WingServer.h"
|
|
||||||
#include "WingHandler.h"
|
|
||||||
#include "WingFetcher.h"
|
|
||||||
#include "WingUtils.h"
|
|
||||||
#include "Animation/AnimBlueprint.h"
|
|
||||||
#include "AnimGraphNode_Base.h"
|
|
||||||
#include "AnimBlueprint_ListSlotNames.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
UCLASS()
|
|
||||||
class UWing_AnimBlueprint_ListSlotNames : public UObject, public IWingHandler
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(meta=(Description="Animation Blueprint package path"))
|
|
||||||
FString Blueprint;
|
|
||||||
|
|
||||||
virtual FString GetDescription() const override
|
|
||||||
{
|
|
||||||
return TEXT("List all animation slot names used in an Animation Blueprint.");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Handle() override
|
|
||||||
{
|
|
||||||
WingFetcher F;
|
|
||||||
UAnimBlueprint* AnimBP = F.Asset(Blueprint).Cast<UAnimBlueprint>();
|
|
||||||
if (!AnimBP) return;
|
|
||||||
|
|
||||||
// Walk all anim nodes to collect slot names
|
|
||||||
TSet<FString> SlotNames;
|
|
||||||
for (UAnimGraphNode_Base* AnimNode : WingUtils::AllNodes<UAnimGraphNode_Base>(AnimBP))
|
|
||||||
{
|
|
||||||
for (TFieldIterator<FNameProperty> PropIt(AnimNode->GetClass()); PropIt; ++PropIt)
|
|
||||||
{
|
|
||||||
if (PropIt->GetName().Contains(TEXT("SlotName")) || PropIt->GetName().Contains(TEXT("Slot")))
|
|
||||||
{
|
|
||||||
FName SlotValue = PropIt->GetPropertyValue_InContainer(AnimNode);
|
|
||||||
if (!SlotValue.IsNone())
|
|
||||||
{
|
|
||||||
SlotNames.Add(SlotValue.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const FString& Slot : SlotNames)
|
|
||||||
{
|
|
||||||
UWingServer::Printf(TEXT("%s\n"), *Slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SlotNames.Num() == 0)
|
|
||||||
{
|
|
||||||
UWingServer::Print(TEXT("No animation slot names found.\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "WingServer.h"
|
|
||||||
#include "WingTypes.h"
|
|
||||||
#include "WingHandler.h"
|
|
||||||
#include "WingFetcher.h"
|
|
||||||
#include "WingUtils.h"
|
|
||||||
#include "Engine/Blueprint.h"
|
|
||||||
#include "Animation/AnimBlueprint.h"
|
|
||||||
#include "Animation/Skeleton.h"
|
|
||||||
#include "Engine/SimpleConstructionScript.h"
|
|
||||||
#include "Engine/SCS_Node.h"
|
|
||||||
#include "Blueprint_Dump.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
UCLASS()
|
|
||||||
class UWing_Blueprint_Dump : public UObject, public IWingHandler
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(meta=(Description="Blueprint path"))
|
|
||||||
FString Blueprint;
|
|
||||||
|
|
||||||
virtual FString GetDescription() const override
|
|
||||||
{
|
|
||||||
return TEXT("Dump a Blueprint's structure: variables, interfaces, components, "
|
|
||||||
"and graph names. Does not include graph contents (use Graph_Dump for that).");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Handle() override
|
|
||||||
{
|
|
||||||
WingFetcher F;
|
|
||||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
|
||||||
if (!BP) return;
|
|
||||||
|
|
||||||
// Header
|
|
||||||
UWingServer::Printf(TEXT("Blueprint: %s\n"), *WingUtils::FormatName(BP));
|
|
||||||
UWingServer::Printf(TEXT("Parent: %s\n"), BP->ParentClass ? *WingUtils::FormatName(BP->ParentClass) : TEXT("None"));
|
|
||||||
UWingServer::Printf(TEXT("Type: %s\n"), *WingUtils::EnumToString(BP->BlueprintType));
|
|
||||||
|
|
||||||
// Animation Blueprint
|
|
||||||
if (UAnimBlueprint* AnimBP = Cast<UAnimBlueprint>(BP))
|
|
||||||
{
|
|
||||||
if (AnimBP->TargetSkeleton)
|
|
||||||
UWingServer::Printf(TEXT("TargetSkeleton: %s\n"), *AnimBP->TargetSkeleton->GetPathName());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interfaces
|
|
||||||
for (const FBPInterfaceDescription& I : BP->ImplementedInterfaces)
|
|
||||||
{
|
|
||||||
if (I.Interface)
|
|
||||||
UWingServer::Printf(TEXT("Interface: %s\n"), *WingUtils::FormatName(I.Interface));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variables
|
|
||||||
if (!BP->NewVariables.IsEmpty())
|
|
||||||
{
|
|
||||||
UWingServer::Print(TEXT("\nVariables:\n"));
|
|
||||||
for (const FBPVariableDescription& V : BP->NewVariables)
|
|
||||||
{
|
|
||||||
UWingServer::Printf(TEXT(" %s %s"),
|
|
||||||
*UWingTypes::TypeToText(V.VarType),
|
|
||||||
*WingUtils::FormatName(V));
|
|
||||||
if (!V.DefaultValue.IsEmpty())
|
|
||||||
UWingServer::Printf(TEXT(" = %s"), *V.DefaultValue);
|
|
||||||
if (!V.Category.IsEmpty() && V.Category.ToString() != TEXT("Default"))
|
|
||||||
UWingServer::Printf(TEXT(" [%s]"), *V.Category.ToString());
|
|
||||||
UWingServer::Print(TEXT("\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Components
|
|
||||||
if (USimpleConstructionScript* SCS = BP->SimpleConstructionScript)
|
|
||||||
{
|
|
||||||
const TArray<USCS_Node*>& AllNodes = SCS->GetAllNodes();
|
|
||||||
if (!AllNodes.IsEmpty())
|
|
||||||
{
|
|
||||||
UWingServer::Print(TEXT("\nComponents:\n"));
|
|
||||||
for (USCS_Node* Node : AllNodes)
|
|
||||||
{
|
|
||||||
if (!Node || !Node->ComponentTemplate) continue;
|
|
||||||
UWingServer::Printf(TEXT(" %s (%s)"),
|
|
||||||
*WingUtils::FormatName(Node->ComponentTemplate),
|
|
||||||
*WingUtils::FormatName(Node->ComponentClass));
|
|
||||||
if (Node->ParentComponentOrVariableName != NAME_None)
|
|
||||||
UWingServer::Printf(TEXT(" parent=%s"), *Node->ParentComponentOrVariableName.ToString());
|
|
||||||
UWingServer::Print(TEXT("\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Graph names (without contents)
|
|
||||||
TArray<UEdGraph*> Graphs = WingUtils::AllGraphs(BP);
|
|
||||||
if (!Graphs.IsEmpty())
|
|
||||||
{
|
|
||||||
UWingServer::Print(TEXT("\nGraphs:\n"));
|
|
||||||
for (UEdGraph* Graph : Graphs)
|
|
||||||
UWingServer::Printf(TEXT(" %s\n"), *WingUtils::FormatName(Graph));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "WingServer.h"
|
|
||||||
#include "WingHandler.h"
|
|
||||||
#include "WingFetcher.h"
|
|
||||||
#include "WingUtils.h"
|
|
||||||
#include "Engine/Blueprint.h"
|
|
||||||
#include "Engine/SimpleConstructionScript.h"
|
|
||||||
#include "Engine/SCS_Node.h"
|
|
||||||
#include "Blueprint_ListComponents.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
UCLASS()
|
|
||||||
class UWing_Blueprint_ListComponents : public UObject, public IWingHandler
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(meta=(Description="Path to a blueprint, e.g. /Game/Tangibles/TAN_Tree"))
|
|
||||||
FString Blueprint;
|
|
||||||
|
|
||||||
virtual FString GetDescription() const override
|
|
||||||
{
|
|
||||||
return TEXT("List all components in a Blueprint's SimpleConstructionScript, "
|
|
||||||
"showing hierarchy and component classes.");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Handle() override
|
|
||||||
{
|
|
||||||
WingFetcher F;
|
|
||||||
F.Walk(Blueprint);
|
|
||||||
if (!F.Ok()) return;
|
|
||||||
|
|
||||||
UBlueprint* BP = F.Cast<UBlueprint>();
|
|
||||||
if (!BP) return;
|
|
||||||
|
|
||||||
USimpleConstructionScript* SCS = BP->SimpleConstructionScript;
|
|
||||||
if (!SCS)
|
|
||||||
{
|
|
||||||
UWingServer::Print(TEXT("ERROR: Not an Actor Blueprint (no SimpleConstructionScript)\n"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TArray<USCS_Node*>& RootNodes = SCS->GetRootNodes();
|
|
||||||
const TArray<USCS_Node*>& AllNodes = SCS->GetAllNodes();
|
|
||||||
|
|
||||||
if (AllNodes.Num() == 0)
|
|
||||||
{
|
|
||||||
UWingServer::Print(TEXT("No components.\n"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UWingServer::Print(TEXT("WARNING: This only lists components added in this blueprint's SCS. "
|
|
||||||
"It does not include inherited components from C++ parent classes "
|
|
||||||
"(available via the CDO's OwnedComponents) or from parent blueprint SCS nodes.\n"));
|
|
||||||
|
|
||||||
// Emit components as a tree, starting from root nodes
|
|
||||||
for (USCS_Node* Root : RootNodes)
|
|
||||||
{
|
|
||||||
if (!Root) continue;
|
|
||||||
EmitNode(Root, 0, Root == RootNodes[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void EmitNode(USCS_Node* Node, int32 Depth, bool bIsSceneRoot)
|
|
||||||
{
|
|
||||||
// Indent to show hierarchy
|
|
||||||
for (int32 i = 0; i < Depth; i++)
|
|
||||||
UWingServer::Print(TEXT(" "));
|
|
||||||
|
|
||||||
FString ClassName = Node->ComponentClass
|
|
||||||
? WingUtils::FormatName(Node->ComponentClass)
|
|
||||||
: TEXT("None");
|
|
||||||
|
|
||||||
UWingServer::Printf(TEXT("%s %s"),
|
|
||||||
*ClassName,
|
|
||||||
*WingUtils::FormatName(Node->ComponentTemplate));
|
|
||||||
|
|
||||||
if (bIsSceneRoot && Depth == 0)
|
|
||||||
UWingServer::Print(TEXT(" [SceneRoot]"));
|
|
||||||
|
|
||||||
UWingServer::Print(TEXT("\n"));
|
|
||||||
|
|
||||||
for (USCS_Node* Child : Node->GetChildNodes())
|
|
||||||
{
|
|
||||||
if (!Child) continue;
|
|
||||||
EmitNode(Child, Depth + 1, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "WingServer.h"
|
|
||||||
#include "WingTypes.h"
|
|
||||||
#include "WingHandler.h"
|
|
||||||
#include "WingFetcher.h"
|
|
||||||
#include "WingUtils.h"
|
|
||||||
#include "Engine/Blueprint.h"
|
|
||||||
#include "EdGraph/EdGraph.h"
|
|
||||||
#include "EdGraph/EdGraphPin.h"
|
|
||||||
#include "K2Node_FunctionEntry.h"
|
|
||||||
#include "K2Node_EditablePinBase.h"
|
|
||||||
#include "Kismet2/BlueprintEditorUtils.h"
|
|
||||||
#include "Blueprint_ListEventDispatchers.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
UCLASS()
|
|
||||||
class UWing_Blueprint_ListEventDispatchers : public UObject, public IWingHandler
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(meta=(Description="Path to a blueprint, e.g. /Game/Foo/MyBlueprint"))
|
|
||||||
FString Blueprint;
|
|
||||||
|
|
||||||
virtual FString GetDescription() const override
|
|
||||||
{
|
|
||||||
return TEXT("List all event dispatchers on a Blueprint, including their parameter signatures.");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Handle() override
|
|
||||||
{
|
|
||||||
WingFetcher F;
|
|
||||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
|
||||||
if (!BP) return;
|
|
||||||
|
|
||||||
TSet<FName> DelegateNameSet;
|
|
||||||
FBlueprintEditorUtils::GetDelegateNameList(BP, DelegateNameSet);
|
|
||||||
|
|
||||||
for (const FName& DelegateName : DelegateNameSet)
|
|
||||||
{
|
|
||||||
UWingServer::Printf(TEXT("%s("), *DelegateName.ToString());
|
|
||||||
|
|
||||||
UEdGraph* SigGraph = FBlueprintEditorUtils::GetDelegateSignatureGraphByName(BP, DelegateName);
|
|
||||||
if (SigGraph)
|
|
||||||
{
|
|
||||||
bool bFirst = true;
|
|
||||||
for (UK2Node_FunctionEntry* FE : WingUtils::AllNodes<UK2Node_FunctionEntry>(SigGraph))
|
|
||||||
{
|
|
||||||
for (const TSharedPtr<FUserPinInfo>& PinInfo : FE->UserDefinedPins)
|
|
||||||
{
|
|
||||||
if (!PinInfo.IsValid()) continue;
|
|
||||||
if (!bFirst) UWingServer::Print(TEXT(", "));
|
|
||||||
bFirst = false;
|
|
||||||
UWingServer::Printf(TEXT("%s %s"),
|
|
||||||
*UWingTypes::TypeToText(PinInfo->PinType),
|
|
||||||
*PinInfo->PinName.ToString());
|
|
||||||
}
|
|
||||||
break; // only need the first entry node
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UWingServer::Print(TEXT(")\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DelegateNameSet.Num() == 0)
|
|
||||||
{
|
|
||||||
UWingServer::Print(TEXT("No event dispatchers found.\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "WingServer.h"
|
|
||||||
#include "WingHandler.h"
|
|
||||||
#include "WingFetcher.h"
|
|
||||||
#include "WingUtils.h"
|
|
||||||
#include "Engine/Blueprint.h"
|
|
||||||
#include "Blueprint_ListInterfaces.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
UCLASS()
|
|
||||||
class UWing_Blueprint_ListInterfaces : public UObject, public IWingHandler
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(meta=(Description="Path to a blueprint, e.g. /Game/Foo/MyBlueprint"))
|
|
||||||
FString Blueprint;
|
|
||||||
|
|
||||||
virtual FString GetDescription() const override
|
|
||||||
{
|
|
||||||
return TEXT("List all Blueprint Interfaces implemented by a Blueprint, "
|
|
||||||
"including their function graphs.");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Handle() override
|
|
||||||
{
|
|
||||||
WingFetcher F;
|
|
||||||
F.Walk(Blueprint);
|
|
||||||
if (!F.Ok()) return;
|
|
||||||
UBlueprint* BP = F.Cast<UBlueprint>();
|
|
||||||
if (!BP) return;
|
|
||||||
|
|
||||||
bool bAny = false;
|
|
||||||
for (const FBPInterfaceDescription& IfaceDesc : BP->ImplementedInterfaces)
|
|
||||||
{
|
|
||||||
if (!IfaceDesc.Interface) continue;
|
|
||||||
bAny = true;
|
|
||||||
|
|
||||||
UWingServer::Printf(TEXT("Interface: %s\n"), *WingUtils::FormatName(IfaceDesc.Interface));
|
|
||||||
for (const UEdGraph* Graph : IfaceDesc.Graphs)
|
|
||||||
{
|
|
||||||
if (!Graph) continue;
|
|
||||||
UWingServer::Printf(TEXT(" %s\n"), *WingUtils::FormatName(Graph));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bAny)
|
|
||||||
{
|
|
||||||
UWingServer::Print(TEXT("No interfaces implemented.\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
258
Plugins/UEWingman/Source/UEWingman/Handlers/Blueprint_Dump.h
Normal file
258
Plugins/UEWingman/Source/UEWingman/Handlers/Blueprint_Dump.h
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "WingServer.h"
|
||||||
|
#include "WingTypes.h"
|
||||||
|
#include "WingHandler.h"
|
||||||
|
#include "WingFetcher.h"
|
||||||
|
#include "WingUtils.h"
|
||||||
|
#include "Engine/Blueprint.h"
|
||||||
|
#include "Animation/AnimBlueprint.h"
|
||||||
|
#include "Animation/Skeleton.h"
|
||||||
|
#include "Engine/SimpleConstructionScript.h"
|
||||||
|
#include "Engine/SCS_Node.h"
|
||||||
|
#include "Components/SceneComponent.h"
|
||||||
|
#include "GameFramework/Actor.h"
|
||||||
|
#include "WingFunctionArgs.h"
|
||||||
|
#include "Kismet2/BlueprintEditorUtils.h"
|
||||||
|
#include "AnimationGraph.h"
|
||||||
|
#include "AnimationGraphSchema.h"
|
||||||
|
#include "AnimationStateMachineSchema.h"
|
||||||
|
#include "Blueprint_Dump.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class UWing_Blueprint_Dump : public UObject, public IWingHandler
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UPROPERTY(meta=(Description="Blueprint path"))
|
||||||
|
FString Blueprint;
|
||||||
|
|
||||||
|
virtual FString GetDescription() const override
|
||||||
|
{
|
||||||
|
return TEXT("Dump a Blueprint's structure: variables, interfaces, components, "
|
||||||
|
"and graph names. Does not include graph contents (use Graph_Dump for that).");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Handle() override
|
||||||
|
{
|
||||||
|
WingFetcher F;
|
||||||
|
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||||
|
if (!BP) return;
|
||||||
|
|
||||||
|
// Header
|
||||||
|
UWingServer::Printf(TEXT("Blueprint: %s\n"), *WingUtils::FormatName(BP));
|
||||||
|
UWingServer::Printf(TEXT("Parent: %s\n"), BP->ParentClass ? *WingUtils::FormatName(BP->ParentClass) : TEXT("None"));
|
||||||
|
UWingServer::Printf(TEXT("Type: %s\n"), *WingUtils::EnumToString(BP->BlueprintType));
|
||||||
|
|
||||||
|
// Animation Blueprint
|
||||||
|
if (UAnimBlueprint* AnimBP = Cast<UAnimBlueprint>(BP))
|
||||||
|
{
|
||||||
|
if (AnimBP->TargetSkeleton)
|
||||||
|
UWingServer::Printf(TEXT("TargetSkeleton: %s\n"), *AnimBP->TargetSkeleton->GetPathName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interfaces
|
||||||
|
for (const FBPInterfaceDescription& I : BP->ImplementedInterfaces)
|
||||||
|
{
|
||||||
|
if (I.Interface)
|
||||||
|
UWingServer::Printf(TEXT("Interface: %s\n"), *WingUtils::FormatName(I.Interface));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
if (!BP->NewVariables.IsEmpty())
|
||||||
|
{
|
||||||
|
UWingServer::Print(TEXT("\nVariables:\n"));
|
||||||
|
for (const FBPVariableDescription& V : BP->NewVariables)
|
||||||
|
{
|
||||||
|
UWingServer::Printf(TEXT(" %s %s"),
|
||||||
|
*UWingTypes::TypeToText(V.VarType),
|
||||||
|
*WingUtils::FormatName(V));
|
||||||
|
if (!V.DefaultValue.IsEmpty())
|
||||||
|
UWingServer::Printf(TEXT(" = %s"), *V.DefaultValue);
|
||||||
|
if (!V.Category.IsEmpty() && V.Category.ToString() != TEXT("Default"))
|
||||||
|
UWingServer::Printf(TEXT(" [%s]"), *V.Category.ToString());
|
||||||
|
UWingServer::Print(TEXT("\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Components
|
||||||
|
bool bHasAny = false;
|
||||||
|
if (UClass* GenClass = BP->GeneratedClass)
|
||||||
|
{
|
||||||
|
// Native components first.
|
||||||
|
if (AActor* CDO = Cast<AActor>(GenClass->GetDefaultObject()))
|
||||||
|
{
|
||||||
|
TArray<UActorComponent*> NativeComponents;
|
||||||
|
CDO->GetComponents(NativeComponents);
|
||||||
|
for (UActorComponent* Comp : NativeComponents)
|
||||||
|
{
|
||||||
|
if (!bHasAny) { UWingServer::Print(TEXT("\nComponents:\n")); bHasAny = true; }
|
||||||
|
PrintComponent(Comp, TEXT("native"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blueprint SCS components (this blueprint and parents)
|
||||||
|
TArray<UBlueprint*> Hierarchy;
|
||||||
|
UBlueprint::GetBlueprintHierarchyFromClass(GenClass, Hierarchy);
|
||||||
|
for (int32 i = Hierarchy.Num() - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
UBlueprint* WalkBP = Hierarchy[i];
|
||||||
|
if (!WalkBP->SimpleConstructionScript) continue;
|
||||||
|
const TCHAR* Annotation = (WalkBP == BP) ? nullptr : TEXT("inherited");
|
||||||
|
for (USCS_Node* Node : WalkBP->SimpleConstructionScript->GetAllNodes())
|
||||||
|
{
|
||||||
|
if (!bHasAny) { UWingServer::Print(TEXT("\nComponents:\n")); bHasAny = true; }
|
||||||
|
PrintComponent(Node, Annotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event Dispatchers
|
||||||
|
if (!BP->DelegateSignatureGraphs.IsEmpty())
|
||||||
|
{
|
||||||
|
UWingServer::Print(TEXT("\nEvent Dispatchers:\n"));
|
||||||
|
for (UEdGraph* Graph : BP->DelegateSignatureGraphs)
|
||||||
|
PrintEventDispatcher(Graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Graphs
|
||||||
|
TSet<UEdGraph*> Printed;
|
||||||
|
|
||||||
|
UWingServer::Print(TEXT("\nGraphs:\n"));
|
||||||
|
for (UEdGraph* Graph : BP->UbergraphPages)
|
||||||
|
{
|
||||||
|
UWingServer::Printf(TEXT(" EventGraph %s\n"), *WingUtils::FormatName(Graph));
|
||||||
|
Printed.Add(Graph);
|
||||||
|
}
|
||||||
|
for (UEdGraph* Graph : BP->FunctionGraphs)
|
||||||
|
{
|
||||||
|
if (Graph->IsA<UAnimationGraph>()) continue;
|
||||||
|
PrintGraph(Graph, TEXT("Function"));
|
||||||
|
Printed.Add(Graph);
|
||||||
|
}
|
||||||
|
for (UEdGraph* Graph : BP->MacroGraphs)
|
||||||
|
{
|
||||||
|
PrintGraph(Graph, TEXT("Macro"));
|
||||||
|
Printed.Add(Graph);
|
||||||
|
}
|
||||||
|
for (const FBPInterfaceDescription& I : BP->ImplementedInterfaces)
|
||||||
|
for (UEdGraph* Graph : I.Graphs)
|
||||||
|
{
|
||||||
|
PrintGraph(Graph, TEXT("Interface"), I.Interface);
|
||||||
|
Printed.Add(Graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delegate signature graphs are not real graphs, but mark them as printed.
|
||||||
|
for (UEdGraph* Graph : BP->DelegateSignatureGraphs)
|
||||||
|
Printed.Add(Graph);
|
||||||
|
|
||||||
|
// Animation graphs and state machines.
|
||||||
|
TArray<UEdGraph*> AllGraphs = WingUtils::AllGraphs(BP);
|
||||||
|
|
||||||
|
FString AnimGraphNames;
|
||||||
|
for (UEdGraph* Graph : AllGraphs)
|
||||||
|
{
|
||||||
|
if (Printed.Contains(Graph)) continue;
|
||||||
|
if (!Graph->Schema || !Graph->Schema->IsChildOf(UAnimationGraphSchema::StaticClass())) continue;
|
||||||
|
if (!AnimGraphNames.IsEmpty()) AnimGraphNames += TEXT(", ");
|
||||||
|
AnimGraphNames += WingUtils::FormatName(Graph);
|
||||||
|
Printed.Add(Graph);
|
||||||
|
}
|
||||||
|
if (!AnimGraphNames.IsEmpty())
|
||||||
|
UWingServer::Printf(TEXT("\nAnimation Graphs: %s\n"), *AnimGraphNames);
|
||||||
|
|
||||||
|
FString StateMachineNames;
|
||||||
|
for (UEdGraph* Graph : AllGraphs)
|
||||||
|
{
|
||||||
|
if (Printed.Contains(Graph)) continue;
|
||||||
|
if (!Graph->Schema || !Graph->Schema->IsChildOf(UAnimationStateMachineSchema::StaticClass())) continue;
|
||||||
|
if (!StateMachineNames.IsEmpty()) StateMachineNames += TEXT(", ");
|
||||||
|
StateMachineNames += WingUtils::FormatName(Graph);
|
||||||
|
Printed.Add(Graph);
|
||||||
|
}
|
||||||
|
if (!StateMachineNames.IsEmpty())
|
||||||
|
UWingServer::Printf(TEXT("\nAnimation State Machines: %s\n"), *StateMachineNames);
|
||||||
|
|
||||||
|
// Catch any graphs we missed.
|
||||||
|
for (UEdGraph* Graph : AllGraphs)
|
||||||
|
{
|
||||||
|
if (Printed.Contains(Graph)) continue;
|
||||||
|
UWingServer::Printf(TEXT("WARNING: unlisted graph: %s (%s)\n"),
|
||||||
|
*WingUtils::FormatName(Graph),
|
||||||
|
*WingUtils::FormatName(Graph->GetSchema()->GetClass()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void PrintEventDispatcher(UEdGraph* Graph)
|
||||||
|
{
|
||||||
|
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
||||||
|
TWeakObjectPtr<UK2Node_EditablePinBase> ResultNode;
|
||||||
|
FBlueprintEditorUtils::GetEntryAndResultNodes(Graph, EntryNode, ResultNode);
|
||||||
|
|
||||||
|
FString Args;
|
||||||
|
if (EntryNode.IsValid() && WingFunctionArgs::HasArgs(EntryNode.Get()))
|
||||||
|
Args = WingFunctionArgs::GetArgs(EntryNode.Get());
|
||||||
|
|
||||||
|
UWingServer::Printf(TEXT(" %s(%s)\n"), *WingUtils::FormatName(Graph), *Args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintComponent(USCS_Node* Node, const TCHAR* Annotation = nullptr)
|
||||||
|
{
|
||||||
|
FString ClassName = Node->ComponentClass
|
||||||
|
? WingUtils::FormatName(Node->ComponentClass)
|
||||||
|
: TEXT("None");
|
||||||
|
UWingServer::Printf(TEXT(" %s %s"),
|
||||||
|
*ClassName,
|
||||||
|
*WingUtils::FormatName(Node));
|
||||||
|
if (Node->ParentComponentOrVariableName != NAME_None)
|
||||||
|
UWingServer::Printf(TEXT(" [parent: %s]"), *Node->ParentComponentOrVariableName.ToString());
|
||||||
|
if (Annotation)
|
||||||
|
UWingServer::Printf(TEXT(" [%s]"), Annotation);
|
||||||
|
UWingServer::Print(TEXT("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintComponent(UActorComponent* Comp, const TCHAR* Annotation = nullptr)
|
||||||
|
{
|
||||||
|
UWingServer::Printf(TEXT(" %s %s"),
|
||||||
|
*WingUtils::FormatName(Comp->GetClass()),
|
||||||
|
*Comp->GetName());
|
||||||
|
if (USceneComponent* Scene = Cast<USceneComponent>(Comp))
|
||||||
|
if (USceneComponent* Parent = Scene->GetAttachParent())
|
||||||
|
UWingServer::Printf(TEXT(" [parent: %s]"), *Parent->GetName());
|
||||||
|
if (Annotation)
|
||||||
|
UWingServer::Printf(TEXT(" [%s]"), Annotation);
|
||||||
|
UWingServer::Print(TEXT("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintGraph(UEdGraph* Graph, const TCHAR* Type, UClass* Interface = nullptr)
|
||||||
|
{
|
||||||
|
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
||||||
|
TWeakObjectPtr<UK2Node_EditablePinBase> ResultNode;
|
||||||
|
FBlueprintEditorUtils::GetEntryAndResultNodes(Graph, EntryNode, ResultNode);
|
||||||
|
|
||||||
|
FString InputArgs;
|
||||||
|
FString OutputArgs;
|
||||||
|
if (EntryNode.IsValid() && WingFunctionArgs::HasArgs(EntryNode.Get()))
|
||||||
|
InputArgs = WingFunctionArgs::GetArgs(EntryNode.Get());
|
||||||
|
if (ResultNode.IsValid() && WingFunctionArgs::HasArgs(ResultNode.Get()))
|
||||||
|
OutputArgs = WingFunctionArgs::GetArgs(ResultNode.Get());
|
||||||
|
|
||||||
|
UWingServer::Printf(TEXT(" %s %s"), Type, *WingUtils::FormatName(Graph));
|
||||||
|
if (!InputArgs.IsEmpty())
|
||||||
|
UWingServer::Printf(TEXT("(%s)"), *InputArgs);
|
||||||
|
if (!OutputArgs.IsEmpty())
|
||||||
|
UWingServer::Printf(TEXT(" -> (%s)"), *OutputArgs);
|
||||||
|
if (Interface)
|
||||||
|
UWingServer::Printf(TEXT(" [%s]"), *WingUtils::FormatName(Interface));
|
||||||
|
UWingServer::Print(TEXT("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "Engine/MemberReference.h"
|
#include "Engine/MemberReference.h"
|
||||||
#include "Engine/World.h"
|
#include "Engine/World.h"
|
||||||
#include "Components/ActorComponent.h"
|
#include "Components/ActorComponent.h"
|
||||||
|
#include "Engine/SCS_Node.h"
|
||||||
#include "EdGraph/EdGraph.h"
|
#include "EdGraph/EdGraph.h"
|
||||||
#include "EdGraph/EdGraphNode.h"
|
#include "EdGraph/EdGraphNode.h"
|
||||||
#include "EdGraph/EdGraphPin.h"
|
#include "EdGraph/EdGraphPin.h"
|
||||||
@@ -85,6 +86,11 @@ FString WingUtils::FormatName(const UActorComponent *C)
|
|||||||
return C->GetName();
|
return C->GetName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FString WingUtils::FormatName(const USCS_Node *Node)
|
||||||
|
{
|
||||||
|
return Node->GetVariableName().ToString();
|
||||||
|
}
|
||||||
|
|
||||||
FString WingUtils::FormatName(const UEdGraph *Graph)
|
FString WingUtils::FormatName(const UEdGraph *Graph)
|
||||||
{
|
{
|
||||||
FString Name = Graph->GetName();
|
FString Name = Graph->GetName();
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ class UBlendSpace;
|
|||||||
class UTexture;
|
class UTexture;
|
||||||
class UScriptStruct;
|
class UScriptStruct;
|
||||||
class UEnum;
|
class UEnum;
|
||||||
|
class USCS_Node;
|
||||||
struct FMemberReference;
|
struct FMemberReference;
|
||||||
struct FBPVariableDescription;
|
struct FBPVariableDescription;
|
||||||
// Stateless utility functions used by MCP handlers and the MCP server.
|
// Stateless utility functions used by MCP handlers and the MCP server.
|
||||||
@@ -50,6 +51,7 @@ public:
|
|||||||
static FString FormatName(const UWorld *World);
|
static FString FormatName(const UWorld *World);
|
||||||
static FString FormatName(const UBlueprint *BP);
|
static FString FormatName(const UBlueprint *BP);
|
||||||
static FString FormatName(const UActorComponent *C);
|
static FString FormatName(const UActorComponent *C);
|
||||||
|
static FString FormatName(const USCS_Node *Node);
|
||||||
static FString FormatName(const UEdGraph *Graph);
|
static FString FormatName(const UEdGraph *Graph);
|
||||||
static FString FormatName(const UEdGraphNode* Node);
|
static FString FormatName(const UEdGraphNode* Node);
|
||||||
static FString FormatName(const UEdGraphPin *Pin);
|
static FString FormatName(const UEdGraphPin *Pin);
|
||||||
|
|||||||
Reference in New Issue
Block a user