void FNodeHandlingFunctor::ResolveAndRegisterScopedTerm(FKismetFunctionContext& Context, UEdGraphPin* Net, TIndirectArray<FBPTerminal>& NetArray)
{
	// Determine the scope this takes place in
	UStruct* SearchScope = Context.Function;

	UEdGraphPin* SelfPin = CompilerContext.GetSchema()->FindSelfPin(*(Net->GetOwningNode()), EGPD_Input);
	if (SelfPin != NULL)
	{
		SearchScope = Context.GetScopeFromPinType(SelfPin->PinType, Context.NewClass);
	}

	// Find the variable in the search scope
	UProperty* BoundProperty = FKismetCompilerUtilities::FindPropertyInScope(SearchScope, Net, CompilerContext.MessageLog, CompilerContext.GetSchema(), Context.NewClass);
	if (BoundProperty != NULL)
	{
		// Create the term in the list
		FBPTerminal* Term = new (NetArray) FBPTerminal();
		Term->CopyFromPin(Net, Net->PinName);
		Term->AssociatedVarProperty = BoundProperty;
		Context.NetMap.Add(Net, Term);

		// Read-only variables and variables in const classes are both const
		if (BoundProperty->HasAnyPropertyFlags(CPF_BlueprintReadOnly) || Context.IsConstFunction())
		{
			Term->bIsConst = true;
		}

		// Resolve the context term
		if (SelfPin != NULL)
		{
			FBPTerminal** pContextTerm = Context.NetMap.Find(FEdGraphUtilities::GetNetFromPin(SelfPin));
			Term->Context = (pContextTerm != NULL) ? *pContextTerm : NULL;
		}
	}
}
예제 #2
0
	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		static const FBoolConfigValueHelper ExecutionAfterReturn(TEXT("Kismet"), TEXT("bExecutionAfterReturn"), GEngineIni);

		if (ExecutionAfterReturn)
		{
			// for backward compatibility only
			FKCHandler_VariableSet::Compile(Context, Node);
		}
		else
		{
			GenerateAssigments(Context, Node);

			if (Context.bCreateDebugData && Node)
			{
				FBlueprintCompiledStatement& TraceStatement = Context.AppendStatementForNode(Node);
				TraceStatement.Type = KCST_WireTraceSite;
				TraceStatement.Comment = Node->NodeComment.IsEmpty() ? Node->GetName() : Node->NodeComment;
			}

			// always go to return
			FBlueprintCompiledStatement& GotoStatement = Context.AppendStatementForNode(Node);
			GotoStatement.Type = KCST_GotoReturn;
		}
	}
	virtual void RegisterNet(FKismetFunctionContext& Context, UEdGraphPin* Net) override
	{
		// This net is an anonymous temporary variable
		FBPTerminal* Term = Context.CreateLocalTerminal(Context.IsEventGraph() ? ETerminalSpecification::TS_ForcedShared : ETerminalSpecification::TS_Unspecified);

		FString NetName = Context.NetNameMap->MakeValidName(Net);

		Term->CopyFromPin(Net, NetName);

		UK2Node_TemporaryVariable* TempVarNode = CastChecked<UK2Node_TemporaryVariable>(Net->GetOwningNode());
		Term->bIsSavePersistent = TempVarNode->bIsPersistent;

		Context.NetMap.Add(Net, Term);
	}
void FKCHandler_ClearDelegate::Compile(FKismetFunctionContext& Context, UEdGraphNode* Node)
{
	UK2Node_BaseMCDelegate* DelegateNode = CastChecked<UK2Node_BaseMCDelegate>(Node);

	UEdGraphPin* SelfPin = CompilerContext.GetSchema()->FindSelfPin(*DelegateNode, EEdGraphPinDirection::EGPD_Input);
	check(SelfPin);

	TArray<UEdGraphPin*> Links = SelfPin->LinkedTo;
	if(!Links.Num())
	{
		Links.Add(SelfPin);
	}

	for (auto NetIt = Links.CreateIterator(); NetIt; ++NetIt)
	{
		UEdGraphPin* NetPin = *NetIt;
		check(NetPin);

		FBlueprintCompiledStatement& AddStatement = Context.AppendStatementForNode(DelegateNode);
		AddStatement.Type = KCST_ClearMulticastDelegate;

		FBPTerminal** VarDelegate = InnerTermMap.Find(FDelegateOwnerId(NetPin, DelegateNode));
		check(VarDelegate && *VarDelegate);
		AddStatement.LHS = *VarDelegate;
	}

	GenerateSimpleThenGoto(Context, *DelegateNode, DelegateNode->FindPin(CompilerContext.GetSchema()->PN_Then));
	FNodeHandlingFunctor::Compile(Context, DelegateNode);
}
	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		UK2Node_FunctionEntry* EntryNode = CastChecked<UK2Node_FunctionEntry>(Node);
		//check(EntryNode->SignatureName != NAME_None);
		if (EntryNode->SignatureName == CompilerContext.GetSchema()->FN_ExecuteUbergraphBase)
		{
			UEdGraphPin* EntryPointPin = Node->FindPin(CompilerContext.GetSchema()->PN_EntryPoint);
			FBPTerminal** pTerm = Context.NetMap.Find(EntryPointPin);
			if ((EntryPointPin != NULL) && (pTerm != NULL))
			{
				FBlueprintCompiledStatement& ComputedGotoStatement = Context.AppendStatementForNode(Node);
				ComputedGotoStatement.Type = KCST_ComputedGoto;
				ComputedGotoStatement.LHS = *pTerm;
			}
			else
			{
				CompilerContext.MessageLog.Error(*LOCTEXT("NoEntryPointPin_Error", "Expected a pin named EntryPoint on @@").ToString(), Node);
			}
		}
		else
		{
			// Generate the output impulse from this node
			GenerateSimpleThenGoto(Context, *Node);
		}
	}
예제 #6
0
	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		UK2Node_MakeArray* ArrayNode = CastChecked<UK2Node_MakeArray>(Node);
		UEdGraphPin* OutputPin = ArrayNode->GetOutputPin();

		FBPTerminal** ArrayTerm = Context.NetMap.Find(OutputPin);
		check(ArrayTerm);

		FBlueprintCompiledStatement& CreateArrayStatement = Context.AppendStatementForNode(Node);
		CreateArrayStatement.Type = KCST_CreateArray;
		CreateArrayStatement.LHS = *ArrayTerm;

		for(auto PinIt = Node->Pins.CreateIterator(); PinIt; ++PinIt)
		{
			UEdGraphPin* Pin = *PinIt;
			if(Pin && Pin->Direction == EGPD_Input)
			{
				FBPTerminal** InputTerm = Context.NetMap.Find(FEdGraphUtilities::GetNetFromPin(Pin));
				if( InputTerm )
				{
					CreateArrayStatement.RHS.Add(*InputTerm);
				}
			}
		}
	}
