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; } } }
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); } }
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); } } } }
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); } } }
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"); } }
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); }
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); } } }
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); } } }
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); } }
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); } } }
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); } }
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); }