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

	const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();

	// Get the enum equality node and the KismetMathLibrary function info for use when we build those nodes
	FName ConditionalFunctionName = "";
	UClass* ConditionalFunctionClass = NULL;
	GetConditionalFunction(ConditionalFunctionName, &ConditionalFunctionClass);

	// Create the conditional node we're replacing the enum node for
	UK2Node_CallFunction* ConditionalNode = SourceGraph->CreateBlankNode<UK2Node_CallFunction>();
	ConditionalNode->FunctionReference.SetExternalMember(ConditionalFunctionName, ConditionalFunctionClass);
	ConditionalNode->AllocateDefaultPins();
	CompilerContext.MessageLog.NotifyIntermediateObjectCreation(ConditionalNode, this);

	// Rewire the enum pins to the new conditional node
	UEdGraphPin* LeftSideConditionalPin = ConditionalNode->FindPinChecked(TEXT("A"));
	UEdGraphPin* RightSideConditionalPin = ConditionalNode->FindPinChecked(TEXT("B"));
	UEdGraphPin* ReturnConditionalPin = ConditionalNode->FindPinChecked(Schema->PN_ReturnValue);
	UEdGraphPin* Input1Pin = GetInput1Pin();
	UEdGraphPin* Input2Pin = GetInput2Pin();
	LeftSideConditionalPin->PinType = Input1Pin->PinType;
	RightSideConditionalPin->PinType = Input2Pin->PinType;
	CompilerContext.MovePinLinksToIntermediate(*Input1Pin, *LeftSideConditionalPin);
	CompilerContext.MovePinLinksToIntermediate(*Input2Pin, *RightSideConditionalPin);
	CompilerContext.MovePinLinksToIntermediate(*GetReturnValuePin(), *ReturnConditionalPin);

	// Break all links to the Select node so it goes away for at scheduling time
	BreakAllNodeLinks();
}
void UK2Node_AddComponent::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);

	auto TransformPin = GetRelativeTransformPin();
	if (TransformPin && !TransformPin->LinkedTo.Num())
	{
		FString DefaultValue;

		// Try and find the template and get relative transform from it
		UEdGraphPin* TemplateNamePin = GetTemplateNamePinChecked();
		const FString TemplateName = TemplateNamePin->DefaultValue;
		check(CompilerContext.Blueprint);
		USceneComponent* SceneCompTemplate = Cast<USceneComponent>(CompilerContext.Blueprint->FindTemplateByName(FName(*TemplateName)));
		if (SceneCompTemplate)
		{
			FTransform TemplateTransform = FTransform(SceneCompTemplate->RelativeRotation, SceneCompTemplate->RelativeLocation, SceneCompTemplate->RelativeScale3D);
			DefaultValue = TemplateTransform.ToString();
		}

		auto ValuePin = InnerHandleAutoCreateRef(this, TransformPin, CompilerContext, SourceGraph, !DefaultValue.IsEmpty());
		if (ValuePin)
		{
			ValuePin->DefaultValue = DefaultValue;
		}
	}

	if (bHasExposedVariable)
	{
		static FString ObjectParamName = FString(TEXT("Object"));
		static FString ValueParamName = FString(TEXT("Value"));
		static FString PropertyNameParamName = FString(TEXT("PropertyName"));

		UK2Node_AddComponent* NewNode = CompilerContext.SpawnIntermediateNode<UK2Node_AddComponent>(this, SourceGraph); 
		NewNode->SetFromFunction(GetTargetFunction());
		NewNode->AllocateDefaultPinsWithoutExposedVariables();

		// function parameters
		const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
		CompilerContext.MovePinLinksToIntermediate(*FindPin(K2Schema->PN_Self), *NewNode->FindPin(K2Schema->PN_Self));
		CompilerContext.MovePinLinksToIntermediate(*GetTemplateNamePinChecked(), *NewNode->GetTemplateNamePinChecked());
		CompilerContext.MovePinLinksToIntermediate(*GetRelativeTransformPin(), *NewNode->GetRelativeTransformPin());
		CompilerContext.MovePinLinksToIntermediate(*GetManualAttachmentPin(), *NewNode->GetManualAttachmentPin());

		UEdGraphPin* ReturnPin = NewNode->GetReturnValuePin();
		UEdGraphPin* OriginalReturnPin = GetReturnValuePin();
		check((NULL != ReturnPin) && (NULL != OriginalReturnPin));
		ReturnPin->PinType = OriginalReturnPin->PinType;
		CompilerContext.MovePinLinksToIntermediate(*OriginalReturnPin, *ReturnPin);
		// exec in
		CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *NewNode->GetExecPin());

		UEdGraphPin* LastThen = FKismetCompilerUtilities::GenerateAssignmentNodes( CompilerContext, SourceGraph, NewNode, this, ReturnPin, GetSpawnedType() );

		CompilerContext.MovePinLinksToIntermediate(*GetThenPin(), *LastThen);
		BreakAllNodeLinks();
	}
}
void UK2Node_EaseFunction::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);

	/**
		At the end of this, the UK2Node_EaseFunction will not be a part of the Blueprint, it merely handles connecting
		the other nodes into the Blueprint.
	*/

	UFunction* Function = UKismetMathLibrary::StaticClass()->FindFunctionByName(*EaseFunctionName);
	if (Function == NULL)
	{
		CompilerContext.MessageLog.Error(*LOCTEXT("InvalidFunctionName", "BaseAsyncTask: Type not supported or not initialized. @@").ToString(), this);
		return;
	}

	const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();

	// The call function does all the real work, each child class implementing easing for  a given type provides
	// the name of the desired function
	UK2Node_CallFunction* CallFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
		
	CallFunction->SetFromFunction(Function);
	CallFunction->AllocateDefaultPins();
	CompilerContext.MessageLog.NotifyIntermediateObjectCreation(CallFunction, this);

	// Move the ease function and the alpha connections from us to the call function
	CompilerContext.MovePinLinksToIntermediate(*FindPin(FEaseFunctionNodeHelper::GetEaseFuncPinName()), *CallFunction->FindPin(TEXT("EasingFunc")));
	CompilerContext.MovePinLinksToIntermediate(*FindPin(FEaseFunctionNodeHelper::GetAlphaPinName()), *CallFunction->FindPin(TEXT("Alpha")));

	// Move base connections to the call function's connections
	CompilerContext.MovePinLinksToIntermediate(*FindPin(FEaseFunctionNodeHelper::GetAPinName()), *CallFunction->FindPin(TEXT("A")));
	CompilerContext.MovePinLinksToIntermediate(*FindPin(FEaseFunctionNodeHelper::GetBPinName()), *CallFunction->FindPin(TEXT("B")));
	CompilerContext.MovePinLinksToIntermediate(*FindPin(FEaseFunctionNodeHelper::GetResultPinName()), *CallFunction->GetReturnValuePin());

	// Now move the custom pins to their new locations
	UEdGraphPin* ShortestPathPin = FindPinChecked(FEaseFunctionNodeHelper::GetShortestPathPinName());
	if (!ShortestPathPin->bHidden)
	{
		CompilerContext.MovePinLinksToIntermediate(*ShortestPathPin, *CallFunction->FindPinChecked(TEXT("bShortestPath")));
	}

	UEdGraphPin* BlendExpPin = FindPinChecked(FEaseFunctionNodeHelper::GetBlendExpPinName());
	if (!BlendExpPin->bHidden)
	{
		CompilerContext.MovePinLinksToIntermediate(*BlendExpPin, *CallFunction->FindPinChecked(FEaseFunctionNodeHelper::GetBlendExpPinName()));
	}

	UEdGraphPin* StepsPin = FindPinChecked(FEaseFunctionNodeHelper::GetStepsPinName());
	if (!StepsPin->bHidden)
	{
		CompilerContext.MovePinLinksToIntermediate(*StepsPin, *CallFunction->FindPinChecked(FEaseFunctionNodeHelper::GetStepsPinName()));
	}

	// Cleanup links to ourself and we are done!
	BreakAllNodeLinks();
}
void UK2Node_CommutativeAssociativeBinaryOperator::ExpandNode(FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);

	if (NumAdditionalInputs > 0)
	{
		const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();

		UEdGraphPin* LastOutPin = NULL;
		const UFunction* const Function = GetTargetFunction();

		const UEdGraphPin* SrcOutPin = FindOutPin();
		const UEdGraphPin* SrcSelfPin = FindSelfPin();
		UEdGraphPin* SrcFirstInput = GetInputPin(0);
		check(SrcFirstInput);

		for(int32 PinIndex = 0; PinIndex < Pins.Num(); PinIndex++)
		{
			UEdGraphPin* CurrentPin = Pins[PinIndex];
			if( (CurrentPin == SrcFirstInput) || (CurrentPin == SrcOutPin) || (SrcSelfPin == CurrentPin) )
			{
				continue;
			}

			UK2Node_CommutativeAssociativeBinaryOperator* NewOperator = SourceGraph->CreateBlankNode<UK2Node_CommutativeAssociativeBinaryOperator>();
			NewOperator->SetFromFunction(Function);
			NewOperator->AllocateDefaultPins();
			CompilerContext.MessageLog.NotifyIntermediateObjectCreation(NewOperator, this);

			UEdGraphPin* NewOperatorInputA = NewOperator->GetInputPin(0);
			check(NewOperatorInputA);
			if(LastOutPin)
			{
				Schema->TryCreateConnection(LastOutPin, NewOperatorInputA);
			}
			else
			{
				// handle first created node (SrcFirstInput is skipped, and has no own node).
				CompilerContext.MovePinLinksToIntermediate(*SrcFirstInput, *NewOperatorInputA);
			}

			UEdGraphPin* NewOperatorInputB = NewOperator->GetInputPin(1);
			check(NewOperatorInputB);
			CompilerContext.MovePinLinksToIntermediate(*CurrentPin, *NewOperatorInputB);

			LastOutPin = NewOperator->FindOutPin();
			check(LastOutPin);
		}

		UEdGraphPin* TrueOutPin = FindOutPin();
		check(TrueOutPin);
		CompilerContext.MovePinLinksToIntermediate(*TrueOutPin, *LastOutPin);

		BreakAllNodeLinks();
	}
}
void UK2Node_GenericCreateObject::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	UK2Node_CallFunction* CallCreateNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
	CallCreateNode->FunctionReference.SetExternalMember(GET_FUNCTION_NAME_CHECKED(UGameplayStatics, SpawnObject), UGameplayStatics::StaticClass());
	CallCreateNode->AllocateDefaultPins();

	bool bSucceeded = true;
	//connect exe
	{
		auto SpawnExecPin = GetExecPin();
		auto CallExecPin = CallCreateNode->GetExecPin();
		bSucceeded &= SpawnExecPin && CallExecPin && CompilerContext.MovePinLinksToIntermediate(*SpawnExecPin, *CallExecPin).CanSafeConnect();
	}

	//connect class
	{
		auto SpawnClassPin = GetClassPin();
		auto CallClassPin = CallCreateNode->FindPin(TEXT("ObjectClass"));
		bSucceeded &= SpawnClassPin && CallClassPin && CompilerContext.MovePinLinksToIntermediate(*SpawnClassPin, *CallClassPin).CanSafeConnect();
	}
		
	//connect outer
	{
		auto SpawnOuterPin = GetOuterPin();
		auto CallOuterPin = CallCreateNode->FindPin(TEXT("Outer"));
		bSucceeded &= SpawnOuterPin && CallOuterPin && CompilerContext.MovePinLinksToIntermediate(*SpawnOuterPin, *CallOuterPin).CanSafeConnect();
	}

	UEdGraphPin* CallResultPin = nullptr;
	//connect result
	{
		auto SpawnResultPin = GetResultPin();
		CallResultPin = CallCreateNode->GetReturnValuePin();

		// cast HACK. It should be safe. The only problem is native code generation.
		if (SpawnResultPin && CallResultPin)
		{
			CallResultPin->PinType = SpawnResultPin->PinType;
		}
		bSucceeded &= SpawnResultPin && CallResultPin && CompilerContext.MovePinLinksToIntermediate(*SpawnResultPin, *CallResultPin).CanSafeConnect();
	}

	//assign exposed values and connect then
	{
		auto LastThen = FKismetCompilerUtilities::GenerateAssignmentNodes(CompilerContext, SourceGraph, CallCreateNode, this, CallResultPin, GetClassToSpawn());
		auto SpawnNodeThen = GetThenPin();
		bSucceeded &= SpawnNodeThen && LastThen && CompilerContext.MovePinLinksToIntermediate(*SpawnNodeThen, *LastThen).CanSafeConnect();
	}

	BreakAllNodeLinks();

	if (!bSucceeded)
	{
		CompilerContext.MessageLog.Error(*LOCTEXT("GenericCreateObject_Error", "ICE: GenericCreateObject error @@").ToString(), this);
	}
}
void UGameplayTagsK2Node_MultiCompareGameplayTagContainerSingleTags::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);

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

	// Get The input and output pins to our node
	UEdGraphPin* InPinSwitch = FindPin(TEXT("Gameplay Tag Container"));
	UEdGraphPin* InPinContainerMatchType = FindPin(TEXT("Tag Container Match Type"));
	UEdGraphPin* InPinTagsMatchType = FindPin(TEXT("Tags Match Type"));

	// For Each Pin Compare against the Tag container
	for (int32 Index = 0; Index < NumberOfPins; ++Index)
	{
		FString InPinName = TEXT("TagCase_") + FString::FormatAsNumber(Index);
		FString OutPinName = TEXT("Case_") + FString::FormatAsNumber(Index) + TEXT(" True");
		UEdGraphPin* InPinCase = FindPin(InPinName);
		UEdGraphPin* OutPinCase = FindPin(OutPinName);

		// Create call function node for the Compare function HasAllMatchingGameplayTags
		UK2Node_CallFunction* PinCallFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
		const UFunction* Function = UBlueprintGameplayTagLibrary::StaticClass()->FindFunctionByName(GET_FUNCTION_NAME_CHECKED(UBlueprintGameplayTagLibrary, DoesContainerHaveTag));
		PinCallFunction->SetFromFunction(Function);
		PinCallFunction->AllocateDefaultPins();

		UEdGraphPin *TagContainerPin = PinCallFunction->FindPinChecked(FString(TEXT("TagContainer")));
		CompilerContext.CopyPinLinksToIntermediate(*InPinSwitch, *TagContainerPin);

		UEdGraphPin *TagPin = PinCallFunction->FindPinChecked(FString(TEXT("Tag")));
		CompilerContext.MovePinLinksToIntermediate(*InPinCase, *TagPin);

		UEdGraphPin *ContainerTagsMatchTypePin = PinCallFunction->FindPinChecked(FString(TEXT("ContainerTagsMatchType")));
		CompilerContext.CopyPinLinksToIntermediate(*InPinContainerMatchType, *ContainerTagsMatchTypePin);

		UEdGraphPin *TagMatchTypePin = PinCallFunction->FindPinChecked(FString(TEXT("TagMatchType")));
		CompilerContext.CopyPinLinksToIntermediate(*InPinTagsMatchType, *TagMatchTypePin);
		
		UEdGraphPin *OutPin = PinCallFunction->FindPinChecked(K2Schema->PN_ReturnValue);

		if (OutPinCase && OutPin)
		{
			OutPin->PinType = OutPinCase->PinType; // Copy type so it uses the right actor subclass
			CompilerContext.MovePinLinksToIntermediate(*OutPinCase, *OutPin);
		}
	}

	// Break any links to the expanded node
	BreakAllNodeLinks();
}
void UK2Node_CastByteToEnum::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);

	if (bSafe && Enum)
	{
		const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();

		// FUNCTION NODE
		const FName FunctionName = GetFunctionName();
		const UFunction* Function = UKismetNodeHelperLibrary::StaticClass()->FindFunctionByName(FunctionName);
		check(NULL != Function);
		UK2Node_CallFunction* CallValidation = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph); 
		CallValidation->SetFromFunction(Function);
		CallValidation->AllocateDefaultPins();
		check(CallValidation->IsNodePure());

		// FUNCTION ENUM PIN
		UEdGraphPin* FunctionEnumPin = CallValidation->FindPinChecked(TEXT("Enum"));
		Schema->TrySetDefaultObject(*FunctionEnumPin, Enum);
		check(FunctionEnumPin->DefaultObject == Enum);

		// FUNCTION INPUT BYTE PIN
		UEdGraphPin* OrgInputPin = FindPinChecked(ByteInputPinName);
		UEdGraphPin* FunctionIndexPin = CallValidation->FindPinChecked(TEXT("EnumeratorIndex"));
		check(EGPD_Input == FunctionIndexPin->Direction && Schema->PC_Byte == FunctionIndexPin->PinType.PinCategory);
		CompilerContext.MovePinLinksToIntermediate(*OrgInputPin, *FunctionIndexPin);

		// UNSAFE CAST NODE
		UK2Node_CastByteToEnum* UsafeCast = CompilerContext.SpawnIntermediateNode<UK2Node_CastByteToEnum>(this, SourceGraph); 
		UsafeCast->Enum = Enum;
		UsafeCast->bSafe = false;
		UsafeCast->AllocateDefaultPins();

		// UNSAFE CAST INPUT
		UEdGraphPin* CastInputPin = UsafeCast->FindPinChecked(ByteInputPinName);
		UEdGraphPin* FunctionReturnPin = CallValidation->GetReturnValuePin();
		check(NULL != FunctionReturnPin);
		Schema->TryCreateConnection(CastInputPin, FunctionReturnPin);

		// OPUTPUT PIN
		UEdGraphPin* OrgReturnPin = FindPinChecked(Schema->PN_ReturnValue);
		UEdGraphPin* NewReturnPin = UsafeCast->FindPinChecked(Schema->PN_ReturnValue);
		CompilerContext.MovePinLinksToIntermediate(*OrgReturnPin, *NewReturnPin);

		BreakAllNodeLinks();
	}
}
void UK2Node_ForEachElementInEnum::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	if (CompilerContext.bIsFullCompile)
	{
		if (!Enum)
		{
			ValidateNodeDuringCompilation(CompilerContext.MessageLog);
			return;
		}

		FForExpandNodeHelper ForLoop;
		if (!ForLoop.BuildLoop(this, CompilerContext, SourceGraph))
		{
			CompilerContext.MessageLog.Error(*NSLOCTEXT("K2Node", "ForEachElementInEnum_ForError", "For Expand error in @@").ToString(), this);
		}

		const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();

		CompilerContext.CheckConnectionResponse(Schema->MovePinLinks(*GetExecPin(), *ForLoop.StartLoopExecInPin), this);
		CompilerContext.CheckConnectionResponse(Schema->MovePinLinks(*FindPinChecked(Schema->PN_Then), *ForLoop.LoopCompleteOutExecPin), this);
		CompilerContext.CheckConnectionResponse(Schema->MovePinLinks(*FindPinChecked(InsideLoopPinName), *ForLoop.InsideLoopExecOutPin), this);

		UK2Node_GetNumEnumEntries* GetNumEnumEntries = CompilerContext.SpawnIntermediateNode<UK2Node_GetNumEnumEntries>(this, SourceGraph);
		GetNumEnumEntries->Enum = Enum;
		GetNumEnumEntries->AllocateDefaultPins();
		bool bResult = Schema->TryCreateConnection(GetNumEnumEntries->FindPinChecked(Schema->PN_ReturnValue), ForLoop.IndexLimitInPin);

		UK2Node_CallFunction* Conv_Func = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph); 
		FName Conv_Func_Name = GET_FUNCTION_NAME_CHECKED(UKismetMathLibrary, Conv_IntToByte);
		Conv_Func->SetFromFunction(UKismetMathLibrary::StaticClass()->FindFunctionByName(Conv_Func_Name));
		Conv_Func->AllocateDefaultPins();
		bResult &= Schema->TryCreateConnection(Conv_Func->FindPinChecked(TEXT("InInt")), ForLoop.IndexOutPin);

		UK2Node_CastByteToEnum* CastByteToEnum = CompilerContext.SpawnIntermediateNode<UK2Node_CastByteToEnum>(this, SourceGraph);
		CastByteToEnum->Enum = Enum;
		CastByteToEnum->bSafe = true;
		CastByteToEnum->AllocateDefaultPins();
		bResult &= Schema->TryCreateConnection(Conv_Func->FindPinChecked(Schema->PN_ReturnValue), CastByteToEnum->FindPinChecked(UK2Node_CastByteToEnum::ByteInputPinName));
		CompilerContext.CheckConnectionResponse(Schema->MovePinLinks(*FindPinChecked(EnumOuputPinName), *CastByteToEnum->FindPinChecked(Schema->PN_ReturnValue)), this);

		if (!bResult)
		{
			CompilerContext.MessageLog.Error(*NSLOCTEXT("K2Node", "ForEachElementInEnum_ExpandError", "Expand error in @@").ToString(), this);
		}

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

	if(NULL == Enum)
	{
		CompilerContext.MessageLog.Error(*FString::Printf(*NSLOCTEXT("K2Node", "GetNumEnumEntries_Error", "@@ must have a valid enum defined").ToString()), this);
		return;
	}

	// Force the enum to load its values if it hasn't already
	if (Enum->HasAnyFlags(RF_NeedLoad))
	{
		Enum->GetLinker()->Preload(Enum);
	}

	const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();
	check(NULL != Schema);

	//MAKE LITERAL
	const FName FunctionName = GET_FUNCTION_NAME_CHECKED(UKismetSystemLibrary, MakeLiteralInt);
	UK2Node_CallFunction* MakeLiteralInt = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph); 
	MakeLiteralInt->SetFromFunction(UKismetSystemLibrary::StaticClass()->FindFunctionByName(FunctionName));
	MakeLiteralInt->AllocateDefaultPins();

	//OPUTPUT PIN
	UEdGraphPin* OrgReturnPin = FindPinChecked(Schema->PN_ReturnValue);
	UEdGraphPin* NewReturnPin = MakeLiteralInt->GetReturnValuePin();
	check(NULL != NewReturnPin);
	CompilerContext.MovePinLinksToIntermediate(*OrgReturnPin, *NewReturnPin);

	//INPUT PIN
	UEdGraphPin* InputPin = MakeLiteralInt->FindPinChecked(TEXT("Value"));
	check(EGPD_Input == InputPin->Direction);
	const FString DefaultValue = FString::FromInt(Enum->NumEnums() - 1);
	InputPin->DefaultValue = DefaultValue;

	BreakAllNodeLinks();
}
Example #10
0
void UK2Node_Message::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);

	const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();

	UEdGraphPin* ExecPin = Schema->FindExecutionPin(*this, EGPD_Input);
	const bool bExecPinConnected = ExecPin && (ExecPin->LinkedTo.Num() > 0);
	UEdGraphPin* ThenPin = Schema->FindExecutionPin(*this, EGPD_Output);
	const bool bThenPinConnected = ThenPin && (ThenPin->LinkedTo.Num() > 0);

	// Skip ourselves if our exec isn't wired up
	if (bExecPinConnected)
	{
		// Make sure our interface is valid
		if (FunctionReference.GetMemberParentClass(this) == NULL)
		{
			CompilerContext.MessageLog.Error(*FString::Printf(*LOCTEXT("MessageNodeInvalid_Error", "Message node @@ has an invalid interface.").ToString()), this);
			return;
		}

		UFunction* MessageNodeFunction = GetTargetFunction();
		if (MessageNodeFunction == NULL)
		{
			//@TODO: Why do this here in teh compiler, it's already done on AllocateDefaultPins() during on-load node reconstruction
			MessageNodeFunction = Cast<UFunction>(UK2Node::FindRemappedField(FunctionReference.GetMemberParentClass(this), FunctionReference.GetMemberName()));
		}

		if (MessageNodeFunction == NULL)
		{
			CompilerContext.MessageLog.Error(*FString::Printf(*LOCTEXT("MessageNodeInvalidFunction_Error", "Unable to find function with name %s for Message node @@.").ToString(), *(FunctionReference.GetMemberName().ToString())), this);
			return;
		}

		// Check to make sure we have a target
		UEdGraphPin* MessageSelfPin = Schema->FindSelfPin(*this, EGPD_Input);
		if( !MessageSelfPin || MessageSelfPin->LinkedTo.Num() == 0 )
		{
			CompilerContext.MessageLog.Error(*FString::Printf(*LOCTEXT("MessageNodeSelfPin_Error", "Message node @@ must have a valid target or reference to self.").ToString()), this);
			return;
		}

		// First, create an internal cast-to-interface node
		UK2Node_DynamicCast* CastToInterfaceNode = CompilerContext.SpawnIntermediateNode<UK2Node_DynamicCast>(this, SourceGraph);
		CastToInterfaceNode->TargetType = MessageNodeFunction->GetOuterUClass();
		CastToInterfaceNode->SetPurity(false);
		CastToInterfaceNode->AllocateDefaultPins();

		UEdGraphPin* CastToInterfaceResultPin = CastToInterfaceNode->GetCastResultPin();
		if( !CastToInterfaceResultPin )
		{
			CompilerContext.MessageLog.Error(*LOCTEXT("InvalidInterfaceClass_Error", "Node @@ has an invalid target interface class").ToString(), this);
			return;
		}

		CastToInterfaceResultPin->PinType.PinSubCategoryObject = *CastToInterfaceNode->TargetType;

		if (ExecPin != nullptr)
		{
			UEdGraphPin* CastExecInput = CastToInterfaceNode->GetExecPin();
			check(CastExecInput != nullptr);

			// Wire up the connections
			CompilerContext.MovePinLinksToIntermediate(*ExecPin, *CastExecInput);
		}

		UEdGraphPin* CastToInterfaceSourceObjectPin = CastToInterfaceNode->GetCastSourcePin();
		CompilerContext.MovePinLinksToIntermediate(*MessageSelfPin, *CastToInterfaceSourceObjectPin);

		// Next, create the function call node
		UK2Node_CallFunction* FunctionCallNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
		FunctionCallNode->bIsInterfaceCall = true;
		FunctionCallNode->FunctionReference = FunctionReference;
		FunctionCallNode->AllocateDefaultPins();

		UEdGraphPin* CastToInterfaceValidPin = CastToInterfaceNode->GetValidCastPin();
		check(CastToInterfaceValidPin != nullptr);

		UEdGraphPin* LastOutCastFaildPin   = CastToInterfaceNode->GetInvalidCastPin();
		check(LastOutCastFaildPin != nullptr);
		UEdGraphPin* LastOutCastSuccessPin = CastToInterfaceValidPin;
		// Wire up the connections
		if (UEdGraphPin* CallFunctionExecPin = Schema->FindExecutionPin(*FunctionCallNode, EGPD_Input))
		{
			CastToInterfaceValidPin->MakeLinkTo(CallFunctionExecPin);
			LastOutCastSuccessPin = Schema->FindExecutionPin(*FunctionCallNode, EGPD_Output);
		}
		
		// Self pin
		UEdGraphPin* FunctionCallSelfPin = Schema->FindSelfPin(*FunctionCallNode, EGPD_Input);
		CastToInterfaceResultPin->MakeLinkTo(FunctionCallSelfPin);

		UFunction* ArrayClearFunction = UKismetArrayLibrary::StaticClass()->FindFunctionByName(FName(TEXT("Array_Clear")));
		check(ArrayClearFunction);

		bool const bIsPureFunc = Super::IsNodePure();
		// Variable pins - Try to associate variable inputs to the message node with the variable inputs and outputs to the call function node
		for( int32 i = 0; i < Pins.Num(); i++ )
		{
			UEdGraphPin* CurrentPin = Pins[i];
			if( CurrentPin && (CurrentPin->PinType.PinCategory != Schema->PC_Exec) && (CurrentPin->PinName != Schema->PN_Self) )
			{
				// Try to find a match for the pin on the function call node
				UEdGraphPin* FunctionCallPin = FunctionCallNode->FindPin(CurrentPin->PinName);
				if( FunctionCallPin )
				{
					// Move pin links if the pin is connected...
					CompilerContext.MovePinLinksToIntermediate(*CurrentPin, *FunctionCallPin);

					// when cast fails all return values must be cleared.
					if (EEdGraphPinDirection::EGPD_Output == CurrentPin->Direction)
					{
						UEdGraphPin* VarOutPin = FunctionCallPin;
						if (bIsPureFunc)
						{
							// since we cannot directly use the output from the
							// function call node (since it is pure, and invoking
							// it with a null target would cause an error), we 
							// have to use a temporary variable in it's place...
							UK2Node_TemporaryVariable* TempVar = CompilerContext.SpawnIntermediateNode<UK2Node_TemporaryVariable>(this, SourceGraph);
							TempVar->VariableType = CurrentPin->PinType;
							TempVar->AllocateDefaultPins();

							VarOutPin = TempVar->GetVariablePin();
							// nodes using the function's outputs directly, now
							// use this TempVar node instead
							CompilerContext.MovePinLinksToIntermediate(*FunctionCallPin, *VarOutPin);

							// on a successful cast, the temp var is filled with
							// the function's value, on a failed cast, the var 
							// is filled with a default value (DefaultValueNode, 
							// below)... this is the node for the success case:
							UK2Node_AssignmentStatement* AssignTempVar = CompilerContext.SpawnIntermediateNode<UK2Node_AssignmentStatement>(this, SourceGraph);
							AssignTempVar->AllocateDefaultPins();
							
							// assign the output from the pure function node to
							// the TempVar (either way, this message node is 
							// returning the TempVar's value, so on a successful 
							// cast we want it to have the function's result)
							UEdGraphPin* ValueInPin = AssignTempVar->GetValuePin();
							Schema->TryCreateConnection(FunctionCallPin, ValueInPin);
							AssignTempVar->PinConnectionListChanged(ValueInPin);

							UEdGraphPin* VarInPin = AssignTempVar->GetVariablePin();
							Schema->TryCreateConnection(VarOutPin, VarInPin);
							AssignTempVar->PinConnectionListChanged(VarInPin);
							// fold this AssignTempVar node into the cast's 
							// success execution chain
							Schema->TryCreateConnection(AssignTempVar->GetExecPin(), LastOutCastSuccessPin);
							LastOutCastSuccessPin = AssignTempVar->GetThenPin();
						}

						UK2Node* DefaultValueNode = NULL;
						UEdGraphPin* DefaultValueThenPin = NULL;
						if (CurrentPin->PinType.bIsArray)
						{
							UK2Node_CallArrayFunction* ClearArray = CompilerContext.SpawnIntermediateNode<UK2Node_CallArrayFunction>(this, SourceGraph);
							DefaultValueNode = ClearArray;
							ClearArray->SetFromFunction(ArrayClearFunction);
							ClearArray->AllocateDefaultPins();

							UEdGraphPin* ArrayPin = ClearArray->GetTargetArrayPin();
							check(ArrayPin);
							Schema->TryCreateConnection(ArrayPin, VarOutPin);
							ClearArray->PinConnectionListChanged(ArrayPin);

							DefaultValueThenPin = ClearArray->GetThenPin();
						} 
						else
						{
							UK2Node_AssignmentStatement* AssignDefaultValue = CompilerContext.SpawnIntermediateNode<UK2Node_AssignmentStatement>(this, SourceGraph);
							DefaultValueNode = AssignDefaultValue;
							AssignDefaultValue->AllocateDefaultPins();

							Schema->TryCreateConnection(AssignDefaultValue->GetVariablePin(), VarOutPin);
							AssignDefaultValue->PinConnectionListChanged(AssignDefaultValue->GetVariablePin());
							Schema->SetPinDefaultValueBasedOnType(AssignDefaultValue->GetValuePin());

							DefaultValueThenPin = AssignDefaultValue->GetThenPin();
						}

						UEdGraphPin* DefaultValueExecPin = DefaultValueNode->GetExecPin();
						check(DefaultValueExecPin);
						Schema->TryCreateConnection(DefaultValueExecPin, LastOutCastFaildPin);
						LastOutCastFaildPin = DefaultValueThenPin;
						check(LastOutCastFaildPin);
					}
				}
				else
				{
					UE_LOG(LogK2Compiler, Log, TEXT("%s"), *LOCTEXT("NoPinConnectionFound_Error", "Unable to find connection for pin!  Check AllocateDefaultPins() for consistency!").ToString());
				}
			}
		}

		if( bThenPinConnected )
		{
			check(LastOutCastFaildPin != nullptr);
			// Failure case for the cast runs straight through to the exit
			CompilerContext.CopyPinLinksToIntermediate(*ThenPin, *LastOutCastFaildPin);

			check(LastOutCastSuccessPin != nullptr);
			// Copy all links from the invalid cast case above to the call function node
			CompilerContext.MovePinLinksToIntermediate(*ThenPin, *LastOutCastSuccessPin);
		}
	}

	// Break all connections to the original node, so it will be pruned
	BreakAllNodeLinks();
}
void UK2Node_VariableGet::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);

	// Do not attempt to expand the node when not a pure get nor when there is no property. Normal compilation error detection will detect the missing property.
	if (!bIsPureGet && GetPropertyForVariable() != nullptr)
	{
		const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();
		UEdGraphPin* ValuePin = GetValuePin();

		// Impure Get nodes convert into three nodes:
		// 1. A pure Get node
		// 2. An IsValid node
		// 3. A Branch node (only impure part
		
		// Create the impure Get node
		UK2Node_VariableGet* VariableGetNode = CompilerContext.SpawnIntermediateNode<UK2Node_VariableGet>(this, SourceGraph);
		VariableGetNode->VariableReference = VariableReference;
		VariableGetNode->AllocateDefaultPins();
		CompilerContext.MessageLog.NotifyIntermediateObjectCreation(VariableGetNode, this);

		// Move pin links from Get node we are expanding, to the new pure one we've created
		CompilerContext.MovePinLinksToIntermediate(*ValuePin, *VariableGetNode->GetValuePin());
		if (!VariableReference.IsLocalScope())
		{
			CompilerContext.MovePinLinksToIntermediate(*FindPin(Schema->PN_Self), *VariableGetNode->FindPin(Schema->PN_Self));
		}

		// Create the IsValid node
		UK2Node_CallFunction* IsValidFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);

		// Based on if the type is an "Object" or a "Class" changes which function to use
		if (ValuePin->PinType.PinCategory == UObject::StaticClass()->GetName())
		{
			IsValidFunction->SetFromFunction(UKismetSystemLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetSystemLibrary, IsValid)));
		}
		else if (ValuePin->PinType.PinCategory == UClass::StaticClass()->GetName())
		{
			IsValidFunction->SetFromFunction(UKismetSystemLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetSystemLibrary, IsValidClass)));
		}
		IsValidFunction->AllocateDefaultPins();
		CompilerContext.MessageLog.NotifyIntermediateObjectCreation(IsValidFunction, this);

		// Connect the value pin from the new Get node to the IsValid
		UEdGraphPin* ObjectPin = IsValidFunction->Pins[1];
		check(ObjectPin->Direction == EGPD_Input);
		ObjectPin->MakeLinkTo(VariableGetNode->GetValuePin());

		// Create the Branch node
		UK2Node_IfThenElse* BranchNode = CompilerContext.SpawnIntermediateNode<UK2Node_IfThenElse>(this, SourceGraph);
		BranchNode->AllocateDefaultPins();
		CompilerContext.MessageLog.NotifyIntermediateObjectCreation(BranchNode, this);

		// Connect the bool output pin from IsValid node to the Branch node
		UEdGraphPin* BoolPin = IsValidFunction->Pins[2];
		check(BoolPin->Direction == EGPD_Output);
		BoolPin->MakeLinkTo(BranchNode->GetConditionPin());

		// Connect the Branch node to the input of the impure Get node
		CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *BranchNode->GetExecPin());

		// Move the two Branch pins to the Branch node
		CompilerContext.MovePinLinksToIntermediate(*FindPin(Schema->PN_Then), *BranchNode->FindPin(Schema->PN_Then));
		CompilerContext.MovePinLinksToIntermediate(*FindPin(Schema->PN_Else), *BranchNode->FindPin(Schema->PN_Else));

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

	const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();

	// Get The input and output pins to our node
	UEdGraphPin* TagInPin = FindPin(TEXT("TagIn"));
	UEdGraphPin* TagOutPin = FindPinChecked(Schema->PN_ReturnValue);

	// Create a Make Struct
	UK2Node_MakeStruct* MakeStructNode = SourceGraph->CreateBlankNode<UK2Node_MakeStruct>();
	MakeStructNode->StructType = FGameplayTagContainer::StaticStruct();
	MakeStructNode->AllocateDefaultPins();

	// Create a Make Array
	UK2Node_MakeArray* MakeArrayNode = SourceGraph->CreateBlankNode<UK2Node_MakeArray>();
	MakeArrayNode->AllocateDefaultPins();
		
	// Connect the output of our MakeArray to the Input of our MakeStruct so it sets the Array Type
	UEdGraphPin* InPin = MakeStructNode->FindPin( TEXT("GameplayTags") );
	if( InPin )
	{
		InPin->MakeLinkTo( MakeArrayNode->GetOutputPin() );
	}

	// Add the FName Values to the MakeArray input pins
	UEdGraphPin* ArrayInputPin = NULL;
	FString TagString = TagInPin->GetDefaultAsString();

	if( TagString.StartsWith( TEXT("(") ) && TagString.EndsWith( TEXT(")") ) )
	{
		TagString = TagString.LeftChop(1);
		TagString = TagString.RightChop(1);
		TagString.Split("=", NULL, &TagString);
		TagString = TagString.LeftChop(1);
		TagString = TagString.RightChop(1);

		FString ReadTag;
		FString Remainder;
		int32 MakeIndex = 0;
		while( TagString.Split( TEXT(","), &ReadTag, &Remainder ) ) 
		{
			TagString = Remainder;

			ArrayInputPin = MakeArrayNode->FindPin( FString::Printf( TEXT("[%d]"), MakeIndex ) );
			ArrayInputPin->PinType.PinCategory = TEXT("struct");
			ArrayInputPin->PinType.PinSubCategoryObject = FGameplayTag::StaticStruct();
			ArrayInputPin->DefaultValue = ReadTag;

			MakeIndex++;
			MakeArrayNode->AddInputPin();
		}
		if( Remainder.IsEmpty() )
		{
			Remainder = TagString;
		}
		if( !Remainder.IsEmpty() )
		{
			ArrayInputPin = MakeArrayNode->FindPin( FString::Printf( TEXT("[%d]"), MakeIndex ) );
			ArrayInputPin->PinType.PinCategory = TEXT("struct");
			ArrayInputPin->PinType.PinSubCategoryObject = FGameplayTag::StaticStruct();
			ArrayInputPin->DefaultValue = Remainder;

			MakeArrayNode->PostReconstructNode();
		}
		else
		{
			MakeArrayNode->RemoveInputPin(MakeArrayNode->FindPin(TEXT("[0]")));
			MakeArrayNode->PostReconstructNode();
		}
	}
	else
	{
		MakeArrayNode->RemoveInputPin(MakeArrayNode->FindPin(TEXT("[0]")));
		MakeArrayNode->PostReconstructNode();
	}

	// Move the Output of the MakeArray to the Output of our node
	UEdGraphPin* OutPin = MakeStructNode->FindPin( MakeStructNode->StructType->GetName() );
	if( OutPin && TagOutPin )
	{
		OutPin->PinType = TagOutPin->PinType; // Copy type so it uses the right actor subclass
		CompilerContext.MovePinLinksToIntermediate(*TagOutPin, *OutPin);
	}

	// Break any links to the expanded node
	BreakAllNodeLinks();
}
void UK2Node_SpawnActor::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);

	if (CompilerContext.bIsFullCompile)
	{
		static FName BeginSpawningBlueprintFuncName = GET_FUNCTION_NAME_CHECKED(UGameplayStatics, BeginSpawningActorFromBlueprint);
		static FString BlueprintParamName = FString(TEXT("Blueprint"));
		static FString WorldContextParamName = FString(TEXT("WorldContextObject"));

		static FName FinishSpawningFuncName = GET_FUNCTION_NAME_CHECKED(UGameplayStatics, FinishSpawningActor);
		static FString ActorParamName = FString(TEXT("Actor"));
		static FString TransformParamName = FString(TEXT("SpawnTransform"));
		static FString NoCollisionFailParamName = FString(TEXT("bNoCollisionFail"));

		static FString ObjectParamName = FString(TEXT("Object"));
		static FString ValueParamName = FString(TEXT("Value"));
		static FString PropertyNameParamName = FString(TEXT("PropertyName"));

		const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();

		UEdGraphPin* SpawnNodeExec = GetExecPin();
		UEdGraphPin* SpawnNodeTransform = GetSpawnTransformPin();
		UEdGraphPin* SpawnNodeNoCollisionFail = GetNoCollisionFailPin();
		UEdGraphPin* SpawnWorldContextPin = GetWorldContextPin();
		UEdGraphPin* SpawnBlueprintPin = GetBlueprintPin();
		UEdGraphPin* SpawnNodeThen = GetThenPin();
		UEdGraphPin* SpawnNodeResult = GetResultPin();

		UBlueprint* SpawnBlueprint = NULL;
		if(SpawnBlueprintPin != NULL)
		{
			SpawnBlueprint = Cast<UBlueprint>(SpawnBlueprintPin->DefaultObject);
		}

		if(0 == SpawnBlueprintPin->LinkedTo.Num())	
		{
			if(NULL == SpawnBlueprint)
			{
				CompilerContext.MessageLog.Error(*LOCTEXT("SpawnActorNodeMissingBlueprint_Error", "Spawn node @@ must have a blueprint specified.").ToString(), this);
				// we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings
				BreakAllNodeLinks();
				return;
			}

			// check if default blueprint is based on Actor
			const UClass* GeneratedClass = SpawnBlueprint->GeneratedClass;
			bool bInvalidBase = GeneratedClass && !GeneratedClass->IsChildOf(AActor::StaticClass());

			const UClass* SkeletonGeneratedClass = Cast<UClass>(SpawnBlueprint->SkeletonGeneratedClass);
			bInvalidBase |= SkeletonGeneratedClass && !SkeletonGeneratedClass->IsChildOf(AActor::StaticClass());

			if(bInvalidBase)
			{
				CompilerContext.MessageLog.Error(*LOCTEXT("SpawnActorNodeInvalidBlueprint_Error", "Spawn node @@ must have a blueprint based on Actor specified.").ToString(), this);
				// we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings
				BreakAllNodeLinks();
				return;
			}
		}

		//////////////////////////////////////////////////////////////////////////
		// create 'begin spawn' call node
		UK2Node_CallFunction* CallBeginSpawnNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
		CallBeginSpawnNode->FunctionReference.SetExternalMember(BeginSpawningBlueprintFuncName, UGameplayStatics::StaticClass());
		CallBeginSpawnNode->AllocateDefaultPins();

		UEdGraphPin* CallBeginExec = CallBeginSpawnNode->GetExecPin();
		UEdGraphPin* CallBeginWorldContextPin = CallBeginSpawnNode->FindPinChecked(WorldContextParamName);
		UEdGraphPin* CallBeginBlueprintPin = CallBeginSpawnNode->FindPinChecked(BlueprintParamName);
		UEdGraphPin* CallBeginTransform = CallBeginSpawnNode->FindPinChecked(TransformParamName);
		UEdGraphPin* CallBeginNoCollisionFail = CallBeginSpawnNode->FindPinChecked(NoCollisionFailParamName);
		UEdGraphPin* CallBeginResult = CallBeginSpawnNode->GetReturnValuePin();

		// Move 'exec' connection from spawn node to 'begin spawn'
		CompilerContext.MovePinLinksToIntermediate(*SpawnNodeExec, *CallBeginExec);

		if(SpawnBlueprintPin->LinkedTo.Num() > 0)
		{
			// Copy the 'blueprint' connection from the spawn node to 'begin spawn'
			CompilerContext.MovePinLinksToIntermediate(*SpawnBlueprintPin, *CallBeginBlueprintPin);
		}
		else
		{
			// Copy blueprint literal onto begin spawn call 
			CallBeginBlueprintPin->DefaultObject = SpawnBlueprint;
		}

		// Copy the world context connection from the spawn node to 'begin spawn' if necessary
		if (SpawnWorldContextPin)
		{
			CompilerContext.MovePinLinksToIntermediate(*SpawnWorldContextPin, *CallBeginWorldContextPin);
		}

		// Copy the 'transform' connection from the spawn node to 'begin spawn'
		CompilerContext.MovePinLinksToIntermediate(*SpawnNodeTransform, *CallBeginTransform);
		
		// Copy the 'bNoCollisionFail' connection from the spawn node to 'begin spawn'
		CompilerContext.MovePinLinksToIntermediate(*SpawnNodeNoCollisionFail, *CallBeginNoCollisionFail);

		//////////////////////////////////////////////////////////////////////////
		// create 'finish spawn' call node
		UK2Node_CallFunction* CallFinishSpawnNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
		CallFinishSpawnNode->FunctionReference.SetExternalMember(FinishSpawningFuncName, UGameplayStatics::StaticClass());
		CallFinishSpawnNode->AllocateDefaultPins();

		UEdGraphPin* CallFinishExec = CallFinishSpawnNode->GetExecPin();
		UEdGraphPin* CallFinishThen = CallFinishSpawnNode->GetThenPin();
		UEdGraphPin* CallFinishActor = CallFinishSpawnNode->FindPinChecked(ActorParamName);
		UEdGraphPin* CallFinishTransform = CallFinishSpawnNode->FindPinChecked(TransformParamName);
		UEdGraphPin* CallFinishResult = CallFinishSpawnNode->GetReturnValuePin();

		// Move 'then' connection from spawn node to 'finish spawn'
		CompilerContext.MovePinLinksToIntermediate(*SpawnNodeThen, *CallFinishThen);
			
		// Copy transform connection
		CompilerContext.CopyPinLinksToIntermediate(*CallBeginTransform, *CallFinishTransform);
		
		// Connect output actor from 'begin' to 'finish'
		CallBeginResult->MakeLinkTo(CallFinishActor);

		// Move result connection from spawn node to 'finish spawn'
		CallFinishResult->PinType = SpawnNodeResult->PinType; // Copy type so it uses the right actor subclass
		CompilerContext.MovePinLinksToIntermediate(*SpawnNodeResult, *CallFinishResult);

		//////////////////////////////////////////////////////////////////////////
		// create 'set var' nodes

		// Get 'result' pin from 'begin spawn', this is the actual actor we want to set properties on
		UK2Node_CallFunction* LastNode = CallBeginSpawnNode;

		// Create 'set var by name' nodes and hook them up
		for(int32 PinIdx=0; PinIdx < Pins.Num(); PinIdx++)
		{
			// Only create 'set param by name' node if this pin is linked to something
			UEdGraphPin* SpawnVarPin = Pins[PinIdx];
			if(SpawnVarPin->LinkedTo.Num() > 0)
			{
				UFunction* SetByNameFunction = Schema->FindSetVariableByNameFunction(SpawnVarPin->PinType);
				if(SetByNameFunction)
				{
					UK2Node_CallFunction* SetVarNode = NULL;
					if(SpawnVarPin->PinType.bIsArray)
					{
						SetVarNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallArrayFunction>(this, SourceGraph);
					}
					else
					{
						SetVarNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
					}
					SetVarNode->SetFromFunction(SetByNameFunction);
					SetVarNode->AllocateDefaultPins();

					// Connect this node into the exec chain
					UEdGraphPin* LastThen = LastNode->GetThenPin();
					UEdGraphPin* SetVarExec = SetVarNode->GetExecPin();
					LastThen->MakeLinkTo(SetVarExec);

					// Connect the new actor to the 'object' pin
					UEdGraphPin* ObjectPin = SetVarNode->FindPinChecked(ObjectParamName);
					CallBeginResult->MakeLinkTo(ObjectPin);

					// Fill in literal for 'property name' pin - name of pin is property name
					UEdGraphPin* PropertyNamePin = SetVarNode->FindPinChecked(PropertyNameParamName);
					PropertyNamePin->DefaultValue = SpawnVarPin->PinName;

					// Move connection from the variable pin on the spawn node to the 'value' pin
					UEdGraphPin* ValuePin = SetVarNode->FindPinChecked(ValueParamName);
					CompilerContext.MovePinLinksToIntermediate(*SpawnVarPin, *ValuePin);
					if(SpawnVarPin->PinType.bIsArray)
					{
						SetVarNode->PinConnectionListChanged(ValuePin);
					}

					// Update 'last node in sequence' var
					LastNode = SetVarNode;
				}
			}
		}

		// Make exec connection between 'then' on last node and 'finish'
		UEdGraphPin* LastThen = LastNode->GetThenPin();
		LastThen->MakeLinkTo(CallFinishExec);

		// Break any links to the expanded node
		BreakAllNodeLinks();
	}
}
void UK2Node_LiveEditObject::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);

	const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();

	UEdGraphPin *SourceExecPin = GetExecPin();
	UEdGraphPin *SourceThenPin = GetThenPin();
	UEdGraphPin *SourceBlueprintPin = GetBlueprintPin();
	UEdGraphPin *SourceBaseClassPin = GetBaseClassPin();
	UEdGraphPin *SourceDescriptionPin = GetDescriptionPin();
	UEdGraphPin *SourcePermittedBindingsPin = GetPermittedBindingsPin();
	UEdGraphPin *SourceOnMidiInputPin = GetOnMidiInputPin();

	UEdGraphPin *SourceVariablePin = GetVariablePin();
	if(NULL == SourceVariablePin)
	{
		CompilerContext.MessageLog.Error(*LOCTEXT("LiveEditObjectNodeMissingBlueprint_Error", "LiveEdit node @@ must have a blueprint specified and a variable selected to tune.").ToString(), this);
		// we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings
		BreakAllNodeLinks();
		return;
	}

	UClass* SpawnClass = GetClassToSpawn();
	if(NULL == SpawnClass)
	{
		CompilerContext.MessageLog.Error(*LOCTEXT("LiveEditObjectNodeMissingBaseClass_Error", "LiveEdit node @@ must have a Base Class specified.").ToString(), this);
		// we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings
		BreakAllNodeLinks();
		return;
	}

	if ( SourcePermittedBindingsPin->LinkedTo.Num() == 0 )
	{
		CompilerContext.MessageLog.Error(*LOCTEXT("LiveEditObjectNodeMissingBinding_Error", "LiveEdit node @@ must specify Permitted Bindings.").ToString(), this);
		// we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings
		BreakAllNodeLinks();
		return;
	}

	//sanity check the VariablePin value
	{
		UProperty *Property = UK2Node_LiveEditObjectStatics::GetPropertyByName( SpawnClass, *SourceVariablePin->DefaultValue );
		if ( Property == NULL || !Property->IsA(UNumericProperty::StaticClass()) )
		{
			CompilerContext.MessageLog.Error(*LOCTEXT("LiveEditObjectNodeInvalidVariable_Error", "LiveEdit node @@ must have a valid variable selected.").ToString(), this);
			// we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings
			BreakAllNodeLinks();
			return;
		}
	}

	//hooks to pins that are generated after a BaseClass is set
	UEdGraphPin *DeltaMultPin = GetDeltaMultPin();
	UEdGraphPin *ShouldClampPin = GetShouldClampPin();
	UEdGraphPin *ClampMinPin = GetClampMinPin();
	UEdGraphPin *ClampMaxPin = GetClampMaxPin();

	UK2Node_Self *SelfNode  = CompilerContext.SpawnIntermediateNode<UK2Node_Self>(this,SourceGraph);
	SelfNode->AllocateDefaultPins();
	UEdGraphPin *SelfNodeThenPin = SelfNode->FindPinChecked(Schema->PN_Self);

	FString EventNameGuid = GetEventName();
		
	//Create the registration part of the LiveEditor binding process
	{
		UK2Node_CallFunction *RegisterForMIDINode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph);
		RegisterForMIDINode->FunctionReference.SetExternalMember( TEXT("RegisterForLiveEditEvent"), ULiveEditorKismetLibrary::StaticClass() );
		RegisterForMIDINode->AllocateDefaultPins();

		UEdGraphPin *ExecPin = RegisterForMIDINode->GetExecPin();
		CompilerContext.MovePinLinksToIntermediate(*SourceExecPin, *ExecPin);

		UEdGraphPin *ThenPin = RegisterForMIDINode->GetThenPin();
		CompilerContext.MovePinLinksToIntermediate(*SourceThenPin, *ThenPin);

		UEdGraphPin *TargetPin = RegisterForMIDINode->FindPinChecked( FString(TEXT("Target")) );
		TargetPin->MakeLinkTo(SelfNodeThenPin);

		UEdGraphPin *EventNamePin = RegisterForMIDINode->FindPinChecked( FString(TEXT("EventName")) );
		EventNamePin->DefaultValue = EventNameGuid;
		
		UEdGraphPin *DescriptionPin = RegisterForMIDINode->FindPinChecked( FString(TEXT("Description")) );
		CompilerContext.CopyPinLinksToIntermediate( *SourceDescriptionPin, *DescriptionPin);

		UEdGraphPin *PermittedBindingsPin = RegisterForMIDINode->FindPinChecked( FString(TEXT("PermittedBindings")) );
		CompilerContext.CopyPinLinksToIntermediate( *SourcePermittedBindingsPin, *PermittedBindingsPin);
	}

	//Create the event handling part of the LiveEditor binding process
	{
		//
		//the event itself
		//
		UFunction *EventMIDISignature = GetEventMIDISignature();
		UK2Node_Event* EventNode = CompilerContext.SpawnIntermediateNode<UK2Node_Event>(this, SourceGraph);
		check(EventNode);
		EventNode->EventSignatureClass = Cast<UClass>(EventMIDISignature->GetOuter());
		EventNode->EventSignatureName = EventMIDISignature->GetFName();
		EventNode->CustomFunctionName = *EventNameGuid;
		EventNode->bInternalEvent = true;
		EventNode->AllocateDefaultPins();

		// Cache these out because we'll connect the sequence to it
		UEdGraphPin *EventThenPin = EventNode->FindPinChecked( Schema->PN_Then );
		UEdGraphPin *EventDeltaPin = EventNode->FindPinChecked( FString(TEXT("Delta")) );
		UEdGraphPin *EventMidiValuePin = EventNode->FindPinChecked( FString(TEXT("MidiValue")) );
		UEdGraphPin *EventControlTypePin = EventNode->FindPinChecked( FString(TEXT("ControlType")) );


		//
		// Check if Blueprint is NULL
		//
		UEdGraphPin *CompareBlueprintToNullBranchThenPin = NULL;
		{
			UK2Node_CallFunction *CompareBlueprintToNullNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph);
			CompareBlueprintToNullNode->FunctionReference.SetExternalMember( TEXT("NotEqual_ObjectObject"), UKismetMathLibrary::StaticClass() );
			CompareBlueprintToNullNode->AllocateDefaultPins();

			//Set A Pin to the Blueprint Pin
			UEdGraphPin *CompareBlueprintToNullAPin = CompareBlueprintToNullNode->FindPinChecked( FString(TEXT("A")) );
			CompilerContext.CopyPinLinksToIntermediate( *SourceBlueprintPin, *CompareBlueprintToNullAPin);

			// hook for Compare Blueprint to NULL result
			UEdGraphPin *CompareBlueprintToNullResultPin = CompareBlueprintToNullNode->GetReturnValuePin();

			// Create the BRANCH that will drive the comparison
			UK2Node_IfThenElse* CompareBlueprintToNullBranchNode = CompilerContext.SpawnIntermediateNode<UK2Node_IfThenElse>(this, SourceGraph);
			CompareBlueprintToNullBranchNode->AllocateDefaultPins();

			//hook up the condition
			CompareBlueprintToNullResultPin->MakeLinkTo( CompareBlueprintToNullBranchNode->GetConditionPin() );

			//hook event to the branck input
			EventThenPin->MakeLinkTo( CompareBlueprintToNullBranchNode->GetExecPin() );

			//cache ot the THEN pin for later linkup
			CompareBlueprintToNullBranchThenPin = CompareBlueprintToNullBranchNode->GetThenPin();
		}

		//
		// Get Class Default Object
		//
		UK2Node_CallFunction *GetClassDefaultObjectNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph);
		GetClassDefaultObjectNode->FunctionReference.SetExternalMember( TEXT("GetBlueprintClassDefaultObject"), ULiveEditorKismetLibrary::StaticClass() );
		GetClassDefaultObjectNode->AllocateDefaultPins();

		UEdGraphPin *GetClassDefaultObjectBlueprintPin = GetClassDefaultObjectNode->FindPinChecked( TEXT("Blueprint") );
		CompilerContext.CopyPinLinksToIntermediate( *SourceBlueprintPin, *GetClassDefaultObjectBlueprintPin);

		//hook for later -> the pointer to the ClassDefaultObject of our BlueprintPin
		UEdGraphPin *GetClassDefaultObjectResultPin = GetClassDefaultObjectNode->GetReturnValuePin();


		//
		// Compare to BaseClass to make sure that the target Blueprint IsA(BaseClass)
		//
		UEdGraphPin *ClassIsChildOfBranchThenPin = NULL;
		{
			//
			//we need to get the class of the Blueprint pin
			UK2Node_CallFunction *GetClassNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph);
			GetClassNode->FunctionReference.SetExternalMember( TEXT("GetObjectClass"), UGameplayStatics::StaticClass() );
			GetClassNode->AllocateDefaultPins();

			//Pin in the GetClassDefaultObjectResultPin to the Object Parameter of the GetObjectClass FUNCTION
			//we want to make sure that the Class of the DEFAULT_OBJECT IsA( BaseClass )
			UEdGraphPin *GetClassObjectPin = GetClassNode->FindPinChecked( FString(TEXT("Object")) );
			GetClassDefaultObjectResultPin->MakeLinkTo( GetClassObjectPin );

			//hook for the Class result
			UEdGraphPin *GetClassReturnValuePin = GetClassNode->GetReturnValuePin();

			//
			//the ClassIsChildOf FUNCTION
			UK2Node_CallFunction *ClassIsChildOfNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph);
			ClassIsChildOfNode->FunctionReference.SetExternalMember( TEXT("ClassIsChildOf"), UKismetMathLibrary::StaticClass() );
			ClassIsChildOfNode->AllocateDefaultPins();

			//hook up the test pin
			UEdGraphPin *ClassIsChildOfTestPin = ClassIsChildOfNode->FindPinChecked( FString(TEXT("TestClass")) );
			GetClassReturnValuePin->MakeLinkTo( ClassIsChildOfTestPin );

			//copy our BaseClass Pin into the ClassIsChildOf Parameter
			UEdGraphPin *ClassIsChildOfParentPin = ClassIsChildOfNode->FindPinChecked( FString(TEXT("ParentClass")) );
			CompilerContext.CopyPinLinksToIntermediate( *SourceBaseClassPin, *ClassIsChildOfParentPin);

			//hook for return value
			UEdGraphPin *ClassIsChildOfResultPin = ClassIsChildOfNode->GetReturnValuePin();

			//
			// Create the BRANCH that will drive the comparison
			UK2Node_IfThenElse* ClassIsChildOfBranchNode = CompilerContext.SpawnIntermediateNode<UK2Node_IfThenElse>(this, SourceGraph);
			ClassIsChildOfBranchNode->AllocateDefaultPins();

			//hook up the previous branch to this one
			check( CompareBlueprintToNullBranchThenPin != NULL );
			CompareBlueprintToNullBranchThenPin->MakeLinkTo( ClassIsChildOfBranchNode->GetExecPin() );

			//hook up our condition
			ClassIsChildOfResultPin->MakeLinkTo( ClassIsChildOfBranchNode->GetConditionPin() );

			//cache ot the THEN pin for later linkup
			ClassIsChildOfBranchThenPin = ClassIsChildOfBranchNode->GetThenPin();
		}


		//
		//The set variable function (to set LiveEdited new value)
		//
		UK2Node_CallFunction *ModifyVarNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph);
		ModifyVarNode->FunctionReference.SetExternalMember( TEXT("ModifyPropertyByName"), ULiveEditorKismetLibrary::StaticClass() );
		ModifyVarNode->AllocateDefaultPins();

		// Make link from the event to the Set variable node
		UEdGraphPin *ModifyVarExecPin = ModifyVarNode->GetExecPin();
		ClassIsChildOfBranchThenPin->MakeLinkTo( ModifyVarExecPin );

		//link up the Target Pin
		UEdGraphPin *ModifyVarNodeTargetPin = ModifyVarNode->FindPinChecked( TEXT("Target") );
		GetClassDefaultObjectResultPin->MakeLinkTo( ModifyVarNodeTargetPin );

		//link up the PropertyName Pin
		UEdGraphPin *ModifyVarNodePropertyNamePin = ModifyVarNode->FindPinChecked( TEXT("PropertyName") );
		ModifyVarNodePropertyNamePin->DefaultValue = SourceVariablePin->DefaultValue;

		//link up the MIDI Value Pin
		UEdGraphPin *ModifyVarNodeMidiValuePin = ModifyVarNode->FindPinChecked( TEXT("MidiValue") );
		EventMidiValuePin->MakeLinkTo(ModifyVarNodeMidiValuePin);

		//link up the ControlType Pin
		UEdGraphPin *ModifyVarNodeControlTypePin = ModifyVarNode->FindPinChecked( TEXT("ControlType") );
		EventControlTypePin->MakeLinkTo(ModifyVarNodeControlTypePin);

		//hook for the Delta Pin
		UEdGraphPin *ModifyVarNodeDeltaPin = ModifyVarNode->FindPinChecked( TEXT("Delta") );

		//Clamping
		if ( ShouldClampPin->DefaultValue == FString(TEXT("true")) )
		{
			UEdGraphPin *ModifyVarNodeShouldClampPin = ModifyVarNode->FindPinChecked( TEXT("bShouldClamp") );
			CompilerContext.CopyPinLinksToIntermediate( *ShouldClampPin, *ModifyVarNodeShouldClampPin);

			check( ClampMinPin != NULL );
			UEdGraphPin *ModifyVarNodeClampMinPin = ModifyVarNode->FindPinChecked( TEXT("ClampMin") );
			CompilerContext.CopyPinLinksToIntermediate( *ClampMinPin, *ModifyVarNodeClampMinPin);

			check( ClampMaxPin != NULL );
			UEdGraphPin *ModifyVarNodeClampMaxPin = ModifyVarNode->FindPinChecked( TEXT("ClampMax") );
			CompilerContext.CopyPinLinksToIntermediate( *ClampMaxPin, *ModifyVarNodeClampMaxPin);
		}

		//hook for ModifyVar THEN
		UEdGraphPin *ModifyVarNodeThenPin = ModifyVarNode->GetThenPin();

		//
		// The Multiply Delta * DeltaMult function
		//
		UK2Node_CallFunction *MultiplyNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph);
		MultiplyNode->FunctionReference.SetExternalMember( TEXT("Multiply_FloatFloat"), UKismetMathLibrary::StaticClass() );
		MultiplyNode->AllocateDefaultPins();

		//cache this out. it will be linked to from the output of the (int)Delta -> (float)Delta Conversion function
		UEdGraphPin *MultiplyNodeFirstPin = MultiplyNode->FindPinChecked( FString(TEXT("A")) );

		// 2nd input to the Add function comes from the Current variable value
		UEdGraphPin *MultiplyNodeSecondPin = MultiplyNode->FindPinChecked( FString(TEXT("B")) );
		CompilerContext.CopyPinLinksToIntermediate( *DeltaMultPin, *MultiplyNodeSecondPin);

		UEdGraphPin *MultiplyNodeReturnValuePin = MultiplyNode->GetReturnValuePin();
		MultiplyNodeReturnValuePin->MakeLinkTo( ModifyVarNodeDeltaPin );

		//
		// The Convert function to go from (int)Delta to ULiveEditorKismetLibrary::ModifyPropertyByName(... float Delta ...)
		//
		FName ConvertFunctionName;
		bool success = Schema->SearchForAutocastFunction( EventDeltaPin, MultiplyNodeFirstPin, ConvertFunctionName );
		check( success );
		UK2Node_CallFunction *ConvertDeltaNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph);
		ConvertDeltaNode->FunctionReference.SetExternalMember( ConvertFunctionName, UKismetMathLibrary::StaticClass() );
		ConvertDeltaNode->AllocateDefaultPins();

		FName PinName;
		success = UK2Node_LiveEditObjectStatics::SearchForConvertPinName( Schema, EventDeltaPin, PinName );
		check( success );
		UEdGraphPin *ConvertDeltaInputPin = ConvertDeltaNode->FindPinChecked( PinName.ToString() );
		EventDeltaPin->MakeLinkTo( ConvertDeltaInputPin );

		UEdGraphPin *ConvertDeltaOutputPin = ConvertDeltaNode->GetReturnValuePin();
		ConvertDeltaOutputPin->MakeLinkTo( MultiplyNodeFirstPin );

		//
		// TODO - markDirty
		//

		//
		// send out the object value updates
		//
		UK2Node_CallFunction *ReplicationNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph);
		ReplicationNode->FunctionReference.SetExternalMember( TEXT("ReplicateChangesToChildren"), ULiveEditorKismetLibrary::StaticClass() );
		ReplicationNode->AllocateDefaultPins();

		UEdGraphPin *ReplicationNodeVarNamePin = ReplicationNode->FindPinChecked( TEXT("PropertyName") );
		ReplicationNodeVarNamePin->DefaultValue = SourceVariablePin->DefaultValue;

		UEdGraphPin *ReplicationNodeArchetypePin = ReplicationNode->FindPinChecked( FString(TEXT("Archetype")) );
		GetClassDefaultObjectResultPin->MakeLinkTo( ReplicationNodeArchetypePin );

		UEdGraphPin *ReplicationNodeExecPin = ReplicationNode->GetExecPin();
		ModifyVarNodeThenPin->MakeLinkTo( ReplicationNodeExecPin );

		UEdGraphPin *ReplicationNodeThenPin = ReplicationNode->FindPinChecked( FString(TEXT("then")) );

		//
		// Finally, activate our OnMidiInput pin
		//
		CompilerContext.CopyPinLinksToIntermediate( *SourceOnMidiInputPin, *ReplicationNodeThenPin);
			
	}

	// Break any links to the expanded node
	BreakAllNodeLinks();
}
void UK2Node_ConvertAsset::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);
	const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();
	
	UClass* TargetType = GetTargetClass();
	if (TargetType && Schema && (2 == Pins.Num()))
	{
		const bool bIsAssetClass = IsAssetClassType();

		//Create Convert Function
		auto ConvertToObjectFunc = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
		const FName ConvertFunctionName = bIsAssetClass 
			? GET_FUNCTION_NAME_CHECKED(UKismetSystemLibrary, Conv_AssetClassToClass) 
			: GET_FUNCTION_NAME_CHECKED(UKismetSystemLibrary, Conv_AssetToObject);
		ConvertToObjectFunc->FunctionReference.SetExternalMember(ConvertFunctionName, UKismetSystemLibrary::StaticClass());
		ConvertToObjectFunc->AllocateDefaultPins();

		//Connect input to convert
		auto InputPin = FindPin(UK2Node_ConvertAssetImpl::InputPinName);
		const FString ConvertInputName = bIsAssetClass
			? FString(TEXT("AssetClass"))
			: FString(TEXT("Asset"));
		auto ConvertInput = ConvertToObjectFunc->FindPin(ConvertInputName);
		bool bIsErrorFree = InputPin && ConvertInput && CompilerContext.MovePinLinksToIntermediate(*InputPin, *ConvertInput).CanSafeConnect();

		auto ConvertOutput = ConvertToObjectFunc->GetReturnValuePin();
		UEdGraphPin* InnerOutput = nullptr;
		if (UObject::StaticClass() != TargetType)
		{
			//Create Cast Node
			UK2Node_DynamicCast* CastNode = bIsAssetClass
				? CompilerContext.SpawnIntermediateNode<UK2Node_ClassDynamicCast>(this, SourceGraph)
				: CompilerContext.SpawnIntermediateNode<UK2Node_DynamicCast>(this, SourceGraph);
			CastNode->SetPurity(true);
			CastNode->TargetType = TargetType;
			CastNode->AllocateDefaultPins();

			// Connect Object/Class to Cast
			auto CastInput = CastNode->GetCastSourcePin();
			bIsErrorFree &= ConvertOutput && CastInput && Schema->TryCreateConnection(ConvertOutput, CastInput);

			// Connect output to cast
			InnerOutput = CastNode->GetCastResultPin();
		}
		else
		{
			InnerOutput = ConvertOutput;
		}

		auto OutputPin = FindPin(UK2Node_ConvertAssetImpl::OutputPinName);
		bIsErrorFree &= OutputPin && InnerOutput && CompilerContext.MovePinLinksToIntermediate(*OutputPin, *InnerOutput).CanSafeConnect();

		if (!bIsErrorFree)
		{
			CompilerContext.MessageLog.Error(*LOCTEXT("InternalConnectionError", "K2Node_ConvertAsset: Internal connection error. @@").ToString(), this);
		}

		BreakAllNodeLinks();
	}
}
void UK2Node_CallFunctionOnMember::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	// This skips UK2Node_CallFunction::ExpandNode.  Instead it spawns a new CallFunction node and does hookup that this is interested in,
	// and then that CallFunction node will get its own Expansion to handle the parent portions
	UK2Node::ExpandNode(CompilerContext, SourceGraph);

	if (CompilerContext.bIsFullCompile)
	{
		const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();
		UFunction* Function = GetTargetFunction();

		// Create real 'call function' node.
		UK2Node_CallFunction* CallFuncNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
		CallFuncNode->SetFromFunction(Function);
		CallFuncNode->AllocateDefaultPins();
		UEdGraphPin* CallFuncSelfPin = Schema->FindSelfPin(*CallFuncNode, EGPD_Input);

		// Now because you can wire multiple variables to a self pin, need to iterate over each one and create a 'get var' node for each
		UEdGraphPin* SelfPin = Schema->FindSelfPin(*this, EGPD_Input);
		if(SelfPin != NULL)
		{
			if (SelfPin->LinkedTo.Num() == 0)
			{
				UK2Node_VariableGet* GetVarNode = CompilerContext.SpawnIntermediateNode<UK2Node_VariableGet>(this, SourceGraph);
				GetVarNode->VariableReference.SetSelfMember(MemberVariableToCallOn.GetMemberName());
				GetVarNode->AllocateDefaultPins();

				if (UEdGraphPin* ValuePin = GetVarNode->GetValuePin())
				{
					ValuePin->MakeLinkTo(CallFuncSelfPin);
				}
			}
			else
			{
				for (int32 TargetIdx = 0; TargetIdx < SelfPin->LinkedTo.Num(); TargetIdx++)
				{
					UEdGraphPin* SourcePin = SelfPin->LinkedTo[TargetIdx];
					if (SourcePin != NULL)
					{
						// Create 'get var' node to get the member
						UK2Node_VariableGet* GetVarNode = CompilerContext.SpawnIntermediateNode<UK2Node_VariableGet>(this, SourceGraph);
						GetVarNode->VariableReference = MemberVariableToCallOn;
						GetVarNode->AllocateDefaultPins();

						UEdGraphPin* VarNodeSelfPin = Schema->FindSelfPin(*GetVarNode, EGPD_Input);
						if (VarNodeSelfPin != NULL)
						{
							VarNodeSelfPin->MakeLinkTo(SourcePin);

							UEdGraphPin* ValuePin = GetVarNode->GetValuePin();
							ValuePin->MakeLinkTo(CallFuncSelfPin);
						}
						else
						{
							// Failed to find the member to call on for this expansion, so warn about it
							CompilerContext.MessageLog.Warning(*LOCTEXT("CallFunctionOnInvalidMember_Warning", "Function node @@ called on invalid target member.").ToString(), this);
						}
					}
				}
			}			
		}

		// Now move the rest of the connections (including exec connections...)
		for(int32 SrcPinIdx=0; SrcPinIdx<Pins.Num(); SrcPinIdx++)
		{
			UEdGraphPin* SrcPin = Pins[SrcPinIdx];
			if(SrcPin != NULL && SrcPin != SelfPin) // check its not the self pin
			{
				UEdGraphPin* DestPin = CallFuncNode->FindPin(SrcPin->PinName);
				if(DestPin != NULL)
				{
					CompilerContext.MovePinLinksToIntermediate(*SrcPin, *DestPin); // Source node is assumed to be owner...
				}
			}
		}

		// Finally, break any remaining links on the 'call func on member' node
		BreakAllNodeLinks();
	}
}
void UK2Node_FormatText::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);

	/**
		At the end of this, the UK2Node_FormatText will not be a part of the Blueprint, it merely handles connecting
		the other nodes into the Blueprint.
	*/

	const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();

	// Create a "Make Array" node to compile the list of arguments into an array for the Format function being called
	UK2Node_MakeArray* MakeArrayNode = CompilerContext.SpawnIntermediateNode<UK2Node_MakeArray>(this, SourceGraph); //SourceGraph->CreateBlankNode<UK2Node_MakeArray>();
	MakeArrayNode->AllocateDefaultPins();
	CompilerContext.MessageLog.NotifyIntermediateObjectCreation(MakeArrayNode, this);

	UEdGraphPin* ArrayOut = MakeArrayNode->GetOutputPin();

	// This is the node that does all the Format work.
	UK2Node_CallFunction* CallFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
	CallFunction->SetFromFunction(UKismetTextLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetTextLibrary, Format)));
	CallFunction->AllocateDefaultPins();
	CompilerContext.MessageLog.NotifyIntermediateObjectCreation(CallFunction, this);

	// Connect the output of the "Make Array" pin to the function's "InArgs" pin
	ArrayOut->MakeLinkTo(CallFunction->FindPin(TEXT("InArgs")));

	// This will set the "Make Array" node's type, only works if one pin is connected.
	MakeArrayNode->PinConnectionListChanged(ArrayOut);

	// For each argument, we will need to add in a "Make Struct" node.
	for(int32 ArgIdx = 0; ArgIdx < PinNames.Num(); ++ArgIdx)
	{
		UEdGraphPin* ArgumentPin = FindArgumentPin(PinNames[ArgIdx]);

		// Spawn a "Make Struct" node to create the struct needed for formatting the text.
		UK2Node_MakeStruct* PinMakeStruct = CompilerContext.SpawnIntermediateNode<UK2Node_MakeStruct>(this, SourceGraph);
		PinMakeStruct->StructType = FFormatTextArgument::StaticStruct();
		PinMakeStruct->AllocateDefaultPins();

		// Set the struct's "ArgumentName" pin literal to be the argument pin's name.
		PinMakeStruct->GetSchema()->TrySetDefaultText(*PinMakeStruct->FindPin("ArgumentName"), FText::AsCultureInvariant(ArgumentPin->PinName));

		// Move the connection of the argument pin to the struct's "TextValue" pin, this will move the literal value if present.
		CompilerContext.MovePinLinksToIntermediate(*ArgumentPin, *PinMakeStruct->FindPin("TextValue"));

		// The "Make Array" node already has one pin available, so don't create one for ArgIdx == 0
		if(ArgIdx > 0)
		{
			MakeArrayNode->AddInputPin();
		}

		// Find the input pin on the "Make Array" node by index.
		FString PinName = FString::Printf(TEXT("[%d]"), ArgIdx);
		UEdGraphPin* InputPin = MakeArrayNode->FindPin(PinName);

		// Find the output for the pin's "Make Struct" node and link it to the corresponding pin on the "Make Array" node.
		FindOutputStructPinChecked(PinMakeStruct)->MakeLinkTo(InputPin);

	}

	// Move connection of FormatText's "Result" pin to the call function's return value pin.
	CompilerContext.MovePinLinksToIntermediate(*FindPin(TEXT("Result")), *CallFunction->GetReturnValuePin());
	// Move connection of FormatText's "Format" pin to the call function's "InPattern" pin
	CompilerContext.MovePinLinksToIntermediate(*GetFormatPin(), *CallFunction->FindPin(TEXT("InPattern")));

	BreakAllNodeLinks();
}
void UK2Node_LoadAsset::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);
	const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();
	check(Schema);
	bool bIsErrorFree = true;

	// Create LoadAsset function call
	auto CallLoadAssetNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
	CallLoadAssetNode->FunctionReference.SetExternalMember(NativeFunctionName(), UKismetSystemLibrary::StaticClass());
	CallLoadAssetNode->AllocateDefaultPins(); 

	// connect to input exe
	{
		auto InputExePin = GetExecPin();
		auto CallFunctionInputExePin = CallLoadAssetNode->GetExecPin();
		bIsErrorFree &= InputExePin && CallFunctionInputExePin && CompilerContext.MovePinLinksToIntermediate(*InputExePin, *CallFunctionInputExePin).CanSafeConnect();
	}

	// Create Local Variable
	UK2Node_TemporaryVariable* TempVarOutput = CompilerContext.SpawnInternalVariable(this, GetOutputCategory(), FString(), UObject::StaticClass(), false);

	// Create assign node
	auto AssignNode = CompilerContext.SpawnIntermediateNode<UK2Node_AssignmentStatement>(this, SourceGraph);
	AssignNode->AllocateDefaultPins();

	auto LoadedObjectVariablePin = TempVarOutput->GetVariablePin();

	// connect local variable to assign node
	{
		auto AssignLHSPPin = AssignNode->GetVariablePin();
		bIsErrorFree &= AssignLHSPPin && LoadedObjectVariablePin && Schema->TryCreateConnection(AssignLHSPPin, LoadedObjectVariablePin);
	}

	// connect local variable to output
	{
		auto OutputObjectPinPin = FindPin(GetOutputPinName());
		bIsErrorFree &= LoadedObjectVariablePin && OutputObjectPinPin && CompilerContext.MovePinLinksToIntermediate(*OutputObjectPinPin, *LoadedObjectVariablePin).CanSafeConnect();
	}

	// connect assign exec input to function output
	{
		auto CallFunctionOutputExePin = CallLoadAssetNode->FindPin(Schema->PN_Then);
		auto AssignInputExePin = AssignNode->GetExecPin();
		bIsErrorFree &= AssignInputExePin && CallFunctionOutputExePin && Schema->TryCreateConnection(AssignInputExePin, CallFunctionOutputExePin);
	}

	// connect assign exec output to output
	{
		auto OutputExePin = FindPin(Schema->PN_Then);
		auto AssignOutputExePin = AssignNode->GetThenPin();
		bIsErrorFree &= OutputExePin && AssignOutputExePin && CompilerContext.MovePinLinksToIntermediate(*OutputExePin, *AssignOutputExePin).CanSafeConnect();
	}

	// connect to asset
	{
		auto AssetPin = FindPin(GetInputPinName());
		auto CallFunctionAssetPin = CallLoadAssetNode->FindPin(GetInputPinName());
		ensure(CallFunctionAssetPin);
		bIsErrorFree &= AssetPin && CallFunctionAssetPin && CompilerContext.MovePinLinksToIntermediate(*AssetPin, *CallFunctionAssetPin).CanSafeConnect();
	}

	// Create OnLoadEvent
	const FString DelegateOnLoadedParamName(TEXT("OnLoaded"));
	auto OnLoadEventNode = CompilerContext.SpawnIntermediateNode<UK2Node_CustomEvent>(this, SourceGraph);
	OnLoadEventNode->CustomFunctionName = *FString::Printf(TEXT("OnLoaded_%s"), *OnLoadEventNode->NodeGuid.ToString());
	OnLoadEventNode->AllocateDefaultPins();
	{
		UFunction* LoadAssetFunction = CallLoadAssetNode->GetTargetFunction();
		UDelegateProperty* OnLoadDelegateProperty = LoadAssetFunction ? FindField<UDelegateProperty>(LoadAssetFunction, *DelegateOnLoadedParamName) : nullptr;
		UFunction* OnLoadedSignature = OnLoadDelegateProperty ? OnLoadDelegateProperty->SignatureFunction : nullptr;
		ensure(OnLoadedSignature);
		for (TFieldIterator<UProperty> PropIt(OnLoadedSignature); PropIt && (PropIt->PropertyFlags & CPF_Parm); ++PropIt)
		{
			const UProperty* Param = *PropIt;
			if (!Param->HasAnyPropertyFlags(CPF_OutParm) || Param->HasAnyPropertyFlags(CPF_ReferenceParm))
			{
				FEdGraphPinType PinType;
				bIsErrorFree &= Schema->ConvertPropertyToPinType(Param, /*out*/ PinType);
				bIsErrorFree &= (NULL != OnLoadEventNode->CreateUserDefinedPin(Param->GetName(), PinType, EGPD_Output));
			}
		}
	}

	// connect delegate
	{
		auto CallFunctionDelegatePin = CallLoadAssetNode->FindPin(DelegateOnLoadedParamName);
		ensure(CallFunctionDelegatePin);
		auto EventDelegatePin = OnLoadEventNode->FindPin(UK2Node_CustomEvent::DelegateOutputName);
		bIsErrorFree &= CallFunctionDelegatePin && EventDelegatePin && Schema->TryCreateConnection(CallFunctionDelegatePin, EventDelegatePin);
	}

	// connect loaded object from event to assign
	{
		auto LoadedAssetEventPin = OnLoadEventNode->FindPin(TEXT("Loaded"));
		ensure(LoadedAssetEventPin);
		auto AssignRHSPPin = AssignNode->GetValuePin();
		bIsErrorFree &= AssignRHSPPin && LoadedAssetEventPin && Schema->TryCreateConnection(LoadedAssetEventPin, AssignRHSPPin);
	}

	if (!bIsErrorFree)
	{
		CompilerContext.MessageLog.Error(*LOCTEXT("InternalConnectionError", "K2Node_LoadAsset: Internal connection error. @@").ToString(), this);
	}

	BreakAllNodeLinks();
}
/**
 *	This is essentially a mix of K2Node_BaseAsyncTask::ExpandNode and K2Node_SpawnActorFromClass::ExpandNode.
 *	Several things are going on here:
 *		-Factory call to create proxy object (K2Node_BaseAsyncTask)
 *		-Task return delegates are created and hooked up (K2Node_BaseAsyncTask)
 *		-A BeginSpawn function is called on proxyu object (similiar to K2Node_SpawnActorFromClass)
 *		-BeginSpawn can choose to spawn or not spawn an actor (and return it)
 *			-If spawned:
 *				-SetVars are run on the newly spawned object (set expose on spawn variables - K2Node_SpawnActorFromClass)
 *				-FinishSpawn is called on the proxy object
 *				
 *				
 *	Also, a K2Node_SpawnActorFromClass could not be used directly here, since we want the proxy object to implement its own
 *	BeginSpawn/FinishSpawn function (custom game logic will often be performed in the native implementation). K2Node_SpawnActorFromClass also
 *	requires a SpawnTransform be wired into it, and in most ability task cases, the spawn transform is implied or not necessary.
 *	
 *	
 */
