Better graph dump that shows exec pin names so that the AI knows how to connect them.
This commit is contained in:
@@ -38,6 +38,13 @@ WingGraphExport::WingGraphExport(UEdGraphNode* InNode, bool Locals, bool Details
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
bool WingGraphExport::IsLinked(UEdGraphPin* Pin)
|
||||
{
|
||||
if (Pin == nullptr) return false;
|
||||
if (Pin->LinkedTo.IsEmpty()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
UEdGraphPin* WingGraphExport::GetLinkedTo(UEdGraphPin* Pin)
|
||||
{
|
||||
if (Pin == nullptr) return nullptr;
|
||||
@@ -64,13 +71,16 @@ bool WingGraphExport::IsDefaultToSelf(UEdGraphPin* Pin)
|
||||
return Pin->PinName.ToString() == DefaultToSelfPinName;
|
||||
}
|
||||
|
||||
TArray<UEdGraphPin*> WingGraphExport::FilterPins(UEdGraphNode* Node, EEdGraphPinDirection Direction, FName Category)
|
||||
TArray<UEdGraphPin*> WingGraphExport::GetPins(
|
||||
UEdGraphNode* Node, EEdGraphPinDirection Direction, PinKind Kind)
|
||||
{
|
||||
TArray<UEdGraphPin*> Result;
|
||||
for (UEdGraphPin* Pin : Node->Pins)
|
||||
{
|
||||
if (Direction != EGPD_MAX && Pin->Direction != Direction) continue;
|
||||
if (!Category.IsNone() && Pin->PinType.PinCategory != Category) continue;
|
||||
if (Pin->bHidden) continue;
|
||||
if (Pin->Direction != Direction) continue;
|
||||
if ((Kind == PK_VALUE) && (Pin->PinType.PinCategory == UEdGraphSchema_K2::PC_Exec)) continue;
|
||||
if ((Kind == PK_EXEC) && (Pin->PinType.PinCategory != UEdGraphSchema_K2::PC_Exec)) continue;
|
||||
Result.Add(Pin);
|
||||
}
|
||||
return Result;
|
||||
@@ -78,78 +88,23 @@ TArray<UEdGraphPin*> WingGraphExport::FilterPins(UEdGraphNode* Node, EEdGraphPin
|
||||
|
||||
bool WingGraphExport::HasExecPin(UEdGraphNode* Node, EEdGraphPinDirection Direction)
|
||||
{
|
||||
return FilterPins(Node, Direction, UEdGraphSchema_K2::PC_Exec).Num() > 0;
|
||||
}
|
||||
|
||||
UEdGraphPin* WingGraphExport::FindFirstPin(UEdGraphNode* Node, EEdGraphPinDirection Direction)
|
||||
{
|
||||
for (UEdGraphPin* Pin : Node->Pins)
|
||||
{
|
||||
if (Pin->Direction == Direction) return Pin;
|
||||
}
|
||||
return nullptr;
|
||||
return GetPins(Node, Direction, PK_EXEC).Num() > 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Traverse and Emit the Nodes.
|
||||
// Traversal
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
FString WingGraphExport::FormatPinSource(UEdGraphPin* Pin)
|
||||
{
|
||||
// If connected, show source node.pin
|
||||
UEdGraphPin* LinkedTo = GetLinkedTo(Pin);
|
||||
if (LinkedTo != nullptr)
|
||||
{
|
||||
UEdGraphNode* LinkedToNode = LinkedTo->GetOwningNode();
|
||||
FString PinLabel = WingUtils::FormatName(LinkedTo);
|
||||
return FString::Printf(TEXT("%s.%s"), *WingUtils::FormatName(LinkedToNode), *PinLabel);
|
||||
}
|
||||
|
||||
// String pins: always show in quotes (even if empty).
|
||||
FName Category = Pin->PinType.PinCategory;
|
||||
if (Category == UEdGraphSchema_K2::PC_String ||
|
||||
Category == UEdGraphSchema_K2::PC_Name ||
|
||||
Category == UEdGraphSchema_K2::PC_Text)
|
||||
{
|
||||
return FString::Printf(TEXT("\"%s\""), *Pin->DefaultValue);
|
||||
}
|
||||
|
||||
// If has a non-empty default, show it.
|
||||
if (!Pin->DefaultValue.IsEmpty())
|
||||
{
|
||||
return Pin->DefaultValue;
|
||||
}
|
||||
|
||||
if (Pin->DefaultObject)
|
||||
{
|
||||
return Pin->DefaultObject->GetName();
|
||||
}
|
||||
|
||||
if (!Pin->DefaultTextValue.IsEmpty())
|
||||
{
|
||||
return FString::Printf(TEXT("\"%s\""), *Pin->DefaultTextValue.ToString());
|
||||
}
|
||||
|
||||
if (IsDefaultToSelf(Pin))
|
||||
{
|
||||
return TEXT("<self>");
|
||||
}
|
||||
else
|
||||
{
|
||||
return TEXT("<default>");
|
||||
}
|
||||
}
|
||||
|
||||
void WingGraphExport::Traverse(UEdGraphNode* Node)
|
||||
{
|
||||
if (Visited.Contains(Node)) return;
|
||||
Visited.Add(Node);
|
||||
|
||||
// First, traverse input nodes
|
||||
for (UEdGraphPin* Pin : FilterPins(Node, EGPD_Input))
|
||||
for (UEdGraphPin* Pin : GetPins(Node, EGPD_Input, PK_BOTH))
|
||||
for (UEdGraphPin* LinkedPin : Pin->LinkedTo)
|
||||
Traverse(LinkedPin->GetOwningNode());
|
||||
|
||||
@@ -159,7 +114,7 @@ void WingGraphExport::Traverse(UEdGraphNode* Node)
|
||||
// Then, traverse exec output nodes only.
|
||||
// Data outputs are not followed — data nodes get pulled in
|
||||
// through their consumers' input traversal.
|
||||
for (UEdGraphPin* Pin : FilterPins(Node, EGPD_Output, UEdGraphSchema_K2::PC_Exec))
|
||||
for (UEdGraphPin* Pin : GetPins(Node, EGPD_Output, PK_EXEC))
|
||||
for (UEdGraphPin* LinkedPin : Pin->LinkedTo)
|
||||
Traverse(LinkedPin->GetOwningNode());
|
||||
}
|
||||
@@ -195,6 +150,62 @@ void WingGraphExport::SortNodes()
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Text Output
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
void WingGraphExport::EmitLinks(UEdGraphPin* Pin)
|
||||
{
|
||||
bool comma = false;
|
||||
for (const UEdGraphPin *Other : Pin->LinkedTo)
|
||||
{
|
||||
if (comma) Output.Append(TEXT(", "));
|
||||
comma = true;
|
||||
Output.Appendf(TEXT("node:%s,pin:%s"),
|
||||
*WingUtils::FormatName(Other->GetOwningNode()), *WingUtils::FormatName(Other));
|
||||
}
|
||||
}
|
||||
|
||||
void WingGraphExport::EmitInputPinValue(UEdGraphPin* Pin)
|
||||
{
|
||||
// If connected, show source node and pin
|
||||
if (IsLinked(Pin)) return EmitLinks(Pin);
|
||||
|
||||
// String pins: always show in quotes (even if empty).
|
||||
FName Category = Pin->PinType.PinCategory;
|
||||
if (Category == UEdGraphSchema_K2::PC_String ||
|
||||
Category == UEdGraphSchema_K2::PC_Name ||
|
||||
Category == UEdGraphSchema_K2::PC_Text)
|
||||
{
|
||||
Output.Appendf(TEXT("\"%s\""), *Pin->DefaultValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// If has a non-empty default, show it.
|
||||
if (!Pin->DefaultValue.IsEmpty())
|
||||
{
|
||||
Output.Append(Pin->DefaultValue);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Pin->DefaultObject)
|
||||
{
|
||||
Output.Append(Pin->DefaultObject->GetName());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Pin->DefaultTextValue.IsEmpty())
|
||||
{
|
||||
Output.Appendf(TEXT("\"%s\""), *Pin->DefaultTextValue.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
Output.Appendf(TEXT("<default>"));
|
||||
}
|
||||
|
||||
|
||||
void WingGraphExport::EmitNode(UEdGraphNode* Node)
|
||||
{
|
||||
if (Node->IsA<UEdGraphNode_Comment>()) return;
|
||||
@@ -218,45 +229,65 @@ void WingGraphExport::EmitNode(UEdGraphNode* Node)
|
||||
SuppressedDetails = true;
|
||||
}
|
||||
|
||||
// Emit the input exec pin(s). Do not show what they're connected to.
|
||||
TArray<UEdGraphPin*> ExecIns = GetPins(Node, EGPD_Input, PK_EXEC);
|
||||
for (UEdGraphPin* Pin : ExecIns)
|
||||
{
|
||||
if (IsLinked(Pin))
|
||||
{
|
||||
Output.Appendf(TEXT(" exec-in %s from "), *WingUtils::FormatName(Pin));
|
||||
EmitLinks(Pin);
|
||||
Output.AppendChar('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
Output.Appendf(TEXT(" exec-in %s (unconnected)\n"), *WingUtils::FormatName(Pin));
|
||||
}
|
||||
}
|
||||
|
||||
// Emit input data pins.
|
||||
for (UEdGraphPin* Pin : FilterPins(Node, EGPD_Input))
|
||||
for (UEdGraphPin* Pin : GetPins(Node, EGPD_Input, PK_VALUE))
|
||||
{
|
||||
if (Pin->PinType.PinCategory == UEdGraphSchema_K2::PC_Exec) continue;
|
||||
if (Pin->bHidden) continue;
|
||||
|
||||
Output.Appendf(TEXT(" input %s %s = %s\n"),
|
||||
Output.Appendf(TEXT(" input-pin %s %s = "),
|
||||
*UWingTypes::TypeToText(Pin->PinType),
|
||||
*WingUtils::FormatName(Pin),
|
||||
*FormatPinSource(Pin));
|
||||
*WingUtils::FormatName(Pin));
|
||||
EmitInputPinValue(Pin);
|
||||
Output.AppendChar('\n');
|
||||
}
|
||||
|
||||
// Emit output data pins as a return line.
|
||||
FString ReturnPins;
|
||||
for (UEdGraphPin* Pin : FilterPins(Node, EGPD_Output))
|
||||
// Emit output data pins as a single 'output-pins' line.
|
||||
TArray<UEdGraphPin*> OutputPins = GetPins(Node, EGPD_Output, PK_VALUE);
|
||||
if (!OutputPins.IsEmpty())
|
||||
{
|
||||
if (Pin->PinType.PinCategory == UEdGraphSchema_K2::PC_Exec) continue;
|
||||
if (Pin->bHidden) continue;
|
||||
if (!ReturnPins.IsEmpty()) ReturnPins += TEXT(", ");
|
||||
ReturnPins += WingUtils::FormatName(Pin);
|
||||
Output.Append(TEXT(" output-pins "));
|
||||
bool comma = false;
|
||||
for (UEdGraphPin *Pin : OutputPins)
|
||||
{
|
||||
if (comma) Output.Append(TEXT(", "));
|
||||
comma = true;
|
||||
Output.Append(UWingTypes::TypeToText(Pin->PinType));
|
||||
Output.AppendChar(' ');
|
||||
Output.Append(WingUtils::FormatName(Pin));
|
||||
}
|
||||
if (!ReturnPins.IsEmpty())
|
||||
{
|
||||
Output.Appendf(TEXT(" output-pins %s\n"), *ReturnPins);
|
||||
Output.AppendChar('\n');
|
||||
}
|
||||
|
||||
// Emit output exec pins as goto statements.
|
||||
TArray<UEdGraphPin*> ExecOuts = FilterPins(Node, EGPD_Output, UEdGraphSchema_K2::PC_Exec);
|
||||
// Emit output exec pins.
|
||||
TArray<UEdGraphPin*> ExecOuts = GetPins(Node, EGPD_Output, PK_EXEC);
|
||||
for (UEdGraphPin* Pin : ExecOuts)
|
||||
{
|
||||
UEdGraphPin* LinkedTo = GetLinkedTo(Pin);
|
||||
if (!LinkedTo) continue;
|
||||
|
||||
FString Target = WingUtils::FormatName(LinkedTo->GetOwningNode());
|
||||
|
||||
if (ExecOuts.Num() == 1)
|
||||
Output.Appendf(TEXT(" goto %s\n"), *Target);
|
||||
if (IsLinked(Pin))
|
||||
{
|
||||
Output.Appendf(TEXT(" exec-out %s to "), *WingUtils::FormatName(Pin));
|
||||
EmitLinks(Pin);
|
||||
Output.AppendChar('\n');
|
||||
}
|
||||
else
|
||||
Output.Appendf(TEXT(" goto-if %s %s\n"), *WingUtils::FormatName(Pin), *Target);
|
||||
{
|
||||
Output.Appendf(TEXT(" exec-out %s (unconnected)\n"), *WingUtils::FormatName(Pin));
|
||||
}
|
||||
}
|
||||
|
||||
Output.Append(TEXT("\n"));
|
||||
|
||||
@@ -22,6 +22,17 @@ private:
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
enum PinKind
|
||||
{
|
||||
PK_EXEC,
|
||||
PK_VALUE,
|
||||
PK_BOTH
|
||||
};
|
||||
|
||||
// Return true if this pin is connected.
|
||||
//
|
||||
static bool IsLinked(UEdGraphPin *Pin);
|
||||
|
||||
// Get the pin that this pin is linked to.
|
||||
//
|
||||
static UEdGraphPin* GetLinkedTo(UEdGraphPin *Pin);
|
||||
@@ -32,27 +43,24 @@ private:
|
||||
static bool IsDefaultToSelf(UEdGraphPin* Pin);
|
||||
|
||||
// Get a subset of the pins in the node, filtered
|
||||
// by direction, category, or both.
|
||||
// by direction, Kind, or both.
|
||||
//
|
||||
static TArray<UEdGraphPin*> FilterPins(UEdGraphNode* Node,
|
||||
EEdGraphPinDirection Direction = EGPD_MAX, FName Category = FName());
|
||||
static TArray<UEdGraphPin*> GetPins(
|
||||
UEdGraphNode* Node, EEdGraphPinDirection Direction, PinKind Kind);
|
||||
|
||||
// Return true if the node has an exec pin that points
|
||||
// in the specified direction.
|
||||
//
|
||||
static bool HasExecPin(UEdGraphNode* Node, EEdGraphPinDirection Direction);
|
||||
|
||||
// Find the first pin that points in the specified direction.
|
||||
//
|
||||
static UEdGraphPin* FindFirstPin(UEdGraphNode* Node, EEdGraphPinDirection Direction);
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Traverse and Emit the Nodes.
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
FString FormatPinSource(UEdGraphPin* Pin);
|
||||
void EmitLinks(UEdGraphPin* Pin);
|
||||
void EmitInputPinValue(UEdGraphPin* Pin);
|
||||
void Traverse(UEdGraphNode* Node);
|
||||
void SortNodes();
|
||||
void EmitNode(UEdGraphNode* Node);
|
||||
|
||||
Reference in New Issue
Block a user