Download

How to call K2 node without manual connection pins in blueprints

I am trying to make it so that when placing K2 nodes in blueprints, I don’t need to connect their input pins to the BeginPlay event. When this pin is executed, the object will be spawned, and events (which execute output pins) are bound to its delegates. I would like this part to work without connecting the pins. How can I do this?


[SPOILER]



// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "K2Node.h"
#include "K2Node_BindQuestTask.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOutputPin_Out);

/**
*
*/
UCLASS(BlueprintType, Blueprintable)
class QUESTSYSTEMSUPPORT_API UK2Node_BindQuestTask : public UK2Node
{
GENERATED_BODY()

public:


//UEdGraphNode implementation
virtual void AllocateDefaultPins() override;
virtual void PinDefaultValueChanged(UEdGraphPin* Pin) override;
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
virtual FText GetTooltipText() const override;

virtual void PostPlacedNewNode() override;
//UEdGraphNode implementation

//K2Node implementation
virtual FText GetMenuCategory() const override;
virtual void ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) override;
virtual void GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const override;
// virtual void NotifyPinConnectionListChanged(UEdGraphPin* Pin) override;
virtual void PinConnectionListChanged(UEdGraphPin* Pin) override;
virtual FNodeHandlingFunctor* CreateNodeHandler(FKismetCompilerContext& CompilerContext) const override;

virtual void ReallocatePinsDuringReconstruction(TArray<UEdGraphPin*>& OldPins) override;
//K2Node implementation


//~ Begin UK2Node Interface
virtual UClass* GetDynamicBindingClass() const override;
virtual void RegisterDynamicBinding(UDynamicBlueprintBinding* BindingObject) const override;
//~ End UK2Node Interface



//Helpers for getting pins
UEdGraphPin* GetThenPin() const;
UEdGraphPin* GetSelfPin() const;
// UEdGraphPin* GetTargetPin() const;
UEdGraphPin* GetReturnValuePin() const;
/** Get the blueprint input pin */
UEdGraphPin* GetClassPin(const TArray<UEdGraphPin*>* InPinsToSearch = NULL) const;


//Custom functions
// static UFunction* FindSetterFunctionByType(FEdGraphPinType& PinType);

UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"))
static void Temp(UObject* WorldContextObject);

UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"))
void TestFunc(UWorld* World);

UFUNCTION(BlueprintCallable)
void NodeBeginPlay();

UPROPERTY(BlueprintAssignable, EditAnywhere, BlueprintReadWrite, BlueprintCallable)
FOutputPin_Out OnEnd;
UPROPERTY(BlueprintAssignable)
FOutputPin_Out OnComplete;

UFUNCTION(BlueprintCallable)
void DEnd() { OnEnd.Broadcast(); };

UFUNCTION(BlueprintCallable)
void DComplete() { OnComplete.Broadcast(); };

/** Refresh pins when class was changed */
void OnClassPinChanged();

UClass* GetClassToSpawn(const TArray<UEdGraphPin*>* InPinsToSearch = NULL) const;

/** Create new pins to show properties on archetype */
virtual void CreatePinsForClass(UClass* InClass, TArray<UEdGraphPin*>* OutClassPins = nullptr);
/** See if this is a spawn variable pin, or a 'default' pin */
virtual bool IsSpawnVarPin(UEdGraphPin* Pin) const;


virtual void PostInitProperties() override;


/** Create BindNode and CustomEventNode */
void CreateBindAndEvent(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph, class UK2Node_AddDelegate** pBindNode, class UK2Node_CustomEvent** pCustomEventNode, FName PropertyName, class UK2Node_GenericCreateObject** ObjNode);

protected:
/** Constructing FText strings can be costly, so we cache the node's title */
//FNodeTextCache CachedNodeTitle;

private:

FDelegateHandle dh;

};



[/SPOILER]

[SPOILER]



// Fill out your copyright notice in the Description page of Project Settings.


#include "K2Node_BindQuestTask.h"

//#include "UObject/UnrealType.h"
//#include "EdGraphSchema_K2.h"
//#include "EdGraph/EdGraphNodeUtils.h"
//#include "EdGraphUtilities.h"
//#include "BPTerminal.h"

//#include "KismetCompilerMisc.h"
#include "KismetCompiler.h"
//#include "EditorCategoryUtils.h"


//#include "Kismet/KismetMathLibrary.h"
#include "BlueprintNodeSpawner.h"
#include "BlueprintActionDatabaseRegistrar.h"

//"BlueprintEditorUtils.h"
#include "Kismet2/BlueprintEditorUtils.h"

#include "K2Node_CallFunction.h"
#include "K2Node_AddDelegate.h"
#include "K2Node_CustomEvent.h"

