void UK2Node_AddComponent::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) { Super::ExpandNode(CompilerContext, SourceGraph); auto TransformPin = GetRelativeTransformPin(); if (TransformPin && !TransformPin->LinkedTo.Num()) { FString DefaultValue; // Try and find the template and get relative transform from it UEdGraphPin* TemplateNamePin = GetTemplateNamePinChecked(); const FString TemplateName = TemplateNamePin->DefaultValue; check(CompilerContext.Blueprint); USceneComponent* SceneCompTemplate = Cast<USceneComponent>(CompilerContext.Blueprint->FindTemplateByName(FName(*TemplateName))); if (SceneCompTemplate) { FTransform TemplateTransform = FTransform(SceneCompTemplate->RelativeRotation, SceneCompTemplate->RelativeLocation, SceneCompTemplate->RelativeScale3D); DefaultValue = TemplateTransform.ToString(); } auto ValuePin = InnerHandleAutoCreateRef(this, TransformPin, CompilerContext, SourceGraph, !DefaultValue.IsEmpty()); if (ValuePin) { ValuePin->DefaultValue = DefaultValue; } } if (bHasExposedVariable) { static FString ObjectParamName = FString(TEXT("Object")); static FString ValueParamName = FString(TEXT("Value")); static FString PropertyNameParamName = FString(TEXT("PropertyName")); UK2Node_AddComponent* NewNode = CompilerContext.SpawnIntermediateNode<UK2Node_AddComponent>(this, SourceGraph); NewNode->SetFromFunction(GetTargetFunction()); NewNode->AllocateDefaultPinsWithoutExposedVariables(); // function parameters const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); CompilerContext.MovePinLinksToIntermediate(*FindPin(K2Schema->PN_Self), *NewNode->FindPin(K2Schema->PN_Self)); CompilerContext.MovePinLinksToIntermediate(*GetTemplateNamePinChecked(), *NewNode->GetTemplateNamePinChecked()); CompilerContext.MovePinLinksToIntermediate(*GetRelativeTransformPin(), *NewNode->GetRelativeTransformPin()); CompilerContext.MovePinLinksToIntermediate(*GetManualAttachmentPin(), *NewNode->GetManualAttachmentPin()); UEdGraphPin* ReturnPin = NewNode->GetReturnValuePin(); UEdGraphPin* OriginalReturnPin = GetReturnValuePin(); check((NULL != ReturnPin) && (NULL != OriginalReturnPin)); ReturnPin->PinType = OriginalReturnPin->PinType; CompilerContext.MovePinLinksToIntermediate(*OriginalReturnPin, *ReturnPin); // exec in CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *NewNode->GetExecPin()); UEdGraphPin* LastThen = FKismetCompilerUtilities::GenerateAssignmentNodes( CompilerContext, SourceGraph, NewNode, this, ReturnPin, GetSpawnedType() ); CompilerContext.MovePinLinksToIntermediate(*GetThenPin(), *LastThen); BreakAllNodeLinks(); } }
//------------------------------------------------------------------------------ // Evolved from a combination of FK2ActionMenuBuilder::CreateAddComponentAction() // and FEdGraphSchemaAction_K2AddComponent::PerformAction(). UEdGraphNode* UBlueprintComponentNodeSpawner::Invoke(UEdGraph* ParentGraph, FBindingSet const& Bindings, FVector2D const Location) const { check(ComponentClass != nullptr); auto PostSpawnLambda = [](UEdGraphNode* NewNode, bool bIsTemplateNode, FCustomizeNodeDelegate UserDelegate) { UK2Node_AddComponent* AddCompNode = CastChecked<UK2Node_AddComponent>(NewNode); UBlueprint* Blueprint = AddCompNode->GetBlueprint(); UFunction* AddComponentFunc = FindFieldChecked<UFunction>(AActor::StaticClass(), UK2Node_AddComponent::GetAddComponentFunctionName()); AddCompNode->FunctionReference.SetFromField<UFunction>(AddComponentFunc, FBlueprintEditorUtils::IsActorBased(Blueprint)); UserDelegate.ExecuteIfBound(NewNode, bIsTemplateNode); }; FCustomizeNodeDelegate PostSpawnDelegate = FCustomizeNodeDelegate::CreateStatic(PostSpawnLambda, CustomizeNodeDelegate); // let SpawnNode() allocate default pins (so we can modify them) UK2Node_AddComponent* NewNode = Super::SpawnNode<UK2Node_AddComponent>(NodeClass, ParentGraph, FBindingSet(), Location, PostSpawnDelegate); // set the return type to be the type of the template UEdGraphPin* ReturnPin = NewNode->GetReturnValuePin(); if (ReturnPin != nullptr) { ReturnPin->PinType.PinSubCategoryObject = *ComponentClass; } bool const bIsTemplateNode = FBlueprintNodeTemplateCache::IsTemplateOuter(ParentGraph); if (!bIsTemplateNode) { UBlueprint* Blueprint = NewNode->GetBlueprint(); UActorComponent* ComponentTemplate = ConstructObject<UActorComponent>(ComponentClass, Blueprint->GeneratedClass); ComponentTemplate->SetFlags(RF_ArchetypeObject); Blueprint->ComponentTemplates.Add(ComponentTemplate); // set the name of the template as the default for the TemplateName param UEdGraphPin* TemplateNamePin = NewNode->GetTemplateNamePinChecked(); if (TemplateNamePin != nullptr) { TemplateNamePin->DefaultValue = ComponentTemplate->GetName(); } } // apply bindings, after we've setup the template pin ApplyBindings(NewNode, Bindings); return NewNode; }
UEdGraphNode* FEdGraphSchemaAction_K2AddComponent::PerformAction(class UEdGraph* ParentGraph, UEdGraphPin* FromPin, const FVector2D Location, bool bSelectNewNode/* = true*/) { if (ComponentClass == NULL) { return NULL; } UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraphChecked(ParentGraph); UEdGraphNode* NewNode = FEdGraphSchemaAction_K2NewNode::PerformAction(ParentGraph, FromPin, Location, bSelectNewNode); if ((NewNode != NULL) && (Blueprint != NULL)) { UK2Node_AddComponent* AddCompNode = CastChecked<UK2Node_AddComponent>(NewNode); ensure(NULL != Cast<UBlueprintGeneratedClass>(Blueprint->GeneratedClass)); // Then create a new template object, and add to array in UActorComponent* NewTemplate = NewObject<UActorComponent>(Blueprint->GeneratedClass, ComponentClass, NAME_None, RF_ArchetypeObject | RF_Public); Blueprint->ComponentTemplates.Add(NewTemplate); // Set the name of the template as the default for the TemplateName param UEdGraphPin* TemplateNamePin = AddCompNode->GetTemplateNamePinChecked(); if (TemplateNamePin) { TemplateNamePin->DefaultValue = NewTemplate->GetName(); } // Set the return type to be the type of the template UEdGraphPin* ReturnPin = AddCompNode->GetReturnValuePin(); if (ReturnPin) { ReturnPin->PinType.PinSubCategoryObject = *ComponentClass; } // Set the asset if(ComponentAsset != NULL) { FComponentAssetBrokerage::AssignAssetToComponent(NewTemplate, ComponentAsset); } AddCompNode->ReconstructNode(); } FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint); return NewNode; }