예제 #7
0
	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		// For imperative nodes, make sure the exec function was actually triggered and not just included due to an output data dependency
		FEdGraphPinType ExpectedExecPinType;
		ExpectedExecPinType.PinCategory = UEdGraphSchema_K2::PC_Exec;

		FEdGraphPinType ExpectedBoolPinType;
		ExpectedBoolPinType.PinCategory = UEdGraphSchema_K2::PC_Boolean;


		UEdGraphPin* ExecTriggeringPin = Context.FindRequiredPinByName(Node, UEdGraphSchema_K2::PN_Execute, EGPD_Input);
		if ((ExecTriggeringPin == NULL) || !Context.ValidatePinType(ExecTriggeringPin, ExpectedExecPinType))
		{
			CompilerContext.MessageLog.Error(*FString::Printf(*LOCTEXT("NoValidExecutionPinForBranch_Error", "@@ must have a valid execution pin @@").ToString()), Node, ExecTriggeringPin);
			return;
		}
		else if (ExecTriggeringPin->LinkedTo.Num() == 0)
		{
			CompilerContext.MessageLog.Warning(*FString::Printf(*LOCTEXT("NodeNeverExecuted_Warning", "@@ will never be executed").ToString()), Node);
			return;
		}

		// Generate the output impulse from this node
		UEdGraphPin* CondPin = Context.FindRequiredPinByName(Node, CompilerContext.GetSchema()->PN_Condition, EGPD_Input);
		UEdGraphPin* ThenPin = Context.FindRequiredPinByName(Node, CompilerContext.GetSchema()->PN_Then, EGPD_Output);
		UEdGraphPin* ElsePin = Context.FindRequiredPinByName(Node, CompilerContext.GetSchema()->PN_Else, EGPD_Output);
		if (Context.ValidatePinType(ThenPin, ExpectedExecPinType) &&
			Context.ValidatePinType(ElsePin, ExpectedExecPinType) &&
			Context.ValidatePinType(CondPin, ExpectedBoolPinType))
		{
			UEdGraphPin* PinToTry = FEdGraphUtilities::GetNetFromPin(CondPin);
			FBPTerminal** CondTerm = Context.NetMap.Find(PinToTry);

			if (CondTerm != NULL) //
			{
				// First skip the if, if the term is false
				{
					FBlueprintCompiledStatement& SkipIfGoto = Context.AppendStatementForNode(Node);
					SkipIfGoto.Type = KCST_GotoIfNot;
					SkipIfGoto.LHS = *CondTerm;
					Context.GotoFixupRequestMap.Add(&SkipIfGoto, ElsePin);
				}

				// Now go to the If branch
				{
					FBlueprintCompiledStatement& GotoThen = Context.AppendStatementForNode(Node);
					GotoThen.Type = KCST_UnconditionalGoto;
					GotoThen.LHS = *CondTerm;
					Context.GotoFixupRequestMap.Add(&GotoThen, ThenPin);
				}
			}
			else
			{
				CompilerContext.MessageLog.Error(*LOCTEXT("ResolveTermPassed_Error", "Failed to resolve term passed into @@").ToString(), CondPin);
			}
		}
	}
예제 #8
0
	virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		FNodeHandlingFunctor::RegisterNets(Context, Node);

		// Create the net for the return value manually as it's a special case Output Direction pin
		UK2Node_Select* SelectNode = Cast<UK2Node_Select>(Node);
		UEdGraphPin* ReturnPin = SelectNode->GetReturnValuePin();

		FBPTerminal* Term = Context.CreateLocalTerminalFromPinAutoChooseScope(ReturnPin, Context.NetNameMap->MakeValidName(ReturnPin));
		Context.NetMap.Add(SelectNode->GetReturnValuePin(), Term);

		// Create a term to determine if the compare was successful or not
		FBPTerminal* BoolTerm = Context.CreateLocalTerminal();
		BoolTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Boolean;
		BoolTerm->Source = Node;
		BoolTerm->Name = Context.NetNameMap->MakeValidName(Node) + TEXT("_CmpSuccess");
		BoolTermMap.Add(Node, BoolTerm);
	}
	virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node)
	{
		FNodeHandlingFunctor::RegisterNets(Context, Node);

		const FString BaseNetName = Context.NetNameMap->MakeValidName(Node);

		// Create a term to store a bool that determines if we're in the first execution of the node or not
		FBPTerminal* FirstRunTerm = Context.CreateLocalTerminal();
		FirstRunTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Boolean;
		FirstRunTerm->Source = Node;
		FirstRunTerm->Name = BaseNetName + TEXT("_FirstRun");
		FirstRunTermMap.Add(Node, FirstRunTerm);

		UK2Node_MultiGate* GateNode = Cast<UK2Node_MultiGate>(Node);
		// If there is already a data node from expansion phase
		if (!GateNode || !GateNode->DataNode)
		{
			FBPTerminal* DataTerm = Context.CreateLocalTerminal();
			DataTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Int;
			DataTerm->Source = Node;
			DataTerm->Name = BaseNetName + TEXT("_Data");
			DataTermMap.Add(Node, DataTerm);
		}

		FFunctionScopedTerms& FuncLocals = FunctionTermMap.FindOrAdd(Context.Function);

		// Create a local scratch bool for run-time if there isn't already one
		if (!FuncLocals.GenericBoolTerm)
		{
			FuncLocals.GenericBoolTerm = Context.CreateLocalTerminal();
			FuncLocals.GenericBoolTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Boolean;
			FuncLocals.GenericBoolTerm->Source = Node;
			FuncLocals.GenericBoolTerm->Name = BaseNetName + TEXT("_ScratchBool");
		}

		// Create a local scratch int for run-time index tracking if there isn't already one
		if (!FuncLocals.IndexTerm)
		{
			FuncLocals.IndexTerm = Context.CreateLocalTerminal();
			FuncLocals.IndexTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Int;
			FuncLocals.IndexTerm->Source = Node;
			FuncLocals.IndexTerm->Name = BaseNetName + TEXT("_ScratchIndex");
		}
	}
