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 }
FReply SGraphPin::OnDrop( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent ) { TSharedPtr<SGraphNode> NodeWidget = OwnerNodePtr.Pin(); bool bReadOnly = NodeWidget.IsValid() ? !NodeWidget->IsNodeEditable() : false; TSharedPtr<FDragDropOperation> Operation = DragDropEvent.GetOperation(); if (!Operation.IsValid() || bReadOnly) { return FReply::Unhandled(); } // Is someone dropping a connection onto this pin? if (Operation->IsOfType<FGraphEditorDragDropAction>()) { TSharedPtr<FGraphEditorDragDropAction> DragConnectionOp = StaticCastSharedPtr<FGraphEditorDragDropAction>(Operation); FVector2D NodeAddPosition = FVector2D::ZeroVector; TSharedPtr<SGraphNode> OwnerNode = OwnerNodePtr.Pin(); if (OwnerNode.IsValid()) { NodeAddPosition = OwnerNode->GetPosition() + MyGeometry.Position; //Don't have access to bounding information for node, using fixed offet that should work for most cases. const float FixedOffset = 200.0f; //Line it up vertically with pin NodeAddPosition.Y += MyGeometry.Size.Y; if(GetDirection() == EEdGraphPinDirection::EGPD_Input) { //left side just offset by fixed amount //@TODO: knowing the width of the node we are about to create would allow us to line this up more precisely, // but this information is not available currently NodeAddPosition.X -= FixedOffset; } else { //right side we need the width of the pin + fixed amount because our reference position is the upper left corner of pin(which is variable length) NodeAddPosition.X += MyGeometry.Size.X + FixedOffset; } } return DragConnectionOp->DroppedOnPin(DragDropEvent.GetScreenSpacePosition(), NodeAddPosition); } // handle dropping an asset on the pin else if (Operation->IsOfType<FAssetDragDropOp>() && NodeWidget.IsValid()) { UEdGraphNode* Node = NodeWidget->GetNodeObj(); if(Node != NULL && Node->GetSchema() != NULL) { TSharedPtr<FAssetDragDropOp> AssetOp = StaticCastSharedPtr<FAssetDragDropOp>(Operation); Node->GetSchema()->DroppedAssetsOnPin(AssetOp->AssetData, DragDropEvent.GetScreenSpacePosition(), GraphPinObj); } return FReply::Handled(); } return FReply::Unhandled(); }
void UEdGraphPin::MakeLinkTo(UEdGraphPin* ToPin) { Modify(); if (ToPin != NULL) { ToPin->Modify(); // Make sure we don't already link to it if (!LinkedTo.Contains(ToPin)) { UEdGraphNode* MyNode = GetOwningNode(); // Check that the other pin does not link to us ensureMsgf(!ToPin->LinkedTo.Contains(this), *GetLinkInfoString( LOCTEXT("MakeLinkTo", "MakeLinkTo").ToString(), LOCTEXT("IsLinked", "is linked with pin").ToString(), ToPin)); ensureMsgf(MyNode->GetOuter() == ToPin->GetOwningNode()->GetOuter(), *GetLinkInfoString( LOCTEXT("MakeLinkTo", "MakeLinkTo").ToString(), LOCTEXT("OuterMismatch", "has a different outer than pin").ToString(), ToPin)); // Ensure both pins belong to the same graph // Add to both lists LinkedTo.Add(ToPin); ToPin->LinkedTo.Add(this); GraphPinHelpers::EnableAllConnectedNodes(MyNode); GraphPinHelpers::EnableAllConnectedNodes(ToPin->GetOwningNode()); } } }
KISMETCOMPILER_API FString FNetNameMapping::MakeBaseName<UEdGraphPin>(const UEdGraphPin* Net) { UEdGraphNode* Owner = Net->GetOwningNode(); FString Part1 = Owner->GetDescriptiveCompiledName(); return FString::Printf(TEXT("%s_%s"), *Part1, *Net->PinName); }
UEdGraphPin* UK2Node_Tunnel::CreatePinFromUserDefinition(const TSharedPtr<FUserPinInfo> NewPinInfo) { // Create the new pin EEdGraphPinDirection Direction = bCanHaveInputs ? EGPD_Input : EGPD_Output; // Let the user pick the pin direction if legal if ( (bCanHaveInputs && NewPinInfo->DesiredPinDirection == EGPD_Input) || (bCanHaveOutputs && NewPinInfo->DesiredPinDirection == EGPD_Output) ) { Direction = NewPinInfo->DesiredPinDirection; } UEdGraphPin* Result = CreatePin(Direction, NewPinInfo->PinType, NewPinInfo->PinName); Result->DefaultValue = Result->AutogeneratedDefaultValue = NewPinInfo->PinDefaultValue; // Make sure it mirrors onto the associated node UEdGraphNode* TargetNode = ((InputSinkNode != NULL) ? InputSinkNode : OutputSourceNode); if (Cast<UK2Node_Composite>(TargetNode) != NULL || Cast<UK2Node_MacroInstance>(TargetNode) != NULL) { UEdGraphPin* HasPinAlready = TargetNode->FindPin(Result->PinName); if (HasPinAlready == NULL) { TargetNode->CreatePin(UEdGraphPin::GetComplementaryDirection(Direction), NewPinInfo->PinType, NewPinInfo->PinName); } } else if (UK2Node_Tunnel* TunnelNode = Cast<UK2Node_Tunnel>(TargetNode)) { TunnelNode->CreateUserDefinedPin(NewPinInfo->PinName, NewPinInfo->PinType, (Direction == EGPD_Input)? EGPD_Output : EGPD_Input); } //@TODO: Automatically update loaded macro instances when this node is changed too return Result; }
/** Prunes any nodes that weren't visited from the graph, printing out a warning */ void FGraphCompilerContext::PruneIsolatedNodes(const TArray<UEdGraphNode*>& RootSet, TArray<UEdGraphNode*>& GraphNodes) { FEdGraphUtilities::FNodeVisitor Visitor; for (TArray<UEdGraphNode*>::TConstIterator It(RootSet); It; ++It) { UEdGraphNode* RootNode = *It; Visitor.TraverseNodes(RootNode); } for (int32 NodeIndex = 0; NodeIndex < GraphNodes.Num(); ++NodeIndex) { UEdGraphNode* Node = GraphNodes[NodeIndex]; if (!Visitor.VisitedNodes.Contains(Node)) { if (!CanIgnoreNode(Node)) { // Disabled this warning, because having orphaned chains is standard workflow for LDs //MessageLog.Warning(TEXT("Node @@ will never be executed and is being pruned"), Node); } if (!ShouldForceKeepNode(Node)) { Node->BreakAllNodeLinks(); GraphNodes.RemoveAtSwap(NodeIndex); --NodeIndex; } } } }
UEdGraphNode* FGraphCompilerContext::FindNodeByClass(const UEdGraph* Graph, TSubclassOf<UEdGraphNode> NodeClass, bool bExpectedUnique) const { UEdGraphNode* FirstResultNode = NULL; for (int32 NodeIndex = 0; NodeIndex < Graph->Nodes.Num(); ++NodeIndex) { UEdGraphNode* Node = Graph->Nodes[NodeIndex]; if (Node->IsA(NodeClass)) { if (bExpectedUnique) { if (FirstResultNode == NULL) { FirstResultNode = Node; } else { MessageLog.Error(*FString::Printf(TEXT("Expected only one %s node in graph @@, but found both @@ and @@"), *(NodeClass->GetName())), Graph, FirstResultNode, Node); } } else { return Node; } } } return FirstResultNode; }
void FNiagaraEditor::DeleteSelectedDuplicatableNodes() { TSharedPtr<SGraphEditor> CurrentGraphEditor = NodeGraphEditorPtr.Pin(); if (!CurrentGraphEditor.IsValid()) { return; } const FGraphPanelSelectionSet OldSelectedNodes = CurrentGraphEditor->GetSelectedNodes(); CurrentGraphEditor->ClearSelectionSet(); for (FGraphPanelSelectionSet::TConstIterator SelectedIter(OldSelectedNodes); SelectedIter; ++SelectedIter) { UEdGraphNode* Node = Cast<UEdGraphNode>(*SelectedIter); if (Node && Node->CanDuplicateNode()) { CurrentGraphEditor->SetNodeSelection(Node, true); } } // Delete the duplicatable nodes DeleteSelectedNodes(); CurrentGraphEditor->ClearSelectionSet(); for (FGraphPanelSelectionSet::TConstIterator SelectedIter(OldSelectedNodes); SelectedIter; ++SelectedIter) { if (UEdGraphNode* Node = Cast<UEdGraphNode>(*SelectedIter)) { CurrentGraphEditor->SetNodeSelection(Node, true); } } }
void UEdGraphSchema::TrySetDefaultText(UEdGraphPin& InPin, const FText& InNewDefaultText) const { if(InNewDefaultText.IsEmpty()) { InPin.DefaultTextValue = InNewDefaultText; } else { #if WITH_EDITOR if(InNewDefaultText.IsCultureInvariant()) { InPin.DefaultTextValue = InNewDefaultText; } else { InPin.DefaultTextValue = FText::ChangeKey(TEXT(""), InPin.GetOwningNode()->NodeGuid.ToString() + TEXT("_") + InPin.PinName, InNewDefaultText); } #endif } #if WITH_EDITOR UEdGraphNode* Node = InPin.GetOwningNode(); check(Node); Node->PinDefaultValueChanged(&InPin); #endif //#if WITH_EDITOR }
//------------------------------------------------------------------------------ static UEdGraphNode* FBlueprintMenuActionItemImpl::InvokeAction(const UBlueprintNodeSpawner* Action, UEdGraph* ParentGraph, FVector2D const Location, IBlueprintNodeBinder::FBindingSet const& Bindings, bool& bOutNewNode) { int32 const PreSpawnNodeCount = ParentGraph->Nodes.Num(); // this could return an existing node UEdGraphNode* SpawnedNode = Action->Invoke(ParentGraph, Bindings, Location); // if a returned node wasn't one that previously existed in the graph const bool bNewNode = PreSpawnNodeCount < ParentGraph->Nodes.Num(); bOutNewNode = bNewNode; if (bNewNode) { check(SpawnedNode != nullptr); SpawnedNode->SnapToGrid(SNodePanel::GetSnapGridSize()); FBlueprintEditorUtils::AnalyticsTrackNewNode(SpawnedNode); } // if this node already existed, then we just want to focus on that node... // some node types are only allowed one instance per blueprint (like events) else if (SpawnedNode != nullptr) { FKismetEditorUtilities::BringKismetToFocusAttentionOnObject(SpawnedNode); } return SpawnedNode; }
void UEdGraphPin::CopyPersistentDataFromOldPin(const UEdGraphPin& SourcePin) { // The name matches already, doesn't get copied here // The PinType, Direction, and bNotConnectable are properties generated from the schema // Only move the default value if it was modified; inherit the new default value otherwise if (SourcePin.DefaultValue != SourcePin.AutogeneratedDefaultValue || SourcePin.DefaultObject != NULL || SourcePin.DefaultTextValue.ToString() != SourcePin.AutogeneratedDefaultValue) { DefaultObject = SourcePin.DefaultObject; DefaultValue = SourcePin.DefaultValue; DefaultTextValue = SourcePin.DefaultTextValue; } // Copy the links for (int32 LinkIndex = 0; LinkIndex < SourcePin.LinkedTo.Num(); ++LinkIndex) { UEdGraphPin* OtherPin = SourcePin.LinkedTo[LinkIndex]; check(NULL != OtherPin); Modify(); OtherPin->Modify(); LinkedTo.Add(OtherPin); // Unlike MakeLinkTo(), we attempt to ensure that the new pin (this) is inserted at the same position as the old pin (source) // in the OtherPin's LinkedTo array. This is necessary to ensure that the node's position in the execution order will remain // unchanged after nodes are reconstructed, because OtherPin may be connected to more than just this node. int32 Index = OtherPin->LinkedTo.Find(const_cast<UEdGraphPin*>(&SourcePin)); if(Index != INDEX_NONE) { OtherPin->LinkedTo.Insert(this, Index); } else { // Fallback to "normal" add, just in case the old pin doesn't exist in the other pin's LinkedTo array for some reason. OtherPin->LinkedTo.Add(this); } } // If the source pin is split, then split the new one, but don't split multiple times, typically splitting is done // by UK2Node::ReallocatePinsDuringReconstruction or FBlueprintEditor::OnSplitStructPin, but there are several code // paths into this, and split state should be persistent: if (SourcePin.SubPins.Num() > 0 && SubPins.Num() == 0) { GetSchema()->SplitPin(this); } #if WITH_EDITORONLY_DATA // Copy advanced visibility property, if it can be changed by user. // Otherwise we don't want to copy this, or we'd be ignoring new metadata that tries to hide old pins. UEdGraphNode* OuterNode = Cast<UEdGraphNode>(GetOuter()); if (OuterNode != nullptr && OuterNode->CanUserEditPinAdvancedViewFlag()) { bAdvancedView = SourcePin.bAdvancedView; } #endif // WITH_EDITORONLY_DATA }
void UEdGraphSchema::TrySetDefaultObject(UEdGraphPin& Pin, UObject* NewDefaultObject) const { Pin.DefaultObject = NewDefaultObject; #if WITH_EDITOR UEdGraphNode* Node = Pin.GetOwningNode(); check(Node); Node->PinDefaultValueChanged(&Pin); #endif //#if WITH_EDITOR }
void UEdGraphSchema::TrySetDefaultText(UEdGraphPin& InPin, const FText& InNewDefaultText) const { InPin.DefaultTextValue = InNewDefaultText; #if WITH_EDITOR UEdGraphNode* Node = InPin.GetOwningNode(); check(Node); Node->PinDefaultValueChanged(&InPin); #endif //#if WITH_EDITOR }
void UEdGraphSchema::TrySetDefaultValue(UEdGraphPin& Pin, const FString& NewDefaultValue) const { Pin.DefaultValue = NewDefaultValue; #if WITH_EDITOR UEdGraphNode* Node = Pin.GetOwningNode(); check(Node); Node->PinDefaultValueChanged(&Pin); #endif //#if WITH_EDITOR }
UEdGraphNode* FEdGraphSchemaAction_K2AddCallOnActor::PerformAction(class UEdGraph* ParentGraph, UEdGraphPin* FromPin, const FVector2D Location, bool bSelectNewNode/* = true*/) { const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); // Snap the node placement location to the grid, ensures calculations later match up better FVector2D LocalLocation; LocalLocation.X = FMath::GridSnap( Location.X, SNAP_GRID ); LocalLocation.Y = FMath::GridSnap( Location.Y, SNAP_GRID ); // First use the base functionality to spawn the 'call function' node UEdGraphNode* CallNode = FEdGraphSchemaAction_K2NewNode::PerformAction(ParentGraph, FromPin, LocalLocation); const float FunctionNodeHeightUnsnapped = UEdGraphSchema_K2::EstimateNodeHeight( CallNode ); // this is the guesstimate of the function node's height, snapped to grid units const float FunctionNodeHeight = FMath::GridSnap( FunctionNodeHeightUnsnapped, SNAP_GRID ); // this is roughly the middle of the function node height const float FunctionNodeMidY = LocalLocation.Y + FunctionNodeHeight * 0.5f; // this is the offset up from the mid point at which we start placing nodes const float StartYOffset = (float((LevelActors.Num() > 0) ? LevelActors.Num()-1 : 0) * -NodeLiteralHeight) * 0.5f; // The Y location we start placing nodes from const float ReferencedNodesPlacementYLocation = FunctionNodeMidY + StartYOffset; // Now we need to create the actor literal to wire up for ( int32 ActorIndex = 0; ActorIndex < LevelActors.Num(); ActorIndex++ ) { AActor* LevelActor = LevelActors[ActorIndex]; if(LevelActor != NULL) { UK2Node_Literal* LiteralNode = NewObject<UK2Node_Literal>(ParentGraph); ParentGraph->AddNode(LiteralNode, false, bSelectNewNode); LiteralNode->SetFlags(RF_Transactional); LiteralNode->SetObjectRef(LevelActor); LiteralNode->AllocateDefaultPins(); LiteralNode->NodePosX = LocalLocation.X - FunctionNodeLiteralReferencesXOffset; // this is the current offset down from the Y start location to place the next node at float CurrentNodeOffset = NodeLiteralHeight * float(ActorIndex); LiteralNode->NodePosY = ReferencedNodesPlacementYLocation + CurrentNodeOffset; LiteralNode->SnapToGrid(SNAP_GRID); // Connect the literal out to the self of the call UEdGraphPin* LiteralOutput = LiteralNode->GetValuePin(); UEdGraphPin* CallSelfInput = CallNode->FindPin(K2Schema->PN_Self); if(LiteralOutput != NULL && CallSelfInput != NULL) { LiteralOutput->MakeLinkTo(CallSelfInput); } } } return CallNode; }
void SFindInBT::MatchTokens(const TArray<FString>& Tokens) { RootSearchResult.Reset(); TWeakPtr<SGraphEditor> FocusedGraphEditor = BehaviorTreeEditorPtr.Pin()->GetFocusedGraphPtr(); UEdGraph* Graph = NULL; if (FocusedGraphEditor.IsValid()) { Graph = FocusedGraphEditor.Pin()->GetCurrentGraph(); } if (Graph == NULL) { return; } RootSearchResult = FSearchResult(new FFindInBTResult(FString("BehaviorTreeRoot"))); for (auto It(Graph->Nodes.CreateConstIterator()); It; ++It) { UEdGraphNode* Node = *It; const FString NodeName = Node->GetNodeTitle(ENodeTitleType::ListView).ToString(); FSearchResult NodeResult(new FFindInBTResult(NodeName, RootSearchResult, Node)); FString NodeSearchString = NodeName + Node->GetClass()->GetName() + Node->NodeComment; NodeSearchString = NodeSearchString.Replace(TEXT(" "), TEXT("")); bool bNodeMatchesSearch = StringMatchesSearchTokens(Tokens, NodeSearchString); UBehaviorTreeGraphNode* BTNode = Cast<UBehaviorTreeGraphNode>(Node); if (BTNode) { // searching through nodes' decorators for (auto DecoratorIt(BTNode->Decorators.CreateConstIterator()); DecoratorIt; ++DecoratorIt) { UBehaviorTreeGraphNode* Decorator = *DecoratorIt; MatchTokensInChild(Tokens, Decorator, NodeResult); } // searching through nodes' services for (auto ServiceIt(BTNode->Services.CreateConstIterator()); ServiceIt; ++ServiceIt) { UBehaviorTreeGraphNode* Service = *ServiceIt; MatchTokensInChild(Tokens, Service, NodeResult); } } if ((NodeResult->Children.Num() > 0) || bNodeMatchesSearch) { NodeResult->SetNodeHighlight(true); ItemsFound.Add(NodeResult); } } }
void SGraphEditorImpl::SelectAllNodes() { FGraphPanelSelectionSet NewSet; for (int32 NodeIndex = 0; NodeIndex < EdGraphObj->Nodes.Num(); ++NodeIndex) { UEdGraphNode* Node = EdGraphObj->Nodes[NodeIndex]; ensureMsg(Node->IsValidLowLevel(), TEXT("Node is invalid")); NewSet.Add(Node); } GraphPanel->SelectionManager.SetSelectionSet(NewSet); }
void FGraphCompilerContext::FindNodesByClass(const UEdGraph* Graph, TSubclassOf<UEdGraphNode> NodeClass, TArray<UEdGraphNode*>& FoundNodes) const { for (int32 NodeIndex = 0; NodeIndex < Graph->Nodes.Num(); ++NodeIndex) { UEdGraphNode* Node = Graph->Nodes[NodeIndex]; if (Node && Node->IsA(NodeClass)) { FoundNodes.Add(Node); } } }
UEdGraphNode* UEdGraph::CreateNode( TSubclassOf<UEdGraphNode> NewNodeClass, bool bSelectNewNode/* = true*/ ) { UEdGraphNode* NewNode = NewObject<UEdGraphNode>(this, NewNodeClass, NAME_None, RF_Transactional); if (HasAnyFlags(RF_Transient)) { NewNode->SetFlags(RF_Transient); } AddNode(NewNode, false, bSelectNewNode ); return NewNode; }
void UBehaviorTreeGraphNode_CompositeDecorator::PrepareForCopying() { Super::PrepareForCopying(); if (BoundGraph) { for (int32 i = 0; i < BoundGraph->Nodes.Num(); i++) { UEdGraphNode* Node = BoundGraph->Nodes[i]; Node->PrepareForCopying(); } } }
bool FSoundCueEditor::CanCopyNodes() const { // If any of the nodes can be duplicated then we should allow copying const FGraphPanelSelectionSet SelectedNodes = GetSelectedNodes(); for (FGraphPanelSelectionSet::TConstIterator SelectedIter(SelectedNodes); SelectedIter; ++SelectedIter) { UEdGraphNode* Node = Cast<UEdGraphNode>(*SelectedIter); if ((Node != NULL) && Node->CanDuplicateNode()) { return true; } } return false; }
bool FNiagaraEditor::CanCopyNodes() const { // If any of the nodes can be duplicated then we should allow copying TSharedPtr<SGraphEditor> CurrentGraphEditor = NodeGraphEditorPtr.Pin(); const FGraphPanelSelectionSet SelectedNodes = CurrentGraphEditor->GetSelectedNodes(); for (FGraphPanelSelectionSet::TConstIterator SelectedIter(SelectedNodes); SelectedIter; ++SelectedIter) { UEdGraphNode* Node = Cast<UEdGraphNode>(*SelectedIter); if (Node && Node->CanDuplicateNode()) { return true; } } return false; }
UEdGraphNode* FEdGraphSchemaAction_K2AddCallOnVariable::PerformAction(class UEdGraph* ParentGraph, UEdGraphPin* FromPin, const FVector2D Location, bool bSelectNewNode/* = true*/) { const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); // Snap the node placement location to the grid, ensures calculations later match up better FVector2D LocalLocation; LocalLocation.X = FMath::GridSnap( Location.X, SNAP_GRID ); LocalLocation.Y = FMath::GridSnap( Location.Y, SNAP_GRID ); // First use the base functionality to spawn the 'call function' node FVector2D TempLocation = LocalLocation; UEdGraphNode* CallNode = FEdGraphSchemaAction_K2NewNode::PerformAction(ParentGraph, FromPin, TempLocation, bSelectNewNode); // this is the guesstimate of the function node's height, snapped to grid units const float FunctionNodeHeight = FMath::GridSnap( TempLocation.Y - LocalLocation.Y, SNAP_GRID ); // this is roughly the middle of the function node height const float FunctionNodeMidY = LocalLocation.Y + FunctionNodeHeight * 0.5f; // this is the offset up from the mid point at which we start placing nodes const float StartYOffset = -NodeLiteralHeight * 0.5f; // The Y location we start placing nodes from const float ReferencedNodesPlacementYLocation = FunctionNodeMidY + StartYOffset; // Now we need to create the variable literal to wire up if(VariableName != NAME_None) { UK2Node_VariableGet* GetVarNode = NewObject<UK2Node_VariableGet>(ParentGraph); ParentGraph->AddNode(GetVarNode, false, bSelectNewNode); GetVarNode->SetFlags(RF_Transactional); GetVarNode->VariableReference.SetSelfMember(VariableName); GetVarNode->AllocateDefaultPins(); GetVarNode->NodePosX = LocalLocation.X - FunctionNodeLiteralReferencesXOffset; GetVarNode->NodePosY = ReferencedNodesPlacementYLocation; GetVarNode->SnapToGrid(SNAP_GRID); // Connect the literal out to the self of the call UEdGraphPin* LiteralOutput = GetVarNode->GetValuePin(); UEdGraphPin* CallSelfInput = CallNode->FindPin(K2Schema->PN_Self); if(LiteralOutput != NULL && CallSelfInput != NULL) { LiteralOutput->MakeLinkTo(CallSelfInput); } } return CallNode; }
FReply FDragConnection::DroppedOnNode(FVector2D ScreenPosition, FVector2D GraphPosition) { bool bHandledPinDropOnNode = false; UEdGraphNode* HoveredNode = GetHoveredNode(); if (HoveredNode) { // Gather any source drag pins TArray<UEdGraphPin*> ValidSourcePins; ValidateGraphPinList(/*out*/ ValidSourcePins); if (ValidSourcePins.Num()) { for (UEdGraphPin* SourcePin : ValidSourcePins) { // Check for pin drop support FText ResponseText; if (SourcePin->GetOwningNode() != HoveredNode && SourcePin->GetSchema()->SupportsDropPinOnNode(HoveredNode, SourcePin->PinType, SourcePin->Direction, ResponseText)) { bHandledPinDropOnNode = true; // Find which pin name to use and drop the pin on the node FString PinName = SourcePin->PinFriendlyName.IsEmpty()? SourcePin->PinName : SourcePin->PinFriendlyName.ToString(); const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "AddInParam", "Add In Parameter" ) ); UEdGraphPin* EdGraphPin = HoveredNode->GetSchema()->DropPinOnNode(GetHoveredNode(), PinName, SourcePin->PinType, SourcePin->Direction); if(EdGraphPin) { SourcePin->Modify(); EdGraphPin->Modify(); SourcePin->GetSchema()->TryCreateConnection(SourcePin, EdGraphPin); } } // If we have not handled the pin drop on node and there is an error message, do not let other actions occur. if(!bHandledPinDropOnNode && !ResponseText.IsEmpty()) { bHandledPinDropOnNode = true; } } } } return bHandledPinDropOnNode? FReply::Handled() : FReply::Unhandled(); }
void UEdGraphNode::AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector) { UEdGraphNode* This = CastChecked<UEdGraphNode>(InThis); // Only register the pool once per GC pass if (This->HasAnyFlags(RF_ClassDefaultObject)) { if (This->GetClass() == UEdGraphNode::StaticClass()) { for (int32 Index = 0; Index < PooledPins.Num(); ++Index) { Collector.AddReferencedObject(PooledPins[Index], This); } } } Super::AddReferencedObjects(This, Collector); }
TSharedPtr<SGraphPin> SGraphPanel::FGraphPinHandle::FindInGraphPanel(const SGraphPanel& InPanel) const { // First off, find the node TSharedPtr<SGraphNode> GraphNode = InPanel.GetNodeWidgetFromGuid(NodeGuid); if (GraphNode.IsValid()) { UEdGraphNode* Node = GraphNode->GetNodeObj(); UEdGraphPin* Pin = Node->FindPin(PinName); if (Pin) { return GraphNode->FindWidgetForPin(Pin); } } return TSharedPtr<SGraphPin>(); }
FText SGraphPin::GetTooltipText() const { FText HoverText = FText::GetEmpty(); UEdGraphNode* GraphNode = GraphPinObj ? GraphPinObj->GetOwningNodeUnchecked() : nullptr; if (GraphNode != nullptr) { FString HoverStr; GraphNode->GetPinHoverText(*GraphPinObj, /*out*/HoverStr); if (!HoverStr.IsEmpty()) { HoverText = FText::FromString(HoverStr); } } return HoverText; }
//------------------------------------------------------------------------------ UEdGraphNode* FBlueprintActionMenuItem::PerformAction(UEdGraph* ParentGraph, TArray<UEdGraphPin*>& FromPins, FVector2D const Location, bool bSelectNewNode/* = true*/) { UEdGraphPin* FromPin = nullptr; if (FromPins.Num() > 0) { FromPin = FromPins[0]; } UEdGraphNode* SpawnedNode = PerformAction(ParentGraph, FromPin, Location, bSelectNewNode); // try auto-wiring the rest of the pins (if there are any) for (int32 PinIndex = 1; PinIndex < FromPins.Num(); ++PinIndex) { SpawnedNode->AutowireNewNode(FromPins[PinIndex]); } return SpawnedNode; }
FReply FDragConnection::DroppedOnPin(FVector2D ScreenPosition, FVector2D GraphPosition) { TArray<UEdGraphPin*> ValidSourcePins; ValidateGraphPinList(/*out*/ ValidSourcePins); const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "GraphEd_CreateConnection", "Create Pin Link") ); UEdGraphPin* PinB = GetHoveredPin(); bool bError = false; TSet<UEdGraphNode*> NodeList; for (UEdGraphPin* PinA : ValidSourcePins) { if ((PinA != NULL) && (PinB != NULL)) { UEdGraph* MyGraphObj = PinA->GetOwningNode()->GetGraph(); if (MyGraphObj->GetSchema()->TryCreateConnection(PinA, PinB)) { NodeList.Add(PinA->GetOwningNode()); NodeList.Add(PinB->GetOwningNode()); } } else { bError = true; } } // Send all nodes that received a new pin connection a notification for (auto It = NodeList.CreateConstIterator(); It; ++It) { UEdGraphNode* Node = (*It); Node->NodeConnectionListChanged(); } if (bError) { return FReply::Unhandled(); } return FReply::Handled(); }
void UEdGraphSchema::BreakNodeLinks(UEdGraphNode& TargetNode) const { #if WITH_EDITOR for (TArray<UEdGraphPin*>::TIterator PinIt(TargetNode.Pins); PinIt; ++PinIt) { BreakPinLinks(*(*PinIt), false); } TargetNode.NodeConnectionListChanged(); #endif //#if WITH_EDITOR }