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