[Config BP Pull Request ] Config File Support in BP, 14 Nodes Turned Into 2 Wild Card Nodes!

Dear Community,

After delving deep into the engine code, and learning a lot about the special K2 nodes that require special classes and special code, I’ve learned how to use wild cards!

I will explain what I’ve learned below!

I’ve compacted the 14 nodes of my Config BP Suite into just 2 !

My 2 nodes support 7 different variable types!

Pull Request Link
https://github.com/EpicGames/UnrealEngine/pull/1083
(You need to be logged into your UE4 Github account to view this link)


**Video of The Pull Request**

Check out this video!

The single pin in my 2 nodes can become 7 different variable types!


https://www.youtube.com/watch?v=xwGMNNJFaz8


If you'd like to see these 2 Wild nodes added to the engine you can post at the link above!

What Is This About?

I’ve observed and received a lot of feedback from the Community that support for config files in BP would be greatly appreciated.

I originally made 14 nodes and submitted this pull request to Epic. https://github.com/EpicGames/UnrealEngine/pull/604

Epic asked me to turn the 14 nodes into 2 wild card nodes that would support the 7 different file types.

I had no idea how to do this.

I spent all last night researching how to do this by reverse engineering one of Epic’s only single-value wild card nodes.

My biggest hurdle was that most wild card nodes were array based, and had special support for not needing to be a K2 node.

Well now I present to you my very first K2 custom class BP node, that has wild card support for 7 different file types!

See the video for full details!


**Pics**