#include "K2Node_ConstructObjectFromClass.h"
#include "K2Node_GenericCreateObject.h"

#include "K2Node_Self.h"

#include "K2Node_VariableGet.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Kismet/GameplayStatics.h"

#include "Delegates/Delegate.h"

#define LOCTEXT_NAMESPACE "UK2Node_BindQuestTask"



namespace FGetPinName
{
static const FName StartPinName(TEXT("Start"));
static const FName FinishPinName(TEXT("Finish"));
//static const FName EndPinName(TEXT("End"));
static const FName CompletePinName(TEXT("Complete"));
static const FName Node(TEXT("Node"));
static const FName TaskPinName(TEXT("Task"));
//static const FName DelegatePinName(TEXT("EndDelegate"));
};



void UK2Node_BindQuestTask::AllocateDefaultPins()
{
const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();

//Input pins
UEdGraphNode::FCreatePinParams PinParams;
PinParams.bIsReference = true;

UEdGraphPin *ep = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Class, UObject::StaticClass(), FGetPinName::TaskPinName);
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, FGetPinName::StartPinName);
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, FGetPinName::FinishPinName);
auto SelfPin = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Object, UObject::StaticClass(), UEdGraphSchema_K2::PN_Self);
SelfPin->SafeSetHidden(true);

//Output pins
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);
//CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Object, UK2Node_BindQuestTask::StaticClass(), FGetPinName::RefName);
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Object, UEdGraphSchema_K2::PN_ReturnValue);
//CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Wildcard, UEdGraphSchema_K2::PN_ReturnValue);
//CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Delegate, FGetPinName::DelegatePinName);
//CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, FGetPinName::EndPinName);
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, FGetPinName::CompletePinName);

//K2Schema->SetPinAutogeneratedDefaultValue(NamePin, FName("My Var Name").ToString());
//K2Schema->SetPinAutogeneratedDefaultValueBasedOnType(OutValidPin);

//FWorldDelegates::OnPostWorldCreation.Remove(dh);
//if (!FWorldDelegates::OnPostWorldCreation.IsBoundToObject(this)) {
// dh = FWorldDelegates::OnPostWorldCreation.AddUObject(this, &UK2Node_BindQuestTask::TestFunc);
// UE_LOG(LogTemp, Error, TEXT("---------------------Bound Function---------------------"));
//}

//if (dh.IsValid()) {
// FWorldDelegates::OnPostWorldCreation.Remove(dh);
// UE_LOG(LogTemp, Error, TEXT("---------------------Remove---------------------"));
//}
//dh = FWorldDelegates::OnPostWorldCreation.AddUObject(this, &UK2Node_BindQuestTask::TestFunc);
//UE_LOG(LogTemp, Error, TEXT("---------------------Bound Function---------------------"));





//auto Result = GetGraph()->CreateIntermediateNode<UK2Node_Event>();
////check (Cast<UK2Node_Event>(Result) == nullptr); -- Removed to avoid any fallout, will replace with care later
//Result->CreateNewGuid();
//Result->AllocateDefaultPins();
//GetSchema()->TryCreateConnection(GetExecPin(), Result->FindPinChecked(UEdGraphSchema_K2::PN_Then));




Super::AllocateDefaultPins();
}


////////////////////////////////////////////////////////////////////////////
//// FKCHandler_Switch

class FKCHandler_AutoRun : public FNodeHandlingFunctor
{
public:
FKCHandler_AutoRun(FKismetCompilerContext& InCompilerContext)
: FNodeHandlingFunctor(InCompilerContext)
{
}

//virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node) override
//{
// UK2Node_SwitchFlow* SwitchNode = Cast<UK2Node_SwitchFlow>(Node);

// FNodeHandlingFunctor::RegisterNets(Context, Node);

// // Create a term to determine if the compare was successful or not
// //@TODO: Ideally we just create one ever, not one per switch
// FBPTerminal* BoolTerm = Context.CreateLocalTerminal();
// BoolTerm->Type.PinCategory = UEdGraphSchema_K2::PC_Boolean;
// BoolTerm->Source = Node;
// BoolTerm->Name = Context.NetNameMap->MakeValidName(Node, TEXT("CmpSuccess"));
// BoolTermMap.Add(Node, BoolTerm);
//}
virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node) override
{
FNodeHandlingFunctor::RegisterNets(Context, Node);
for (UEdGraphPin* Pin : Node->Pins)
{
UE_LOG(LogTemp, Error, TEXT("---------------------NetLoopPin - %s---------------------"), *Pin->GetName());
}
}

