FKCHandler_Switch is where the node compiles:
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(*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(*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))
{
UEdGraphPin* FuncPin = SwitchNode->GetFunctionPin();
FBPTerminal* FuncContext = Context.NetMap.FindRef(FuncPin);
UEdGraphPin* DefaultPin = SwitchNode->GetDefaultPin();
// We don't need to generate if checks if there are no connections to it if there is no default pin or if the default pin is not linked
// If there is a default pin that is linked then it would fall through to that default if we do not generate the cases
const bool bCanSkipUnlinkedCase = (DefaultPin == nullptr || DefaultPin->LinkedTo.Num() == 0);
// Pull out function to use
UClass* FuncClass = Cast<UClass>(FuncPin->PinType.PinSubCategoryObject.Get());
UFunction* FunctionPtr = FindUField<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) && (!bCanSkipUnlinkedCase || Pin->LinkedTo.Num() > 0))
{
// Create a term for the switch case value
FBPTerminal* CaseValueTerm = new FBPTerminal();
Context.Literals.Add(CaseValueTerm);
CaseValueTerm->Name = SwitchNode->GetExportTextForPin(Pin);
CaseValueTerm->Type = SwitchNode->GetInnerCaseType();
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);
}
}