![bcd0b22068ff36639b821c6351ce51cf1fe58ec9.jpeg|1027x733](upload://qWkTngnMvlP5tc6RFp32oEwiNHH.jpeg)


![90fe78017b1652ef0cb3999dc45ba31cc511d511.jpeg|1800x1350](upload://kGFX3Hq4uMInMTcGSbR05zRFUu5.jpeg)

![569bedb1d8f20387355994d213c577304ed1fab5.jpeg|751x554](upload://cmb8xo9bysKDrGcIYerr7ByFLHn.jpeg)

How Wild Card Nodes Work

I thought I’d offer a brief explanation of what I’ve learned so far about how wild card nodes work!

Inside of K2 nodes there is this section like this:



void UK2Node_GetGameConfigVar::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);


Within this function, the BP node can be converted into other “invisible” nodes that exist only within the Blueprint Graph Intermediate.

These are nodes you never see!

But you can programatically generate these other nodes and connect their pins using the ExpandNode function!

So basically you are making nodes and connecting pins for invisible nodes with C++ code !


**Why Create Nodes Within Nodes?**

Why would you want to do this?

Well for one thing, wild cards of course! (another reason is SpawnActor which actually internally made of BeginSpawn and FinishSpawn hidden nodes)

Now what you see as the generic BP node is actually going to "morph" behind the scenes based on the type it determines you have given it, as you see in my video above.

When the BP graph is compiled, this generic node transforms invisibly into the correct type.

This means that the correct BP node with the correct typed inputs/outputs has to exist somewhere.

ConfigBPLibrary

In my engine integration I created ConfigBPLibrary to house these nodes, which are hidden from the context menu via



UFUNCTION(meta = (BlueprintInternalUseOnly = "true"),


My K2 nodes,

UK2Node_GetGameConfigVar
UK2Node_SetGameConfigVar

Each call the 7 different kinds of Get/Set nodes that I put in the ConfigBPLibrary, and choose which one to “morph” into at ExpandNode time.

To be clear though, the wild card node actually deletes itself and is not part of the final blueprint graph from the runtime engine’s perspective!

This is actually important for packaging the game!

My K2 nodes, like the others, have a lot of Editor dependencies, and the game would not package very happily depending on UnrealEd and KismetCompiler, etc etc.

So the ConfigBPLibrary is a runtime library, whereas the K2 node are Editor-side.

This means that my K2 Editor-only nodes quietly delete themselves and replace themselves with the appropriate Runtime-friendly type-specific nodes!


**The Most Technical Part**

The most technical part of this process is in ExpandNode where you must carefully "wire" the nodes that you create together!

Here's a small code sample (legal reasons)



```


//!
// Move the input pins to the function
CompilerContext.MovePinLinksToIntermediate(*FindPin(FGetConfigNodeName::GetSectionPinName()), *CallFunction->FindPin(TEXT("SectionName"))); //See video to see this in action!

CompilerContext.MovePinLinksToIntermediate(*FindPin(FGetConfigNodeName::GetVarNamePinName()), *CallFunction->FindPin(TEXT("VariableName")));  //See video to see this in action!
//!

//~~~
	
//! Connect the return pin of the visible node to the return pin of the internal function return value!
CompilerContext.MovePinLinksToIntermediate(*FindPin(FGetConfigNodeName::GetResultPinName()), *CallFunction->GetReturnValuePin());
	


```



**Notice how I have to wire the newly created BP node together myself!**

I must be very careful to wire the return node of the WildCard node (that deletes itself) to the newly created node, so that the return wire that you choose to connect is maintained!

So basically in my code on Github you can see that I am replacing the Wild Card node with a type-specific node from the ConfigBPLibrary, based on what type of wire you plugged into my Get/Set Config Wild Card node!

Again I reverse engineered this from various K2 nodes within the Epic code base, so I do not take credit for this great idea, **but I sure did have fun figuring out how Epic does wild card BP nodes!**

Conclusion

And that’s how Wild Card Nodes work!

All my code is on Github
https://github.com/EpicGames/UnrealEngine/pull/1083

:heart:

Rama

Sweet addition!

Hi Rama, it looks like custom K2Nodes are actually very powerful. Your addition will be very appreciated indeed.

I myself have been trying to create my own custom K2Nodes but I’m having a lot of trouble with it, not being able to figure out my own mistakes, as the available information aside from the source code on the topic is very scarce. I’d like to know which sources of information did you use, if possible. Having more information would maybe help me advance on this topic.

I already posted my problem both in the answerhub and in the forums, but I am still stuck after almost three weeks.

Any help would be very appreciated.

I also want to thank you for all your tutorials and contributions, they helped me find other ways I could set up custom nodes, like through exposing c++ functions.

Lovely to hear from you Kitatus and KRushin!



[QUOTE=Irvaxis AcidFire;277504]
I'd like to know which sources of information did you use, if possible. Having more information would maybe help me advance on this topic.
[/QUOTE]


I just looked at the K2 Nodes in the UE4 code base!

I trimmed out all the stuff I did not need for my config node and what was left is on github!

Took me a while to sort thru all the code and figure out which parts were relevant to my own K2 node :)

Everything I learned from looking through the UE4 code base is in my pull request on github!


[QUOTE=Irvaxis AcidFire;277504]
I also want to thank you for all your tutorials and contributions, they helped me find other ways I could set up custom nodes, like through exposing c++ functions.
[/QUOTE]


You're welcome!

:)

Rama

I did the same (looking through UE4’s K2Nodes source code trying to understand everything) but I ended up with several unanswered questions which at this time I still haven’t been able to figure out. I am gathering more information from your custom K2Node code submissions in github as another very valuable source of information, thank you very much! I also have got two relevant questions which would really help me find my mistakes:

1 - I assume based on the tutorial I followed that it is possible to add custom K2Nodes (not exposed functions, but fully coded custom K2Nodes) through an editor module without needing to add the nodes to the engine source itself. Aside from getting said editor module properly recognized by the engine/editor, do I need to set up anything else so that the engine/editor itself recognizes the custom K2Node as well and recognizes it as part of the system (meaning it will show up in the context menu of the blueprint graph editor that lets you add new nodes into the graph)?

Self-Answer to this one: I just got his two custom K2Nodes from his pull request to work inside my editor module, so then all my problems come from my node’s implementation itself! Thank you so much! That kills half the problem already!

2 - Is there any sort of feedback from the engine/editor (aside from the C++ compiler) when trying to add new custom K2Nodes? Aside from the blueprint graph editor itself I mean, because I had no feeedback other than “the node isn’t on the add node context menu list” (and yes, I tried to disable context sensitivity with the same results). I don’t know if the problem is the node itself, the editor module, some kind of link between the two, or any other possibility, so I’m stuck with trial and error and no feedback other than “it doesn’t even show up”. Any tips here?

*Added comment: *This one would help me sort through my implementation mistakes instead of being a pure trial and error with no feedback process. Any help would be very appreciated.

Thank you again for any provided help, it is very appreciated.

You’re welcome! I am glad my github code helped you out, yaaay!

:heart:

Rama

Did you add the various K2 overrides to give your node a proper name and place within the context menu?

Specifically:



GetContextMenuActions


and



GetMenuActions


and



GetNodeTitle


Please note I’m not including much code here for legal reasons.

All my relevant code is at my github link:
https://github.com/EpicGames/UnrealEngine/pull/1083

:heart:

Rama

Thanks you Rama.

Will be nice if add something to read/write in custom .ini files.

Found it! My problem was that I was using GetMenuEntries(), as stated in the tutorial I was following. However, in the API it is stated that* there is a replacement method for it*, and it was GetMenuActions()! I replaced the first method with the second and my node finally showed up!

Now I can start to see how my code affects my node! I cannot thank you enough for your help, I hope that if anybody else finds himself in the same situation this can be as helpful for him as it was to me.

Also, it seems like I didn’t need GetContextMenuActions() in my node for some reason. I guess it has to do with the situation where from another compatible pin you’d be able to use this particular node, am I right?

Update (it doesn’t work yet): I now have a custom K2Node which takes an int as a parameter (input pin) and returns a boolean (output pin). It is supposed to be used as a fetch node, like your get game.ini config variable node.

However, when I connect the output pin from my K2Node to another boolean input pin from any other node (like a branch node for instance), it seems like it always returns “false”. Even if inside the called function of my K2Node has only one line of code inside: return true. I don’t know if it’s because it’s not fetching the value, because it is always returning “false” because there is a badly connected pin or because I screwed up with something else.

  • I have my pins defined properly in AllocateDefaultPins, because they do show up on my node exactly as expected.

Inside the ExpandNode function:

  • I spawned the CallFunction intermediate node and allocated its default pins.
  • I used SetFromFunction to set the function I am trying to call (the one inside my BlueprintFunctionLibrary). No messages are shown on the message log, using the same condition you did to check if it was null just in case.
  • I notified about the intermediate node creation just as you did.
  • I moved my pin connections to the intermediate CallFunction node and used BreakAllNodeLinks to clean all self links at the end.

I tried to put a UE_LOG message inside my BlueprintFunctionLibrary function but it didn’t do anything, which tells me that either it doesn’t work in that context or the function is not even being called.

I am using your pull request’s get game.ini config variable custom node code to compare everything with my own and to try to understand why my function is not being called.

Do I need to do anything special aside from everything I already mentioned in order to get my function called? Is there any way, without having to compile against the engine’s source code on github, that I can sort of “debug” or log messages from within these contexts (custom K2Node functions and BlueprintFunctionLibrary functions)? Thank you very much in advance.

Woohoo!

So everything is working for you now?!

:slight_smile:

Rama

Actually, it doesn’t work yet, the function itself is not being called and I can’t figure out why. I posted an update in my previous post with more information.

Very good find Rama, I think this is something I can use in my save game system because I have so many nodes, however I think that there is one thing which is not very clear and does not correspond with Epic standards. Nodes which don’t have execute pin should be green (sometimes called pure/const).

Lovely to hear from you Nonder! Once I hear back from Epic on Github about the status of the pull request that is something I can easily fix :slight_smile:

Rama

Can you post just the code where you are calling your function itself within the K2_node ?

You call functions by their name as a string, so make sure you are spelling it right?

Rama

This is my function in my BlueprintFunctionLibrary class named InputGraph_BlueprintNodes. It is Blueprintcallable:


**static bool CheckMyDubs(int32 n);**

Now for the custom node. In AllocateDefaultPins I define these pins:




        //This is the input int pin
**	UEdGraphPin *NPin = CreatePin(EGPD_Input, K2Schema->PC_Int, TEXT(""), NULL, false, false, TEXT("n"));
	SetPinToolTip(*NPin, LOCTEXT("NPinTooltip", "Number to check"));**

        //This is the return boolean pin
**	UEdGraphPin *ResultPin = CreatePin(EGPD_Output, K2Schema->PC_Boolean, TEXT(""), NULL, false, false, TEXT("checked"));
	SetPinToolTip(*ResultPin, LOCTEXT("ResultPinDescription", "Are there any dubs checked?"));**



This is where, in Expand Node I assign my function to the new CallFunction intermediate node:




        //Call to super's Expand Node

	**UFunction* function = UInputGraph_BlueprintNodes::StaticClass()->FindFunctionByName(TEXT("CheckMyDubs")); // As you can see, the spelling is the same.**
        //Same "if" as yours here

	//I spawn the intermediate node just like you do

	**CallFunction->SetFromFunction(function); // The function is set here.**

	//I call Allocate Default Pins and notify about the intermediate object creation just as you do
        //Finally, I move the pins just as you do

**	CompilerContext.MovePinLinksToIntermediate(*FindPin(TEXT("n")), *CallFunction->FindPin(TEXT("n")));
	CompilerContext.MovePinLinksToIntermediate(*FindPin(TEXT("checked")), *CallFunction->GetReturnValuePin());**

        //And I break all self-links just as you do



Any ideas?

A Way to Victory

How about you try using my node and gutting it and calling your function instead? perhaps in the process of reverse engineering you will see the issue.

I know its definitely better than just looking over your code 300 more times and not seeing the issue.

Get a different perspective, **reverse engineer a working node and slowly start putting your code in and making sure each step of integration works properly :slight_smile:
**

:slight_smile:

Rama

I just found something after removing the BlueprintInternalUseOnly meta: I could call the function itself from outside as a non-pure node (if I recall correctly, pure means that the function itself does not need execution pins, only input and ouput, which corresponds to fetch nodes or const nodes). And I just found that I was using BlueprintCallable instead of BlueprintPure. It’s finally working as intended! Thank you so much!

**
Woohoo! Congratulations Irvaxis!**

Yay!

:slight_smile:

Rama

Video of The Pull Request

Check out this video!

This is a pull request for adding BP nodes to the engine to get/set custom config variables in the Game.ini.

I condensed my 14 nodes for get/set into just two wildcard nodes!

The wildcard pin in my 2 nodes can become 7 different variable types!

Youtube Video


**Git**

If you'd like to see these 2 Wild nodes added to the engine you can post at this link!

**Pull Request Link**
https://github.com/EpicGames/UnrealEngine/pull/1083
(You need to be logged into your UE4 Github account to view this link)

:)

Rama