virtual void RegisterNet(FKismetFunctionContext& Context, UEdGraphPin* Net) override
{
UE_LOG(LogTemp, Error, TEXT("---------------------RegisterNet - %s---------------------"), *Net->GetName());
//if (!Context.IsEventGraph())
//{
// Context.MessageLog.Error(TEXT("Event node @@ registers net @@ in a non-event graph."), Net ? Net->GetOwningNodeUnchecked() : nullptr, Net);
// return;
//}

//// This net is an event parameter; push to be a private class member variable
//FBPTerminal* Term = Context.CreateLocalTerminal(ETerminalSpecification::TS_ForcedShared);
//Term->CopyFromPin(Net, Context.NetNameMap->MakeValidName(Net));

//Context.NetMap.Add(Net, Term);
}
virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
{
UE_LOG(LogTemp, Error, TEXT("---------------------Compile---------------------"));
// Generate the output impulse from this node
//FBlueprintCompiledStatement& Statement = GenerateSimpleThenGoto(Context, *Node);
}

};


FNodeHandlingFunctor* UK2Node_BindQuestTask::CreateNodeHandler(FKismetCompilerContext& CompilerContext) const
{
//UE_LOG(LogTemp, Error, TEXT("---------------------Create node hundler---------------------"));
return new FKCHandler_AutoRun(CompilerContext);
//return Super::CreateNodeHandler(CompilerContext);
}



FText UK2Node_BindQuestTask::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
return LOCTEXT("BindQuestTaskK2Node_Title", "Quick Bind QuestTask");
}
FText UK2Node_BindQuestTask::GetTooltipText() const
{
return LOCTEXT("BindQuestTaskK2Node_Tooltip", "Bind QuestTask to Exec");
}
FText UK2Node_BindQuestTask::GetMenuCategory() const
{
return LOCTEXT("BindQuestTaskK2Node_MenuCategory", "QuestTask");
}
void UK2Node_BindQuestTask::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
{
Super::GetMenuActions(ActionRegistrar);

UClass* Action = GetClass();

if (ActionRegistrar.IsOpenForRegistration(Action))
{
UBlueprintNodeSpawner* Spawner = UBlueprintNodeSpawner::Create(GetClass());
check(Spawner != nullptr);

ActionRegistrar.AddBlueprintAction(Action, Spawner);
}
}



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

const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();


// //GetVar node
//UK2Node_VariableGet* GetVarNode = CompilerContext.SpawnIntermediateNode<UK2Node_VariableGet>(this, SourceGraph);
////GetVarNode->VariableReference.SetLocalMember("self", "self", NodeGuid);
//GetVarNode->VariableReference.SetSelfMember("this");
//GetVarNode->AllocateDefaultPins();
//UEdGraphPin* ValuePin = GetVarNode->GetValuePin();
//for (auto it : GetVarNode->Pins) {
// UE_LOG(LogTemp, Error, TEXT("Pin - %s "), *it->PinName.ToString());
// if (it->DefaultObject) {
// UE_LOG(LogTemp, Error, TEXT("Pin default value - %s "), *it->DefaultObject->GetName());
// }
//}
//if (ValuePin)
//{
// UE_LOG(LogTemp, Error, TEXT("GetSelf Pin default value - %s "), *GetVarNode->GetValuePin()->DefaultObject->GetName());
// // Move pin links from Get node we are expanding, to the new pure one we've created
// //CompilerContext.MovePinLinksToIntermediate(*GetVarNode->GetOutputPin(), *ValuePin);
//}
//else
//{
// CompilerContext.MessageLog.Error(*LOCTEXT("ExpandForPin_Error", "ExpandForPin error, no property found for ").ToString());
//}
//CompilerContext.MessageLog.NotifyIntermediateObjectCreation(GetVarNode, this);






//Create SelfRef node
UK2Node_Self* SelfNode = CompilerContext.SpawnIntermediateNode<UK2Node_Self>(this, SourceGraph);
SelfNode->AllocateDefaultPins();
SelfNode->FindPinChecked(UEdGraphSchema_K2::PN_Self)->DefaultObject = GetBlueprint()->GetOuter();



//auto Obj = UGameplayStatics::SpawnObject(GetClassToSpawn(), FindPinChecked(UEdGraphSchema_K2::PN_Self)->DefaultObject->GetWorld());
//UE_LOG(LogTemp, Error, TEXT("obj = %s, class = %s"), *Obj->GetName(), *Obj->GetClass()->GetName());
//if (Obj->GetOuter())
//{
// UE_LOG(LogTemp, Error, TEXT("obj outer = %s"), *Obj->GetOuter()->GetName());
//}


// //Create object
//if (UKismetSystemLibrary::IsValidClass(GetClassToSpawn()))
//{
// UE_LOG(LogTemp, Log, TEXT("Spawn"));
// QuestTask = NewObject<UObject>(this, GetClassToSpawn());
// //QuestTask = UGameplayStatics::SpawnObject(UImprovedObject::StaticClass(), this);
// UE_LOG(LogTemp, Log, TEXT("Spawned: %s, Outer: %s"), *QuestTask->GetName(), *QuestTask->GetOuter()->GetName());
//}
//else
//{
// UE_LOG(LogTemp, Log, TEXT("No spawn"));
//}