예제 #10
0
	virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
 		UK2Node_MakeArray* ArrayNode = CastChecked<UK2Node_MakeArray>(Node);
 		UEdGraphPin* OutputPin = ArrayNode->GetOutputPin();

		FNodeHandlingFunctor::RegisterNets(Context, Node);

		// Create a local term to drop the array into
		FBPTerminal* Term = Context.CreateLocalTerminalFromPinAutoChooseScope(OutputPin, Context.NetNameMap->MakeValidName(OutputPin));
		Term->bPassedByReference = false;
		Term->Source = Node;
 		Context.NetMap.Add(OutputPin, Term);
	}
	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		const UK2Node_DelegateSet* DelegateNode = Cast<UK2Node_DelegateSet>(Node);
		check(DelegateNode);

		// Verify that the event has a darget to be bound to
		UEdGraphPin* DelegateOwnerPin = DelegateNode->GetDelegateOwner();

		if (DelegateOwnerPin == nullptr || DelegateOwnerPin->LinkedTo.Num() == 0)
		{
			CompilerContext.MessageLog.Error(*FString(*LOCTEXT("FindDynamicallyBoundDelegate_Error", "Couldn't find target for dynamically bound delegate node @@").ToString()), DelegateNode);
			return;
		}

		FBPTerminal** pDelegateOwnerTerm = Context.NetMap.Find(DelegateOwnerPin);

		// Create a delegate name term
		FBPTerminal* DelegateNameTerm = Context.CreateLocalTerminal(ETerminalSpecification::TS_Literal);
		DelegateNameTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Name;
		DelegateNameTerm->Name = DelegateNode->GetDelegateTargetEntryPointName().ToString();
		DelegateNameTerm->bIsLiteral = true;

		// Create a local delegate, which we can then add to the multicast delegate
		FBPTerminal* LocalDelegate = *LocalDelegateMap.Find(Node);
		FBlueprintCompiledStatement& Statement = Context.AppendStatementForNode(Node);
		Statement.Type = KCST_Assignment;
		Statement.LHS = LocalDelegate;
		Statement.RHS.Add(DelegateNameTerm);

		// Add the local delegate to the MC delegate
		FBlueprintCompiledStatement& AddStatement = Context.AppendStatementForNode(Node);
		AddStatement.Type = KCST_AddMulticastDelegate;
		AddStatement.LHS = *pDelegateOwnerTerm;
		AddStatement.RHS.Add(LocalDelegate);

		GenerateSimpleThenGoto(Context, *Node, DelegateNode->FindPin(CompilerContext.GetSchema()->PN_Then));

		FNodeHandlingFunctor::Compile(Context, Node);
	}
예제 #12
0
void FKCHandler_VariableSet::InnerAssignment(FKismetFunctionContext& Context, UEdGraphNode* Node, UEdGraphPin* VariablePin, UEdGraphPin* ValuePin)
{
    FBPTerminal** VariableTerm = Context.NetMap.Find(VariablePin);
    if (VariableTerm == NULL)
    {
        VariableTerm = Context.NetMap.Find(FEdGraphUtilities::GetNetFromPin(VariablePin));
    }

    FBPTerminal** ValueTerm = Context.LiteralHackMap.Find(ValuePin);
    if (ValueTerm == NULL)
    {
        ValueTerm = Context.NetMap.Find(FEdGraphUtilities::GetNetFromPin(ValuePin));
    }

    if ((VariableTerm != NULL) && (ValueTerm != NULL))
    {
        FKismetCompilerUtilities::CreateObjectAssignmentStatement(Context, Node, *ValueTerm, *VariableTerm);

        if (!(*VariableTerm)->IsTermWritable())
        {
            // If the term is not explicitly marked as read-only, then we're attempting to set a variable on a const target
            if(!(*VariableTerm)->AssociatedVarProperty->HasAnyPropertyFlags(CPF_BlueprintReadOnly))
            {
                if(Context.EnforceConstCorrectness())
                {
                    CompilerContext.MessageLog.Error(*LOCTEXT("WriteToReadOnlyContext_Error", "Variable @@ is read-only within this context and cannot be set to a new value").ToString(), VariablePin);
                }
                else
                {
                    // Warn, but still allow compilation to succeed
                    CompilerContext.MessageLog.Warning(*LOCTEXT("WriteToReadOnlyContext_Warning", "Variable @@ is considered to be read-only within this context and should not be set to a new value").ToString(), VariablePin);
                }
            }
            else
            {
                CompilerContext.MessageLog.Error(*LOCTEXT("WriteConst_Error", "Cannot write to const @@").ToString(), VariablePin);
            }
        }
    }
    else
    {
        if (VariablePin != ValuePin)
        {
            CompilerContext.MessageLog.Error(*LOCTEXT("ResolveValueIntoVariablePin_Error", "Failed to resolve term @@ passed into @@").ToString(), ValuePin, VariablePin);
        }
        else
        {
            CompilerContext.MessageLog.Error(*LOCTEXT("ResolveTermPassed_Error", "Failed to resolve term passed into @@").ToString(), VariablePin);
        }
    }
}
예제 #13
0
	virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		UK2Node_Switch* SwitchNode = Cast<UK2Node_Switch>(Node);

		FNodeHandlingFunctor::RegisterNets(Context, Node);

		// Create a term to determine if the compare was successful or not
		//@TODO: Ideally we just create one ever, not one per switch
		FBPTerminal* BoolTerm = Context.CreateLocalTerminal();
		BoolTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Boolean;
		BoolTerm->Source = Node;
		BoolTerm->Name = Context.NetNameMap->MakeValidName(Node) + TEXT("_CmpSuccess");
		BoolTermMap.Add(Node, BoolTerm);
	}
void FKCHandler_CreateDelegate::Compile(FKismetFunctionContext& Context, UEdGraphNode* Node)
{
	UK2Node_CreateDelegate * DelegateNode = CastChecked<UK2Node_CreateDelegate>(Node);
	check(NULL != DelegateNode);

	FBlueprintCompiledStatement& Statement = Context.AppendStatementForNode(Node);
	Statement.Type = KCST_BindDelegate;

	{
		UEdGraphPin* OutPin = DelegateNode->GetDelegateOutPin();
		check(NULL != OutPin);
		UEdGraphPin* Net = FEdGraphUtilities::GetNetFromPin(OutPin);
		check(NULL != Net);
		FBPTerminal** FoundTerm = Context.NetMap.Find(Net);
		check(FoundTerm && *FoundTerm);
		Statement.LHS = *FoundTerm;
	}

	{
		FBPTerminal* DelegateNameTerm = Context.CreateLocalTerminal(ETerminalSpecification::TS_Literal);
		DelegateNameTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Name;
		DelegateNameTerm->Name = DelegateNode->GetFunctionName().ToString();
		DelegateNameTerm->bIsLiteral = true;
		Statement.RHS.Add(DelegateNameTerm);
	}

	{
		UEdGraphPin* InputPin = DelegateNode->GetObjectInPin();
		check(NULL != InputPin);
		UEdGraphPin* Net = FEdGraphUtilities::GetNetFromPin(InputPin);
		FBPTerminal** FoundTerm = Context.NetMap.Find(Net);
		check(FoundTerm && *FoundTerm);
		Statement.RHS.Add(*FoundTerm);
	}

	FNodeHandlingFunctor::Compile(Context, Node);
}
bool FNodeHandlingFunctor::ValidateAndRegisterNetIfLiteral(FKismetFunctionContext& Context, UEdGraphPin* Net)
{
	if (Net->LinkedTo.Num() == 0)
	{
		// Make sure the default value is valid
		FString DefaultAllowedResult = CompilerContext.GetSchema()->IsCurrentPinDefaultValid(Net);
		if (DefaultAllowedResult != TEXT(""))
		{
			CompilerContext.MessageLog.Error(*FString::Printf(*LOCTEXT("InvalidDefaultValue_Error", "Default value '%s' for @@ is invalid: '%s'").ToString(), *(Net->GetDefaultAsString()), *DefaultAllowedResult), Net);
			return false;
		}

		FBPTerminal* LiteralTerm = Context.RegisterLiteral(Net);
		Context.LiteralHackMap.Add(Net, LiteralTerm);
	}

	return true;
}
	virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		UK2Node_DelegateSet* DelegateNode = Cast<UK2Node_DelegateSet>(Node);
		if( DelegateNode )
		{
			CompilerContext.MessageLog.Warning(*FString(*LOCTEXT("DeprecatedDelegateSet_Warning", "DelegateSet node @@ is Deprecated. It should be replaced by an EventCaller Bind node").ToString()), DelegateNode);

			// Create a term to store the locally created delegate that we'll use to add to the MC delegate
			FBPTerminal* DelegateTerm = Context.CreateLocalTerminal();
			DelegateTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Delegate;
			FMemberReference::FillSimpleMemberReference<UFunction>(DelegateNode->GetDelegateSignature(), DelegateTerm->Type.PinSubCategoryMemberReference);
			DelegateTerm->Source = Node;
			DelegateTerm->Name = Context.NetNameMap->MakeValidName(Node) + TEXT("_TempBindingDelegate");
			LocalDelegateMap.Add(Node, DelegateTerm);

			// The only net we need to register for this node is the delegate's target (self) pin, since the others are expanded to their own event node
			RegisterDelegateNet(Context, DelegateNode);
		}
	}
