Custom blueprint node internals

Hello to all,

This is my first posting here so be gentle:)

I’m trying to make custom node and so far everything was going really well but now I got tangled I feel at the very end.

I created custom plugin and then created module for that plugin and as a test I have created library with one function that just adds number to int and in my custom node I spawned function node got references to pins, connected everything and got value back that worked great.

It was basically done following logic here:

This was just test to figure out how things work and I’m happy to say it worked.

Now I tried to expand my node, I added option to create pins dynamically and idea is to add as much pins as you want (they are all of type bool as is the output) and I modified my function to now accept array of bools and I wanted to create array pass it to my function and then the function will do it’s processing and for example if all bool pins are true it will return true else it will return false.

If I understood correctly now I can’t just take all pins and connect it to my function since it’s input parameter is array so I have to make array out of them and then pass that to my function.
As far as I found the way to do this is to spawn intermediate node make array, connect all my node input pins to make array intermediate node and output of make array connect to input of my function so it can receive array and return bool. But that’s not working for me.

This is just my function that receives just array of bool types, for now it returns just false but in future it will do more processing.

bool UMyNodeBaseLib::EvaluateAndLogic(TArray<bool> inputs)
{
	return false;
}

Here is how I connect everything in ExpandNode, It’s a bit hacky because of different ways I was trying to do things, basically this worked ok when I spanwed function node and passed it simple int and got back result, but now that I want to pass it array trough MakeArray node it gives me an error.

void UMyNewNode::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	UE_LOG(LogTemp, Warning, TEXT("EXPANDING NODE ACTIVE"));
	Super::ExpandNode(CompilerContext, SourceGraph);

	static FName calculateFuncName = GET_FUNCTION_NAME_CHECKED(UMyNodeBaseLib, EvaluateAndLogic);
	static FString arrayParamName = FString(TEXT("inputs"));

	UMyNewNode* myNewNode = this;
	UEdGraphPin* SpawnNodeExec = myNewNode ->GetExecPin();
	UEdGraphPin* SpawnNodeThen = myNewNode ->GetThenPin();
	
	UEdGraphPin* SpawnNodeOut = myNewNode ->FindPin(FString(TEXT("boolOUT")));

	int32 pinIndex = 0;
	TArray<UEdGraphPin*> inputPins;
	for (int i = 0; i < myNewNode ->Pins.Num(); i++)
	{
		if (myNewNode ->Pins[i]->Direction == EGPD_Input && myNewNode ->Pins[i]->PinName != UEdGraphSchema_K2::PN_Execute)
		{
			inputPins.Add(myNewNode ->Pins[i]);
			pinIndex++;
		}
	}

	UK2Node_MakeArray *arrayNode = CompilerContext.SpawnIntermediateNode<UK2Node_MakeArray>(myNewNode , SourceGraph);
	arrayNode->AllocateDefaultPins();
	CompilerContext.MessageLog.NotifyIntermediateObjectCreation(arrayNode, this);
	UEdGraphPin* arrayOut = arrayNode->GetOutputPin();
	UEdGraphPin* arrayExec = arrayNode->GetExecPin();

	arrayOut->PinType.bIsArray = true;
	UE_LOG(LogTemp, Warning, TEXT("Output pin is %s"), *arrayOut->PinName);


	for (int i = 1; i < inputPins.Num(); i++)
	{
		arrayNode->AddInputPin();
	}

	for (int i = 0; i < inputPins.Num(); i++)
	{
		UE_LOG(LogTemp, Warning, TEXT("adding %s and %s"), *inputPins[i]->PinName, *arrayNode->Pins[i+1]->PinName);
		CompilerContext.MovePinLinksToIntermediate(*inputPins[i], *arrayNode->Pins[i + 1]);
		arrayNode->NotifyPinConnectionListChanged(arrayNode->Pins[i + 1]);
	}

	UK2Node_CallFunction* functionNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(myNewNode , SourceGraph);
	functionNode->FunctionReference.SetExternalMember(calculateFuncName, UMyNodeBaseLib::StaticClass());
	functionNode->AllocateDefaultPins();

	UEdGraphPin* CallExec = functionNode->GetExecPin();
	UEdGraphPin* CallInput = functionNode->FindPinChecked(arrayParamName);
	UEdGraphPin* CallThen = functionNode->GetThenPin();
	UEdGraphPin* CallOutput = functionNode->GetReturnValuePin();

	//
	//Connect array output pin to function input pin
	//
	CompilerContext.MovePinLinksToIntermediate(*arrayOut, *CallInput);

	
	CompilerContext.MovePinLinksToIntermediate(*SpawnNodeExec, *CallExec);
	CompilerContext.MovePinLinksToIntermediate(*SpawnNodeThen, *CallThen);
	CompilerContext.MovePinLinksToIntermediate(*SpawnNodeOut, *CallOutput);

	myNewNode ->BreakAllNodeLinks();
}

And here is the error I get in blueprint when I connect everything:

Now I’m struggling with this solution of spawning intermediate MakeArray node and spawning intermediate function node, but perhaps there is simpler solution, can I take value from input pins and make array right in my node class and then pass array to the function directly without making node out of it and then just put value in to my node output pin or something like that. I Could not find in the documentation or examples how to get and put value in to UEdGraphPin or something in more detail that could shed light to my problem so I decided to try here.

I hope you can unstuck me:)

Thanks,

Dejan.

This really took some time researching and just as I posted question I accidentally found solution so for future reference instead of:

CompilerContext.MovePinLinksToIntermediate(*arrayOut, *CallInput);

It should be:

CompilerContext.GetSchema()->TryCreateConnection(arrayOut, CallInput);

It was not (at least for me) 100% clear it should go like this from documentation but here it is for future refernce:)

Cheers.