//Create ConstructObject node
UK2Node_GenericCreateObject* ConstructQuestTaskObjNode = CompilerContext.SpawnIntermediateNode<UK2Node_GenericCreateObject>(this, SourceGraph);
ConstructQuestTaskObjNode->AllocateDefaultPins();
//Schema->TrySetDefaultObject(*ConstructQuestTaskObjNode->GetOuterPin(), this); //or GetOuter()->GetOuter()

Schema->TryCreateConnection(SelfNode->FindPinChecked(UEdGraphSchema_K2::PN_Self), ConstructQuestTaskObjNode->GetOuterPin());
//Change ReturnRef type
auto RetPin = this->FindPin(UEdGraphSchema_K2::PN_ReturnValue);
auto ResultPin = ConstructQuestTaskObjNode->GetResultPin();
ResultPin->PinType = RetPin->PinType;
CompilerContext.MessageLog.NotifyIntermediateObjectCreation(ConstructQuestTaskObjNode, this);

CompilerContext.MovePinLinksToIntermediate(*this->GetClassPin(), *ConstructQuestTaskObjNode->GetClassPin());



//Create OnEnd nodes
UK2Node_AddDelegate* BindNode{ nullptr };
UK2Node_CustomEvent* CustomEventNode{ nullptr };
CreateBindAndEvent(CompilerContext, SourceGraph, &BindNode, &CustomEventNode, "OnEnd", &ConstructQuestTaskObjNode);
if (!BindNode || !CustomEventNode)
{
CompilerContext.MessageLog.Error(*LOCTEXT("BindQuestTask_NotCreated", "Not created nodes.").ToString(), this);
return;
}

//Create OnComplete nodes
UK2Node_AddDelegate* BindNode2{ nullptr };
UK2Node_CustomEvent* CustomEventNode2{ nullptr };
CreateBindAndEvent(CompilerContext, SourceGraph, &BindNode2, &CustomEventNode2, "__OnComplete", &ConstructQuestTaskObjNode);
if (!BindNode2 || !CustomEventNode2)
{
CompilerContext.MessageLog.Error(*LOCTEXT("BindQuestTask_NotCreated2", "Not created nodes2.").ToString(), this);
return;
}


//Create TestFuncnion node
UFunction* BlueprintFunction = FindFunction(FName("TestFunc"));
if (!BlueprintFunction)
{
CompilerContext.MessageLog.Error(*LOCTEXT("BindQuestTask_InvalidFunctionName", "The function has not been found.").ToString(), this);
return;
}
UK2Node_CallFunction* CallFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
CallFunction->SetFromFunction(BlueprintFunction);
CallFunction->AllocateDefaultPins();
Schema->TrySetDefaultObject(*CallFunction->FindPin(UEdGraphSchema_K2::PN_Self, EGPD_Input), this);
CompilerContext.MessageLog.NotifyIntermediateObjectCreation(CallFunction, this);



//Create CallStart node
UFunction* StartUFunction = GetClassToSpawn()->FindFunctionByName(FName("Start"));
if (!StartUFunction)
{
CompilerContext.MessageLog.Error(*LOCTEXT("BindQuestTask_InvalidStartFunctionName", "The Start function has not been found.").ToString(), this);
return;
}
UK2Node_CallFunction* CallStartFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
CallStartFunction->SetFromFunction(StartUFunction);
CallStartFunction->AllocateDefaultPins();
CompilerContext.GetSchema()->TryCreateConnection(CallStartFunction->FindPinChecked(UEdGraphSchema_K2::PN_Self, EGPD_Input), ConstructQuestTaskObjNode->GetResultPin());
CompilerContext.MessageLog.NotifyIntermediateObjectCreation(CallStartFunction, this);

CompilerContext.MovePinLinksToIntermediate(*this->FindPin(FGetPinName::StartPinName), *CallStartFunction->GetExecPin());


//Create CallComplete node
UFunction* CompleteUFunction = GetClassToSpawn()->FindFunctionByName(FName("Complete"));
if (!CompleteUFunction)
{
CompilerContext.MessageLog.Error(*LOCTEXT("BindQuestTask_InvalidStartFunctionName", "The Start function has not been found.").ToString(), this);
return;
}
UK2Node_CallFunction* CallCompleteFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
CallCompleteFunction->SetFromFunction(CompleteUFunction);
CallCompleteFunction->AllocateDefaultPins();
CompilerContext.GetSchema()->TryCreateConnection(CallCompleteFunction->FindPinChecked(UEdGraphSchema_K2::PN_Self, EGPD_Input), ConstructQuestTaskObjNode->GetResultPin());
CompilerContext.MessageLog.NotifyIntermediateObjectCreation(CallCompleteFunction, this);