void FNodeHandlingFunctor::RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node)
{
	for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex)
	{
		UEdGraphPin* Pin = Node->Pins[PinIndex];
		if (!CompilerContext.GetSchema()->IsMetaPin(*Pin)
			|| (CompilerContext.GetSchema()->IsSelfPin(*Pin) && Pin->LinkedTo.Num() == 0 && Pin->DefaultObject) )
		{
			UEdGraphPin* Net = FEdGraphUtilities::GetNetFromPin(Pin);

			if (Context.NetMap.Find(Net) == NULL)
			{
				// New net, resolve the term that will be used to construct it
				FBPTerminal* Term = NULL;

				if ((Net->Direction == EGPD_Input) && (Net->LinkedTo.Num() == 0))
				{
					// Make sure the default value is valid
					FString DefaultAllowedResult = CompilerContext.GetSchema()->IsCurrentPinDefaultValid(Net);
					if (DefaultAllowedResult != TEXT(""))
					{
						CompilerContext.MessageLog.Error(*FString::Printf(*LOCTEXT("InvalidDefaultValue_Error", "Default value '%s' for @@ is invalid: '%s'").ToString(), *(Net->GetDefaultAsString()), *DefaultAllowedResult), Net);

						// Skip over these properties if they are array or ref properties, because the backend can't emit valid code for them
						if( Pin->PinType.bIsArray || Pin->PinType.bIsReference )
						{
							continue;
						}
					}

					Term = Context.RegisterLiteral(Net);
					Context.NetMap.Add(Net, Term);
				}
				else
				{
					RegisterNet(Context, Pin);
				}
			}
		}
	}
}
void FKCHandler_AddRemoveDelegate::RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node)
{
	UK2Node_BaseMCDelegate * DelegateNode = CastChecked<UK2Node_BaseMCDelegate>(Node);

	FKCHandlerDelegateHelper::RegisterMultipleSelfAndMCDelegateProperty(Context, DelegateNode, CompilerContext.MessageLog, CompilerContext.GetSchema(), InnerTermMap);

	UEdGraphPin* Pin = DelegateNode->GetDelegatePin();	
	check(NULL != Pin);
	if(0 == Pin->LinkedTo.Num())
	{
		CompilerContext.MessageLog.Error(*FString(*LOCTEXT("AddRemoveDelegate_NoDelegateInput", "Event Dispatcher pin is not connected @@").ToString()), DelegateNode);
	}
	UEdGraphPin* Net = FEdGraphUtilities::GetNetFromPin(Pin);
	FBPTerminal** FoundTerm = Context.NetMap.Find(Net);
	FBPTerminal* Term = FoundTerm ? *FoundTerm : NULL;
	if(NULL == Term)
	{
		Term = Context.CreateLocalTerminalFromPinAutoChooseScope(Net, Context.NetNameMap->MakeValidName(Net));
		Context.NetMap.Add(Net, Term);
	}
}
void FKCHandler_DynamicCast::RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node)
{
	FNodeHandlingFunctor::RegisterNets(Context, Node);

	if (const UK2Node_DynamicCast* DynamicCastNode = Cast<UK2Node_DynamicCast>(Node))
	{
		UEdGraphPin* BoolSuccessPin = DynamicCastNode->GetBoolSuccessPin();
		// this is to support backwards compatibility (when a cast node is generating code, but has yet to be reconstructed)
		// @TODO: remove this at some point, when backwards compatibility isn't a concern
		if (BoolSuccessPin == nullptr)
		{
			// Create a term to determine if the cast was successful or not
			FBPTerminal* BoolTerm = Context.CreateLocalTerminal();
			BoolTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Boolean;
			BoolTerm->Source = Node;
			BoolTerm->Name = Context.NetNameMap->MakeValidName(Node) + TEXT("_CastSuccess");
			BoolTermMap.Add(Node, BoolTerm);
		}
	}
	
}
	void InnerAssignment(FKismetFunctionContext& Context, UEdGraphNode* Node, UEdGraphPin* VariablePin, UEdGraphPin* ValuePin)
	{
		FBPTerminal** VariableTerm = Context.NetMap.Find(VariablePin);
		if (VariableTerm == NULL)
		{
			VariableTerm = Context.NetMap.Find(FEdGraphUtilities::GetNetFromPin(VariablePin));
		}

		FBPTerminal** ValueTerm = Context.LiteralHackMap.Find(ValuePin);
		if (ValueTerm == NULL)
		{
			ValueTerm = Context.NetMap.Find(FEdGraphUtilities::GetNetFromPin(ValuePin));
		}

		if ((VariableTerm != NULL) && (ValueTerm != NULL))
		{
			FBlueprintCompiledStatement& Statement = Context.AppendStatementForNode(Node);

			Statement.Type = KCST_Assignment;
			Statement.LHS = *VariableTerm;
			Statement.RHS.Add(*ValueTerm);

			if (!(*VariableTerm)->IsTermWritable())
			{
				CompilerContext.MessageLog.Error(*LOCTEXT("WriteConst_Error", "Cannot write to const @@").ToString(), VariablePin);
			}
		}
		else
		{
			if (VariablePin != ValuePin)
			{
				CompilerContext.MessageLog.Error(*LOCTEXT("ResolveValueIntoVariablePin_Error", "Failed to resolve term @@ passed into @@").ToString(), ValuePin, VariablePin);
			}
			else
			{
				CompilerContext.MessageLog.Error(*LOCTEXT("ResolveTermPassed_Error", "Failed to resolve term passed into @@").ToString(), VariablePin);
			}
		}
	}
