Diagnose/Resolve Linking Errors and Unusual Syntax in AnimGraphNode

I’ve made a custom AnimNode and AnimGraphNode based on LayeredBoneBlend and managed to get it to work. I tried making a child class, but it was giving me all sorts or cryptic error messages so I gave up and just copied them and made the changes I needed. However, there is one section that I could not figure out how to get working and I don’t understand what is happening. This class uses an unusual syntax. I can compile, run, and package the project with the modifications below, but I’m both curious about what’s happening and concerned this will give me a headache in the future.

Here is original code in question:
(AnimGraphNode_LayeredBoneBlend.h)

UCLASS(MinimalAPI)
class UAnimGraphNode_LayeredBoneBlend : public UAnimGraphNode_BlendListBase
...

// Adds a new pose pin
//@TODO: Generalize this behavior (returning a list of actions/delegates maybe?)
ANIMGRAPH_API virtual void AddPinToBlendByFilter();
ANIMGRAPH_API virtual void RemovePinFromBlendByFilter(UEdGraphPin* Pin);

(AnimGraphNode_LayeredBoneBlend.cpp)

void UAnimGraphNode_LayeredBoneBlendChild::AddPinToBlendByFilter()
{
	FScopedTransaction Transaction(LOCTEXT("AddPinToBlend", "AddPinToBlendByFilter"));
	Modify();

	Node.AddPose();
	ReconstructNode();
	FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetBlueprint());
}

To get this working I have to make the following modifications:

(AnimGraphNode_LayeredBoneBlendCustom.h)

UCLASS()
class MYEDITORMODULE_API UAnimGraphNode_LayeredBoneBlendCustom : public UAnimGraphNode_BlendListBase
...
// Adds a new pose pin
//@TODO: Generalize this behavior (returning a list of actions/delegates maybe?)
//ANIMGRAPH_API 
virtual void AddPinToBlendByFilter();
//ANIMGRAPH_API 
virtual void RemovePinFromBlendByFilter(UEdGraphPin* Pin);

(AnimGraphNode_LayeredBoneBlendCustom.cpp)

void UAnimGraphNode_LayeredBoneBlendCustom::AddPinToBlendByFilter()
{
	//FScopedTransaction Transaction(LOCTEXT("AddPinToBlend", "AddPinToBlendByFilter"));
	Modify();

	Node.AddPose();
	ReconstructNode();
	//FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetBlueprint());
}

void UAnimGraphNode_LayeredBoneBlendCustom::RemovePinFromBlendByFilter(UEdGraphPin* Pin)
(I also have to comment out any references to FScopedTransaction or FBlueprintEditorUtils here to get it to compile.)

Compiling

FScopedTransaction Transaction(LOCTEXT(“AddPinToBlend”, “AddPinToBlendByFilter”))
or
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetBlueprint());

with ANIMGRAPH_API removed from AddPinToBlendByFilter/RemovePinFromBlendByFilter generates the following output:

Output: “… error LNK2019: unresolved external symbol …”
Error: “Severity Code Description Project File Line Suppression State
Error (active) E0020 identifier “UK2Node_CallFunction” is undefined Main D:\Program Files\Epic Games\UE_4.26\Engine\Source\Editor\UnrealEd\Public\Kismet2\BlueprintEditorUtils.h 340”

If I leave ANIMGRAPH_API in front of them I get:
Output: “error C2487: ‘AddPinToBlendByFilter’: member of dll interface class may not be declared with dll interface”
Error: “Severity Code Description Project File Line Suppression State
Error (active) E1393 a member of a class declared with dllexport/dllimport cannot itself be declared with such a specifier …”

a) Can someone help me understand what is happening? Am I missing a module or something? Am I missing a header file include?

Here is my build.cs module includes:

PublicDependencyModuleNames.AddRange(
new string[]
{
“Core”,
“CoreUObject”,
“Engine”,
“AnimationCore”,
“AnimGraphRuntime”
}
);

Here are my header includes:
h file includes
#include “CoreMinimal.h”
#include “UObject/ObjectMacros.h”
#include “AnimGraphNode_BlendListBase.h”
cpp file includes
#include “ToolMenus.h”
#include “Kismet2/BlueprintEditorUtils.h”
#include “GraphEditorActions.h”
#include “ScopedTransaction.h”

b) What does it mean to include the API in front of a function declaration (i.e. ANIMGRAPH_API virtual void AddPinToBlendByFilter();). Is that a weird way of inheriting from another API/Class?

c) What is MINIMAL_API, why is that used in this AnimGraphNode instead of the ANIMGRAPH_API?

I could be way off here, it looks like you’re trying to override virtual functions from the original UAnimGraphNode_BlendListBase, but you haven’t included the override specifier at the end of the declare in your header file.

 ANIMGRAPH_API virtual void AddPinToBlendByFilter() override;
 ANIMGRAPH_API virtual void RemovePinFromBlendByFilter(UEdGraphPin* Pin) override;

That might clear things up for you, as the linker could find issue with these functions as you are altering their definitions in the child class, which inherits their original definitions from their parent class. Let me know if this helps resolve your issue.

Thanks for the great suggestion. Unfortunately that wasn’t the answer. I get the following error:

“‘AddPinToBlendByFilter’: member of dll interface class may not be declared with dll interface”
-I do not know what this means.

My AnimNode currently doesn’t inherent from the one it is based on as doing it that way was even more volatile. This is essentially a rewrite and so those functions aren’t defined until my AnimNode.

Also, as far as I know the main problem isn’t with the way the functions are declared, it is with FScopedTransaction and FBlueprintEditorUtils. Trying to create a FScopedTransaction or calling a function from FBlueprintEditorUtils is what generates the linking errors.

A bit late to the party, coincidentally trying to make a few changes to UAnimGraphNode_LayeredBoneBlend also and ran into the exact same issue with AddPinToBlendByFilter and RemovePinFromBlendByFilter, so (for now) I’m just removing them via an #if 0 block.

To solve the linker error with FScopedTransaction, do “jump to definition” on FScopedTransaction and you’ll end up in the following file, which gives you a clue that it’s specific to “UnrealEd”:
...\Engine\Source\Editor\UnrealEd\Private\ScopedTransaction.cpp

So in your build.cs you should have something with PublicDependencyModuleNames.AddRange. You’ll want to add “UnrealEd” to that to solve the linker error.

Next similar one I had was related to FToolMenuEntry, using the same strategy shows you need to add “ToolMenus” in the build.cs.