Making a Custom Blueprint K2Node in C++, can anybody help me, please?

Update 28/04/2015 . Solution found here.

1) Introduction:

First of all, thanks in advance to anybody who tries to help me with all of this. I realize it’s a very long post but I think it’ll be better to detail everything as much I can because I can’t figure out where exactly did I make a mistake and I also have several related questions to the same topic that could help me understand exactly what’s happening. If you think this post is too long, please jump right to the last part (4) Conclusions: ) after reading this introduction.

I’m trying to extend the blueprint system by creating a new K2Node. My current goal is to create a test K2Node and expose it to the blueprint system so that I can use it in the blueprint graph editor. To do so, I am following this tutorial:
https://wiki.unrealengine.com/Create_Custom_K2_Node_For_Blueprint

I already know that this is not the recommended way to create your custom nodes. However, because I want to create more complex blueprints in the near future than the ones created by simply exposing functions to the blueprint system, I will need to do it this way (unless I’m terribly wrong about this). For instance, blueprint nodes like the sequence one where you can add more pins or subtract them. You can even add your own custom pins to your custom K2Node, and this is another advantage I’m interested in being able to use. This tutorial shows how:
https://wiki.unrealengine.com/How_To_Create_Custom_Blueprint_Pin

Because I needed to create an Editor Module for the K2Node, I followed this answer posted on the answer hub:
https://answers.unrealengine.com/questions/41509/extending-editor-engine.html

However, I’m having a lot of trouble following these tutorials, as** there are several questions I have that I have not been able to answer yet** by researching or looking at the engine’s default blueprints source code available on the Unreal Engine GitHub repository. The main reason why I’m having trouble is because I don’t see any way I could have feedback in the editor that tells me if there’s an error somewhere.

2) Adding a new Editor Module:

Update 25/04/2015 - This part has been solved. Jump to the next part.

I’ll expose the steps I’ve taken until now: first I created the Editor Module as I’ve stated before. My test project is called RTSCameraTest. Quoting the third link’s answer:

*"If you go to the Source folder for your project, you’ll notice you have two .Target.cs files; in my case I’m going to pretend your project is called “MyCodeProject” (replace as appropriate), so you’d see:

MyCodeProject.Target.cs

MyCodeProjectEditor.Target.cs

If you open up these files, you’ll notice that they both output a single module from SetupBinaries, what we’re going to do is add an extra module called “MyCodeProjectEditor” to contain your editor code."
*

1) First question: consider the name of your project as “X”. What it is found in the stated folder is indeed a XEditor.Target.cs. However, the next sentence states that we’re going to add an exta module named “XEditor” to contain the editor code. Does the new Editor module necessarily have to be named “XEditor”, or can it be named “Y”? (where “X” and “Y” are entirely different names, as in “X” = “TestProject”, “XEditor” = “TestProjectEditor”, and “Y” = “CustomNodes”.)
I want to state now that I’ve tried both ways but my custom node hasn’t showed up in the blueprint graph editor.

I’ve decided to name my module “CustomK2NodeLibrary_InputSystem”. Then I added the following code to the RTSCameraTest.target.cs file inside Setup Binaries:



	public override void SetupBinaries(
		TargetInfo Target,
		ref List<UEBuildBinaryConfiguration> OutBuildBinaryConfigurations,
		ref List<string> OutExtraModuleNames
		)
	{
		OutExtraModuleNames.AddRange( new string] { "RTSCameraTest" } );

		//Add Input Module
		if (UEBuildConfiguration.bBuildEditor){
			OutExtraModuleNames.Add("CustomK2NodeLibrary_InputSystem");
		}

	}


Then in the RTSCameraTestEditor.target.cs file.



	public override void SetupBinaries(
		TargetInfo Target,
		ref List<UEBuildBinaryConfiguration> OutBuildBinaryConfigurations,
		ref List<string> OutExtraModuleNames
		)
	{
		OutExtraModuleNames.AddRange( new string] { "RTSCameraTest" } );

		//Add Input Module
		OutExtraModuleNames.Add("CustomK2NodeLibrary_InputSystem");

	}


Then, the posted answer states the following:

*“Now, inside your Source folder, create a new folder called “MyCodeProjectEditor”, and copy the following files from the “MyCodeProject” folder, into “MyCodeProjectEditor” folder:”

