Graph export is more sophisticated about details, and GraphNode_Add now shows the node it created.

This commit is contained in:
2026-04-07 21:19:12 -04:00
parent 854e41d6c3
commit b124cf72aa
7 changed files with 86 additions and 64 deletions

View File

@@ -7,6 +7,7 @@
#include "WingProperty.h" #include "WingProperty.h"
#include "WingUtils.h" #include "WingUtils.h"
#include "WingGraphActions.h" #include "WingGraphActions.h"
#include "WingGraphExport.h"
#include "EdGraph/EdGraph.h" #include "EdGraph/EdGraph.h"
#include "EdGraph/EdGraphNode.h" #include "EdGraph/EdGraphNode.h"
#include "EdGraph/EdGraphSchema.h" #include "EdGraph/EdGraphSchema.h"
@@ -82,11 +83,13 @@ public:
UEdGraphNode* NewNode = Entry.Action->Execute(FVector2D(Entry.PosX, Entry.PosY)); UEdGraphNode* NewNode = Entry.Action->Execute(FVector2D(Entry.PosX, Entry.PosY));
if (NewNode) if (NewNode)
{ {
WingOut::Stdout.Printf(TEXT("Spawned: %s %s\n"), *Entry.Type, *WingUtils::FormatName(NewNode)); WingOut::Stdout.Printf(TEXT("Spawned: %s\n"), *Entry.Type);
WingGraphExport Export(NewNode, false, true);
WingOut::Stdout.Print(Export.GetOutput());
} }
else else
{ {
WingOut::Stdout.Printf(TEXT("FAILED: %s\n"), *Entry.Type); WingOut::Stdout.Printf(TEXT("Failed: %s\n\n"), *Entry.Type);
continue; continue;
} }
} }

View File

@@ -21,6 +21,9 @@ public:
UPROPERTY(EditAnywhere, meta=(Description="Target node")) UPROPERTY(EditAnywhere, meta=(Description="Target node"))
FString Node; FString Node;
UPROPERTY(EditAnywhere, meta=(Optional, Description="True to show minor node properties"))
bool Details = false;
virtual void Register() override virtual void Register() override
{ {
UWingServer::AddHandler(this, UWingServer::AddHandler(this,
@@ -33,8 +36,7 @@ private:
UEdGraphNode* NodeObj = F.Walk(Node).Cast<UEdGraphNode>(); UEdGraphNode* NodeObj = F.Walk(Node).Cast<UEdGraphNode>();
if (!NodeObj) return; if (!NodeObj) return;
WingGraphExport Exporter(NodeObj); WingGraphExport Exporter(NodeObj, false, Details);
WingOut::Stdout.Print(*Exporter.GetOutput()); WingOut::Stdout.Print(Exporter.GetOutput());
WingOut::Stdout.Print(Exporter.GetDetails());
} }
}; };

View File

@@ -26,8 +26,8 @@ public:
UPROPERTY(EditAnywhere, meta=(Description="Path to graph")) UPROPERTY(EditAnywhere, meta=(Description="Path to graph"))
FString Graph; FString Graph;
UPROPERTY(EditAnywhere, meta=(Optional, Description="True to include less-significant details")) UPROPERTY(EditAnywhere, meta=(Optional, Description="True to show minor node properties"))
bool IncludeDetails; bool Details = false;
virtual void Register() override virtual void Register() override
{ {
@@ -40,15 +40,7 @@ public:
UEdGraph *G = F.Walk(Graph).Cast<UEdGraph>(); UEdGraph *G = F.Walk(Graph).Cast<UEdGraph>();
if (!G) return; if (!G) return;
WingGraphExport Exporter(G); WingGraphExport Exporter(G, true, Details);
WingOut::Stdout.Print(*Exporter.GetOutput()); WingOut::Stdout.Print(Exporter.GetOutput());
if (IncludeDetails)
{
WingOut::Stdout.Print(Exporter.GetDetails());
}
else
{
WingOut::Stdout.Printf(TEXT("\nNote: use bDetails=true to see suppressed details."));
}
} }
}; };

View File

