Creating K2Node with multiple output exec pins linked to delegates

I have the following bit of code:

DECLARE_DYNAMIC_DELEGATE(FMyDelegate);

UCLASS()
class UMyClass : public UObject
{
  GENERATED_BODY()

public:
  UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = true))
  static void DoStuff(const TArray<FMyDelegate>& delegates);
}

I would like to create a K2Node that wraps around the function DoStuff. The node should look like this:


I’ve already managed to get the output exec pins to generate dynamically based on the default value of the Number Of Delegates pin.
However, I’m having some trouble getting the ExpandNode function to work. In my mind, the expanded node should look like this:

So, in ExpandNode, I’m generating a UK2Node_CallFunction for the DoStuff function, a UK2Node_MakeArray node, and a number of UK2Node_CustomEvent nodes. Here is my current ExpandNode function:

void UK2Node_MyNode::ExpandNode(FKismetCompilerContext& compilerContext, UEdGraph* sourceGraph)
{
  Super::ExpandNode(compilerContext, sourceGraph);
  
  const UEdGraphSchema_K2* schema = compilerContext.GetSchema();
  
  // Generate CallFunction node
  
  UK2Node_CallFunction* functionNode =
    compilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, sourceGraph);
 
  functionNode->FunctionReference.SetExternalMember(
    GET_FUNCTION_NAME_CHECKED(UMyClass, DoStuff), UMyClass::StaticClass());
 
  functionNode->AllocateDefaultPins();
  
  compilerContext.MovePinLinksToIntermediate(*GetExecPin(), *functionNode->GetExecPin());
  compilerContext.MovePinLinksToIntermediate(*GetThenPin(), *functionNode->GetThenPin());
  
  // Generate MakeArray node
  
  UK2Node_MakeArray* makeArrayNode =
      compilerContext.SpawnIntermediateNode<UK2Node_MakeArray>(this, sourceGraph);
	  
  makeArrayNode->AllocateDefaultPins();
  
  // Connect MakeArray node to CallFunction node
  
  schema->TryCreateConnection(
    makeArrayNode->GetOutputPin(), functionNode->FindPin(TEXT("delegates")));
	
  // Generate CustomEvent nodes
  
  const int32 numOfEvents = FCString::Atoi(*FindPin(numDelegatesPinName)->DefaultValue);
  for (int i = 0; i < numOfEvents; ++i)
  {
    UK2Node_CustomEvent* eventNode =
      compilerContext.SpawnIntermediateNode<UK2Node_CustomEvent>(this, sourceGraph);
	  
    eventNode->CustomFunctionName = TEXT("MyCustomEvent");
    eventNode->RenameCustomEventCloseToName();
    eventNode->bInternalEvent = true;
    eventNode->AllocateDefaultPins();
	
    // Connect CustomEvent node to MakeArray node
	
    makeArrayNode->AddInputPin();
    schema->TryCreateConnection(
      eventNode->GetDelegatePin(), makeArrayNode->FindPin(makeArrayNode->GetPinName(i)));
	  
    // Connect original node's output exec pin to CustomEvent node's exec pin
	
    compilerContext.MovePinLinksToIntermediate(
      *FindPin(delegatePinNames[i]), *eventNode->GetThenPin());
  }
  
  BreakAllNodeLinks();
}

Note that numDelegatesPinName is the FName of the Number Of Delegates pin, and delegatePinNames is a TArray of FNames that contains the names of the dynamically generated output exec pins.
When compiling the blueprint, I get the following errors on the custom node:


Presumably I have to tell the CustomEvent nodes that their signature is supposed to match the signature of FMyDelegate? But I have no clue how to do this.
Things I have tried, with no success:

  • Using the CustomEvent node’s SetDelegateSignature
UFunction* signatureFunc = FindObject<UFunction>(ANY_PACKAGE, TEXT("MyDelegate__DelegateSignature"));
eventNode->SetDelegateSignature(signatureFunc);
  • Setting the CustomEvent node’s EventReference via SetGlobalField
UPackage* package = FindPackage(nullptr, TEXT("/Script/MyGameProject"));
eventNode->EventReference.SetGlobalField(TEXT("MyDelegate__DelegateSignature"), package);

It’s entirely possible I’m doing something else wrong, like using the wrong types of nodes or not setting up the CallFunction/MakeArray nodes properly.
Any help would be appreciated. Thanks in advance!