MyCodeProject.Build.cs

MyCodeProject.h

MyCodeProject.cpp

Rename these files in the “MyCodeProjectEditor” folder so you see:

MyCodeProjectEditor.Build.cs

MyCodeProjectEditor.h

MyCodeProjectEditor.cpp

Open MyCodeProjectEditor.Build.cs and rename the class from “MyCodeProject” to “MyCodeProjectEditor”.*

Here I have the same question that I stated before, except that now it’s about these folders and files. The correct names are “XEditor” as in “RTSCameraTestEditor” or can they be “Y” as in “CustomK2NodeLibrary_InputSystem”?

Then, as stated next, I renamed the class inside “CustomK2NodeLibrary_InputSystem.build.cs” to this:




public class CustomK2NodeLibrary_InputSystem : ModuleRules
{
	public CustomK2NodeLibrary_InputSystem(TargetInfo Target)

...



And fixed the include inside the “CustomK2NodeLibrary_InputSystem.build.cs” file:



#include "CustomK2NodeLibrary_InputSystem.h"

IMPLEMENT_GAME_MODULE( FDefaultGameModuleImpl, CustomK2NodeLibrary_InputSystem );


Then I opened the .uproject as stated and changed the following:



	"Modules": 
		{
			"Name": "RTSCameraTest",
			"Type": "Runtime",
			"LoadingPhase": "Default"
		},
		{
			"Name": "CustomK2NodeLibrary_InputSystem",
			"Type": "Developer",
			"LoadingPhase": "Default"			
		}
	]


Question time: Does it have to be an Editor Module or it can be a Developer Module? I’ve read in another thread that an Editor Module is not included in the final game, but a Developer Module is. Even though I tried both ways, my node still doesn’t show up.

After all of this was done, I rebuilt the project in Visual Studio and I got it to compile successfully. Then I could add code to my new module as you can see here in this screenshot:

http://gyazo.com/741e251838167f5a3ad2667222a914ec

My conclusion up to now is that the new module has been added successfully. If I’m wrong, I’d like to know why and how to fix it.

3) Creating the Custom K2 Node:

Now, here’s where the fun starts. If I successfully created the module and it shows in the editor, I understand that it should be working properly. Therefore, the problem might not lie there, even though I’m not even sure about that.

Back to the first link: https://wiki.unrealengine.com/Create_Custom_K2_Node_For_Blueprint

Instead of going though .uplugin, I went with .uproject because the creator of this tutorial states that “First you need to add custom Editor Module your plugin, game or engine module.” and I found the previously linked answer in the answer hub to be my best bet to succeed with this. Does it necessarily have to be a plugin or it can be an editor module?

***Self-Answer: An Editor Module works just fine. ***

Then the author states: “Now in runtime module we need to add, BlueprintFunctionLibrary, and in it at least one function.” And so I added InputGraph_BlueprintNodes as a BlueprintFunctionLibrary to the runtime module.

http://gyazo.com/0b23e3abb2245c2563f8ff28f568dbae

InputGraph_BlueprintNodes.h



#pragma once

#include "Kismet/BlueprintFunctionLibrary.h"
#include "InputGraph_BlueprintNodes.generated.h"

UCLASS()
class RTSCAMERATEST_API UInputGraph_BlueprintNodes : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
	
public:

	UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject", FriendlyName = "Input System Test Node", BlueprintInternalUseOnly = "true"), Category = "Custom UK2Node Input Module")
	static bool CheckMyDubs(int32 n);
	
};


If I’m not wrong, GENERATED_UCLASS_BODY() is a macro from a previous version and not longer used, since now classes generate automatically with a GENERATED_BODY macro instead.

Another question I have about this: What does WorldContext represent? Do I need to have it there? I’ve left it just in case.

InputGraph_BlueprintNodes.cpp



#include "RTSCameraTest.h"
#include "InputGraph_BlueprintNodes.h"

bool UInputGraph_BlueprintNodes::CheckMyDubs(int n){
	if (n % 11 == 0){
		return true;
	}
	return false;
}


The function itself is just for test purposes. As long as my node shows up and is it properly executed, I’m fine with that.

The next step stated by the author is this one:

*“Also don’t forget to add implementation. Which will return pointer to created item. You can do it just by using ConstructObject<> or you can create template function like this:”



template< class T >
T* CreateDataItem(APlayerController* OwningPlayer, UClass* UserWidgetClass)
{
    if (!UserWidgetClass->IsChildOf(UGISItemData::StaticClass()))
    {
        return nullptr;
    }
 
// Assign the outer to the game instance if it exists, otherwise use the player controller's world
    UWorld* World = OwningPlayer->GetWorld();
    StaticCast<UObject*>(World);
    UGISItemData* NewWidget = ConstructObject<UGISItemData>(UserWidgetClass, OwningPlayer);
    return Cast<T>(NewWidget);
}


Now, here’s where I got lost. I understand that this is his particular function to be called by his custom K2Node, for his particular project. Therefore, I just need to implement my particular function as I did in my .cpp, like I showed previously, to be called afterwards in my custom K2Node. Am I right or did I not understand this correctly?

The next stated step is the following one:

*Now move to editor module and open YourModuleName.Build.cs

Add this:


   
PublicIncludePaths.AddRange(
       new string] {
           "YourRunTimeModule",
           "YourRunTimeModule/Public"
          // ... add public include paths required here ...
       }
   );
   PrivateIncludePaths.AddRange(
       new string] {
           "YourRunTimeModuleEditor/Private",
           // ... add other private include paths required here ...
       }
   );
   PublicDependencyModuleNames.AddRange(
       new string]
       {
           "Core",
           "YourRunTimeModule"
           // ... add other public dependencies that you statically link with here ...
       }
   );

...


And here I have the same question again: It seems like the dependencies are all named “XEditor”, however, the author states at first that you can name your editor however you’d like. Does it have to be “XEditor” or it can be “Y”? This is what I did in my CustomK2NodeLibrary_InputSystem.build.cs file:


 
...

PublicIncludePaths.AddRange(
       new string] {
           "RTSCameraTest",
           "RTSCameraTest/Public"
          // ... add public include paths required here ...
       }
   );
   PrivateIncludePaths.AddRange(
       new string] {
           "CustomK2NodeLibrary_InputSystem/Private",
           // ... add other private include paths required here ...
       }
   );
   PublicDependencyModuleNames.AddRange(
       new string]
       {
           "Core",
           "RTSCameraTest"
           // ... add other public dependencies that you statically link with here ...
       }
   );

...


Self-Answer: You can name your editor module however you’d like, as in “Y” instead of “XEditor”.

Finally, the last step is to implement the node itself. I decided to call my node “K2Node_DubsChecker” and I added it to my editor module, as you can see in the screenshot.

http://gyazo.com/2aac1e683183c004fc4de401fb2a1f8b

Now, I’ve got several questions about this, since I am really confused about this part. Several questions I still have:

1 - Which are the necessary methods that I need to implement for this to be included in the Blueprint Graph Editor?

2 - Is WorldContextObject something that I need or is it something particular about his specific custom node?

3 - Expand Node seems to be the method that gets the job done. However, as I’ve seen in Unreal Engine’s source repository in GitHub, there are several nodes, like those under the Flow Control category that do not seem to implement this method. They even inherit from a different class instead of a K2Node. Can somebody shed some light on this subject, please?

4 - Since I inherit directly from UK2Node, unlike the shown example that inherits from “UK2Node_ConstructObjectFromClass”, there are several methods that I needed to look for their implementation inside that parent class, so that my implementation was complete.

K2Node_DubsChecker.h



#pragma once

#include "K2Node.h"
#include "K2Node_DubsChecker.generated.h"

UCLASS(BlueprintType, Blueprintable)
class CUSTOMK2NODELIBRARY_INPUTSYSTEM_API UK2Node_DubsChecker : public UK2Node{

	GENERATED_BODY()

	UK2Node_DubsChecker(const FObjectInitializer& ObjectInitializer);

	virtual void AllocateDefaultPins() override;
	virtual FLinearColor GetNodeTitleColor() const override;
	virtual void ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) override;
	virtual FText GetMenuCategory() const override;
	void GetMenuEntries(FGraphContextMenuBuilder& ContextMenuBuilder) const;

	/** Get the world context input pin, can return NULL */
	UEdGraphPin* GetWorldContextPin() const;

	UEdGraphPin* GetThenPin() const;