@@ -13,23 +13,21 @@
#include "MaterialGraph/MaterialGraphNode.h" #include "MaterialGraph/MaterialGraphNode.h"
#include "Kismet2/BlueprintEditorUtils.h" #include "Kismet2/BlueprintEditorUtils.h"
WingGraphExport::WingGraphExport(UEdGraph* InGraph) WingGraphExport::WingGraphExport(UEdGraph* InGraph, bool Locals, bool Details)
: Graph(InGraph) : Graph(InGraph), ShowLocals(Locals), ShowDetails(Details)
{ {
SortNodes(); SortNodes();
EmitLocalVariables(); EmitLocalVariables();
EmitDetails();
EmitGraph(); EmitGraph();
EmitComments(); EmitComments();
} }
WingGraphExport::WingGraphExport(UEdGraphNode* InNode) WingGraphExport::WingGraphExport(UEdGraphNode* InNode, bool Locals, bool Details)
: Graph(InNode->GetGraph()) : Graph(InNode->GetGraph()), ShowLocals(Locals), ShowDetails(Details)
{ {
SortedNodes.Add(InNode); SortedNodes.Add(InNode);
Visited.Add(InNode); Visited.Add(InNode);
EmitLocalVariables(); EmitLocalVariables();
EmitDetails();
EmitGraph(); EmitGraph();
EmitComments(); EmitComments();
} }
@@ -201,10 +199,24 @@ void WingGraphExport::EmitNode(UEdGraphNode* Node)
{ {
if (Node->IsA<UEdGraphNode_Comment>()) return; if (Node->IsA<UEdGraphNode_Comment>()) return;
Output.Appendf(TEXT("\nnode %s: %s\n"), *WingUtils::FormatName(Node), *WingUtils::FormatNodeTitle(Node)); Output.Appendf(TEXT("node %s: %s\n"), *WingUtils::FormatName(Node), *WingUtils::FormatNodeTitle(Node));
Output.Appendf(TEXT(" pos %d, %d\n"), Node->NodePosX, Node->NodePosY);
// Emit node properties (if applicable). // Emit node properties.
EmitNodeProperties(Node, &Output, true); TArray<FWingProperty> Primary, Secondary;
GetProperties(Node, Primary, Secondary);
for (const FWingProperty &Prop : Primary) Prop.Print(Output);
// Emit secondary node properties.
if (ShowDetails || Secondary.Num() < 2)
{
for (const FWingProperty &Prop : Secondary) Prop.Print(Output);
}
else if (Secondary.Num() > 0)
{
Output.Appendf(TEXT(" minor properties: %d\n"), Secondary.Num());
SuppressedDetails = true;
}
// Emit input data pins. // Emit input data pins.
for (UEdGraphPin* Pin : FilterPins(Node, EGPD_Input)) for (UEdGraphPin* Pin : FilterPins(Node, EGPD_Input))
@@ -246,36 +258,37 @@ void WingGraphExport::EmitNode(UEdGraphNode* Node)
else else
Output.Appendf(TEXT(" goto-if %s %s\n"), *WingUtils::FormatName(Pin), *Target); Output.Appendf(TEXT(" goto-if %s %s\n"), *WingUtils::FormatName(Pin), *Target);
} }
Output.Append(TEXT("\n"));
} }
void WingGraphExport::EmitNodeProperties(UEdGraphNode* Node, WingOut Out, bool bPrimary) void WingGraphExport::GetProperties(UEdGraphNode* Node,
TArray<FWingProperty> &Primary, TArray<FWingProperty> &Secondary)
{ {
TArray<FWingProperty> Props = FWingProperty::GetDetails(Node, false); Primary = FWingProperty::GetDetails(Node, false);
Secondary.Empty();
FString PrimaryCategory;
if (UMaterialGraphNode* MatNode = Cast<UMaterialGraphNode>(Node)) if (UMaterialGraphNode* MatNode = Cast<UMaterialGraphNode>(Node))
{ {
PrimaryCategory = MatNode->MaterialExpression->GetClass()->GetName(); FString PrimaryCategory = MatNode->MaterialExpression->GetClass()->GetName();
for (const FWingProperty& P : Props) TArray<FWingProperty> NewPrimary;
for (const FWingProperty& P : Primary)
{ {
FString Category = P.GetCategory(); if (P.GetCategory() == PrimaryCategory) NewPrimary.Add(P);
if ((Category == PrimaryCategory) == bPrimary) else Secondary.Add(P);
P.Print(Out);
} }
} Swap(NewPrimary, Primary);
else if (bPrimary)
{
for (const FWingProperty& P : Props)
P.Print(Out);
} }
} }
void WingGraphExport::EmitLocalVariables() void WingGraphExport::EmitLocalVariables()
{ {
if (!ShowLocals) return;
WingVariables Vars; WingVariables Vars;
Vars.SetBackingStore(Graph, WingOut::Stdout); Vars.SetBackingStore(Graph, WingOut::Stdout);
Vars.Load(WingOut::Stdout); Vars.Load(WingOut::Stdout);
Vars.Print(Output); Vars.Print(Output);
if (!Vars.IsEmpty()) Output.Append(TEXT("\n"));
} }
void WingGraphExport::EmitGraph() void WingGraphExport::EmitGraph()
@@ -284,19 +297,6 @@ void WingGraphExport::EmitGraph()
{ {
EmitNode(Node); EmitNode(Node);
} }
Output.Append(TEXT("\n"));
}
void WingGraphExport::EmitDetails()
{
for (UEdGraphNode* Node : SortedNodes)
{
if (Node->IsA<UEdGraphNode_Comment>()) continue;
Details.Appendf(TEXT("\ndetails %s\n"), *WingUtils::FormatName(Node));
Details.Appendf(TEXT(" pos %d, %d\n"), Node->NodePosX, Node->NodePosY);
EmitNodeProperties(Node, &Details, false);
}
} }
void WingGraphExport::EmitComments() void WingGraphExport::EmitComments()
@@ -311,10 +311,10 @@ void WingGraphExport::EmitComments()
int32 CH = CommentNode->NodeHeight; int32 CH = CommentNode->NodeHeight;
// Emit header. // Emit header.
Output.Appendf(TEXT("\ncomment %s:\n"), *WingUtils::FormatName(CommentNode)); Output.Appendf(TEXT("comment %s:\n"), *WingUtils::FormatName(CommentNode));
// Emit wrapped, indented body. // Emit wrapped, indented body.
Output.Append(WingUtils::WrapText(CommentNode->NodeComment, 70, TEXT(" - "))); Output.Append(WingUtils::WrapText(CommentNode->NodeComment, 70, TEXT(" - ")));
// Find contained nodes. // Find contained nodes.
TArray<FString> ContainedNames; TArray<FString> ContainedNames;
@@ -329,7 +329,16 @@ void WingGraphExport::EmitComments()
if (ContainedNames.Num() > 0) if (ContainedNames.Num() > 0)
{ {
Output.Appendf(TEXT(" applies to: %s\n"), *FString::Join(ContainedNames, TEXT(", "))); Output.Appendf(TEXT(" applies to: %s\n"), *FString::Join(ContainedNames, TEXT(", ")));
} }
Output.Append(TEXT("\n"));
}
}
void WingGraphExport::EmitDetailsSuggestion()
{
if (SuppressedDetails)
{
Output.Appendf(TEXT("Minor node properties were suppressed, use details=true to show.\n\n"));
} }
} }

