void UK2Node_SpawnActor::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) { Super::ExpandNode(CompilerContext, SourceGraph); static FName BeginSpawningBlueprintFuncName = GET_FUNCTION_NAME_CHECKED(UGameplayStatics, BeginSpawningActorFromBlueprint); static FString BlueprintParamName = FString(TEXT("Blueprint")); static FString WorldContextParamName = FString(TEXT("WorldContextObject")); static FName FinishSpawningFuncName = GET_FUNCTION_NAME_CHECKED(UGameplayStatics, FinishSpawningActor); static FString ActorParamName = FString(TEXT("Actor")); static FString TransformParamName = FString(TEXT("SpawnTransform")); static FString NoCollisionFailParamName = FString(TEXT("bNoCollisionFail")); static FString ObjectParamName = FString(TEXT("Object")); static FString ValueParamName = FString(TEXT("Value")); static FString PropertyNameParamName = FString(TEXT("PropertyName")); const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema(); UEdGraphPin* SpawnNodeExec = GetExecPin(); UEdGraphPin* SpawnNodeTransform = GetSpawnTransformPin(); UEdGraphPin* SpawnNodeNoCollisionFail = GetNoCollisionFailPin(); UEdGraphPin* SpawnWorldContextPin = GetWorldContextPin(); UEdGraphPin* SpawnBlueprintPin = GetBlueprintPin(); UEdGraphPin* SpawnNodeThen = GetThenPin(); UEdGraphPin* SpawnNodeResult = GetResultPin(); UBlueprint* SpawnBlueprint = NULL; if(SpawnBlueprintPin != NULL) { SpawnBlueprint = Cast<UBlueprint>(SpawnBlueprintPin->DefaultObject); } if(NULL == SpawnBlueprint) { CompilerContext.MessageLog.Error(*LOCTEXT("SpawnActorNodeMissingBlueprint_Error", "Spawn node @@ must have a blueprint specified.").ToString(), this); // we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings BreakAllNodeLinks(); return; } if(0 == SpawnBlueprintPin->LinkedTo.Num()) { if(NULL == SpawnBlueprint) { CompilerContext.MessageLog.Error(*LOCTEXT("SpawnActorNodeMissingBlueprint_Error", "Spawn node @@ must have a blueprint specified.").ToString(), this); // we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings BreakAllNodeLinks(); return; } // check if default blueprint is based on Actor const UClass* GeneratedClass = SpawnBlueprint->GeneratedClass; bool bInvalidBase = GeneratedClass && !GeneratedClass->IsChildOf(AActor::StaticClass()); const UClass* SkeletonGeneratedClass = Cast<UClass>(SpawnBlueprint->SkeletonGeneratedClass); bInvalidBase |= SkeletonGeneratedClass && !SkeletonGeneratedClass->IsChildOf(AActor::StaticClass()); if(bInvalidBase) { CompilerContext.MessageLog.Error(*LOCTEXT("SpawnActorNodeInvalidBlueprint_Error", "Spawn node @@ must have a blueprint based on Actor specified.").ToString(), this); // we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings BreakAllNodeLinks(); return; } } ////////////////////////////////////////////////////////////////////////// // create 'begin spawn' call node UK2Node_CallFunction* CallBeginSpawnNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph); CallBeginSpawnNode->FunctionReference.SetExternalMember(BeginSpawningBlueprintFuncName, UGameplayStatics::StaticClass()); CallBeginSpawnNode->AllocateDefaultPins(); UEdGraphPin* CallBeginExec = CallBeginSpawnNode->GetExecPin(); UEdGraphPin* CallBeginWorldContextPin = CallBeginSpawnNode->FindPinChecked(WorldContextParamName); UEdGraphPin* CallBeginBlueprintPin = CallBeginSpawnNode->FindPinChecked(BlueprintParamName); UEdGraphPin* CallBeginTransform = CallBeginSpawnNode->FindPinChecked(TransformParamName); UEdGraphPin* CallBeginNoCollisionFail = CallBeginSpawnNode->FindPinChecked(NoCollisionFailParamName); UEdGraphPin* CallBeginResult = CallBeginSpawnNode->GetReturnValuePin(); // Move 'exec' connection from spawn node to 'begin spawn' CompilerContext.MovePinLinksToIntermediate(*SpawnNodeExec, *CallBeginExec); if(SpawnBlueprintPin->LinkedTo.Num() > 0) { // Copy the 'blueprint' connection from the spawn node to 'begin spawn' CompilerContext.MovePinLinksToIntermediate(*SpawnBlueprintPin, *CallBeginBlueprintPin); } else { // Copy blueprint literal onto begin spawn call CallBeginBlueprintPin->DefaultObject = SpawnBlueprint; } // Copy the world context connection from the spawn node to 'begin spawn' if necessary if (SpawnWorldContextPin) { CompilerContext.MovePinLinksToIntermediate(*SpawnWorldContextPin, *CallBeginWorldContextPin); } // Copy the 'transform' connection from the spawn node to 'begin spawn' CompilerContext.MovePinLinksToIntermediate(*SpawnNodeTransform, *CallBeginTransform); // Copy the 'bNoCollisionFail' connection from the spawn node to 'begin spawn' CompilerContext.MovePinLinksToIntermediate(*SpawnNodeNoCollisionFail, *CallBeginNoCollisionFail); ////////////////////////////////////////////////////////////////////////// // create 'finish spawn' call node UK2Node_CallFunction* CallFinishSpawnNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph); CallFinishSpawnNode->FunctionReference.SetExternalMember(FinishSpawningFuncName, UGameplayStatics::StaticClass()); CallFinishSpawnNode->AllocateDefaultPins(); UEdGraphPin* CallFinishExec = CallFinishSpawnNode->GetExecPin(); UEdGraphPin* CallFinishThen = CallFinishSpawnNode->GetThenPin(); UEdGraphPin* CallFinishActor = CallFinishSpawnNode->FindPinChecked(ActorParamName); UEdGraphPin* CallFinishTransform = CallFinishSpawnNode->FindPinChecked(TransformParamName); UEdGraphPin* CallFinishResult = CallFinishSpawnNode->GetReturnValuePin(); // Move 'then' connection from spawn node to 'finish spawn' CompilerContext.MovePinLinksToIntermediate(*SpawnNodeThen, *CallFinishThen); // Copy transform connection CompilerContext.CopyPinLinksToIntermediate(*CallBeginTransform, *CallFinishTransform); // Connect output actor from 'begin' to 'finish' CallBeginResult->MakeLinkTo(CallFinishActor); // Move result connection from spawn node to 'finish spawn' CallFinishResult->PinType = SpawnNodeResult->PinType; // Copy type so it uses the right actor subclass CompilerContext.MovePinLinksToIntermediate(*SpawnNodeResult, *CallFinishResult); ////////////////////////////////////////////////////////////////////////// // create 'set var' nodes // Get 'result' pin from 'begin spawn', this is the actual actor we want to set properties on UK2Node_CallFunction* LastNode = CallBeginSpawnNode; // Create 'set var by name' nodes and hook them up for(int32 PinIdx=0; PinIdx < Pins.Num(); PinIdx++) { // Only create 'set param by name' node if this pin is linked to something UEdGraphPin* SpawnVarPin = Pins[PinIdx]; if(SpawnVarPin->LinkedTo.Num() > 0) { UFunction* SetByNameFunction = Schema->FindSetVariableByNameFunction(SpawnVarPin->PinType); if(SetByNameFunction) { UK2Node_CallFunction* SetVarNode = NULL; if(SpawnVarPin->PinType.bIsArray) { SetVarNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallArrayFunction>(this, SourceGraph); } else { SetVarNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph); } SetVarNode->SetFromFunction(SetByNameFunction); SetVarNode->AllocateDefaultPins(); // Connect this node into the exec chain UEdGraphPin* LastThen = LastNode->GetThenPin(); UEdGraphPin* SetVarExec = SetVarNode->GetExecPin(); LastThen->MakeLinkTo(SetVarExec); // Connect the new actor to the 'object' pin UEdGraphPin* ObjectPin = SetVarNode->FindPinChecked(ObjectParamName); CallBeginResult->MakeLinkTo(ObjectPin); // Fill in literal for 'property name' pin - name of pin is property name UEdGraphPin* PropertyNamePin = SetVarNode->FindPinChecked(PropertyNameParamName); PropertyNamePin->DefaultValue = SpawnVarPin->PinName; // Move connection from the variable pin on the spawn node to the 'value' pin UEdGraphPin* ValuePin = SetVarNode->FindPinChecked(ValueParamName); CompilerContext.MovePinLinksToIntermediate(*SpawnVarPin, *ValuePin); if(SpawnVarPin->PinType.bIsArray) { SetVarNode->PinConnectionListChanged(ValuePin); } // Update 'last node in sequence' var LastNode = SetVarNode; } } } // Make exec connection between 'then' on last node and 'finish' UEdGraphPin* LastThen = LastNode->GetThenPin(); LastThen->MakeLinkTo(CallFinishExec); // Break any links to the expanded node BreakAllNodeLinks(); }
void UK2Node_GetEnumeratorName::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) { Super::ExpandNode(CompilerContext, SourceGraph); UEnum* Enum = GetEnum(); if(NULL == Enum) { CompilerContext.MessageLog.Error(*FString::Printf(*NSLOCTEXT("K2Node", "GetEnumeratorNam_Error_MustHaveValidName", "@@ must have a valid enum defined").ToString()), this); return; } const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema(); const UFunction* Function = UKismetNodeHelperLibrary::StaticClass()->FindFunctionByName( GetFunctionName() ); check(NULL != Function); UK2Node_CallFunction* CallGetName = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph); CallGetName->SetFromFunction(Function); CallGetName->AllocateDefaultPins(); check(CallGetName->IsNodePure()); //OPUTPUT PIN UEdGraphPin* OrgReturnPin = FindPinChecked(Schema->PN_ReturnValue); UEdGraphPin* NewReturnPin = CallGetName->GetReturnValuePin(); check(NULL != NewReturnPin); CompilerContext.MovePinLinksToIntermediate(*OrgReturnPin, *NewReturnPin); //ENUM PIN UEdGraphPin* EnumPin = CallGetName->FindPinChecked(TEXT("Enum")); Schema->TrySetDefaultObject(*EnumPin, Enum); check(EnumPin->DefaultObject == Enum); //VALUE PIN UEdGraphPin* OrgInputPin = FindPinChecked(EnumeratorPinName); UEdGraphPin* IndexPin = CallGetName->FindPinChecked(TEXT("EnumeratorValue")); check(EGPD_Input == IndexPin->Direction && Schema->PC_Byte == IndexPin->PinType.PinCategory); CompilerContext.MovePinLinksToIntermediate(*OrgInputPin, *IndexPin); if (!IndexPin->LinkedTo.Num()) { //MAKE LITERAL BYTE FROM LITERAL ENUM const FString EnumLiteral = IndexPin->GetDefaultAsString(); const int32 NumericValue = Enum->GetValueByName(*EnumLiteral); if (NumericValue == INDEX_NONE) { CompilerContext.MessageLog.Error(*FString::Printf(*NSLOCTEXT("K2Node", "GetEnumeratorNam_Error_InvalidName", "@@ has invalid enum value '%s'").ToString(), *EnumLiteral), this); return; } const FString DefaultByteValue = FString::FromInt(NumericValue); // LITERAL BYTE FUNCTION const FName FunctionName = GET_FUNCTION_NAME_CHECKED(UKismetSystemLibrary, MakeLiteralByte); UK2Node_CallFunction* MakeLiteralByte = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph); MakeLiteralByte->SetFromFunction(UKismetSystemLibrary::StaticClass()->FindFunctionByName(FunctionName)); MakeLiteralByte->AllocateDefaultPins(); UEdGraphPin* MakeLiteralByteReturnPin = MakeLiteralByte->FindPinChecked(Schema->PN_ReturnValue); Schema->TryCreateConnection(MakeLiteralByteReturnPin, IndexPin); UEdGraphPin* MakeLiteralByteInputPin = MakeLiteralByte->FindPinChecked(TEXT("Value")); MakeLiteralByteInputPin->DefaultValue = DefaultByteValue; } BreakAllNodeLinks(); }
//amd this is where magic really happens. This will expand node for our custom object, with properties //which are set as EditAwnywhere and meta=(ExposeOnSpawn), or equivalent in blueprint. void UBPNode_CreateItemData::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) { Super::ExpandNode(CompilerContext, SourceGraph); //look for static function in BlueprintFunctionLibrary //In this class and of this name static FName Create_FunctionName = GET_FUNCTION_NAME_CHECKED(UGISBlueprintFunctionLibrary, CreateItem); //with these inputs (as a Side note, these should be probabaly FName not FString) static FString WorldContextObject_ParamName = FString(TEXT("WorldContextObject")); static FString WidgetType_ParamName = FString(TEXT("ItemClass")); static FString OwningPlayer_ParamName = FString(TEXT("OwningPlayer")); //get pointer to self; UBPNode_CreateItemData* CreateItemDataNode = this; //get pointers to default pins. //Exec pins are those big arrows, connected with thick white lines. UEdGraphPin* SpawnNodeExec = CreateItemDataNode->GetExecPin(); //gets world context pin from our static function UEdGraphPin* SpawnWorldContextPin = CreateItemDataNode->GetWorldContextPin(); //the same as above UEdGraphPin* SpawnOwningPlayerPin = CreateItemDataNode->GetOwningPlayerPin(); //get class pin which is used to determine which class to spawn. UEdGraphPin* SpawnClassPin = CreateItemDataNode->GetClassPin(); //then pin is the same as exec pin, just on the other side (the out arrow). UEdGraphPin* SpawnNodeThen = CreateItemDataNode->GetThenPin(); //result pin, which will output our spawned object. UEdGraphPin* SpawnNodeResult = CreateItemDataNode->GetResultPin(); UClass* SpawnClass = (SpawnClassPin != NULL) ? Cast<UClass>(SpawnClassPin->DefaultObject) : NULL; if ((0 == SpawnClassPin->LinkedTo.Num()) && (NULL == SpawnClass)) { CompilerContext.MessageLog.Error(*LOCTEXT("CreateItemDAtaNodeMissingClass_Error", "Spawn node @@ must have a class specified.").ToString(), CreateItemDataNode); // we break exec links so this is the only error we get, don't want the CreateItemData node being considered and giving 'unexpected node' type warnings CreateItemDataNode->BreakAllNodeLinks(); return; } ////////////////////////////////////////////////////////////////////////// // create 'UWidgetBlueprintLibrary::Create' call node UK2Node_CallFunction* CallCreateNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(CreateItemDataNode, SourceGraph); CallCreateNode->FunctionReference.SetExternalMember(Create_FunctionName, UBPNode_CreateItemData::StaticClass()); CallCreateNode->AllocateDefaultPins(); //allocate nodes for created widget. UEdGraphPin* CallCreateExec = CallCreateNode->GetExecPin(); UEdGraphPin* CallCreateWorldContextPin = CallCreateNode->FindPinChecked(WorldContextObject_ParamName); UEdGraphPin* CallCreateWidgetTypePin = CallCreateNode->FindPinChecked(WidgetType_ParamName); UEdGraphPin* CallCreateOwningPlayerPin = CallCreateNode->FindPinChecked(OwningPlayer_ParamName); UEdGraphPin* CallCreateResult = CallCreateNode->GetReturnValuePin(); // Move 'exec' connection from create widget node to 'UWidgetBlueprintLibrary::Create' CompilerContext.MovePinLinksToIntermediate(*SpawnNodeExec, *CallCreateExec); if (SpawnClassPin->LinkedTo.Num() > 0) { // Copy the 'blueprint' connection from the spawn node to 'UWidgetBlueprintLibrary::Create' CompilerContext.MovePinLinksToIntermediate(*SpawnClassPin, *CallCreateWidgetTypePin); } else { // Copy blueprint literal onto 'UWidgetBlueprintLibrary::Create' call CallCreateWidgetTypePin->DefaultObject = SpawnClass; } // Copy the world context connection from the spawn node to 'UWidgetBlueprintLibrary::Create' if necessary if (SpawnWorldContextPin) { CompilerContext.MovePinLinksToIntermediate(*SpawnWorldContextPin, *CallCreateWorldContextPin); } // Copy the 'Owning Player' connection from the spawn node to 'UWidgetBlueprintLibrary::Create' CompilerContext.MovePinLinksToIntermediate(*SpawnOwningPlayerPin, *CallCreateOwningPlayerPin); // Move result connection from spawn node to 'UWidgetBlueprintLibrary::Create' CallCreateResult->PinType = SpawnNodeResult->PinType; // Copy type so it uses the right actor subclass CompilerContext.MovePinLinksToIntermediate(*SpawnNodeResult, *CallCreateResult); ////////////////////////////////////////////////////////////////////////// // create 'set var' nodes // Get 'result' pin from 'begin spawn', this is the actual actor we want to set properties on UEdGraphPin* LastThen = FKismetCompilerUtilities::GenerateAssignmentNodes(CompilerContext, SourceGraph, CallCreateNode, CreateItemDataNode, CallCreateResult, GetClassToSpawn()); // Move 'then' connection from create widget node to the last 'then' CompilerContext.MovePinLinksToIntermediate(*SpawnNodeThen, *LastThen); // Break any links to the expanded node CreateItemDataNode->BreakAllNodeLinks(); }
void UK2Node_SpawnActorFromClass::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) { Super::ExpandNode(CompilerContext, SourceGraph); static FName BeginSpawningBlueprintFuncName = GET_FUNCTION_NAME_CHECKED(UGameplayStatics, BeginSpawningActorFromClass); static FString ActorClassParamName = FString(TEXT("ActorClass")); static FString WorldContextParamName = FString(TEXT("WorldContextObject")); static FName FinishSpawningFuncName = GET_FUNCTION_NAME_CHECKED(UGameplayStatics, FinishSpawningActor); static FString ActorParamName = FString(TEXT("Actor")); static FString TransformParamName = FString(TEXT("SpawnTransform")); static FString NoCollisionFailParamName = FString(TEXT("bNoCollisionFail")); static FString OwnerParamName = FString(TEXT("Owner")); static FString ObjectParamName = FString(TEXT("Object")); static FString ValueParamName = FString(TEXT("Value")); static FString PropertyNameParamName = FString(TEXT("PropertyName")); UK2Node_SpawnActorFromClass* SpawnNode = this; UEdGraphPin* SpawnNodeExec = SpawnNode->GetExecPin(); UEdGraphPin* SpawnNodeTransform = SpawnNode->GetSpawnTransformPin(); UEdGraphPin* SpawnNodeNoCollisionFail = GetNoCollisionFailPin(); UEdGraphPin* SpawnWorldContextPin = SpawnNode->GetWorldContextPin(); UEdGraphPin* SpawnClassPin = SpawnNode->GetClassPin(); UEdGraphPin* SpawnNodeOwnerPin = SpawnNode->GetOwnerPin(); UEdGraphPin* SpawnNodeThen = SpawnNode->GetThenPin(); UEdGraphPin* SpawnNodeResult = SpawnNode->GetResultPin(); UClass* SpawnClass = (SpawnClassPin != NULL) ? Cast<UClass>(SpawnClassPin->DefaultObject) : NULL; if((0 == SpawnClassPin->LinkedTo.Num()) && (NULL == SpawnClass)) { CompilerContext.MessageLog.Error(*LOCTEXT("SpawnActorNodeMissingClass_Error", "Spawn node @@ must have a class specified.").ToString(), SpawnNode); // we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings SpawnNode->BreakAllNodeLinks(); return; } ////////////////////////////////////////////////////////////////////////// // create 'begin spawn' call node UK2Node_CallFunction* CallBeginSpawnNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(SpawnNode, SourceGraph); CallBeginSpawnNode->FunctionReference.SetExternalMember(BeginSpawningBlueprintFuncName, UGameplayStatics::StaticClass()); CallBeginSpawnNode->AllocateDefaultPins(); UEdGraphPin* CallBeginExec = CallBeginSpawnNode->GetExecPin(); UEdGraphPin* CallBeginWorldContextPin = CallBeginSpawnNode->FindPinChecked(WorldContextParamName); UEdGraphPin* CallBeginActorClassPin = CallBeginSpawnNode->FindPinChecked(ActorClassParamName); UEdGraphPin* CallBeginTransform = CallBeginSpawnNode->FindPinChecked(TransformParamName); UEdGraphPin* CallBeginNoCollisionFail = CallBeginSpawnNode->FindPinChecked(NoCollisionFailParamName); UEdGraphPin* CallBeginOwnerPin = CallBeginSpawnNode->FindPinChecked(FK2Node_SpawnActorFromClassHelper::OwnerPinName); UEdGraphPin* CallBeginResult = CallBeginSpawnNode->GetReturnValuePin(); // Move 'exec' connection from spawn node to 'begin spawn' CompilerContext.MovePinLinksToIntermediate(*SpawnNodeExec, *CallBeginExec); if(SpawnClassPin->LinkedTo.Num() > 0) { // Copy the 'blueprint' connection from the spawn node to 'begin spawn' CompilerContext.MovePinLinksToIntermediate(*SpawnClassPin, *CallBeginActorClassPin); } else { // Copy blueprint literal onto begin spawn call CallBeginActorClassPin->DefaultObject = SpawnClass; } // Copy the world context connection from the spawn node to 'begin spawn' if necessary if (SpawnWorldContextPin) { CompilerContext.MovePinLinksToIntermediate(*SpawnWorldContextPin, *CallBeginWorldContextPin); } if (SpawnNodeOwnerPin != nullptr) { CompilerContext.MovePinLinksToIntermediate(*SpawnNodeOwnerPin, *CallBeginOwnerPin); } // Copy the 'transform' connection from the spawn node to 'begin spawn' CompilerContext.MovePinLinksToIntermediate(*SpawnNodeTransform, *CallBeginTransform); // Copy the 'bNoCollisionFail' connection from the spawn node to 'begin spawn' CompilerContext.MovePinLinksToIntermediate(*SpawnNodeNoCollisionFail, *CallBeginNoCollisionFail); ////////////////////////////////////////////////////////////////////////// // create 'finish spawn' call node UK2Node_CallFunction* CallFinishSpawnNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(SpawnNode, SourceGraph); CallFinishSpawnNode->FunctionReference.SetExternalMember(FinishSpawningFuncName, UGameplayStatics::StaticClass()); CallFinishSpawnNode->AllocateDefaultPins(); UEdGraphPin* CallFinishExec = CallFinishSpawnNode->GetExecPin(); UEdGraphPin* CallFinishThen = CallFinishSpawnNode->GetThenPin(); UEdGraphPin* CallFinishActor = CallFinishSpawnNode->FindPinChecked(ActorParamName); UEdGraphPin* CallFinishTransform = CallFinishSpawnNode->FindPinChecked(TransformParamName); UEdGraphPin* CallFinishResult = CallFinishSpawnNode->GetReturnValuePin(); // Move 'then' connection from spawn node to 'finish spawn' CompilerContext.MovePinLinksToIntermediate(*SpawnNodeThen, *CallFinishThen); // Copy transform connection CompilerContext.CopyPinLinksToIntermediate(*CallBeginTransform, *CallFinishTransform); // Connect output actor from 'begin' to 'finish' CallBeginResult->MakeLinkTo(CallFinishActor); // Move result connection from spawn node to 'finish spawn' CallFinishResult->PinType = SpawnNodeResult->PinType; // Copy type so it uses the right actor subclass CompilerContext.MovePinLinksToIntermediate(*SpawnNodeResult, *CallFinishResult); ////////////////////////////////////////////////////////////////////////// // create 'set var' nodes // Get 'result' pin from 'begin spawn', this is the actual actor we want to set properties on UEdGraphPin* LastThen = FKismetCompilerUtilities::GenerateAssignmentNodes(CompilerContext, SourceGraph, CallBeginSpawnNode, SpawnNode, CallBeginResult, GetClassToSpawn() ); // Make exec connection between 'then' on last node and 'finish' LastThen->MakeLinkTo(CallFinishExec); // Break any links to the expanded node SpawnNode->BreakAllNodeLinks(); }
void UK2Node_FormatText::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) { Super::ExpandNode(CompilerContext, SourceGraph); if (CompilerContext.bIsFullCompile) { /** At the end of this, the UK2Node_FormatText will not be a part of the Blueprint, it merely handles connecting the other nodes into the Blueprint. */ const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema(); // Create a "Make Array" node to compile the list of arguments into an array for the Format function being called UK2Node_MakeArray* MakeArrayNode = CompilerContext.SpawnIntermediateNode<UK2Node_MakeArray>(this, SourceGraph); //SourceGraph->CreateBlankNode<UK2Node_MakeArray>(); MakeArrayNode->AllocateDefaultPins(); CompilerContext.MessageLog.NotifyIntermediateObjectCreation(MakeArrayNode, this); UEdGraphPin* ArrayOut = MakeArrayNode->GetOutputPin(); // This is the node that does all the Format work. UK2Node_CallFunction* CallFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph); CallFunction->SetFromFunction(UK2Node_FormatText::StaticClass()->FindFunctionByName("Format")); CallFunction->AllocateDefaultPins(); CompilerContext.MessageLog.NotifyIntermediateObjectCreation(CallFunction, this); // Connect the output of the "Make Array" pin to the function's "InArgs" pin ArrayOut->MakeLinkTo(CallFunction->FindPin(TEXT("InArgs"))); // This will set the "Make Array" node's type, only works if one pin is connected. MakeArrayNode->PinConnectionListChanged(ArrayOut); // For each argument, we will need to add in a "Make Struct" node. for(int32 ArgIdx = 0; ArgIdx < PinNames.Num(); ++ArgIdx) { UEdGraphPin* ArgumentPin = FindArgumentPin(PinNames[ArgIdx]); // Spawn a "Make Struct" node to create the struct needed for formatting the text. UK2Node_MakeStruct* PinMakeStruct = CompilerContext.SpawnIntermediateNode<UK2Node_MakeStruct>(this, SourceGraph); //SourceGraph->CreateBlankNode<UK2Node_CallFunction>(); PinMakeStruct->StructType = FFormatTextArgument::StaticStruct(); PinMakeStruct->AllocateDefaultPins(); // Set the struct's "ArgumentName" pin literal to be the argument pin's name. PinMakeStruct->GetSchema()->TrySetDefaultText(*PinMakeStruct->FindPin("ArgumentName"), FText::FromString(ArgumentPin->PinName)); // Move the connection of the argument pin to the struct's "TextValue" pin, this will move the literal value if present. CompilerContext.CheckConnectionResponse(Schema->MovePinLinks(*ArgumentPin, *PinMakeStruct->FindPin("TextValue")), this); // The "Make Array" node already has one pin available, so don't create one for ArgIdx == 0 if(ArgIdx > 0) { MakeArrayNode->AddInputPin(); } // Find the input pin on the "Make Array" node by index. FString PinName = FString::Printf(TEXT("[%d]"), ArgIdx); UEdGraphPin* InputPin = MakeArrayNode->FindPin(PinName); // Find the output for the pin's "Make Struct" node and link it to the corresponding pin on the "Make Array" node. FindOutputStructPinChecked(PinMakeStruct)->MakeLinkTo(InputPin); } // Move connection of FormatText's "Result" pin to the call function's return value pin. CompilerContext.CheckConnectionResponse(Schema->MovePinLinks(*FindPin(TEXT("Result")), *CallFunction->GetReturnValuePin()), this); // Move connection of FormatText's "Format" pin to the call function's "InPattern" pin CompilerContext.CheckConnectionResponse(Schema->MovePinLinks(*FindPin(TEXT("Format")), *CallFunction->FindPin(TEXT("InPattern"))), this); BreakAllNodeLinks(); } }