CompilerContext.MovePinLinksToIntermediate(*this->FindPin(FGetPinName::FinishPinName), *CallCompleteFunction->GetExecPin());


////Test -Connect delegate pin- Test
//CompilerContext.MovePinLinksToIntermediate(*this->FindPin(FGetPinName::DelegatePinName), *CustomEventNode->FindPinChecked(UK2Node_CustomEvent::DelegateOutputName));




TArray<UEdGraph*> graphs;
GetBlueprint()->GetAllGraphs(graphs);
UE_LOG(LogTemp, Error, TEXT("Blueprint - %s"), *GetBlueprint()->GetName());
for (auto it : graphs)
{
UE_LOG(LogTemp, Error, TEXT("Graph - %s"), *it->GetName());
for (auto node : it->Nodes)
{
UE_LOG(LogTemp, Error, TEXT("Node - %s"), *node->GetName());
if (node->GetClass() == GetClass())
{
UE_LOG(LogTemp, Error, TEXT("Node - %s, in graph - %s "), *node->GetName(), *it->GetName());
}
}
}

//UK2Node_Event
TArray<UK2Node_Event*> arr;
SourceGraph->GetNodesOfClass<UK2Node_Event>(arr);

UK2Node_Event *BeginPlay = nullptr;
for (auto it : arr) {
//UE_LOG(LogTemp, Error, TEXT("Class - %s "), *it->GetClass()->GetName());
//UE_LOG(LogTemp, Error, TEXT("Title - %s "), *it->GetNodeTitle(ENodeTitleType::FullTitle).ToString());
//UE_LOG(LogTemp, Error, TEXT("Function - %s"), *it->GetFunctionName().ToString());
//UE_LOG(LogTemp, Error, TEXT("FunctionRefName - %s"), *it->EventReference.GetMemberName().ToString());
//UE_LOG(LogTemp, Error, TEXT("------------------------------------------"));
//if(it->GetFunctionName() == "ReceiveBeginPlay")
//{
// BeginPlay = it;
//}
//if (it->GetNodeTitle()) {
// UE_LOG(LogTemp, Error, TEXT("Pin default value - %s "), *it->DefaultObject->GetName());
//}
//else
//{
// UE_LOG(LogTemp, Error, TEXT("Pin %s default value not valid"), *it->PinName.ToString());
//}
}



//Connect Return Value
CompilerContext.MovePinLinksToIntermediate(*this->GetReturnValuePin(), *ConstructQuestTaskObjNode->GetResultPin());
//Connect BindNode and CustomEvent nodes
//CompilerContext.MovePinLinksToIntermediate(*this->FindPin(FGetPinName::EndPinName), *CustomEventNode->FindPin(UEdGraphSchema_K2::PN_Then));
//Connect BindNode and CustomEvent nodes2
CompilerContext.MovePinLinksToIntermediate(*this->FindPin(FGetPinName::CompletePinName), *CustomEventNode2->FindPin(UEdGraphSchema_K2::PN_Then));
//Connect Execs
CompilerContext.MovePinLinksToIntermediate(*this->GetExecPin(), *ConstructQuestTaskObjNode->GetExecPin());
//if(BeginPlay) Schema->TryCreateConnection(BeginPlay->FindPin(UEdGraphSchema_K2::PN_Then), ConstructQuestTaskObjNode->GetExecPin());
Schema->TryCreateConnection(ConstructQuestTaskObjNode->GetThenPin(), BindNode->GetExecPin());
Schema->TryCreateConnection(BindNode->FindPin(UEdGraphSchema_K2::PN_Then), BindNode2->GetExecPin());
Schema->TryCreateConnection(BindNode2->FindPin(UEdGraphSchema_K2::PN_Then), CallFunction->GetExecPin());
CompilerContext.MovePinLinksToIntermediate(*this->GetThenPin(), *CallFunction->GetThenPin());

//ProcessEvent(CustomEventNode->FindEventSignatureFunction(), 0);
//UE_LOG(LogTemp, Warning, TEXT("---------------------End compile---------------------"));

//After we are done we break all links to this node (not the internally created one)
BreakAllNodeLinks();

}




void UK2Node_BindQuestTask::Temp(UObject * WorldContextObject)
{
UE_LOG(LogTemp, Error, TEXT("---------------------Temp function call---------------------"));
}



