TL;DR
I’m trying to mimic the functionality of e.g. K2Node_VariableGet, where there is only one K2Node class that sweeps for avaible properties within a Blueprint, and populates Actions Menu with multiple Node entries per every avaible property.
Context:
I want to create a custom K2Node that would appear in Actions Menu only when the targeted Blueprint has a specific Component in it. I also want this node to behave slightly diffrent for each of these Components, so the Actions Menu should be populated with multiple entries of this Node (one Node per Component).
Example:
I bieleve every subclass of K2Node_Variable and K2Node_StructOperation does something similiar to what I’m looking for.
(For comparison, on the screenshots above are K2Node_VariableGet and K2Node_BreakStruct )
My issue:
Well, I’m just stuck at figuring out the logic behind this all, and I feel I’m wasting my time at this point.
As I understand such logic should be executed in override of UK2Node::GetMenuActions, but I failed with implementing it.
What I’ve tried:
-
Googling… looking for tutorials…
I believe the only good online resource about K2Nodes is this post on Gamedev.net but it doesn’t tell anything useful about my case. Haven’t seen any diffrent post about such case on this forum. -
Checking source code:
- Aparently these classes do not override GetMenuActions at all: K2Node_Variable, K2Node_VariableGet, K2Node_VariableSet. They’re probably implementing such logic in diffrent way, which is unknown to my knowleadge and seems like a dead end.
- Class like K2Node_BreakStruct just passes the logic of GetMenuActions somewhere else, to probably this function from K2Node_StructOperation, but this seems to involve a logic only specific for USTRUCTs
void UK2Node_BreakStruct::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
{
Super::SetupMenuActions(ActionRegistrar, FMakeStructSpawnerAllowedDelegate::CreateStatic(&UK2Node_BreakStruct::CanBeBroken), EGPD_Output);
}
/** Utility function to set up menu actions to set the struct type and promote category */
DECLARE_DELEGATE_RetVal_TwoParams(bool, FMakeStructSpawnerAllowedDelegate, const UScriptStruct*, bool);
void SetupMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar, const FMakeStructSpawnerAllowedDelegate& AllowedDelegate, EEdGraphPinDirection PinDirectionToPromote) const;
- At this point diving into source code results in finding new questions more often than answering the ones already existing.
- I’ve tried to implement such logic on my own, by writing this code (I hope it’s readable):
void UK2Node_MyCustomNode::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
{
UClass* ActionKey = GetClass();
if (ActionRegistrar.IsOpenForRegistration(ActionKey))
{
UBlueprint* OwningBlueprint = GetBlueprint();
UObject* OwningObject = Cast<UObject>(OwningBlueprint);
check(OwningObject)
TArray<UObject*> Subobjects;
OwningObject->GetDefaultSubobjects(Subobjects);
for (UObject* Object : Subobjects)
{
UMyComponent* MyComponent = Cast<UMyComponent>(Object);
if (MyComponent)
{
UBlueprintNodeSpawner::FCustomizeNodeDelegate PostSpawnDelegate;
PostSpawnDelegate.BindLambda(
[MyComponent](UEdGraphNode* NewNode, bool bIsTemplateNode)
{
UK2Node_MyCustomNode* ThisNode = Cast<UK2Node_MyCustomNode>(NewNode);
check(ThisNode)
ThisNode->TargetedComponent = MyComponent;
});
UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create(ActionKey, nullptr, PostSpawnDelegate);
check(NodeSpawner != nullptr);
ActionRegistrar.AddBlueprintAction(ActionKey, NodeSpawner);
}
}
}
}
But it always throws the following assertion at the beggining, so the GetBlueprint always returns nullptr. It happens right when I open Blueprint class in the Editor.
Assertion failed: Result [File:D:\build\++UE5\Sync\Engine\Source\Editor\UnrealEd\Private\Kismet2\BlueprintEditorUtils.cpp] [Line: 2220]
FBlueprintEditorUtils::FindBlueprintForNodeChecked(/Script/StatefulAbility.Default__K2Node_ExecuteAbility) failed to find a Blueprint.
I’ll be really thankful for any kind of help or guideance
I’m not familiar with K2Nodes so I’m clearly missing something here.