void UK2Node_LatentAbilityCall::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	bool validatedActorSpawn = ValidateActorSpawning(CompilerContext, false);
	bool validatedActorArraySpawn = ValidateActorArraySpawning(CompilerContext, false);

	UEdGraphPin* ClassPin = GetClassPin();
	if (ClassPin == nullptr)
	{
		// Nothing special about this task, just call super
		Super::ExpandNode(CompilerContext, SourceGraph);
		return;
	}

	UK2Node::ExpandNode(CompilerContext, SourceGraph);

	if (!validatedActorSpawn && !validatedActorArraySpawn)
	{
		ValidateActorSpawning(CompilerContext, true);
		ValidateActorArraySpawning(CompilerContext, true);
	}

	const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();
	check(SourceGraph && Schema);
	bool bIsErrorFree = true;


	// ------------------------------------------------------------------------------------------
	// CREATE A CALL TO FACTORY THE PROXY OBJECT
	// ------------------------------------------------------------------------------------------
	UK2Node_CallFunction* const CallCreateProxyObjectNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
	CallCreateProxyObjectNode->FunctionReference.SetExternalMember(ProxyFactoryFunctionName, ProxyFactoryClass);
	CallCreateProxyObjectNode->AllocateDefaultPins();
	bIsErrorFree &= CompilerContext.MovePinLinksToIntermediate(*FindPinChecked(Schema->PN_Execute), *CallCreateProxyObjectNode->FindPinChecked(Schema->PN_Execute)).CanSafeConnect();
	for (auto CurrentPin : Pins)
	{
		if (FBaseAsyncTaskHelper::ValidDataPin(CurrentPin, EGPD_Input, Schema))
		{
			UEdGraphPin* DestPin = CallCreateProxyObjectNode->FindPin(CurrentPin->PinName); // match function inputs, to pass data to function from CallFunction node

			// NEW: if no DestPin, assume it is a Class Spawn PRoperty - not an error
			if (DestPin)
			{
				bIsErrorFree &= CompilerContext.CopyPinLinksToIntermediate(*CurrentPin, *DestPin).CanSafeConnect();
			}
		}
	}
	// ------------------------------------------------------------------------------------------
	// GATHER OUTPUT PARAMETERS AND PAIR THEM WITH LOCAL VARIABLES
	// ------------------------------------------------------------------------------------------
	TArray<FBaseAsyncTaskHelper::FOutputPinAndLocalVariable> VariableOutputs;
	for (auto CurrentPin : Pins)
	{
		if (FBaseAsyncTaskHelper::ValidDataPin(CurrentPin, EGPD_Output, Schema))
		{
			const FEdGraphPinType& PinType = CurrentPin->PinType;
			UK2Node_TemporaryVariable* TempVarOutput = CompilerContext.SpawnInternalVariable(
				this, PinType.PinCategory, PinType.PinSubCategory, PinType.PinSubCategoryObject.Get(), PinType.bIsArray);
			bIsErrorFree &= TempVarOutput->GetVariablePin() && CompilerContext.MovePinLinksToIntermediate(*CurrentPin, *TempVarOutput->GetVariablePin()).CanSafeConnect();
			VariableOutputs.Add(FBaseAsyncTaskHelper::FOutputPinAndLocalVariable(CurrentPin, TempVarOutput));
		}
	}

	// ------------------------------------------------------------------------------------------
	// FOR EACH DELEGATE DEFINE EVENT, CONNECT IT TO DELEGATE AND IMPLEMENT A CHAIN OF ASSIGMENTS
	// ------------------------------------------------------------------------------------------
	UEdGraphPin* LastThenPin = CallCreateProxyObjectNode->FindPinChecked(Schema->PN_Then);
	UEdGraphPin* const ProxyObjectPin = CallCreateProxyObjectNode->GetReturnValuePin();
	for (TFieldIterator<UMulticastDelegateProperty> PropertyIt(ProxyClass, EFieldIteratorFlags::ExcludeSuper); PropertyIt && bIsErrorFree; ++PropertyIt)
	{
		bIsErrorFree &= FBaseAsyncTaskHelper::HandleDelegateImplementation(*PropertyIt, VariableOutputs, ProxyObjectPin, LastThenPin, this, SourceGraph, CompilerContext);
	}

	if (CallCreateProxyObjectNode->FindPinChecked(Schema->PN_Then) == LastThenPin)
	{
		CompilerContext.MessageLog.Error(*LOCTEXT("MissingDelegateProperties", "BaseAsyncTask: Proxy has no delegates defined. @@").ToString(), this);
		return;
	}


	// ------------------------------------------------------------------------------------------
	// NEW: CREATE A CALL TO THE PRESPAWN FUNCTION, IF IT RETURNS TRUE, THEN WE WILL SPAWN THE NEW ACTOR
	// ------------------------------------------------------------------------------------------

	FName ProxyPrespawnFunctionName = validatedActorArraySpawn ? *FK2Node_LatentAbilityCallHelper::BeginSpawnArrayFuncName : *FK2Node_LatentAbilityCallHelper::BeginSpawnFuncName;
	UFunction* PreSpawnFunction = ProxyFactoryClass->FindFunctionByName(ProxyPrespawnFunctionName);

	FName ProxyPostpawnFunctionName = validatedActorArraySpawn ? *FK2Node_LatentAbilityCallHelper::FinishSpawnArrayFuncName : *FK2Node_LatentAbilityCallHelper::FinishSpawnFuncName;
	UFunction* PostSpawnFunction = ProxyFactoryClass->FindFunctionByName(ProxyPostpawnFunctionName);

	if (PreSpawnFunction == nullptr)
	{
		if (validatedActorArraySpawn)
		{
			CompilerContext.MessageLog.Error(*LOCTEXT("MissingBeginSpawningActorArrayFunction", "AbilityTask: Proxy is missing BeginSpawningActorArray native function. @@").ToString(), this);
		}
		else
		{
			CompilerContext.MessageLog.Error(*LOCTEXT("MissingBeginSpawningActorFunction", "AbilityTask: Proxy is missing BeginSpawningActor native function. @@").ToString(), this);
		}
		return;
	}

	if (PostSpawnFunction == nullptr)
	{
		if (validatedActorArraySpawn)
		{
			CompilerContext.MessageLog.Error(*LOCTEXT("MissingFinishSpawningActorArrayFunction", "AbilityTask: Proxy is missing FinishSpawningActorArray native function. @@").ToString(), this);
		}
		else
		{
			CompilerContext.MessageLog.Error(*LOCTEXT("MissingFinishSpawningActorFunction", "AbilityTask: Proxy is missing FinishSpawningActor native function. @@").ToString(), this);
		}
		return;
	}


	UK2Node_CallFunction* const CallPrespawnProxyObjectNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
	CallPrespawnProxyObjectNode->FunctionReference.SetExternalMember(ProxyPrespawnFunctionName, ProxyClass);
	CallPrespawnProxyObjectNode->AllocateDefaultPins();

	// Hook up the self connection
	UEdGraphPin* PrespawnCallSelfPin = Schema->FindSelfPin(*CallPrespawnProxyObjectNode, EGPD_Input);
	check(PrespawnCallSelfPin);

	bIsErrorFree &= Schema->TryCreateConnection(ProxyObjectPin, PrespawnCallSelfPin);

	// Hook up input parameters to PreSpawn
	for (auto CurrentPin : Pins)
	{
		if (FBaseAsyncTaskHelper::ValidDataPin(CurrentPin, EGPD_Input, Schema))
		{
			UEdGraphPin* DestPin = CallPrespawnProxyObjectNode->FindPin(CurrentPin->PinName);
			if (DestPin)
			{
				bIsErrorFree &= CompilerContext.CopyPinLinksToIntermediate(*CurrentPin, *DestPin).CanSafeConnect();
			}
		}
	}		

	// Hook the activate node up in the exec chain
	UEdGraphPin* PrespawnExecPin = CallPrespawnProxyObjectNode->FindPinChecked(Schema->PN_Execute);
	UEdGraphPin* PrespawnThenPin = CallPrespawnProxyObjectNode->FindPinChecked(Schema->PN_Then);
	UEdGraphPin* PrespawnReturnPin = CallPrespawnProxyObjectNode->FindPinChecked(Schema->PN_ReturnValue);
	UEdGraphPin* SpawnedActorReturnPin = CallPrespawnProxyObjectNode->FindPinChecked(FK2Node_LatentAbilityCallHelper::SpawnedActorPinName);

	bIsErrorFree &= Schema->TryCreateConnection(LastThenPin, PrespawnExecPin);

	LastThenPin = PrespawnThenPin;

	// -------------------------------------------
	// Branch based on return value of Prespawn
	// -------------------------------------------
		
	UK2Node_IfThenElse* BranchNode = SourceGraph->CreateBlankNode<UK2Node_IfThenElse>();
	BranchNode->AllocateDefaultPins();
	CompilerContext.MessageLog.NotifyIntermediateObjectCreation(BranchNode, this);

	// Link return value of prespawn with the branch condtional
	bIsErrorFree &= Schema->TryCreateConnection(PrespawnReturnPin, BranchNode->GetConditionPin());

	// Link our Prespawn call to the branch node
	bIsErrorFree &= Schema->TryCreateConnection(LastThenPin, BranchNode->GetExecPin());

	UEdGraphPin* BranchElsePin = BranchNode->GetElsePin();

	LastThenPin = BranchNode->GetThenPin();

	UClass* ClassToSpawn = GetClassToSpawn();
	if (validatedActorArraySpawn && ClassToSpawn)
	{
		//Branch for main loop control
		UK2Node_IfThenElse* Branch = CompilerContext.SpawnIntermediateNode<UK2Node_IfThenElse>(this, SourceGraph);
		Branch->AllocateDefaultPins();

		//Create int Iterator
		UK2Node_TemporaryVariable* IteratorVar = CompilerContext.SpawnIntermediateNode<UK2Node_TemporaryVariable>(this, SourceGraph);
		IteratorVar->VariableType.PinCategory = Schema->PC_Int;
		IteratorVar->AllocateDefaultPins();

		//Iterator assignment (initialization to zero)
		UK2Node_AssignmentStatement* IteratorInitialize = CompilerContext.SpawnIntermediateNode<UK2Node_AssignmentStatement>(this, SourceGraph);
		IteratorInitialize->AllocateDefaultPins();
		IteratorInitialize->GetValuePin()->DefaultValue = TEXT("0");

		//Iterator assignment (incrementing)
		UK2Node_AssignmentStatement* IteratorAssign = CompilerContext.SpawnIntermediateNode<UK2Node_AssignmentStatement>(this, SourceGraph);
		IteratorAssign->AllocateDefaultPins();

		//Increment iterator command
		UK2Node_CallFunction* Increment = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
		Increment->SetFromFunction(UKismetMathLibrary::StaticClass()->FindFunctionByName(TEXT("Add_IntInt")));
		Increment->AllocateDefaultPins();
		Increment->FindPinChecked(TEXT("B"))->DefaultValue = TEXT("1");

		//Array length
		UK2Node_CallArrayFunction* ArrayLength = CompilerContext.SpawnIntermediateNode<UK2Node_CallArrayFunction>(this, SourceGraph);
		ArrayLength->SetFromFunction(UKismetArrayLibrary::StaticClass()->FindFunctionByName(TEXT("Array_Length")));
		ArrayLength->AllocateDefaultPins();

		//Array element retrieval
		UK2Node_CallArrayFunction* GetElement = CompilerContext.SpawnIntermediateNode<UK2Node_CallArrayFunction>(this, SourceGraph);
		GetElement->SetFromFunction(UKismetArrayLibrary::StaticClass()->FindFunctionByName(TEXT("Array_Get")));
		GetElement->AllocateDefaultPins();

		//Check node for iterator versus array length
		UK2Node_CallFunction* Condition = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
		Condition->SetFromFunction(UKismetMathLibrary::StaticClass()->FindFunctionByName(TEXT("Less_IntInt")));
		Condition->AllocateDefaultPins();

		//Connections to set up the loop
		UEdGraphSchema_K2 const* const K2Schema = Cast<const UEdGraphSchema_K2>(Schema);
		bIsErrorFree &= Schema->TryCreateConnection(LastThenPin, IteratorInitialize->GetExecPin());
		bIsErrorFree &= Schema->TryCreateConnection(IteratorVar->GetVariablePin(), IteratorInitialize->GetVariablePin());
		bIsErrorFree &= Schema->TryCreateConnection(IteratorInitialize->GetThenPin(), Branch->GetExecPin());
		bIsErrorFree &= Schema->TryCreateConnection(SpawnedActorReturnPin, ArrayLength->GetTargetArrayPin());
		bIsErrorFree &= Schema->TryCreateConnection(Condition->GetReturnValuePin(), Branch->GetConditionPin());
		bIsErrorFree &= Schema->TryCreateConnection(IteratorVar->GetVariablePin(), Condition->FindPinChecked(TEXT("A")));
		bIsErrorFree &= Schema->TryCreateConnection(ArrayLength->FindPin(K2Schema->PN_ReturnValue), Condition->FindPinChecked(TEXT("B")));

		//Connections to establish loop iteration
		bIsErrorFree &= Schema->TryCreateConnection(IteratorVar->GetVariablePin(), Increment->FindPinChecked(TEXT("A")));
		bIsErrorFree &= Schema->TryCreateConnection(IteratorVar->GetVariablePin(), IteratorAssign->GetVariablePin());
		bIsErrorFree &= Schema->TryCreateConnection(Increment->GetReturnValuePin(), IteratorAssign->GetValuePin());
		bIsErrorFree &= Schema->TryCreateConnection(IteratorAssign->GetThenPin(), Branch->GetExecPin());

		//This is the inner loop
		LastThenPin = Branch->GetThenPin();		//Connect the loop branch to the spawn-assignment code block
		bIsErrorFree &= Schema->TryCreateConnection(SpawnedActorReturnPin, GetElement->GetTargetArrayPin());
		bIsErrorFree &= Schema->TryCreateConnection(IteratorVar->GetVariablePin(), GetElement->FindPinChecked(K2Schema->PN_Index));
		bIsErrorFree &= ConnectSpawnProperties(ClassToSpawn, Schema, CompilerContext, SourceGraph, LastThenPin, GetElement->FindPinChecked(K2Schema->PN_Item));		//Last argument is the array element
		bIsErrorFree &= Schema->TryCreateConnection(LastThenPin, IteratorAssign->GetExecPin());		//Connect the spawn-assignment code block to the iterator increment
		
		//Finish by providing the proper path out
		LastThenPin = Branch->GetElsePin();
	}

	// -------------------------------------------
	// Set spawn variables
	//  Borrowed heavily from FKismetCompilerUtilities::GenerateAssignmentNodes
	// -------------------------------------------
	
	if (validatedActorSpawn && ClassToSpawn)
	{
		bIsErrorFree &= ConnectSpawnProperties(ClassToSpawn, Schema, CompilerContext, SourceGraph, LastThenPin, SpawnedActorReturnPin);
	}
	
	// -------------------------------------------
	// Call FinishSpawning
	// -------------------------------------------

	UK2Node_CallFunction* const CallPostSpawnnProxyObjectNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
	CallPostSpawnnProxyObjectNode->FunctionReference.SetExternalMember(ProxyPostpawnFunctionName, ProxyClass);
	CallPostSpawnnProxyObjectNode->AllocateDefaultPins();

	// Hook up the self connection
	UEdGraphPin* PostspawnCallSelfPin = Schema->FindSelfPin(*CallPostSpawnnProxyObjectNode, EGPD_Input);
	check(PostspawnCallSelfPin);

	bIsErrorFree &= Schema->TryCreateConnection(ProxyObjectPin, PostspawnCallSelfPin);

	// Link our Postspawn call in
	bIsErrorFree &= Schema->TryCreateConnection(LastThenPin, CallPostSpawnnProxyObjectNode->FindPinChecked(Schema->PN_Execute));

	// Hook up any other input parameters to PostSpawn
	for (auto CurrentPin : Pins)
	{
		if (FBaseAsyncTaskHelper::ValidDataPin(CurrentPin, EGPD_Input, Schema))
		{
			UEdGraphPin* DestPin = CallPostSpawnnProxyObjectNode->FindPin(CurrentPin->PinName);
			if (DestPin)
			{
				bIsErrorFree &= CompilerContext.CopyPinLinksToIntermediate(*CurrentPin, *DestPin).CanSafeConnect();
			}
		}
	}


	UEdGraphPin* InSpawnedActorPin = CallPostSpawnnProxyObjectNode->FindPin(TEXT("SpawnedActor"));
	if (InSpawnedActorPin == nullptr)
	{
		CompilerContext.MessageLog.Error(*LOCTEXT("MissingSpawnedActorInputPin", "AbilityTask: Proxy is missing SpawnedActor input pin in FinishSpawningActor. @@").ToString(), this);
		return;
	}

	bIsErrorFree &= Schema->TryCreateConnection(SpawnedActorReturnPin, InSpawnedActorPin);

	LastThenPin = CallPostSpawnnProxyObjectNode->FindPinChecked(Schema->PN_Then);


	// Move the connections from the original node then pin to the last internal then pin
	bIsErrorFree &= CompilerContext.MovePinLinksToIntermediate(*FindPinChecked(Schema->PN_Then), *LastThenPin).CanSafeConnect();
	bIsErrorFree &= CompilerContext.CopyPinLinksToIntermediate(*LastThenPin, *BranchElsePin).CanSafeConnect();
	
	if (!bIsErrorFree)
	{
		CompilerContext.MessageLog.Error(*LOCTEXT("InternalConnectionError", "BaseAsyncTask: Internal connection error. @@").ToString(), this);
	}

	// Make sure we caught everything
	BreakAllNodeLinks();
}
void UK2Node_GetEnumeratorName::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);

	UEnum* Enum = GetEnum();
	if(NULL == Enum)
	{
		CompilerContext.MessageLog.Error(*FString::Printf(*NSLOCTEXT("K2Node", "GetEnumeratorNam_Error_MustHaveValidName", "@@ must have a valid enum defined").ToString()), this);
		return;
	}

	const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();
		
	const UFunction* Function = UKismetNodeHelperLibrary::StaticClass()->FindFunctionByName( GetFunctionName() );
	check(NULL != Function);
	UK2Node_CallFunction* CallGetName = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph); 
	CallGetName->SetFromFunction(Function);
	CallGetName->AllocateDefaultPins();
	check(CallGetName->IsNodePure());
		
	//OPUTPUT PIN
	UEdGraphPin* OrgReturnPin = FindPinChecked(Schema->PN_ReturnValue);
	UEdGraphPin* NewReturnPin = CallGetName->GetReturnValuePin();
	check(NULL != NewReturnPin);
	CompilerContext.MovePinLinksToIntermediate(*OrgReturnPin, *NewReturnPin);

	//ENUM PIN
	UEdGraphPin* EnumPin = CallGetName->FindPinChecked(TEXT("Enum"));
	Schema->TrySetDefaultObject(*EnumPin, Enum);
	check(EnumPin->DefaultObject == Enum);

	//VALUE PIN
	UEdGraphPin* OrgInputPin = FindPinChecked(EnumeratorPinName);
	UEdGraphPin* IndexPin = CallGetName->FindPinChecked(TEXT("EnumeratorValue"));
	check(EGPD_Input == IndexPin->Direction && Schema->PC_Byte == IndexPin->PinType.PinCategory);
	CompilerContext.MovePinLinksToIntermediate(*OrgInputPin, *IndexPin);

	if (!IndexPin->LinkedTo.Num())
	{
		//MAKE LITERAL BYTE FROM LITERAL ENUM
		const FString EnumLiteral = IndexPin->GetDefaultAsString();
		const int32 NumericValue = Enum->GetValueByName(*EnumLiteral);
		if (NumericValue == INDEX_NONE) 
		{
			CompilerContext.MessageLog.Error(*FString::Printf(*NSLOCTEXT("K2Node", "GetEnumeratorNam_Error_InvalidName", "@@ has invalid enum value '%s'").ToString(), *EnumLiteral), this);
			return;
		}
		const FString DefaultByteValue = FString::FromInt(NumericValue);

		// LITERAL BYTE FUNCTION
		const FName FunctionName = GET_FUNCTION_NAME_CHECKED(UKismetSystemLibrary, MakeLiteralByte);
		UK2Node_CallFunction* MakeLiteralByte = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph); 
		MakeLiteralByte->SetFromFunction(UKismetSystemLibrary::StaticClass()->FindFunctionByName(FunctionName));
		MakeLiteralByte->AllocateDefaultPins();

		UEdGraphPin* MakeLiteralByteReturnPin = MakeLiteralByte->FindPinChecked(Schema->PN_ReturnValue);
		Schema->TryCreateConnection(MakeLiteralByteReturnPin, IndexPin);

		UEdGraphPin* MakeLiteralByteInputPin = MakeLiteralByte->FindPinChecked(TEXT("Value"));
		MakeLiteralByteInputPin->DefaultValue = DefaultByteValue;
	}

	BreakAllNodeLinks();
}