protected:

	/** Gets the default node title when no class is selected */
	virtual FText GetBaseNodeTitle() const;
	/** Gets the node title when a class has been selected. */
	virtual FText GetNodeTitleFormat() const;
	/** Gets base class to use for the 'class' pin.  UObject by default. */
	virtual UClass* GetClassPinBaseClass() const;


};


K2Node_DubsChecker.cpp

First part: If I’m right this should be for the right click menu in the Blueprint Graph Editor, so that the node is shown under a category. My node neither shows up under the stated category nor by typing its name or category in the search field.




#include "CustomK2NodeLibrary_InputSystem.h"
#include "InputGraph_BlueprintNodes.h"

#include "KismetCompiler.h"
#include "BlueprintNodeSpawner.h"
#include "EditorCategoryUtils.h"
#include "K2ActionMenuBuilder.h"

#include "K2Node_DubsChecker.h"

#define LOCTEXT_NAMESPACE "InputSystemModule"

...

void UK2Node_DubsChecker::GetMenuEntries(FGraphContextMenuBuilder& ContextMenuBuilder) const{
	UK2Node_DubsChecker* TemplateNode = NewObject<UK2Node_DubsChecker>(GetTransientPackage(), GetClass());

	const FString Category = TEXT("UCustom UK2Node Input Module");
	const FText   MenuDesc = LOCTEXT("CheckMyDubsMenuOption", "Check My Dubs...");
	const FString Tooltip = TEXT("Check if the number ends in Dubs");

	TSharedPtr<FEdGraphSchemaAction_K2NewNode> NodeAction = FK2ActionMenuBuilder::AddNewNodeAction(ContextMenuBuilder, Category, MenuDesc, Tooltip);
	NodeAction->NodeTemplate = TemplateNode;
}

FText UK2Node_DubsChecker::GetMenuCategory() const{
	return FText::FromString("Custom UK2Node Input Module");
}

...


Second part: Expand Node. I know it’s probably not implemented properly. What I need to know first is what exactly do I need to do for my node to show up in the Blueprint Graph Editor. Does it need to be working properly before it shows up? If so, could you please help me in that regard, please? If I can fix it after it shows up in the Blueprint Graph Editor, then that’s something I can do afterwards.



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

	static FName Create_FunctionName = GET_FUNCTION_NAME_CHECKED(UInputGraph_BlueprintNodes, CheckMyDubs);

	static FString WorldContextObject_ParamName = FString(TEXT("WorldContextObject"));
	static FString WidgetType_ParamName = FString(TEXT("ItemType"));

	//get pointer to self;
	UK2Node_DubsChecker* CreateDubsCheckerNode = this;

	//get pointers to default pins.
	//Exec pins are those big arrows, connected with thick white lines.
	UEdGraphPin* SpawnNodeExec = CreateDubsCheckerNode->GetExecPin();
	//gets world context pin from our static function
	UEdGraphPin* SpawnWorldContextPin = CreateDubsCheckerNode->GetWorldContextPin();
	//then pin is the same as exec pin, just on the other side (the out arrow).
	UEdGraphPin* SpawnNodeThen = CreateDubsCheckerNode->GetThenPin();

	//////////////////////////////////////////////////////////////////////////
	// create 'UWidgetBlueprintLibrary::Create' call node
	UK2Node_CallFunction* CallCreateNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(CreateDubsCheckerNode, SourceGraph);
	CallCreateNode->FunctionReference.SetExternalMember(Create_FunctionName, UK2Node_DubsChecker::StaticClass());
	CallCreateNode->AllocateDefaultPins();

	//allocate nodes for created widget.
	UEdGraphPin* CallCreateExec = CallCreateNode->GetExecPin();
	UEdGraphPin* CallCreateWorldContextPin = CallCreateNode->FindPinChecked(WorldContextObject_ParamName);
	UEdGraphPin* CallCreateWidgetTypePin = CallCreateNode->FindPinChecked(WidgetType_ParamName);
	UEdGraphPin* CallCreateResult = CallCreateNode->GetReturnValuePin();

	// Break any links to the expanded node
	CreateDubsCheckerNode->BreakAllNodeLinks();

}