View File

@@ -232,6 +232,14 @@ void WingVariables::Empty()
OutputVariables.Empty(); OutputVariables.Empty();
} }
bool WingVariables::IsEmpty()
{
return (BlueprintVariables.IsEmpty() &&
LocalVariables.IsEmpty() &&
InputVariables.IsEmpty() &&
OutputVariables.IsEmpty());
}
void WingVariables::ClearLinks() void WingVariables::ClearLinks()
{ {
BlueprintVariables.ClearLinks(); BlueprintVariables.ClearLinks();

View File

@@ -10,11 +10,10 @@
class WingGraphExport class WingGraphExport
{ {
public: public:
WingGraphExport(UEdGraph* InGraph); WingGraphExport(UEdGraph* InGraph, bool Locals, bool Details);
WingGraphExport(UEdGraphNode* InNode); WingGraphExport(UEdGraphNode* InNode, bool Locals, bool Details);
const FString GetOutput() { return Output.ToString(); } const FString GetOutput() { return Output.ToString(); }
const FString GetDetails() { return Details.ToString(); }
private: private:
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
@@ -62,11 +61,12 @@ private:
void Traverse(UEdGraphNode* Node); void Traverse(UEdGraphNode* Node);
void SortNodes(); void SortNodes();
void EmitNode(UEdGraphNode* Node); void EmitNode(UEdGraphNode* Node);
void EmitNodeProperties(UEdGraphNode* Node, WingOut Out, bool bPrimary);
void EmitLocalVariables(); void EmitLocalVariables();
void EmitGraph(); void EmitGraph();
void EmitDetails();
void EmitComments(); void EmitComments();
void EmitDetailsSuggestion();
void GetProperties(UEdGraphNode *Node,
TArray<FWingProperty> &Primary, TArray<FWingProperty> &Secondary);
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// //
@@ -74,8 +74,10 @@ private:
// //
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
UEdGraph* Graph = nullptr;
UEdGraph* Graph; bool ShowLocals = false;
bool ShowDetails = false;
bool SuppressedDetails = false;
// Data populated by passes. // Data populated by passes.
TArray<UEdGraphNode*> SortedNodes; TArray<UEdGraphNode*> SortedNodes;
@@ -83,5 +85,4 @@ private:
// Output buffers. // Output buffers.
TStringBuilder<4096> Output; TStringBuilder<4096> Output;
TStringBuilder<4096> Details;
}; };

View File

@@ -51,9 +51,12 @@ public:
// Constructor. // Constructor.
WingVariableList(const TCHAR *MyListName) : ListName(MyListName) {} WingVariableList(const TCHAR *MyListName) : ListName(MyListName) {}
// Return true if the variables are empty. // Empty the variable list.
void Empty() { Variables.Empty(); } void Empty() { Variables.Empty(); }
// Return true if the variables are empty.
bool IsEmpty() { return Variables.IsEmpty(); }
// Print the variables to a string builder. // Print the variables to a string builder.
void Print(WingOut Out); void Print(WingOut Out);
@@ -107,6 +110,10 @@ public:
void Empty(); void Empty();
// Return true if there are any variables in the workspace.
//
bool IsEmpty();
// Clear the BPVar and Pin fields. // Clear the BPVar and Pin fields.
void ClearLinks(); void ClearLinks();