void UK2Node_BindQuestTask::TestFunc(UWorld* World)
{
//UE_LOG(LogTemp, Error, TEXT("TestFunc start"));

//FScriptDelegate Delegate;
//Delegate.BindUFunction(CustomEventNode->FindEventSignatureFunction(), CustomEventNode->DelegateOutputName);
//OnEnd.Add(Delegate);


//FTimerDynamicDelegate Delegate2;
//Delegate2.BindUFunction(this, "Temp");
//UKismetSystemLibrary::K2_SetTimerDelegate(Delegate2, 3.0f, false);

//FTimerHandle UnusedHandle;
//auto World = WorldContextObject->GetWorld();
//if(World)
//{
// World->GetTimerManager().SetTimer(UnusedHandle, this, &UK2Node_BindQuestTask::DEnd, 3.f, false);
//}
//else {
// UE_LOG(LogTemp, Error, TEXT("Invalid world"));
//}


UE_LOG(LogTemp, Error, TEXT("TestFunc end"));
}

void UK2Node_BindQuestTask::CreateBindAndEvent(FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph, UK2Node_AddDelegate** pBindNode, UK2Node_CustomEvent** pCustomEventNode, FName PropertyName, UK2Node_GenericCreateObject** ObjNode) {

//Find delegat Prorerty
if (!UKismetSystemLibrary::IsValidClass(GetClassToSpawn()))
{
CompilerContext.MessageLog.Error(*LOCTEXT("CreateBindAndEvent_InvalidClass", "Task class == none.").ToString(), this);
return;
}


FProperty *FindProperty = GetClassToSpawn()->FindPropertyByName(PropertyName);
FMulticastDelegateProperty* Property = CastField<FMulticastDelegateProperty>(FindProperty);
if (!FindProperty)
{
CompilerContext.MessageLog.Error(*FText::Format(LOCTEXT("CreateBindAndEvent_InvalidProperty", "The property {0} has not been found."), FText::FromName(PropertyName)).ToString(), this);
return;
}


//for (TFieldIterator<FMulticastDelegateProperty> PropertyIt(GetClassToSpawn()); PropertyIt; ++PropertyIt)
//{
// UE_LOG(LogTemp, Error, TEXT("Field - %s "), *PropertyIt->GetName());
// Property = *PropertyIt;
// break;
//}


//Create Bind node
UK2Node_AddDelegate* BindNode = CompilerContext.SpawnIntermediateNode<UK2Node_AddDelegate>(this, SourceGraph);
BindNode->SetFromProperty(Property, false, Property->GetOwnerClass());
BindNode->AllocateDefaultPins();
CompilerContext.MessageLog.NotifyIntermediateObjectCreation(BindNode, this);

UK2Node_CustomEvent* CustomEventNode = CompilerContext.SpawnIntermediateEventNode<UK2Node_CustomEvent>(this, BindNode->GetDelegatePin(), SourceGraph);
//CustomEventNode->bInternalEvent = true;
//CustomEventNode->bCallInEditor = true;
CustomEventNode->CustomFunctionName = *FString::Printf(TEXT("%s_%s"), *Property->GetName(), *CompilerContext.GetGuid(this));
CustomEventNode->AllocateDefaultPins();
CompilerContext.MessageLog.NotifyIntermediateObjectCreation(CustomEventNode, this);

*pBindNode = BindNode;
*pCustomEventNode = CustomEventNode;

CompilerContext.GetSchema()->TryCreateConnection(BindNode->FindPinChecked(UEdGraphSchema_K2::PN_Self, EGPD_Input), (*ObjNode)->GetResultPin());
CompilerContext.GetSchema()->TryCreateConnection(BindNode->GetDelegatePin(), CustomEventNode->FindPinChecked(UK2Node_CustomEvent::DelegateOutputName));
}