예제 #21
0
	virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		check(Context.Schema && Cast<UK2Node_EnumLiteral>(Node));
		FNodeHandlingFunctor::RegisterNets(Context, Node);

		UEdGraphPin* InPin = Node->FindPinChecked(UK2Node_EnumLiteral::GetEnumInputPinName());
		UEdGraphPin* Net = FEdGraphUtilities::GetNetFromPin(InPin);
		if (Context.NetMap.Find(Net) == NULL)
		{
			FBPTerminal* Term = Context.CreateLocalTerminalFromPinAutoChooseScope(Net, Context.NetNameMap->MakeValidName(Net));
			Context.NetMap.Add(Net, Term);
		}

		FBPTerminal** ValueSource = Context.NetMap.Find(Net);
		check(ValueSource && *ValueSource);
		UEdGraphPin* OutPin = Node->FindPinChecked(Context.Schema->PN_ReturnValue);
		if (ensure(Context.NetMap.Find(OutPin) == NULL))
		{
			FBPTerminal* TerminalPtr = *ValueSource; //necessary because of CheckAddress in Map::Add
			Context.NetMap.Add(OutPin, TerminalPtr);
		}
	}
    void RegisterOutputTerm(FKismetFunctionContext& Context, UScriptStruct* StructType, UEdGraphPin* Net, FBPTerminal* ContextTerm)
    {
        UProperty* BoundProperty = FindField<UProperty>(StructType, *(Net->PinName));

        if (BoundProperty != NULL)
        {
            FBPTerminal* Term = new (Context.IsEventGraph() ? Context.EventGraphLocals : Context.Locals) FBPTerminal();
            Term->CopyFromPin(Net, Net->PinName);
            Term->AssociatedVarProperty = BoundProperty;
            Context.NetMap.Add(Net, Term);
            Term->Context = ContextTerm;

            if (BoundProperty->HasAnyPropertyFlags(CPF_BlueprintReadOnly))
            {
                Term->bIsConst = true;
            }
        }
        else
        {
            CompilerContext.MessageLog.Error(TEXT("Failed to find a struct member for @@"), Net);
        }
    }
예제 #23
0
	virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		FNodeHandlingFunctor::RegisterNets(Context, Node); //handle literals

		UEdGraphPin* InPin = Node->FindPinChecked(UK2Node_CastByteToEnum::ByteInputPinName);
		UEdGraphPin* Net = FEdGraphUtilities::GetNetFromPin(InPin);
		if (Context.NetMap.Find(Net) == NULL)
		{
			FBPTerminal* Term = Context.CreateLocalTerminalFromPinAutoChooseScope(Net, Context.NetNameMap->MakeValidName(Net));
			Context.NetMap.Add(Net, Term);
		}

		FBPTerminal** ValueSource = Context.NetMap.Find(Net);
		check(ValueSource && *ValueSource);
		const UEdGraphSchema_K2* Schema = GetDefault<UEdGraphSchema_K2>();
		UEdGraphPin* OutPin = Node->FindPinChecked(Schema->PN_ReturnValue);
		if (ensure(Context.NetMap.Find(OutPin) == NULL))
		{
			// We need to copy here to avoid passing in a reference to an element inside the map. The array
			// that owns the map members could be reallocated, causing the reference to become stale.
			FBPTerminal* ValueSourceCopy = *ValueSource;
			Context.NetMap.Add(OutPin, ValueSourceCopy);
		}
	}
	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		UEdGraphPin* InputPin = NULL;
		for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex)
		{
			UEdGraphPin* Pin = Node->Pins[PinIndex];
			if (Pin && (EGPD_Input == Pin->Direction))
			{
				InputPin = Pin;
				break;
			}
		}
		UEdGraphPin *InNet = FEdGraphUtilities::GetNetFromPin(InputPin);
		UClass *Class = Cast<UClass>(StaticLoadObject(UClass::StaticClass(), NULL, TEXT("class'VaRestPlugin.VaRestJsonObject'")));
		FBPTerminal **SourceTerm = Context.NetMap.Find(InNet);
		if (SourceTerm == nullptr)
		{
			return;
		}
		for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex)
		{
			UEdGraphPin* Pin = Node->Pins[PinIndex];
			if (Pin && (EGPD_Output == Pin->Direction))
			{
				if (Pin->LinkedTo.Num() < 1)
				{
					continue;
				}
				FBPTerminal **Target = Context.NetMap.Find(Pin);
				const FString &FieldName = Pin->PinName;
				const FString &FieldType = Pin->PinType.PinCategory;
				FBPTerminal* FieldNameTerm = Context.CreateLocalTerminal(ETerminalSpecification::TS_Literal);
				FieldNameTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_String;
				FieldNameTerm->Source = Pin;
				FieldNameTerm->Name = FieldName;
				FieldNameTerm->TextLiteral = FText::FromString(FieldName);
 				FBlueprintCompiledStatement& Statement = Context.AppendStatementForNode(Node);
				FName FunctionName;
				bool bIsArray = Pin->PinType.bIsArray;
				if (FieldType == CompilerContext.GetSchema()->PC_Boolean)
				{
					FunctionName = bIsArray ? TEXT("GetBoolArrayField") : TEXT("GetBoolField");
				}
				else if (FieldType == CompilerContext.GetSchema()->PC_Float)
				{
					FunctionName = bIsArray ? TEXT("GetNumberArrayField") : TEXT("GetNumberField");
				}
				else if (FieldType == CompilerContext.GetSchema()->PC_String)
				{
					FunctionName = bIsArray ? TEXT("GetStringArrayField") : TEXT("GetStringField");
				}
				else if (FieldType == CompilerContext.GetSchema()->PC_Object)
				{
					FunctionName = bIsArray ? TEXT("GetObjectArrayField") : TEXT("GetObjectField");
				}
				else
				{
					continue;
				}
			
				UFunction *FunctionPtr = Class->FindFunctionByName(FunctionName);
				Statement.Type = KCST_CallFunction;
				Statement.FunctionToCall = FunctionPtr;
				Statement.FunctionContext = *SourceTerm;
				Statement.bIsParentContext = false;
				Statement.LHS = *Target;
				Statement.RHS.Add(FieldNameTerm);
			}
		}
	}
