void UK2Node_FunctionEntry::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) { Super::ExpandNode(CompilerContext, SourceGraph); const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema(); UEdGraphPin* OldStartExecPin = nullptr; if(Pins[0]->LinkedTo.Num()) { OldStartExecPin = Pins[0]->LinkedTo[0]; } UEdGraphPin* LastActiveOutputPin = Pins[0]; // Only look for FunctionEntry nodes who were duplicated and have a source object if ( UK2Node_FunctionEntry* OriginalNode = Cast<UK2Node_FunctionEntry>(CompilerContext.MessageLog.FindSourceObject(this)) ) { check(OriginalNode->GetOuter()); // Find the associated UFunction UFunction* Function = FindField<UFunction>(CompilerContext.Blueprint->SkeletonGeneratedClass, *OriginalNode->GetOuter()->GetName()); for (TFieldIterator<UProperty> It(Function); It; ++It) { if (const UProperty* Property = *It) { for (auto& LocalVar : LocalVariables) { if (LocalVar.VarName == Property->GetFName() && !LocalVar.DefaultValue.IsEmpty()) { // Add a variable set node for the local variable and hook it up immediately following the entry node or the last added local variable UK2Node_VariableSet* VariableSetNode = CompilerContext.SpawnIntermediateNode<UK2Node_VariableSet>(this, SourceGraph); VariableSetNode->SetFromProperty(Property, false); Schema->ConfigureVarNode(VariableSetNode, LocalVar.VarName, Function, CompilerContext.Blueprint); VariableSetNode->AllocateDefaultPins(); CompilerContext.MessageLog.NotifyIntermediateObjectCreation(VariableSetNode, this); if(UEdGraphPin* SetPin = VariableSetNode->FindPin(Property->GetName())) { if(LocalVar.VarType.bIsArray) { TSharedPtr<FStructOnScope> StructData = MakeShareable(new FStructOnScope(Function)); FBlueprintEditorUtils::PropertyValueFromString(Property, LocalVar.DefaultValue, StructData->GetStructMemory()); // Create a Make Array node to setup the array's defaults UK2Node_MakeArray* MakeArray = CompilerContext.SpawnIntermediateNode<UK2Node_MakeArray>(this, SourceGraph); MakeArray->AllocateDefaultPins(); MakeArray->GetOutputPin()->MakeLinkTo(SetPin); MakeArray->PostReconstructNode(); const UArrayProperty* ArrayProperty = Cast<UArrayProperty>(Property); check(ArrayProperty); FScriptArrayHelper_InContainer ArrayHelper(ArrayProperty, StructData->GetStructMemory()); FScriptArrayHelper_InContainer DefaultArrayHelper(ArrayProperty, StructData->GetStructMemory()); uint8* StructDefaults = NULL; UStructProperty* StructProperty = dynamic_cast<UStructProperty*>(ArrayProperty->Inner); if ( StructProperty != NULL ) { checkSlow(StructProperty->Struct); StructDefaults = (uint8*)FMemory::Malloc(StructProperty->Struct->GetStructureSize()); StructProperty->InitializeValue(StructDefaults); } // Go through each element in the array to set the default value for( int32 ArrayIndex = 0 ; ArrayIndex < ArrayHelper.Num() ; ArrayIndex++ ) { uint8* PropData = ArrayHelper.GetRawPtr(ArrayIndex); // Always use struct defaults if the inner is a struct, for symmetry with the import of array inner struct defaults uint8* PropDefault = ( StructProperty != NULL ) ? StructDefaults : ( ( StructData->GetStructMemory() && DefaultArrayHelper.Num() > ArrayIndex ) ? DefaultArrayHelper.GetRawPtr(ArrayIndex) : NULL ); // Retrieve the element's default value FString DefaultValue; FBlueprintEditorUtils::PropertyValueToString(ArrayProperty->Inner, PropData, DefaultValue); if(ArrayIndex > 0) { MakeArray->AddInputPin(); } // Add one to the index for the pin to set the default on to skip the output pin Schema->TrySetDefaultValue(*MakeArray->Pins[ArrayIndex + 1], DefaultValue); } } else { // Set the default value Schema->TrySetDefaultValue(*SetPin, LocalVar.DefaultValue); } } LastActiveOutputPin->BreakAllPinLinks(); LastActiveOutputPin->MakeLinkTo(VariableSetNode->Pins[0]); LastActiveOutputPin = VariableSetNode->Pins[1]; } } } } // Finally, hook up the last node to the old node the function entry node was connected to if(OldStartExecPin) { LastActiveOutputPin->MakeLinkTo(OldStartExecPin); } } }
void UK2Node_Knot::NotifyPinConnectionListChanged(UEdGraphPin* Pin) { const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); UEdGraphPin* MyInputPin = GetInputPin(); UEdGraphPin* MyOutputPin = GetOutputPin(); const int32 NumLinks = MyInputPin->LinkedTo.Num() + MyOutputPin->LinkedTo.Num(); if (Pin->LinkedTo.Num() > 0) { // Just made a connection, was it the first? if (NumLinks == 1) { UEdGraphPin* TypeSource = Pin->LinkedTo[0]; MyInputPin->PinType = TypeSource->PinType; MyOutputPin->PinType = TypeSource->PinType; } } else { // Just broke a connection, was it the last? if (NumLinks == 0) { // Revert to wildcard MyInputPin->BreakAllPinLinks(); MyInputPin->PinType.ResetToDefaults(); MyInputPin->PinType.PinCategory = K2Schema->PC_Wildcard; MyOutputPin->BreakAllPinLinks(); MyOutputPin->PinType.ResetToDefaults(); MyOutputPin->PinType.PinCategory = K2Schema->PC_Wildcard; } } }
void UK2Node_GetArrayItem::NotifyPinConnectionListChanged(UEdGraphPin* Pin) { Super::NotifyPinConnectionListChanged(Pin); if (Pin != GetIndexPin() && Pin->ParentPin == nullptr) { UEdGraphPin* ArrayPin = Pins[0]; UEdGraphPin* ResultPin = Pins[2]; auto ClearWildcardType = [ArrayPin, ResultPin]() { ArrayPin->PinType.PinCategory = UEdGraphSchema_K2::PC_Wildcard; ArrayPin->PinType.PinSubCategory = TEXT(""); ArrayPin->PinType.PinSubCategoryObject = NULL; ResultPin->PinType.PinCategory = UEdGraphSchema_K2::PC_Wildcard; ResultPin->PinType.PinSubCategory = TEXT(""); ResultPin->PinType.PinSubCategoryObject = NULL; ResultPin->PinType.bIsReference = true; ArrayPin->BreakAllPinLinks(); ResultPin->BreakAllPinLinks(); }; const int32 NewLinkCount = Pin->LinkedTo.Num(); const bool bPinsHasLinks = (NewLinkCount > 0); if (ArrayPin == Pin) { if (bPinsHasLinks) { // if we had more than one input, we'd have to find the common base type ensure(NewLinkCount == 1); // the input array has authority, change output types, even if they are connected PropagatePinType(Pin->LinkedTo[0]->PinType); } // if the array pin was disconnected from everything, and... else if (ResultPin->LinkedTo.Num() == 0) { ClearWildcardType(); } } else if (ArrayPin->LinkedTo.Num() == 0) { // if we cleared the result pin's connections if (!bPinsHasLinks) { ClearWildcardType(); } // if this is the first connection to the result pin... else if (NewLinkCount == 1) { PropagatePinType(Pin->LinkedTo[0]->PinType); } // else, the result pin already had a connection and a type, leave // it alone, as it is what facilitated this connection as well } // else, leave this node alone, the array input is still connected and // it has authority over the wildcard types (the type set should already be good) } }
void UK2Node_VariableSetRef::CoerceTypeFromPin(const UEdGraphPin* Pin) { const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); UEdGraphPin* TargetPin = GetTargetPin(); UEdGraphPin* ValuePin = GetValuePin(); if( Pin ) { check((Pin != TargetPin) || (Pin->PinType.bIsReference && !Pin->PinType.bIsArray)); TargetPin->PinType = Pin->PinType; TargetPin->PinType.bIsReference = true; ValuePin->PinType = Pin->PinType; ValuePin->PinType.bIsReference = false; } else { // Pin disconnected...revert to wildcard TargetPin->PinType.PinCategory = K2Schema->PC_Wildcard; TargetPin->PinType.PinSubCategory = TEXT(""); TargetPin->PinType.PinSubCategoryObject = NULL; TargetPin->BreakAllPinLinks(); ValuePin->PinType.PinCategory = K2Schema->PC_Wildcard; ValuePin->PinType.PinSubCategory = TEXT(""); ValuePin->PinType.PinSubCategoryObject = NULL; ValuePin->BreakAllPinLinks(); CachedNodeTitle.MarkDirty(); } }
void FKCHandler_VariableSet::Transform(FKismetFunctionContext& Context, UEdGraphNode* Node) { // Expands node out to include a (local) call to the RepNotify function if necessary UK2Node_VariableSet* SetNotify = Cast<UK2Node_VariableSet>(Node); if ((SetNotify != NULL)) { if (SetNotify->ShouldFlushDormancyOnSet()) { // Create CallFuncNode UK2Node_CallFunction* CallFuncNode = Node->GetGraph()->CreateBlankNode<UK2Node_CallFunction>(); CallFuncNode->FunctionReference.SetExternalMember(NAME_FlushNetDormancy, AActor::StaticClass() ); CallFuncNode->AllocateDefaultPins(); // Copy self pin UEdGraphPin* NewSelfPin = CallFuncNode->FindPinChecked(CompilerContext.GetSchema()->PN_Self); UEdGraphPin* OldSelfPin = Node->FindPinChecked(CompilerContext.GetSchema()->PN_Self); NewSelfPin->CopyPersistentDataFromOldPin(*OldSelfPin); // link new CallFuncNode -> Set Node UEdGraphPin* OldExecPin = Node->FindPin(CompilerContext.GetSchema()->PN_Execute); check(OldExecPin); UEdGraphPin* NewExecPin = CallFuncNode->GetExecPin(); if (ensure(NewExecPin)) { NewExecPin->CopyPersistentDataFromOldPin(*OldExecPin); OldExecPin->BreakAllPinLinks(); CallFuncNode->GetThenPin()->MakeLinkTo(OldExecPin); } } if (SetNotify->HasLocalRepNotify()) { UK2Node_CallFunction* CallFuncNode = Node->GetGraph()->CreateBlankNode<UK2Node_CallFunction>(); CallFuncNode->FunctionReference.SetExternalMember(SetNotify->GetRepNotifyName(), SetNotify->GetVariableSourceClass() ); CallFuncNode->AllocateDefaultPins(); // Copy self pin UEdGraphPin* NewSelfPin = CallFuncNode->FindPinChecked(CompilerContext.GetSchema()->PN_Self); UEdGraphPin* OldSelfPin = Node->FindPinChecked(CompilerContext.GetSchema()->PN_Self); NewSelfPin->CopyPersistentDataFromOldPin(*OldSelfPin); // link Set Node -> new CallFuncNode UEdGraphPin* OldThenPin = Node->FindPin(CompilerContext.GetSchema()->PN_Then); check(OldThenPin); UEdGraphPin* NewThenPin = CallFuncNode->GetThenPin(); if (ensure(NewThenPin)) { // Link Set Node -> Notify NewThenPin->CopyPersistentDataFromOldPin(*OldThenPin); OldThenPin->BreakAllPinLinks(); OldThenPin->MakeLinkTo(CallFuncNode->GetExecPin()); } } } }
void UK2Node_FormatText::PinConnectionListChanged(UEdGraphPin* Pin) { const auto FormatPin = GetFormatPin(); Modify(); // Clear all pins. if(Pin == FormatPin && !FormatPin->DefaultTextValue.IsEmpty()) { PinNames.Empty(); GetSchema()->TrySetDefaultText(*FormatPin, FText::GetEmpty()); for(auto It = Pins.CreateConstIterator(); It; ++It) { UEdGraphPin* CheckPin = *It; if(CheckPin != FormatPin && CheckPin->Direction == EGPD_Input) { CheckPin->Modify(); CheckPin->BreakAllPinLinks(); Pins.Remove(CheckPin); --It; } } FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetBlueprint()); } }
void UEdGraphSchema::BreakPinLinks(UEdGraphPin& TargetPin, bool bSendsNodeNotifcation) const { #if WITH_EDITOR // Copy the old pin links TArray<class UEdGraphPin*> OldLinkedTo(TargetPin.LinkedTo); #endif TargetPin.BreakAllPinLinks(); #if WITH_EDITOR TSet<UEdGraphNode*> NodeList; // Notify this node TargetPin.GetOwningNode()->PinConnectionListChanged(&TargetPin); NodeList.Add(TargetPin.GetOwningNode()); // As well as all other nodes that were connected for (TArray<UEdGraphPin*>::TIterator PinIt(OldLinkedTo); PinIt; ++PinIt) { UEdGraphPin* OtherPin = *PinIt; UEdGraphNode* OtherNode = OtherPin->GetOwningNode(); OtherNode->PinConnectionListChanged(OtherPin); NodeList.Add(OtherNode); } if (bSendsNodeNotifcation) { // Send all nodes that received a new pin connection a notification for (auto It = NodeList.CreateConstIterator(); It; ++It) { UEdGraphNode* Node = (*It); Node->NodeConnectionListChanged(); } } #endif //#if WITH_EDITOR }
FPinConnectionResponse UEdGraphSchema::MovePinLinks(UEdGraphPin& MoveFromPin, UEdGraphPin& MoveToPin, bool bIsIntermediateMove) const { #if WITH_EDITOR ensureMsg(bIsIntermediateMove || !MoveToPin.GetOwningNode()->GetGraph()->HasAnyFlags(RF_Transient), TEXT("When moving to an Intermediate pin, use FKismetCompilerContext::MovePinLinksToIntermediate() instead of UEdGraphSchema::MovePinLinks()")); #endif // #if WITH_EDITOR FPinConnectionResponse FinalResponse = FPinConnectionResponse(CONNECT_RESPONSE_MAKE, TEXT("")); // First copy the current set of links TArray<UEdGraphPin*> CurrentLinks = MoveFromPin.LinkedTo; // Then break all links at pin we are moving from MoveFromPin.BreakAllPinLinks(); // Try and make each new connection for (int32 i=0; i<CurrentLinks.Num(); i++) { UEdGraphPin* NewLink = CurrentLinks[i]; FPinConnectionResponse Response = CanCreateConnection(&MoveToPin, NewLink); if(Response.CanSafeConnect()) { MoveToPin.MakeLinkTo(NewLink); } else { FinalResponse = Response; } } // Move over the default values MoveToPin.DefaultValue = MoveFromPin.DefaultValue; MoveToPin.DefaultObject = MoveFromPin.DefaultObject; MoveToPin.DefaultTextValue = MoveFromPin.DefaultTextValue; return FinalResponse; }
void USoundCueGraphNode_Base::ReconstructNode() { // Break any links to 'orphan' pins for (int32 PinIndex = 0; PinIndex < Pins.Num(); ++PinIndex) { UEdGraphPin* Pin = Pins[PinIndex]; TArray<class UEdGraphPin*>& LinkedToRef = Pin->LinkedTo; for (int32 LinkIdx=0; LinkIdx < LinkedToRef.Num(); LinkIdx++) { UEdGraphPin* OtherPin = LinkedToRef[LinkIdx]; // If we are linked to a pin that its owner doesn't know about, break that link if (!OtherPin->GetOwningNode()->Pins.Contains(OtherPin)) { Pin->LinkedTo.Remove(OtherPin); } } } // Store the old Input and Output pins TArray<UEdGraphPin*> OldInputPins; GetInputPins(OldInputPins); UEdGraphPin* OldOutputPin = GetOutputPin(); // Move the existing pins to a saved array TArray<UEdGraphPin*> OldPins(Pins); Pins.Empty(); // Recreate the new pins AllocateDefaultPins(); // Get new Input and Output pins TArray<UEdGraphPin*> NewInputPins; GetInputPins(NewInputPins); UEdGraphPin* NewOutputPin = GetOutputPin(); for (int32 PinIndex = 0; PinIndex < OldInputPins.Num(); PinIndex++) { if (PinIndex < NewInputPins.Num()) { NewInputPins[PinIndex]->CopyPersistentDataFromOldPin(*OldInputPins[PinIndex]); } } NewOutputPin->CopyPersistentDataFromOldPin(*OldOutputPin); OldInputPins.Empty(); OldOutputPin = NULL; // Throw away the original pins for (int32 OldPinIndex = 0; OldPinIndex < OldPins.Num(); ++OldPinIndex) { UEdGraphPin* OldPin = OldPins[OldPinIndex]; OldPin->Modify(); OldPin->BreakAllPinLinks(); UEdGraphNode::DestroyPin(OldPin); } OldPins.Empty(); }
void UMaterialGraphNode_Base::ReplaceNode(UMaterialGraphNode_Base* OldNode) { check(OldNode); check(OldNode != this); // Get Pins from node passed in TArray<UEdGraphPin*> OldInputPins; TArray<UEdGraphPin*> OldOutputPins; OldNode->GetInputPins(OldInputPins); OldNode->GetOutputPins(OldOutputPins); // Get our Input and Output pins TArray<UEdGraphPin*> NewInputPins; TArray<UEdGraphPin*> NewOutputPins; GetInputPins(NewInputPins); GetOutputPins(NewOutputPins); // Copy Inputs from old node for (int32 PinIndex = 0; PinIndex < OldInputPins.Num(); PinIndex++) { if (PinIndex < NewInputPins.Num()) { ModifyAndCopyPersistentPinData(*NewInputPins[PinIndex], *OldInputPins[PinIndex]); } } // Copy Outputs from old node for (int32 PinIndex = 0; PinIndex < OldOutputPins.Num(); PinIndex++) { // If we can't find an equivalent output in this node, just use the first // The user will have to fix up any issues from the mismatch int32 FoundPinIndex = 0; // Try to find an equivalent output in this node for (int32 NewPinIndex = 0; NewPinIndex < NewOutputPins.Num(); NewPinIndex++) { if (OldOutputPins[PinIndex]->PinType == NewOutputPins[NewPinIndex]->PinType) { FoundPinIndex = NewPinIndex; break; } } if (FoundPinIndex < NewOutputPins.Num()) { ModifyAndCopyPersistentPinData(*NewOutputPins[FoundPinIndex], *OldOutputPins[PinIndex]); } } // Break the original pin links for (int32 OldPinIndex = 0; OldPinIndex < OldNode->Pins.Num(); ++OldPinIndex) { UEdGraphPin* OldPin = OldNode->Pins[OldPinIndex]; OldPin->Modify(); OldPin->BreakAllPinLinks(); } }
void UK2Node_SpawnActorFromClass::OnClassPinChanged() { const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); // Remove all pins related to archetype variables TArray<UEdGraphPin*> OldPins = Pins; TArray<UEdGraphPin*> OldClassPins; for (int32 i = 0; i < OldPins.Num(); i++) { UEdGraphPin* OldPin = OldPins[i]; if (IsSpawnVarPin(OldPin)) { Pins.Remove(OldPin); OldClassPins.Add(OldPin); } } CachedNodeTitle.MarkDirty(); UClass* UseSpawnClass = GetClassToSpawn(); TArray<UEdGraphPin*> NewClassPins; if (UseSpawnClass != NULL) { CreatePinsForClass(UseSpawnClass, NewClassPins); } UEdGraphPin* ResultPin = GetResultPin(); // Cache all the pin connections to the ResultPin, we will attempt to recreate them TArray<UEdGraphPin*> ResultPinConnectionList = ResultPin->LinkedTo; // Because the archetype has changed, we break the output link as the output pin type will change ResultPin->BreakAllPinLinks(); // Recreate any pin links to the Result pin that are still valid for (UEdGraphPin* Connections : ResultPinConnectionList) { K2Schema->TryCreateConnection(ResultPin, Connections); } K2Schema->ConstructBasicPinTooltip(*ResultPin, LOCTEXT("ResultPinDescription", "The spawned Actor"), ResultPin->PinToolTip); // Rewire the old pins to the new pins so connections are maintained if possible RewireOldPinsToNewPins(OldClassPins, NewClassPins); // Destroy the old pins DestroyPinList(OldClassPins); // Refresh the UI for the graph so the pin changes show up UEdGraph* Graph = GetGraph(); Graph->NotifyGraphChanged(); // Mark dirty FBlueprintEditorUtils::MarkBlueprintAsModified(GetBlueprint()); }
void UK2Node_EaseFunction::ResetToWildcards() { FScopedTransaction Transaction(LOCTEXT("ResetToDefaultsTx", "ResetToDefaults")); Modify(); // Get pin refs UEdGraphPin* APin = FindPin(FEaseFunctionNodeHelper::GetAPinName()); UEdGraphPin* BPin = FindPin(FEaseFunctionNodeHelper::GetBPinName()); UEdGraphPin* ResultPin = FindPin(FEaseFunctionNodeHelper::GetResultPinName()); // Set all to defaults and break links APin->DefaultValue = TEXT(""); BPin->DefaultValue = TEXT(""); APin->BreakAllPinLinks(); BPin->BreakAllPinLinks(); ResultPin->BreakAllPinLinks(); // Do the rest of the work, we will not recompile because the wildcard pins will prevent it PinTypeChanged(APin); }
void UK2Node_EaseFunction::RefreshPinVisibility() { const auto EaseFuncPin = GetEaseFuncPin(); UEnum * Enum = FindObject<UEnum>(ANY_PACKAGE, TEXT("EEasingFunc"), true); check(Enum != NULL); const int32 NewEasingFunc = CanCustomizeCurve() ? Enum->GetValueByName(*EaseFuncPin->DefaultValue) : -1; // Early exit in case no changes are required const UEdGraphSchema_K2* K2Schema = Cast<const UEdGraphSchema_K2>(GetSchema()); UEdGraphPin* BlendExpPin = FindPinChecked(FEaseFunctionNodeHelper::GetBlendExpPinName()); if (NewEasingFunc == -1 || NewEasingFunc == EEasingFunc::EaseIn || NewEasingFunc == EEasingFunc::EaseOut || NewEasingFunc == EEasingFunc::EaseInOut) { // Show the BlendExpPin BlendExpPin->bHidden = false; } else { // Hide the BlendExpPin: BlendExpPin->BreakAllPinLinks(); BlendExpPin->bHidden = true; } UEdGraphPin* StepsPin = FindPinChecked(FEaseFunctionNodeHelper::GetStepsPinName()); if (NewEasingFunc == -1 || NewEasingFunc == EEasingFunc::Step) { // Show the Steps pin: StepsPin->bHidden = false; } else { // Hide the Steps pin: StepsPin->BreakAllPinLinks(); StepsPin->bHidden = true; } }
void UK2Node_SpawnActor::PinDefaultValueChanged(UEdGraphPin* ChangedPin) { if (ChangedPin->PinName == BlueprintPinName) { const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); // Because the archetype has changed, we break the output link as the output pin type will change UEdGraphPin* ResultPin = GetResultPin(); ResultPin->BreakAllPinLinks(); // Remove all pins related to archetype variables TArray<UEdGraphPin*> OldPins = Pins; for (int32 i = 0; i < OldPins.Num(); i++) { UEdGraphPin* OldPin = OldPins[i]; if (IsSpawnVarPin(OldPin)) { OldPin->BreakAllPinLinks(); Pins.Remove(OldPin); } } CachedNodeTitle.MarkDirty(); UClass* UseSpawnClass = GetClassToSpawn(); if(UseSpawnClass != NULL) { CreatePinsForClass(UseSpawnClass); } // Refresh the UI for the graph so the pin changes show up UEdGraph* Graph = GetGraph(); Graph->NotifyGraphChanged(); // Mark dirty FBlueprintEditorUtils::MarkBlueprintAsModified(GetBlueprint()); } }
void UK2Node_EditablePinBase::RemoveUserDefinedPin(TSharedPtr<FUserPinInfo> PinToRemove) { // Try to find the pin with the same name and params as the specified description, if any const FString PinName = PinToRemove->PinName; for(int32 i = 0; i < Pins.Num(); i++) { UEdGraphPin* Pin = Pins[i]; if( Pin->PinName == PinName ) { Pin->BreakAllPinLinks(); Pins.Remove(Pin); } } // Remove the description from the user-defined pins array UserDefinedPins.Remove(PinToRemove); }
void UK2Node_EaseFunction::GenerateExtraPins() { const UEdGraphSchema_K2* K2Schema = Cast<const UEdGraphSchema_K2>(GetSchema()); // Add pins based on the pin type const UEdGraphPin* APin = FindPinChecked(FEaseFunctionNodeHelper::GetAPinName()); const bool bIsRotator = APin->PinType.PinCategory == K2Schema->PC_Struct && APin->PinType.PinSubCategoryObject.Get()->GetName() == TEXT("Rotator"); UEdGraphPin* ShortestPathPin = FindPinChecked(FEaseFunctionNodeHelper::GetShortestPathPinName()); if (bIsRotator) { ShortestPathPin->bHidden = false; } else { ShortestPathPin->BreakAllPinLinks(); ShortestPathPin->bHidden = true; } }
void USoundClassGraph::RefreshGraphLinks() { Modify(); for (int32 NodeIndex = 0; NodeIndex < Nodes.Num(); NodeIndex++) { USoundClassGraphNode* Node = CastChecked<USoundClassGraphNode>(Nodes[NodeIndex]); if (!Node->CheckRepresentsSoundClass()) { UEdGraphPin* ChildPin = Node->GetChildPin(); Node->Modify(); ChildPin->BreakAllPinLinks(); for (int32 ChildIndex = 0; ChildIndex < Node->SoundClass->ChildClasses.Num(); ChildIndex++) { USoundClass* ChildClass = Node->SoundClass->ChildClasses[ChildIndex]; if (ChildClass) { USoundClassGraphNode* ChildNode = FindExistingNode(ChildClass); if (!ChildNode) { // New Child not yet represented on graph ConstructNodes(ChildClass, Node->NodePosX+400, Node->NodePosY); ChildNode = FindExistingNode(ChildClass); } ChildPin->MakeLinkTo(ChildNode->GetParentPin()); } } Node->PostEditChange(); } } NotifyGraphChanged(); }
bool UEdGraphNode::RemovePin(UEdGraphPin* Pin) { check( Pin ); Modify(); UEdGraphPin* RootPin = (Pin->ParentPin != nullptr)? Pin->ParentPin : Pin; RootPin->BreakAllPinLinks(); if (Pins.Remove( RootPin )) { // Remove any children pins to ensure the entirety of the pin's representation is removed for (UEdGraphPin* ChildPin : RootPin->SubPins) { Pins.Remove(ChildPin); ChildPin->Modify(); ChildPin->BreakAllPinLinks(); } return true; } return false; }
void UK2Node_FormatText::PinDefaultValueChanged(UEdGraphPin* Pin) { const auto FormatPin = GetFormatPin(); if(Pin == FormatPin && FormatPin->LinkedTo.Num() == 0) { const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); TArray< FString > ArgumentParams; FText::GetFormatPatternParameters(FormatPin->DefaultTextValue, ArgumentParams); PinNames.Empty(); for(auto It = ArgumentParams.CreateConstIterator(); It; ++It) { if(!FindArgumentPin(FText::FromString(*It))) { CreatePin(EGPD_Input, K2Schema->PC_Text, TEXT(""), NULL, false, false, *It); } PinNames.Add(FText::AsCultureInvariant(*It)); } for(auto It = Pins.CreateConstIterator(); It; ++It) { UEdGraphPin* CheckPin = *It; if(CheckPin != FormatPin && CheckPin->Direction == EGPD_Input) { int Index = 0; if(!ArgumentParams.Find(CheckPin->PinName, Index)) { CheckPin->BreakAllPinLinks(); Pins.Remove(CheckPin); --It; } } } GetGraph()->NotifyGraphChanged(); } }
void UMaterialGraphNode::RecreateAndLinkNode() { // Throw away the original pins for (int32 PinIndex = 0; PinIndex < Pins.Num(); ++PinIndex) { UEdGraphPin* Pin = Pins[PinIndex]; Pin->Modify(); Pin->BreakAllPinLinks(); #if 0 UEdGraphNode::ReturnPinToPool(Pin); #else Pin->Rename(NULL, GetTransientPackage(), REN_None); Pin->RemoveFromRoot(); Pin->MarkPendingKill(); #endif } Pins.Empty(); AllocateDefaultPins(); CastChecked<UMaterialGraph>(GetGraph())->LinkGraphNodesFromMaterial(); }
void UNiagaraNodeOutput::ReallocatePins() { Modify(); // Break any links to 'orphan' pins for (int32 PinIndex = 0; PinIndex < Pins.Num(); ++PinIndex) { UEdGraphPin* Pin = Pins[PinIndex]; TArray<class UEdGraphPin*>& LinkedToRef = Pin->LinkedTo; for (int32 LinkIdx = 0; LinkIdx < LinkedToRef.Num(); LinkIdx++) { UEdGraphPin* OtherPin = LinkedToRef[LinkIdx]; // If we are linked to a pin that its owner doesn't know about, break that link if (!OtherPin->GetOwningNode()->Pins.Contains(OtherPin)) { Pin->LinkedTo.Remove(OtherPin); } } } // Store the old Input and Output pins TArray<UEdGraphPin*> OldInputPins; TArray<UEdGraphPin*> OldOutputPins; GetInputPins(OldInputPins); GetOutputPins(OldOutputPins); // Move the existing pins to a saved array TArray<UEdGraphPin*> OldPins(Pins); Pins.Empty(); // Recreate the new pins AllocateDefaultPins(); // Get new Input and Output pins TArray<UEdGraphPin*> NewInputPins; TArray<UEdGraphPin*> NewOutputPins; GetInputPins(NewInputPins); GetOutputPins(NewOutputPins); for (int32 PinIndex = 0; PinIndex < OldInputPins.Num(); PinIndex++) { if (PinIndex < NewInputPins.Num()) { NewInputPins[PinIndex]->CopyPersistentDataFromOldPin(*OldInputPins[PinIndex]); } } for (int32 PinIndex = 0; PinIndex < OldOutputPins.Num(); PinIndex++) { if (PinIndex < NewOutputPins.Num()) { NewOutputPins[PinIndex]->CopyPersistentDataFromOldPin(*OldOutputPins[PinIndex]); } } OldInputPins.Empty(); OldOutputPins.Empty(); // Throw away the original pins for (int32 OldPinIndex = 0; OldPinIndex < OldPins.Num(); ++OldPinIndex) { UEdGraphPin* OldPin = OldPins[OldPinIndex]; OldPin->Modify(); OldPin->BreakAllPinLinks(); #if 0 UEdGraphNode::ReturnPinToPool(OldPin); #else OldPin->Rename(NULL, GetTransientPackage(), REN_None); OldPin->RemoveFromRoot(); OldPin->MarkPendingKill(); #endif } OldPins.Empty(); GetGraph()->NotifyGraphChanged(); }
void UNiagaraNodeInput::ReallocatePins() { const UEdGraphSchema_Niagara* Schema = GetDefault<UEdGraphSchema_Niagara>(); Modify(); // Break any links to 'orphan' pins for (int32 PinIndex = 0; PinIndex < Pins.Num(); ++PinIndex) { UEdGraphPin* Pin = Pins[PinIndex]; TArray<class UEdGraphPin*>& LinkedToRef = Pin->LinkedTo; for (int32 LinkIdx = 0; LinkIdx < LinkedToRef.Num(); LinkIdx++) { UEdGraphPin* OtherPin = LinkedToRef[LinkIdx]; // If we are linked to a pin that its owner doesn't know about, break that link if (!OtherPin->GetOwningNode()->Pins.Contains(OtherPin)) { Pin->LinkedTo.Remove(OtherPin); } } } // Store the old Input and Output pins TArray<UEdGraphPin*> OldInputPins; TArray<UEdGraphPin*> OldOutputPins; GetInputPins(OldInputPins); GetOutputPins(OldOutputPins); // Move the existing pins to a saved array TArray<UEdGraphPin*> OldPins(Pins); Pins.Empty(); switch (Input.Type) { case ENiagaraDataType::Scalar: { CreatePin(EGPD_Output, Schema->PC_Float, TEXT(""), NULL, false, false, Input.Name.ToString()); } break; case ENiagaraDataType::Vector: { CreatePin(EGPD_Output, Schema->PC_Vector, TEXT(""), NULL, false, false, Input.Name.ToString()); } break; case ENiagaraDataType::Matrix: { CreatePin(EGPD_Output, Schema->PC_Matrix, TEXT(""), NULL, false, false, Input.Name.ToString()); } break; case ENiagaraDataType::Curve: { CreatePin(EGPD_Output, Schema->PC_Curve, TEXT(""), NULL, false, false, Input.Name.ToString()); } break; }; // Get new Input and Output pins TArray<UEdGraphPin*> NewInputPins; TArray<UEdGraphPin*> NewOutputPins; GetInputPins(NewInputPins); GetOutputPins(NewOutputPins); for (int32 PinIndex = 0; PinIndex < OldInputPins.Num(); PinIndex++) { if (PinIndex < NewInputPins.Num()) { NewInputPins[PinIndex]->CopyPersistentDataFromOldPin(*OldInputPins[PinIndex]); } } for (int32 PinIndex = 0; PinIndex < OldOutputPins.Num(); PinIndex++) { if (PinIndex < NewOutputPins.Num()) { NewOutputPins[PinIndex]->CopyPersistentDataFromOldPin(*OldOutputPins[PinIndex]); } } OldInputPins.Empty(); OldOutputPins.Empty(); // Throw away the original pins for (int32 OldPinIndex = 0; OldPinIndex < OldPins.Num(); ++OldPinIndex) { UEdGraphPin* OldPin = OldPins[OldPinIndex]; OldPin->Modify(); OldPin->BreakAllPinLinks(); #if 0 UEdGraphNode::ReturnPinToPool(OldPin); #else OldPin->Rename(NULL, GetTransientPackage(), REN_None); OldPin->RemoveFromRoot(); OldPin->MarkPendingKill(); #endif } OldPins.Empty(); GetGraph()->NotifyGraphChanged(); }
void UK2Node::ReconstructNode() { Modify(); UBlueprint* Blueprint = GetBlueprint(); // Break any links to 'orphan' pins for (int32 PinIndex = 0; PinIndex < Pins.Num(); ++PinIndex) { UEdGraphPin* Pin = Pins[PinIndex]; TArray<class UEdGraphPin*> LinkedToCopy = Pin->LinkedTo; for (int32 LinkIdx = 0; LinkIdx < LinkedToCopy.Num(); LinkIdx++) { UEdGraphPin* OtherPin = LinkedToCopy[LinkIdx]; // If we are linked to a pin that its owner doesn't know about, break that link if ((OtherPin == NULL) || !OtherPin->GetOwningNodeUnchecked() || !OtherPin->GetOwningNode()->Pins.Contains(OtherPin)) { Pin->LinkedTo.Remove(OtherPin); } } } // Move the existing pins to a saved array TArray<UEdGraphPin*> OldPins(Pins); Pins.Empty(); // Recreate the new pins ReallocatePinsDuringReconstruction(OldPins); bool bDestroyOldPins = true; if (Pins.Num() == 0) { //keep old pins on callfunction so that graph doesn't get broken up just because function is missing if (IsA(UK2Node_CallFunction::StaticClass()) || IsA(UK2Node_MacroInstance::StaticClass())) { Pins = OldPins; bDestroyOldPins = false; } } else { // Rewire any connection to pins that are matched by name (O(N^2) right now) //@TODO: Can do moderately smart things here if only one pin changes name by looking at it's relative position, etc..., // rather than just failing to map it and breaking the links for (int32 OldPinIndex = 0; OldPinIndex < OldPins.Num(); ++OldPinIndex) { UEdGraphPin* OldPin = OldPins[OldPinIndex]; for (int32 NewPinIndex = 0; NewPinIndex < Pins.Num(); ++NewPinIndex) { UEdGraphPin* NewPin = Pins[NewPinIndex]; const ERedirectType RedirectType = DoPinsMatchForReconstruction(NewPin, NewPinIndex, OldPin, OldPinIndex); if (RedirectType != ERedirectType_None) { ReconstructSinglePin(NewPin, OldPin, RedirectType); break; } } } } if (bDestroyOldPins) { // Throw away the original pins for (int32 OldPinIndex = 0; OldPinIndex < OldPins.Num(); ++OldPinIndex) { UEdGraphPin* OldPin = OldPins[OldPinIndex]; OldPin->Modify(); OldPin->BreakAllPinLinks(); // just in case this pin was set to watch (don't want to save PinWatches with dead pins) Blueprint->PinWatches.Remove(OldPin); #if 0 UEdGraphNode::ReturnPinToPool(OldPin); #else OldPin->Rename(NULL, GetTransientPackage(), (Blueprint->bIsRegeneratingOnLoad ? REN_ForceNoResetLoaders : REN_None)); OldPin->RemoveFromRoot(); OldPin->MarkPendingKill(); #endif } } // Let subclasses do any additional work PostReconstructNode(); GetGraph()->NotifyGraphChanged(); }