void UK2Node_BindQuestTask::CreatePinsForClass(UClass* InClass, TArray<UEdGraphPin*>* OutClassPins)
{
check(InClass);

const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();

const UObject* const ClassDefaultObject = InClass->GetDefaultObject(false);

for (TFieldIterator<FProperty> PropertyIt(InClass, EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt)
{
FProperty* Property = *PropertyIt;
UClass* PropertyClass = CastChecked<UClass>(Property->GetOwner<UObject>());
const bool bIsDelegate = Property->IsA(FMulticastDelegateProperty::StaticClass());
const bool bIsExposedToSpawn = UEdGraphSchema_K2::IsPropertyExposedOnSpawn(Property);
const bool bIsSettableExternally = !Property->HasAnyPropertyFlags(CPF_DisableEditOnInstance);

if (bIsExposedToSpawn &&
!Property->HasAnyPropertyFlags(CPF_Parm) &&
bIsSettableExternally &&
Property->HasAllPropertyFlags(CPF_BlueprintVisible) &&
!bIsDelegate &&
(nullptr == FindPin(Property->GetFName())) &&
FBlueprintEditorUtils::PropertyStillExists(Property))
{
if (UEdGraphPin* Pin = CreatePin(EGPD_Input, NAME_None, Property->GetFName()))
{
K2Schema->ConvertPropertyToPinType(Property, /*out*/ Pin->PinType);
if (OutClassPins)
{
OutClassPins->Add(Pin);
}

if (ClassDefaultObject && K2Schema->PinDefaultValueIsEditable(*Pin))
{
FString DefaultValueAsString;
const bool bDefaultValueSet = FBlueprintEditorUtils::PropertyValueToString(Property, reinterpret_cast<const uint8*>(ClassDefaultObject), DefaultValueAsString, this);
check(bDefaultValueSet);
K2Schema->SetPinAutogeneratedDefaultValue(Pin, DefaultValueAsString);
}

// Copy tooltip from the property.
K2Schema->ConstructBasicPinTooltip(*Pin, Property->GetToolTipText(), Pin->PinToolTip);
}
}
}

// Change class of output pin
UEdGraphPin* ResultPin = FindPinChecked(UEdGraphSchema_K2::PN_ReturnValue);
ResultPin->PinType.PinSubCategoryObject = InClass->GetAuthoritativeClass();
}

void UK2Node_BindQuestTask::ReallocatePinsDuringReconstruction(TArray<UEdGraphPin*>& OldPins)
{
AllocateDefaultPins();
if (UClass* UseSpawnClass = GetClassToSpawn(&OldPins))
{
CreatePinsForClass(UseSpawnClass);
}
RestoreSplitPins(OldPins);
}

void UK2Node_BindQuestTask::PostPlacedNewNode()
{
Super::PostPlacedNewNode();

if (UClass* UseSpawnClass = GetClassToSpawn())
{
CreatePinsForClass(UseSpawnClass);
}
}

bool UK2Node_BindQuestTask::IsSpawnVarPin(UEdGraphPin* Pin) const
{
return(Pin->PinName != UEdGraphSchema_K2::PN_Execute &&
Pin->PinName != UEdGraphSchema_K2::PN_Then &&
Pin->PinName != UEdGraphSchema_K2::PN_ReturnValue &&
Pin->PinName != UEdGraphSchema_K2::PN_Self &&
Pin->PinName != FGetPinName::StartPinName &&
Pin->PinName != FGetPinName::FinishPinName &&
//Pin->PinName != FGetPinName::EndPinName &&
Pin->PinName != FGetPinName::CompletePinName &&
Pin->PinName != FGetPinName::TaskPinName &&
Pin->PinName != FGetPinName::Node);
//Pin->PinName != FGetPinName::DelegatePinName);
}

void UK2Node_BindQuestTask::OnClassPinChanged()
{
UE_LOG(LogTemp, Error, TEXT("OnClassPinChanged call"));
// Remove all pins related to archetype variables
TArray<UEdGraphPin*> OldPins = Pins;
TArray<UEdGraphPin*> OldClassPins;

for (UEdGraphPin* OldPin : OldPins)
{
if (IsSpawnVarPin(OldPin))
{
Pins.Remove(OldPin);
OldClassPins.Add(OldPin);
}
}

//CachedNodeTitle.MarkDirty();

TArray<UEdGraphPin*> NewClassPins;
if (UClass* UseSpawnClass = GetClassToSpawn())
{
CreatePinsForClass(UseSpawnClass, &NewClassPins);
}

RestoreSplitPins(OldPins);

UEdGraphPin* ResultPin = FindPinChecked(UEdGraphSchema_K2::PN_ReturnValue);
// Cache all the pin connections to the ResultPin, we will attempt to recreate them
TArray<UEdGraphPin*> ResultPinConnectionList = ResultPin->LinkedTo;
// Because the archetype has changed, we break the output link as the output pin type will change
ResultPin->BreakAllPinLinks(true);

const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();

// Recreate any pin links to the Result pin that are still valid
for (UEdGraphPin* Connections : ResultPinConnectionList)
{
K2Schema->TryCreateConnection(ResultPin, Connections);
}

// Rewire the old pins to the new pins so connections are maintained if possible
RewireOldPinsToNewPins(OldClassPins, Pins, nullptr);

// Refresh the UI for the graph so the pin changes show up
GetGraph()->NotifyGraphChanged();

// Mark dirty
FBlueprintEditorUtils::MarkBlueprintAsModified(GetBlueprint());
}

void UK2Node_BindQuestTask::PinConnectionListChanged(UEdGraphPin* Pin)
{
Super::PinConnectionListChanged(Pin);

if (Pin && (Pin->PinName == FGetPinName::TaskPinName))
{
OnClassPinChanged();
}
}

void UK2Node_BindQuestTask::PinDefaultValueChanged(UEdGraphPin* ChangedPin)
{
if (ChangedPin && (ChangedPin->PinName == FGetPinName::TaskPinName))
{
OnClassPinChanged();
}
}

UClass* UK2Node_BindQuestTask::GetClassToSpawn(const TArray<UEdGraphPin*>* InPinsToSearch /*=NULL*/) const
{
UClass* UseSpawnClass = nullptr;
const TArray<UEdGraphPin*>* PinsToSearch = InPinsToSearch ? InPinsToSearch : &Pins;

UEdGraphPin* ClassPin = GetClassPin(PinsToSearch);
if (ClassPin && ClassPin->DefaultObject && ClassPin->LinkedTo.Num() == 0)
{
UseSpawnClass = CastChecked<UClass>(ClassPin->DefaultObject);
}
else if (ClassPin && ClassPin->LinkedTo.Num())
{
UEdGraphPin* ClassSource = ClassPin->LinkedTo[0];
UseSpawnClass = ClassSource ? Cast<UClass>(ClassSource->PinType.PinSubCategoryObject.Get()) : nullptr;
}

return UseSpawnClass;
}

UEdGraphPin* UK2Node_BindQuestTask::GetClassPin(const TArray<UEdGraphPin*>* InPinsToSearch /*= NULL*/) const
{
const TArray<UEdGraphPin*>* PinsToSearch = InPinsToSearch ? InPinsToSearch : &Pins;

UEdGraphPin* Pin = nullptr;
for (UEdGraphPin* TestPin : *PinsToSearch)
{
if (TestPin && TestPin->PinName == FGetPinName::TaskPinName)
{
Pin = TestPin;
break;
}
}
check(Pin == nullptr || Pin->Direction == EGPD_Input);
return Pin;
}


UEdGraphPin* UK2Node_BindQuestTask::GetThenPin() const
{
UEdGraphPin* Pin = FindPinChecked(UEdGraphSchema_K2::PN_Then);
check(Pin->Direction == EGPD_Output);
//check(Pin == nullptr || Pin->Direction == EGPD_Output); // If pin exists, it must be input
return Pin;
}
UEdGraphPin * UK2Node_BindQuestTask::GetReturnValuePin() const
{
UEdGraphPin* Pin = FindPin(UEdGraphSchema_K2::PN_ReturnValue);
check(Pin == nullptr || Pin->Direction == EGPD_Output);
return Pin;
}
UEdGraphPin* UK2Node_BindQuestTask::GetSelfPin() const
{
UEdGraphPin* Pin = FindPin(UEdGraphSchema_K2::PN_Self);
check(Pin == nullptr || Pin->Direction == EGPD_Input);
return Pin;
}


void UK2Node_BindQuestTask::PostInitProperties()
{
Super::PostInitProperties();
//Вызываем только в игре, когда есть мир. В редакторе BeginPlay вызван не будет
if (GetOuter()->GetOuter() && GetOuter()->GetOuter()->GetWorld())
{
UE_LOG(LogTemp, Error, TEXT("PostInitProperties2"));
NodeBeginPlay();
}
}

void UK2Node_BindQuestTask::NodeBeginPlay() {
UE_LOG(LogTemp, Error, TEXT("NodeBeginPlay"));
}




UClass* UK2Node_BindQuestTask::GetDynamicBindingClass() const
{
UE_LOG(LogTemp, Error, TEXT("GetDynamicBindingClass()"));
// FWorldDelegates::OnPostWorldCreation
return nullptr;
//return UInputKeyDelegateBinding::StaticClass();
}

void UK2Node_BindQuestTask::RegisterDynamicBinding(UDynamicBlueprintBinding* BindingObject) const
{
UE_LOG(LogTemp, Error, TEXT("RegisterDynamicBinding()()"));
//UInputKeyDelegateBinding* InputKeyBindingObject = CastChecked<UInputKeyDelegateBinding>(BindingObject);

//FBlueprintInputKeyDelegateBinding Binding;
//Binding.InputChord = InputChord;
//Binding.InputKeyEvent = InputKeyEvent;
//Binding.bConsumeInput = bConsumeInput;
//Binding.bExecuteWhenPaused = bExecuteWhenPaused;
//Binding.bOverrideParentBinding = bOverrideParentBinding;
//Binding.FunctionNameToBind = CustomFunctionName;

//InputKeyBindingObject->InputKeyDelegateBindings.Add(Binding);
}

#undef LOCTEXT_NAMESPACE


[/SPOILER]

You can’t but the approach doesn’t make sense anyway - in C++ this would be like writing a function somewhere, but never calling it and expecting it to run at some point anyway.

The code has to be called/executed from somewhere. The BeginPlay node doesn’t just fire itself off for example, it’s called from C++.