From b124cf72aa9816d71435210aa76bac406ae9e6cf Mon Sep 17 00:00:00 2001 From: jyelon Date: Tue, 7 Apr 2026 21:19:12 -0400 Subject: [PATCH] Graph export is more sophisticated about details, and GraphNode_Add now shows the node it created. --- .../Source/UEWingman/Handlers/GraphNode_Add.h | 7 +- .../UEWingman/Handlers/GraphNode_Dump.h | 8 +- .../Source/UEWingman/Handlers/Graph_Dump.h | 16 +--- .../UEWingman/Private/WingGraphExport.cpp | 85 ++++++++++--------- .../UEWingman/Private/WingVariables.cpp | 8 ++ .../Source/UEWingman/Public/WingGraphExport.h | 17 ++-- .../Source/UEWingman/Public/WingVariables.h | 9 +- 7 files changed, 86 insertions(+), 64 deletions(-) diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_Add.h b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_Add.h index b47954ee..3cb47bf3 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_Add.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_Add.h @@ -7,6 +7,7 @@ #include "WingProperty.h" #include "WingUtils.h" #include "WingGraphActions.h" +#include "WingGraphExport.h" #include "EdGraph/EdGraph.h" #include "EdGraph/EdGraphNode.h" #include "EdGraph/EdGraphSchema.h" @@ -82,11 +83,13 @@ public: UEdGraphNode* NewNode = Entry.Action->Execute(FVector2D(Entry.PosX, Entry.PosY)); 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 { - WingOut::Stdout.Printf(TEXT("FAILED: %s\n"), *Entry.Type); + WingOut::Stdout.Printf(TEXT("Failed: %s\n\n"), *Entry.Type); continue; } } diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_Dump.h b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_Dump.h index 8d1012c3..52cae633 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_Dump.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_Dump.h @@ -21,6 +21,9 @@ public: UPROPERTY(EditAnywhere, meta=(Description="Target node")) FString Node; + UPROPERTY(EditAnywhere, meta=(Optional, Description="True to show minor node properties")) + bool Details = false; + virtual void Register() override { UWingServer::AddHandler(this, @@ -33,8 +36,7 @@ private: UEdGraphNode* NodeObj = F.Walk(Node).Cast(); if (!NodeObj) return; - WingGraphExport Exporter(NodeObj); - WingOut::Stdout.Print(*Exporter.GetOutput()); - WingOut::Stdout.Print(Exporter.GetDetails()); + WingGraphExport Exporter(NodeObj, false, Details); + WingOut::Stdout.Print(Exporter.GetOutput()); } }; diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Graph_Dump.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Graph_Dump.h index 81f475cc..11fc1891 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Graph_Dump.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Graph_Dump.h @@ -26,8 +26,8 @@ public: UPROPERTY(EditAnywhere, meta=(Description="Path to graph")) FString Graph; - UPROPERTY(EditAnywhere, meta=(Optional, Description="True to include less-significant details")) - bool IncludeDetails; + UPROPERTY(EditAnywhere, meta=(Optional, Description="True to show minor node properties")) + bool Details = false; virtual void Register() override { @@ -40,15 +40,7 @@ public: UEdGraph *G = F.Walk(Graph).Cast(); if (!G) return; - WingGraphExport Exporter(G); - 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.")); - } + WingGraphExport Exporter(G, true, Details); + WingOut::Stdout.Print(Exporter.GetOutput()); } }; diff --git a/Plugins/UEWingman/Source/UEWingman/Private/WingGraphExport.cpp b/Plugins/UEWingman/Source/UEWingman/Private/WingGraphExport.cpp index 21210ab4..df339492 100644 --- a/Plugins/UEWingman/Source/UEWingman/Private/WingGraphExport.cpp +++ b/Plugins/UEWingman/Source/UEWingman/Private/WingGraphExport.cpp @@ -13,23 +13,21 @@ #include "MaterialGraph/MaterialGraphNode.h" #include "Kismet2/BlueprintEditorUtils.h" -WingGraphExport::WingGraphExport(UEdGraph* InGraph) - : Graph(InGraph) +WingGraphExport::WingGraphExport(UEdGraph* InGraph, bool Locals, bool Details) + : Graph(InGraph), ShowLocals(Locals), ShowDetails(Details) { SortNodes(); EmitLocalVariables(); - EmitDetails(); EmitGraph(); EmitComments(); } -WingGraphExport::WingGraphExport(UEdGraphNode* InNode) - : Graph(InNode->GetGraph()) +WingGraphExport::WingGraphExport(UEdGraphNode* InNode, bool Locals, bool Details) + : Graph(InNode->GetGraph()), ShowLocals(Locals), ShowDetails(Details) { SortedNodes.Add(InNode); Visited.Add(InNode); EmitLocalVariables(); - EmitDetails(); EmitGraph(); EmitComments(); } @@ -201,11 +199,25 @@ void WingGraphExport::EmitNode(UEdGraphNode* Node) { if (Node->IsA()) 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). - EmitNodeProperties(Node, &Output, true); + // Emit node properties. + TArray 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. for (UEdGraphPin* Pin : FilterPins(Node, EGPD_Input)) { @@ -246,36 +258,37 @@ void WingGraphExport::EmitNode(UEdGraphNode* Node) else 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 &Primary, TArray &Secondary) { - TArray Props = FWingProperty::GetDetails(Node, false); + Primary = FWingProperty::GetDetails(Node, false); + Secondary.Empty(); - FString PrimaryCategory; if (UMaterialGraphNode* MatNode = Cast(Node)) { - PrimaryCategory = MatNode->MaterialExpression->GetClass()->GetName(); - for (const FWingProperty& P : Props) + FString PrimaryCategory = MatNode->MaterialExpression->GetClass()->GetName(); + TArray NewPrimary; + for (const FWingProperty& P : Primary) { - FString Category = P.GetCategory(); - if ((Category == PrimaryCategory) == bPrimary) - P.Print(Out); + if (P.GetCategory() == PrimaryCategory) NewPrimary.Add(P); + else Secondary.Add(P); } - } - else if (bPrimary) - { - for (const FWingProperty& P : Props) - P.Print(Out); + Swap(NewPrimary, Primary); } } void WingGraphExport::EmitLocalVariables() { + if (!ShowLocals) return; WingVariables Vars; Vars.SetBackingStore(Graph, WingOut::Stdout); Vars.Load(WingOut::Stdout); Vars.Print(Output); + if (!Vars.IsEmpty()) Output.Append(TEXT("\n")); } void WingGraphExport::EmitGraph() @@ -284,19 +297,6 @@ void WingGraphExport::EmitGraph() { EmitNode(Node); } - Output.Append(TEXT("\n")); -} - -void WingGraphExport::EmitDetails() -{ - for (UEdGraphNode* Node : SortedNodes) - { - if (Node->IsA()) 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() @@ -311,10 +311,10 @@ void WingGraphExport::EmitComments() int32 CH = CommentNode->NodeHeight; // Emit header. - Output.Appendf(TEXT("\ncomment %s:\n"), *WingUtils::FormatName(CommentNode)); + Output.Appendf(TEXT("comment %s:\n"), *WingUtils::FormatName(CommentNode)); // Emit wrapped, indented body. - Output.Append(WingUtils::WrapText(CommentNode->NodeComment, 70, TEXT(" - "))); + Output.Append(WingUtils::WrapText(CommentNode->NodeComment, 70, TEXT(" - "))); // Find contained nodes. TArray ContainedNames; @@ -329,7 +329,16 @@ void WingGraphExport::EmitComments() 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")); } } diff --git a/Plugins/UEWingman/Source/UEWingman/Private/WingVariables.cpp b/Plugins/UEWingman/Source/UEWingman/Private/WingVariables.cpp index 17c8d86d..a49ca259 100644 --- a/Plugins/UEWingman/Source/UEWingman/Private/WingVariables.cpp +++ b/Plugins/UEWingman/Source/UEWingman/Private/WingVariables.cpp @@ -232,6 +232,14 @@ void WingVariables::Empty() OutputVariables.Empty(); } +bool WingVariables::IsEmpty() +{ + return (BlueprintVariables.IsEmpty() && + LocalVariables.IsEmpty() && + InputVariables.IsEmpty() && + OutputVariables.IsEmpty()); +} + void WingVariables::ClearLinks() { BlueprintVariables.ClearLinks(); diff --git a/Plugins/UEWingman/Source/UEWingman/Public/WingGraphExport.h b/Plugins/UEWingman/Source/UEWingman/Public/WingGraphExport.h index a3592759..f3e5f0d0 100644 --- a/Plugins/UEWingman/Source/UEWingman/Public/WingGraphExport.h +++ b/Plugins/UEWingman/Source/UEWingman/Public/WingGraphExport.h @@ -10,11 +10,10 @@ class WingGraphExport { public: - WingGraphExport(UEdGraph* InGraph); - WingGraphExport(UEdGraphNode* InNode); + WingGraphExport(UEdGraph* InGraph, bool Locals, bool Details); + WingGraphExport(UEdGraphNode* InNode, bool Locals, bool Details); const FString GetOutput() { return Output.ToString(); } - const FString GetDetails() { return Details.ToString(); } private: //////////////////////////////////////////////////////// @@ -62,11 +61,12 @@ private: void Traverse(UEdGraphNode* Node); void SortNodes(); void EmitNode(UEdGraphNode* Node); - void EmitNodeProperties(UEdGraphNode* Node, WingOut Out, bool bPrimary); void EmitLocalVariables(); void EmitGraph(); - void EmitDetails(); void EmitComments(); + void EmitDetailsSuggestion(); + void GetProperties(UEdGraphNode *Node, + TArray &Primary, TArray &Secondary); //////////////////////////////////////////////////////// // @@ -74,8 +74,10 @@ private: // //////////////////////////////////////////////////////// - - UEdGraph* Graph; + UEdGraph* Graph = nullptr; + bool ShowLocals = false; + bool ShowDetails = false; + bool SuppressedDetails = false; // Data populated by passes. TArray SortedNodes; @@ -83,5 +85,4 @@ private: // Output buffers. TStringBuilder<4096> Output; - TStringBuilder<4096> Details; }; diff --git a/Plugins/UEWingman/Source/UEWingman/Public/WingVariables.h b/Plugins/UEWingman/Source/UEWingman/Public/WingVariables.h index b1987923..32c415ac 100644 --- a/Plugins/UEWingman/Source/UEWingman/Public/WingVariables.h +++ b/Plugins/UEWingman/Source/UEWingman/Public/WingVariables.h @@ -51,9 +51,12 @@ public: // Constructor. WingVariableList(const TCHAR *MyListName) : ListName(MyListName) {} - // Return true if the variables are empty. + // Empty the variable list. void Empty() { Variables.Empty(); } + // Return true if the variables are empty. + bool IsEmpty() { return Variables.IsEmpty(); } + // Print the variables to a string builder. void Print(WingOut Out); @@ -107,6 +110,10 @@ public: void Empty(); + // Return true if there are any variables in the workspace. + // + bool IsEmpty(); + // Clear the BPVar and Pin fields. void ClearLinks();