From 3ba80ae64311c16da609e39110c56998d22816be Mon Sep 17 00:00:00 2001 From: Yury Rakhuba Date: Fri, 24 Oct 2025 14:27:37 +0200 Subject: [PATCH] Support for situation when one output pin connected with few input. --- Source/Private/Core/N2CNodeTranslator.cpp | 4 ++-- Source/Private/Core/N2CSerializer.cpp | 13 +++++++++---- .../Utils/Validators/N2CBlueprintValidator.cpp | 17 ++++++++++------- Source/Public/Models/N2CBlueprint.h | 11 ++++++++++- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/Source/Private/Core/N2CNodeTranslator.cpp b/Source/Private/Core/N2CNodeTranslator.cpp index 1544e77..9918903 100644 --- a/Source/Private/Core/N2CNodeTranslator.cpp +++ b/Source/Private/Core/N2CNodeTranslator.cpp @@ -873,7 +873,7 @@ void FN2CNodeTranslator::ProcessNodeFlows(UK2Node* Node, const TArrayDirection == EGPD_Output) { - CurrentGraph->Flows.Data.Add(SourceRef, TargetRef); + CurrentGraph->Flows.Data.FindOrAdd(SourceRef).TargetPins.Add(TargetRef); // Log data flow FString FlowContext = FString::Printf(TEXT("Added data flow: %s.%s (%s.%s) -> %s.%s (%s.%s)"), @@ -887,7 +887,7 @@ void FN2CNodeTranslator::ProcessNodeFlows(UK2Node* Node, const TArrayFlows.Data.Add(TargetRef, SourceRef); + CurrentGraph->Flows.Data.FindOrAdd(TargetRef).TargetPins.Add(SourceRef); // Log data flow FString FlowContext = FString::Printf(TEXT("Added data flow: %s.%s (%s.%s) -> %s.%s (%s.%s)"), diff --git a/Source/Private/Core/N2CSerializer.cpp b/Source/Private/Core/N2CSerializer.cpp index 02f56b7..be7053c 100644 --- a/Source/Private/Core/N2CSerializer.cpp +++ b/Source/Private/Core/N2CSerializer.cpp @@ -287,12 +287,17 @@ TSharedPtr FN2CSerializer::FlowsToJsonObject(const FN2CFlows& Flows JsonObject->SetArrayField(TEXT("execution"), ExecutionArray); // Add data flows object - TSharedPtr DataFlowsObject = MakeShared(); + TArray> DataFlowConnections; for (const auto& DataFlow : Flows.Data) { - DataFlowsObject->SetStringField(DataFlow.Key, DataFlow.Value); + for (const auto& InputConnector : DataFlow.Value.TargetPins) + { + TSharedPtr DataFlowConnection= MakeShared(FString::Printf(TEXT("%s -> %s"), *DataFlow.Key, *InputConnector)); + DataFlowConnections.Add(DataFlowConnection); + } } - JsonObject->SetObjectField(TEXT("data"), DataFlowsObject); + TSharedPtr DataFlowsObject = MakeShared(DataFlowConnections); + JsonObject->SetField(TEXT("data"), DataFlowsObject); return JsonObject; } @@ -751,7 +756,7 @@ bool FN2CSerializer::ParseFlowsFromJson(const TSharedPtr& JsonObjec { if (DataFlow.Value->Type == EJson::String) { - OutFlows.Data.Add(DataFlow.Key, DataFlow.Value->AsString()); + OutFlows.Data.FindOrAdd(DataFlow.Key).TargetPins.Add(DataFlow.Value->AsString()); } } diff --git a/Source/Private/Utils/Validators/N2CBlueprintValidator.cpp b/Source/Private/Utils/Validators/N2CBlueprintValidator.cpp index 4dcbde1..a96835f 100644 --- a/Source/Private/Utils/Validators/N2CBlueprintValidator.cpp +++ b/Source/Private/Utils/Validators/N2CBlueprintValidator.cpp @@ -221,14 +221,17 @@ bool FN2CBlueprintValidator::ValidateFlowReferences(const FN2CGraph& Graph, FStr return false; } - // Validate target pin format (N#.P#) - TArray TargetParts; - DataFlow.Value.ParseIntoArray(TargetParts, TEXT(".")); - if (TargetParts.Num() != 2 || !NodeIds.Contains(TargetParts[0])) + for (const auto& TargetPinName : DataFlow.Value.TargetPins) { - OutError = FString::Printf(TEXT("Invalid target pin format %s in graph %s"), *DataFlow.Value, *Graph.Name); - FN2CLogger::Get().LogError(OutError); - return false; + // Validate target pin format (N#.P#) + TArray TargetParts; + TargetPinName.ParseIntoArray(TargetParts, TEXT(".")); + if (TargetParts.Num() != 2 || !NodeIds.Contains(TargetParts[0])) + { + OutError = FString::Printf(TEXT("Invalid target pin format %s in graph %s"), *TargetPinName, *Graph.Name); + FN2CLogger::Get().LogError(OutError); + return false; + } } } diff --git a/Source/Public/Models/N2CBlueprint.h b/Source/Public/Models/N2CBlueprint.h index f3f02eb..4e2e8e7 100644 --- a/Source/Public/Models/N2CBlueprint.h +++ b/Source/Public/Models/N2CBlueprint.h @@ -72,6 +72,15 @@ struct FN2CMetadata FN2CMetadata() : Name(TEXT("")), BlueprintType(EN2CBlueprintType::Normal), BlueprintClass(TEXT("")) {} }; +USTRUCT(BlueprintType) +struct FN2CInputConnectors +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Node to Code") + TSet TargetPins; +}; + /** * @struct FN2CFlows * @brief Contains all execution and data flow connections between nodes @@ -87,7 +96,7 @@ struct FN2CFlows /** Data connections: a mapping from "N1.P4" to "N2.P3" */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Node to Code") - TMap Data; + TMap Data; FN2CFlows() {