4) Conclusions:

There could be a number of reasons why my node doesn’t show up, but I can’t figure out which ones are the ones that are causing it to not show up. 4 days ago, I posted this question in the Answer Hub:
https://answers.unrealengine.com/questions/205699/custom-blueprint-k2node-creation-node-doesnt-show.html

I haven’t got an answer yet, probably because I didn’t provide enough details and/or information about my problem. That’s why I’m trying my luck now here in the forums. So, for anybody who made the effort to read all of this, thank you very much for your time.

If anybody can shed some light on why is this happening, any kind of hint, help or information, even if it’s incomplete, can help me right now and will be very appreciated, so I’ll welcome it with open arms. Thank you again everybody. If you need anything else, don’t hestitate to ask me about it, I’ll gladly try to help.

- Update 25/4/2015:

After my current findings now I know that:

- For your editor module setup, the only naming requisite itself is the YourProjectName.target.cs and the YourProjectNameEditor.target.cs inside the Source folder of your project. Your editor module can be named however you’d like, and that name will be the same you will use on your base c++ classes for your module and your editor module’s c++ source folder inside the Source folder of your project, as well as where required inside the YourProjectNameEditor.target.cs file.

- Update 28/4/2015: SOLVED!

I’ll add the information, at the start of my post. I personally thank everybody who has helped me!

Solution found here.

1 Like

Could you upload source, so I can take a look. It’s going to be hard to determine, what’s really wrong, without looking at entire source.

[URL Removed by myself since it’s no longer relevant.]
These are all the source files mentioned in the original post (all my source code is there). If you need the whole project, I’m uploading it right now, but it’s going to take a while with my humble 0,3 mb upload speed. I’ll post the link as soon as it finishes uploading.

Update: It’s uploaded. I’ll send you the link through PM. (I don’t know if I can post the link to the full project in the public forum because of the EULA.)

I’ve tried to do it again from scratch following the tutorials, except this time I started with a new c++ project instead of a blueprint one (see project wizard). However, for some reason I couldn’t even compile it. I even recreated it again and compiled afterwards without touching, with the same results. The problem seems to be related with “-canskiplink” and the compiler says it can’t find the target rules, specifically mentioning this file: “-canskiplink_EditorRecompileModuleRules.dll”.

After another week, I still can’t manage to get a basic custom node to show up in the blueprint graph editor though, and I still don’t know why. I’ve tried some other random things, but I’m pretty much lost as of now. Any help or information on the topic would be really appreciated.

By the way, I’ll add in another question: Does posting a public link here in the forums to a test project which contains nothing special but has the basic package that comes in with the editor itself included violate the EULA on distribution? If it does not I’ll post the link so anybody can take a look if necessary.

I’ve found your ARPG project in github, and browsing through it I’ve seen that it uses the exact code and classes you posted in your tutorial, including the custom K2Node. I thought of using it as another source of information, as an example, to compare side by side with my own and to see how a working custom K2Node looks in the blueprint graph editor. I’ve followed the instructions in your readme file and I managed to compile it in Visual Studio. However, whenever I try to open the project itself with the Unreal Editor, it crashes on load. I suspect this might have something to do with this:

“5. Ok everything have hopefully build. To make it work, you will need content from ThirdPersonGameTemplate, StarterContent, and AnimStarterPack.
Most blueprint should work, but references to content might be broken right now. It should be easy to fix though.”

I understand that these are files I can find already in my Unreal Engine installation. However, I don’t seem to be able to find the exact folders where this content is located. I assume porting the content will be a matter of copy pasting it though. So, my questions here would be: Could it be crashing because I need to port that content first? If so, which are the exact folders where the required content is found? If appliable, do I need to use the code version or the blueprint version? Thank you very much in advance.

I just killed half the problem. It seems like** I can confirm that the problem is not the Editor Module** itself, because I just got two properly implemented nodes to work and show up in the blueprint graph editor. I got them from Rama’s pull request as he suggested when I asked him here. I will now update my posts to reflect my current findings, which could aid anybody who finds himself in the same boat.

However, I now have another question: is there any kind of feedback aside from the node not showing up to find implementation mistakes in your custom K2 Node? As always, any help would be very appreciated.

**UPDATE: Problem solved! See the solution at the top of the original post! **