More fixes to blueprint exporter.

This commit is contained in:
2026-02-16 21:02:01 -05:00
parent 15997aee62
commit 55ad662d3f
5 changed files with 55 additions and 25 deletions

View File

@@ -115,6 +115,7 @@ Do not use git to make changes (commit, push, branch, etc.). Read-only git comma
## Coding Conventions
- Prefer early returns and `continue` to reduce nesting (never-nester style).
- Do not use static functions in Unreal code. Use class methods or namespace-scoped functions instead.
- Use `LogLuprexIntegration` for log messages, not `LogTemp`.
- When writing UFUNCTIONs that take an `AActor*`, `UObject*`, or similar "self" parameter, add `DefaultToSelf` meta to that pin. Most functions should have this on the obvious pin so the user doesn't have to manually wire it in blueprints.

Binary file not shown.

View File

@@ -10,35 +10,34 @@ The exporter class (`Source/Integration/BlueprintExporter.h/.cpp`) processes one
## Output Format
Each file has two sections:
The graph file is written to `Saved/BlueprintExports/<BlueprintName>/<GraphName>.txt`. A details file with node-name-to-GUID mappings is written to `Saved/BlueprintExports/<BlueprintName>/DETAILS/<GraphName>.txt`.
**NodeList** maps readable node names to GUIDs:
```
NodeList:
Event_Tick = 44BAE739C72246DD9E9A72803C3B67CA
Set_Tick_Delta_Seconds = 204486800C0C4906A456A378F9F7ADE4
```
Every line in the graph file starts with a keyword, making it easy to parse. The format is:
**Graph** shows the flow with pins and connections:
```
Graph:
Event_Tick
return Output_Delegate,Delta_Seconds
node Event_Tick
return Output_Delegate, Delta_Seconds
goto Set_Tick_Delta_Seconds
Set_Tick_Delta_Seconds
Real Tick_Delta_Seconds = Event_Tick.Delta_Seconds
node Set_Tick_Delta_Seconds
input Real Tick_Delta_Seconds = Event_Tick.Delta_Seconds
return Output_Get
goto CallFunctionByName
```
- Input data pins: `Type Name = Source` where Source is a `Node.Pin` reference, a literal value, `<self>`, or `<default>`.
- Output data pins: `return Pin1,Pin2`.
- Exec flow: `goto Target` (single output), `goto Target if PinName` (multiple outputs), or `then goto`/`else goto` (branch nodes).
### Line Keywords
- `node Name` — starts a new node block.
- `input Type Name = Source` — an input data pin. Source is a `Node.Pin` reference, a literal value, `<self>`, or `<default>`.
- `return Pin1, Pin2` — output data pins.
- `goto Target` — exec flow (single output).
- `goto-if PinName Target` — exec flow (multiple outputs, e.g. branch true/false).
- `// comment text` — comment node.
### Special Handling
- String defaults are shown in quotes.
- Variable get nodes are inlined (the variable name appears directly at the point of use).
- Comment nodes appear as `// comment text`.
- Variable get nodes are inlined (the variable name appears directly at the point of use rather than as a separate node).
- Knot (reroute) nodes are followed through transparently.
## Node Ordering

View File

@@ -11,12 +11,14 @@
#include "EdGraphNode_Comment.h"
#include "K2Node_VariableGet.h"
#include "K2Node_CallFunction.h"
#include "K2Node_FunctionEntry.h"
FlxBlueprintExporter::FlxBlueprintExporter(UEdGraph* InGraph)
: Graph(InGraph)
{
SortNodes();
AssignNodeNames();
EmitLocalVariables();
EmitNodeList();
EmitGraph();
}
@@ -33,20 +35,27 @@ FString FlxBlueprintExporter::SanitizeName(const FString& Title)
return Result.IsEmpty() ? TEXT("_") : Result;
}
FString FlxBlueprintExporter::FormatPinType(UEdGraphPin* Pin)
FString FlxBlueprintExporter::FormatPinType(const FEdGraphPinType& PinType)
{
if (UObject* SubObj = Pin->PinType.PinSubCategoryObject.Get())
if (UObject* SubObj = PinType.PinSubCategoryObject.Get())
{
return SubObj->GetName();
}
FString Type = Pin->PinType.PinCategory.ToString();
FString Type = PinType.PinCategory.ToString();
Type[0] = FChar::ToUpper(Type[0]);
return Type;
}
FString FlxBlueprintExporter::FormatPinType(UEdGraphPin* Pin)
{
return FormatPinType(Pin->PinType);
}
FString FlxBlueprintExporter::FormatNodeBaseName(UEdGraphNode* Node)
{
return SanitizeName(Node->GetNodeTitle(ENodeTitleType::ListView).ToString());
FString Title = Node->GetNodeTitle(ENodeTitleType::ListView).ToString();
Title = FName::NameToDisplayString(*Title, false);
return SanitizeName(Title);
}
@@ -344,6 +353,25 @@ void FlxBlueprintExporter::EmitNode(UEdGraphNode* Node)
}
}
void FlxBlueprintExporter::EmitLocalVariables()
{
for (UEdGraphNode* Node : Graph->Nodes)
{
UK2Node_FunctionEntry* EntryNode = Cast<UK2Node_FunctionEntry>(Node);
if (!EntryNode) continue;
for (const FBPVariableDescription& Var : EntryNode->LocalVariables)
{
FString Default = Var.DefaultValue.IsEmpty() ? TEXT("<default>") : Var.DefaultValue;
Output.Appendf(TEXT("local %s %s = %s\n"),
*FormatPinType(Var.VarType),
*SanitizeName(Var.VarName.ToString()),
*Default);
}
break;
}
}
void FlxBlueprintExporter::EmitGraph()
{
for (UEdGraphNode* Node : SortedNodes)

View File

@@ -33,6 +33,7 @@ private:
// or struct, for example. But that's OK, we don't
// need precise type info, we just need readability.
//
static FString FormatPinType(const FEdGraphPinType& PinType);
static FString FormatPinType(UEdGraphPin* Pin);
// Get the node base name as a sanitized string.
@@ -101,6 +102,7 @@ private:
void SortNodes();
void AssignNodeNames();
void EmitNode(UEdGraphNode* Node);
void EmitLocalVariables();
void EmitGraph();
void EmitNodeList();