예제 #25
0
	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		UK2Node_Switch* SwitchNode = CastChecked<UK2Node_Switch>(Node);

		FEdGraphPinType ExpectedExecPinType;
		ExpectedExecPinType.PinCategory = UEdGraphSchema_K2::PC_Exec;

		// Make sure that the input pin is connected and valid for this block
		UEdGraphPin* ExecTriggeringPin = Context.FindRequiredPinByName(SwitchNode, UEdGraphSchema_K2::PN_Execute, EGPD_Input);
		if ((ExecTriggeringPin == NULL) || !Context.ValidatePinType(ExecTriggeringPin, ExpectedExecPinType))
		{
			CompilerContext.MessageLog.Error(*FString::Printf(*LOCTEXT("NoValidExecutionPinForSwitch_Error", "@@ must have a valid execution pin @@").ToString()), SwitchNode, ExecTriggeringPin);
			return;
		}

		// Make sure that the selection pin is connected and valid for this block
		UEdGraphPin* SelectionPin = SwitchNode->GetSelectionPin();
		if ((SelectionPin == NULL) || !Context.ValidatePinType(SelectionPin, SwitchNode->GetPinType()))
		{
			CompilerContext.MessageLog.Error(*FString::Printf(*LOCTEXT("NoValidSelectionPinForSwitch_Error", "@@ must have a valid execution pin @@").ToString()), SwitchNode, SelectionPin);
			return;
		}

		// Find the boolean intermediate result term, so we can track whether the compare was successful
		FBPTerminal* BoolTerm = BoolTermMap.FindRef(SwitchNode);

		// Generate the output impulse from this node
		UEdGraphPin* SwitchSelectionNet = FEdGraphUtilities::GetNetFromPin(SelectionPin);
		FBPTerminal* SwitchSelectionTerm = Context.NetMap.FindRef(SwitchSelectionNet);

		if ((BoolTerm != NULL) && (SwitchSelectionTerm != NULL))
		{
			UEdGraphNode* TargetNode = NULL;
			UEdGraphPin* FuncPin = SwitchNode->GetFunctionPin();
			FBPTerminal* FuncContext = Context.NetMap.FindRef(FuncPin);
			UEdGraphPin* DefaultPin = SwitchNode->GetDefaultPin();

			// Pull out function to use
			UClass* FuncClass = Cast<UClass>(FuncPin->PinType.PinSubCategoryObject.Get());
			UFunction* FunctionPtr = FindField<UFunction>(FuncClass, *FuncPin->PinName);
			check(FunctionPtr);

			// Run thru all the output pins except for the default label
			for (auto PinIt = SwitchNode->Pins.CreateIterator(); PinIt; ++PinIt)
			{
				UEdGraphPin* Pin = *PinIt;

				if ((Pin->Direction == EGPD_Output) && (Pin != DefaultPin))
				{
					// Create a term for the switch case value
					FBPTerminal* CaseValueTerm = new (Context.Literals) FBPTerminal();
					CaseValueTerm->Name = Pin->PinName;
					CaseValueTerm->Type = SelectionPin->PinType;
					CaseValueTerm->SourcePin = Pin;
					CaseValueTerm->bIsLiteral = true;

					// Call the comparison function associated with this switch node
					FBlueprintCompiledStatement& Statement = Context.AppendStatementForNode(SwitchNode);
					Statement.Type = KCST_CallFunction;
					Statement.FunctionToCall = FunctionPtr;
					Statement.FunctionContext = FuncContext;
					Statement.bIsParentContext = false;

					Statement.LHS = BoolTerm;
					Statement.RHS.Add(SwitchSelectionTerm);
					Statement.RHS.Add(CaseValueTerm);

					// Jump to output if strings are actually equal
					FBlueprintCompiledStatement& IfFailTest_SucceedAtBeingEqualGoto = Context.AppendStatementForNode(SwitchNode);
					IfFailTest_SucceedAtBeingEqualGoto.Type = KCST_GotoIfNot;
					IfFailTest_SucceedAtBeingEqualGoto.LHS = BoolTerm;

					Context.GotoFixupRequestMap.Add(&IfFailTest_SucceedAtBeingEqualGoto, Pin);
				}
			}

			// Finally output default pin
			GenerateSimpleThenGoto(Context, *SwitchNode, DefaultPin);
		}
		else
		{
			CompilerContext.MessageLog.Error(*LOCTEXT("ResolveTermPassed_Error", "Failed to resolve term passed into @@").ToString(), SelectionPin);
		}
	}
예제 #26
0
	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		// Cast the node and get all the input pins
		UK2Node_Select* SelectNode = Cast<UK2Node_Select>(Node);
		TArray<UEdGraphPin*> OptionPins;
		SelectNode->GetOptionPins(OptionPins);
		UEdGraphPin* IndexPin = SelectNode->GetIndexPin();

		// Get the kismet term for the (Condition or Index) that will determine which option to use
		UEdGraphPin* PinToTry = FEdGraphUtilities::GetNetFromPin(IndexPin);
		FBPTerminal** ConditionTerm = Context.NetMap.Find(PinToTry);

		// Get the kismet term for the return value
		UEdGraphPin* ReturnPin = SelectNode->GetReturnValuePin();
		FBPTerminal** ReturnTerm = Context.NetMap.Find(ReturnPin);

		// Don't proceed if there is no return value or there is no selection
		if (ConditionTerm != NULL && ReturnTerm != NULL)
		{
			FName ConditionalFunctionName = "";
			UClass* ConditionalFunctionClass = NULL;
			SelectNode->GetConditionalFunction(ConditionalFunctionName, &ConditionalFunctionClass);
			UFunction* ConditionFunction = FindField<UFunction>(ConditionalFunctionClass, ConditionalFunctionName);

			// Find the local boolean for use in the equality call function below (BoolTerm = result of EqualEqual_IntInt or NotEqual_BoolBool)
			FBPTerminal* BoolTerm = BoolTermMap.FindRef(SelectNode);

			// We need to keep a pointer to the previous IfNot statement so it can be linked to the next conditional statement
			FBlueprintCompiledStatement* PrevIfNotStatement = NULL;

			// Keep an array of all the unconditional goto statements so we can clean up their jumps after the noop statement is created
			TArray<FBlueprintCompiledStatement*> GotoStatementList;

			// Loop through all the options
			for (int32 OptionIdx = 0; OptionIdx < OptionPins.Num(); OptionIdx++)
			{
				// Create a CallFunction statement with the condition function from the Select class
				FBlueprintCompiledStatement& Statement = Context.AppendStatementForNode(Node);
				Statement.Type = KCST_CallFunction;
				Statement.FunctionToCall = ConditionFunction;
				Statement.FunctionContext = NULL;
				Statement.bIsParentContext = false;
				// BoolTerm will be the return value of the condition statement
				Statement.LHS = BoolTerm;
				// The condition passed into the Select node
				Statement.RHS.Add(*ConditionTerm);
				// Create a local int for use in the equality call function below (LiteralTerm = the right hand side of the EqualEqual_IntInt or NotEqual_BoolBool statement)
				FBPTerminal* LiteralTerm = Context.CreateLocalTerminal(ETerminalSpecification::TS_Literal);
				LiteralTerm->bIsLiteral = true;
				LiteralTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Int;
				LiteralTerm->Name = FString::Printf(TEXT("%d"), OptionIdx);
				Statement.RHS.Add(LiteralTerm);
				// If there is a previous IfNot statement, hook this one to that one for jumping
				if (PrevIfNotStatement)
				{
					Statement.bIsJumpTarget = true;
					PrevIfNotStatement->TargetLabel = &Statement;
				}

				// Create a GotoIfNot statement using the BoolTerm from above as the condition
				FBlueprintCompiledStatement* IfNotStatement = &Context.AppendStatementForNode(Node);
				IfNotStatement->Type = KCST_GotoIfNot;
				IfNotStatement->LHS = BoolTerm;

				// Create an assignment statement
				FBlueprintCompiledStatement& AssignStatement = Context.AppendStatementForNode(Node);
				AssignStatement.Type = KCST_Assignment;
				AssignStatement.LHS = *ReturnTerm;
				// Get the kismet term from the option pin
				UEdGraphPin* OptionPinToTry = FEdGraphUtilities::GetNetFromPin(OptionPins[OptionIdx]);
				FBPTerminal** OptionTerm = Context.NetMap.Find(OptionPinToTry);
				if (!OptionTerm)
				{
					Context.MessageLog.Error(*LOCTEXT("Error_UnregisterOptionPin", "Unregister option pin @@").ToString(), OptionPins[OptionIdx]);
					return;
				}
				AssignStatement.RHS.Add(*OptionTerm);

				// Create an unconditional goto to exit the node
				FBlueprintCompiledStatement& GotoStatement = Context.AppendStatementForNode(Node);
				GotoStatement.Type = KCST_UnconditionalGoto;
				GotoStatementList.Add(&GotoStatement);

				// If this is the last IfNot statement, hook the jump to an error message
				if (OptionIdx == OptionPins.Num() - 1)
				{
					// Create a CallFunction statement for doing a print string of our error message
					FBlueprintCompiledStatement& PrintStatement = Context.AppendStatementForNode(Node);
					PrintStatement.Type = KCST_CallFunction;
					PrintStatement.bIsJumpTarget = true;
					FName PrintStringFunctionName = "";
					UClass* PrintStringFunctionClass = NULL;
					SelectNode->GetPrintStringFunction(PrintStringFunctionName, &PrintStringFunctionClass);
					UFunction* PrintFunction = FindField<UFunction>(PrintStringFunctionClass, PrintStringFunctionName);
					PrintStatement.FunctionToCall = PrintFunction;
					PrintStatement.FunctionContext = NULL;
					PrintStatement.bIsParentContext = false;

					// Create a local int for use in the equality call function below (LiteralTerm = the right hand side of the EqualEqual_IntInt or NotEqual_BoolBool statement)
					FBPTerminal* LiteralStringTerm = Context.CreateLocalTerminal(ETerminalSpecification::TS_Literal);
					LiteralStringTerm->bIsLiteral = true;
					LiteralStringTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_String;

					FString SelectionNodeType(TEXT("NONE"));
					if (IndexPin)
					{
						UEnum* EnumObject = Cast<UEnum>(IndexPin->PinType.PinSubCategoryObject.Get());
						if (EnumObject != NULL)
						{
							SelectionNodeType = EnumObject->GetName();
						}
						else
						{
							// Not an enum, so just use the basic type
							SelectionNodeType = IndexPin->PinType.PinCategory;
						}
					}

					const UEdGraph* OwningGraph = Context.MessageLog.FindSourceObjectTypeChecked<UEdGraph>( SelectNode->GetGraph() );
					LiteralStringTerm->Name =
						FString::Printf(*LOCTEXT("SelectNodeIndexWarning", "Graph %s: Selection Node of type %s failed! Out of bounds indexing of the options. There are only %d options available.").ToString(),
						(OwningGraph) ? *OwningGraph->GetFullName() : TEXT("NONE"),
						*SelectionNodeType,
						OptionPins.Num());
					PrintStatement.RHS.Add(LiteralStringTerm);

					// Hook the IfNot statement's jump target to this statement
					IfNotStatement->TargetLabel = &PrintStatement;
				}

				PrevIfNotStatement = IfNotStatement;
			}

			// Create a noop to jump to so the unconditional goto statements can exit the node after successful assignment
			FBlueprintCompiledStatement& NopStatement = Context.AppendStatementForNode(Node);
			NopStatement.Type = KCST_Nop;
			NopStatement.bIsJumpTarget = true;
			// Loop through the unconditional goto statements and fix their jump targets
			for (auto It = GotoStatementList.CreateConstIterator(); It; It++)
			{
				(*It)->TargetLabel = &NopStatement;
			}
		}
	}
void FKCHandler_DynamicCast::Compile(FKismetFunctionContext& Context, UEdGraphNode* Node)
{
	const UK2Node_DynamicCast* DynamicCastNode = CastChecked<UK2Node_DynamicCast>(Node);

	if (DynamicCastNode->TargetType == NULL)
	{
		CompilerContext.MessageLog.Error(*LOCTEXT("BadCastNoTargetType_Error", "Node @@ has an invalid target type, please delete and recreate it").ToString(), Node);
	}

	// Self Pin
	UEdGraphPin* SourceObjectPin = DynamicCastNode->GetCastSourcePin();
	UEdGraphPin* PinToTry = FEdGraphUtilities::GetNetFromPin(SourceObjectPin);
	FBPTerminal** ObjectToCast = Context.NetMap.Find(PinToTry);

	if (!ObjectToCast)
	{
		ObjectToCast = Context.LiteralHackMap.Find(PinToTry);

		if (!ObjectToCast || !(*ObjectToCast))
		{
			CompilerContext.MessageLog.Error(*LOCTEXT("InvalidConnectionOnNode_Error", "Node @@ has an invalid connection on @@").ToString(), Node, SourceObjectPin);
			return;
		}
	}

	// Output pin
	const UEdGraphPin* CastOutputPin = DynamicCastNode->GetCastResultPin();
	if( !CastOutputPin )
	{
		CompilerContext.MessageLog.Error(*LOCTEXT("InvalidDynamicCastClass_Error", "Node @@ has an invalid target class").ToString(), Node);
		return;
	}

	FBPTerminal** CastResultTerm = Context.NetMap.Find(CastOutputPin);
	if (!CastResultTerm || !(*CastResultTerm))
	{
		CompilerContext.MessageLog.Error(*LOCTEXT("InvalidDynamicCastClass_CompilerError", "Node @@ has an invalid target class. (Inner compiler error?)").ToString(), Node);
		return;
	}

	// Create a literal term from the class specified in the node
	FBPTerminal* ClassTerm = Context.CreateLocalTerminal(ETerminalSpecification::TS_Literal);
	ClassTerm->Name = DynamicCastNode->TargetType->GetName();
	ClassTerm->bIsLiteral = true;
	ClassTerm->Source = Node;
	ClassTerm->ObjectLiteral = DynamicCastNode->TargetType;
	ClassTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Class;

	UClass const* const InputObjClass  = Cast<UClass>((*ObjectToCast)->Type.PinSubCategoryObject.Get());
	UClass const* const OutputObjClass = Cast<UClass>((*CastResultTerm)->Type.PinSubCategoryObject.Get());

	const bool bIsOutputInterface = ((OutputObjClass != NULL) && OutputObjClass->HasAnyClassFlags(CLASS_Interface));
	const bool bIsInputInterface  = ((InputObjClass != NULL) && InputObjClass->HasAnyClassFlags(CLASS_Interface));

	EKismetCompiledStatementType CastOpType = KCST_DynamicCast;
	if (bIsInputInterface)
	{
		if (bIsOutputInterface)
		{
			CastOpType = KCST_CrossInterfaceCast;
		}
		else
		{
			CastOpType = KCST_CastInterfaceToObj;
		}
	}
	else if (bIsOutputInterface)
	{
		CastOpType = KCST_CastObjToInterface;
	}

	if (KCST_MetaCast == CastType)
	{
		if (bIsInputInterface || bIsOutputInterface)
		{
			CompilerContext.MessageLog.Error(*LOCTEXT("InvalidClassDynamicCastClass_Error", "Node @@ has an invalid target class. Interfaces are not supported.").ToString(), Node);
			return;
		}
		CastOpType = KCST_MetaCast;
	}

	// Cast Statement
	FBlueprintCompiledStatement& CastStatement = Context.AppendStatementForNode(Node);
	CastStatement.Type = CastOpType;
	CastStatement.LHS = *CastResultTerm;
	CastStatement.RHS.Add(ClassTerm);
	CastStatement.RHS.Add(*ObjectToCast);

	FBPTerminal** BoolSuccessTerm = nullptr;
	if (UEdGraphPin* BoolSuccessPin = DynamicCastNode->GetBoolSuccessPin())
	{
		BoolSuccessTerm = Context.NetMap.Find(BoolSuccessPin);
	}
	else
	{
		BoolSuccessTerm = BoolTermMap.Find(DynamicCastNode);
	}	
	check(BoolSuccessTerm != nullptr);

	// Check result of cast statement
	FBlueprintCompiledStatement& CheckResultStatement = Context.AppendStatementForNode(Node);
	CheckResultStatement.Type = KCST_ObjectToBool;
	CheckResultStatement.LHS  = *BoolSuccessTerm;
	CheckResultStatement.RHS.Add(*CastResultTerm);

	UEdGraphPin* SuccessExecPin = DynamicCastNode->GetValidCastPin();
	bool const bIsPureCast = (SuccessExecPin == nullptr);
	if (!bIsPureCast)
	{
		UEdGraphPin* FailurePin = DynamicCastNode->GetInvalidCastPin();
		check(FailurePin != nullptr);
		// Failure condition...skip to the failed output
		FBlueprintCompiledStatement& FailCastGoto = Context.AppendStatementForNode(Node);
		FailCastGoto.Type = KCST_GotoIfNot;
		FailCastGoto.LHS  = *BoolSuccessTerm;
		Context.GotoFixupRequestMap.Add(&FailCastGoto, FailurePin);

		// Successful cast...hit the success output node
		FBlueprintCompiledStatement& SuccessCastGoto = Context.AppendStatementForNode(Node);
		SuccessCastGoto.Type = KCST_UnconditionalGoto;
		SuccessCastGoto.LHS  = *BoolSuccessTerm;
		Context.GotoFixupRequestMap.Add(&SuccessCastGoto, SuccessExecPin);
	}
}
	void RegisterOutputTerm(FKismetFunctionContext& Context, UEdGraphPin* OutputPin, FBPTerminal* ContextTerm)
	{
		FBPTerminal *Term = Context.CreateLocalTerminalFromPinAutoChooseScope(OutputPin, OutputPin->PinName);
		Context.NetMap.Add(OutputPin, Term);
	}
void FKCHandler_CreateDelegate::RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node)
{
	UK2Node_CreateDelegate * DelegateNode = CastChecked<UK2Node_CreateDelegate>(Node);
	check(NULL != DelegateNode);

	const FName DelegateFunctionName = DelegateNode->GetFunctionName();
	if(DelegateFunctionName == NAME_None)
	{
		CompilerContext.MessageLog.Error(*LOCTEXT("NoDelegateFunctionName", "No delegate function name @@").ToString(), DelegateNode);
		return;
	}

	if(!DelegateNode->GetDelegateSignature())
	{
		const FString ErrorStr = FString::Printf(
			*LOCTEXT("NoDelegateFunction", "No delegate function '%' @@").ToString(),
			*DelegateFunctionName.ToString());
		CompilerContext.MessageLog.Error(*ErrorStr, DelegateNode);
		return;
	}

	{
		UEdGraphPin* InputPin = DelegateNode->GetObjectInPin();
		check(NULL != InputPin);

		UEdGraphPin* Net = FEdGraphUtilities::GetNetFromPin(InputPin);

		FBPTerminal** FoundTerm = Context.NetMap.Find(Net);
		FBPTerminal* InputObjTerm = FoundTerm ? *FoundTerm : NULL;
		if(NULL == InputObjTerm)
		{
			if (InputPin->LinkedTo.Num() == 0)
			{
				InputObjTerm = Context.CreateLocalTerminal(ETerminalSpecification::TS_Literal);
				InputObjTerm->Name = Context.NetNameMap->MakeValidName(Net);
				InputObjTerm->Type.PinSubCategory = CompilerContext.GetSchema()->PN_Self;
			}
			else
			{
				InputObjTerm = Context.CreateLocalTerminalFromPinAutoChooseScope(Net, Context.NetNameMap->MakeValidName(Net));
			}

			Context.NetMap.Add(Net, InputObjTerm);
		}
	}

	{
		UEdGraphPin* OutPin = DelegateNode->GetDelegateOutPin();
		check(NULL != OutPin);
		if(!OutPin->LinkedTo.Num())
		{
			CompilerContext.MessageLog.Error(*LOCTEXT("NoDelegateSignature", "No delegate signature @@").ToString(), DelegateNode);
			return;
		}
		UEdGraphPin* Net = FEdGraphUtilities::GetNetFromPin(OutPin);

		FBPTerminal** FoundTerm = Context.NetMap.Find(Net);
		FBPTerminal* OutDelegateTerm = FoundTerm ? *FoundTerm : NULL;
		if(NULL == OutDelegateTerm)
		{
			OutDelegateTerm = Context.CreateLocalTerminalFromPinAutoChooseScope(Net, Context.NetNameMap->MakeValidName(Net));
			if (NULL == FMemberReference::ResolveSimpleMemberReference<UFunction>(OutDelegateTerm->Type.PinSubCategoryMemberReference))
			{
				FMemberReference::FillSimpleMemberReference<UFunction>(DelegateNode->GetDelegateSignature(), OutDelegateTerm->Type.PinSubCategoryMemberReference);
			}
			if (NULL == FMemberReference::ResolveSimpleMemberReference<UFunction>(OutDelegateTerm->Type.PinSubCategoryMemberReference))
			{
				CompilerContext.MessageLog.Error(*LOCTEXT("UnconnectedDelegateSig", "Event Dispatcher has no signature @@").ToString(), OutPin);
				return;
			}
			Context.NetMap.Add(Net, OutDelegateTerm);
		}
	}
}
void FKCHandler_MathExpression::RegisterNet(FKismetFunctionContext& Context, UEdGraphPin* Net) 
{
	FBPTerminal* Term = Context.CreateLocalTerminalFromPinAutoChooseScope(Net, Context.NetNameMap->MakeValidName(Net));
	Context.NetMap.Add(Net, Term);
}