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_CommutativeAssociativeBinaryOperator::RemoveInputPin(UEdGraphPin* Pin)
{
	if(CanRemovePin(Pin))
	{
		FScopedTransaction Transaction( LOCTEXT("RemovePinTx", "RemovePin") );
		Modify();

		if (RemovePin(Pin))
		{
			--NumAdditionalInputs;

			int32 NameIndex = 0;
			const UEdGraphPin* OutPin = FindOutPin();
			const UEdGraphPin* SelfPin = FindSelfPin();
			for (int32 PinIndex = 0; PinIndex < Pins.Num(); ++PinIndex)
			{
				UEdGraphPin* LocalPin = Pins[PinIndex];
				if(LocalPin && (LocalPin != OutPin) && (LocalPin != SelfPin))
				{
					const FString PinName = GetNameForPin(NameIndex);
					if(PinName != LocalPin->PinName)
					{
						LocalPin->Modify();
						LocalPin->PinName = PinName;
					}
					NameIndex++;
				}
			}
			FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetBlueprint());
		}
	}
}
Esempio n. 3
0
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
}
UEdGraphPin* FWeakGraphPinPtr::Get()
{
	UEdGraphNode* Node = NodeObjectPtr.Get();
	if(Node != NULL)
	{
		// If pin is no longer valid or has a different owner, attempt to fix up the reference
		UEdGraphPin* Pin = PinObjectPtr.Get();
		if(Pin == NULL || Pin->GetOuter() != Node)
		{
			for(auto PinIter = Node->Pins.CreateConstIterator(); PinIter; ++PinIter)
			{
				UEdGraphPin* TestPin = *PinIter;
				if(TestPin->PinName.Equals(PinName))
				{
					Pin = TestPin;
					PinObjectPtr = Pin;
					break;
				}
			}
		}

		return Pin;
	}

	return NULL;
}
void USoundCueGraphNode_Base::InsertNewNode(UEdGraphPin* FromPin, UEdGraphPin* NewLinkPin, TSet<UEdGraphNode*>& OutNodeList)
{
	const USoundCueGraphSchema* Schema = CastChecked<USoundCueGraphSchema>(GetSchema());

	// The pin we are creating from already has a connection that needs to be broken. We want to "insert" the new node in between, so that the output of the new node is hooked up too
	UEdGraphPin* OldLinkedPin = FromPin->LinkedTo[0];
	check(OldLinkedPin);

	FromPin->BreakAllPinLinks();

	// Hook up the old linked pin to the first valid output pin on the new node
	for (int32 OutpinPinIdx=0; OutpinPinIdx<Pins.Num(); OutpinPinIdx++)
	{
		UEdGraphPin* OutputExecPin = Pins[OutpinPinIdx];
		check(OutputExecPin);
		if (ECanCreateConnectionResponse::CONNECT_RESPONSE_MAKE == Schema->CanCreateConnection(OldLinkedPin, OutputExecPin).Response)
		{
			if (Schema->TryCreateConnection(OldLinkedPin, OutputExecPin))
			{
				OutNodeList.Add(OldLinkedPin->GetOwningNode());
				OutNodeList.Add(this);
			}
			break;
		}
	}

	if (Schema->TryCreateConnection(FromPin, NewLinkPin))
	{
		OutNodeList.Add(FromPin->GetOwningNode());
		OutNodeList.Add(this);
	}
}
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());
	}
}
Esempio n. 7
0
UEdGraphPin* UEdGraphNode::CreatePin(EEdGraphPinDirection Dir, const FEdGraphPinType& InPinType, const FString& PinName, int32 Index /*= INDEX_NONE*/)
{
	UEdGraphPin* NewPin = NewObject<UEdGraphPin>(this);
	NewPin->PinName = PinName;
	NewPin->Direction = Dir;

	NewPin->PinType = InPinType;

	NewPin->SetFlags(RF_Transactional);

	if (HasAnyFlags(RF_Transient))
	{
		NewPin->SetFlags(RF_Transient);
	}

	Modify(false);
	if (Pins.IsValidIndex(Index))
	{
		Pins.Insert(NewPin, Index);
	}
	else
	{
		Pins.Add(NewPin);
	}
	return NewPin;
}
void UK2Node_SwitchEnum::AddPinToSwitchNode()
{
	// first try to restore unconnected pin, since connected one is always visible
	for(auto PinIt = Pins.CreateIterator(); PinIt; ++PinIt)
	{
		UEdGraphPin* Pin = *PinIt;
		if(Pin && (0 == Pin->LinkedTo.Num()) && Pin->bAdvancedView)
		{
			Pin->Modify();
			Pin->bAdvancedView = false;
			return;
		}
	}

	for(auto PinIt = Pins.CreateIterator(); PinIt; ++PinIt)
	{
		UEdGraphPin* Pin = *PinIt;
		if(Pin && Pin->bAdvancedView)
		{
			Pin->Modify();
			Pin->bAdvancedView = false;
			return;
		}
	}
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
void UK2Node_Select::PostReconstructNode()
{
	bReconstructNode = false;

	const UEdGraphSchema_K2* Schema = Cast<UEdGraphSchema_K2>(GetSchema());

	UEdGraphPin* ReturnPin = GetReturnValuePin();
	PinConnectionListChanged(ReturnPin);
	const bool bFillTypeFromReturn = Schema && ReturnPin && (ReturnPin->PinType.PinCategory != Schema->PC_Wildcard);

	TArray<UEdGraphPin*> OptionPins;
	GetOptionPins(OptionPins);
	for (auto It = OptionPins.CreateConstIterator(); It; It++)
	{
		UEdGraphPin* Pin = *It;
		const bool bTypeShouldBeFilled = Schema && Pin && (Pin->PinType.PinCategory == Schema->PC_Wildcard);
		if (bTypeShouldBeFilled && bFillTypeFromReturn)
		{
			Pin->Modify();
			Pin->PinType = ReturnPin->PinType;
			UEdGraphSchema_K2::ValidateExistingConnections(Pin);
		}

		PinConnectionListChanged(*It);
	}

	//After ReconstructNode we must be sure, that no additional reconstruction is required
	bReconstructNode = false;
}
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)
	}
}
Esempio n. 12
0
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
}
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();
	}
}
Esempio n. 14
0
FPinConnectionResponse UEdGraphSchema::CopyPinLinks(UEdGraphPin& CopyFromPin, UEdGraphPin& CopyToPin, bool bIsIntermediateCopy) const
{
#if WITH_EDITOR
	ensureMsg(bIsIntermediateCopy || !CopyToPin.GetOwningNode()->GetGraph()->HasAnyFlags(RF_Transient),
		TEXT("When copying to an Intermediate pin, use FKismetCompilerContext::CopyPinLinksToIntermediate() instead of UEdGraphSchema::CopyPinLinks()"));
#endif // #if WITH_EDITOR

	FPinConnectionResponse FinalResponse = FPinConnectionResponse(CONNECT_RESPONSE_MAKE, TEXT(""));
	for (int32 i=0; i<CopyFromPin.LinkedTo.Num(); i++)
	{
		UEdGraphPin* NewLink = CopyFromPin.LinkedTo[i];
		FPinConnectionResponse Response = CanCreateConnection(&CopyToPin, NewLink);
		if (Response.CanSafeConnect())
		{
			CopyToPin.MakeLinkTo(NewLink);
		}
		else
		{
			FinalResponse = Response;
		}
	}

	CopyToPin.DefaultValue = CopyFromPin.DefaultValue;
	CopyToPin.DefaultObject = CopyFromPin.DefaultObject;
	CopyToPin.DefaultTextValue = CopyFromPin.DefaultTextValue;
	return FinalResponse;
}
Esempio n. 15
0
bool SGraphPin::TryHandlePinConnection(SGraphPin& OtherSPin)
{
	UEdGraphPin* PinA = GetPinObj();
	UEdGraphPin* PinB = OtherSPin.GetPinObj();
	UEdGraph* MyGraphObj = PinA->GetOwningNode()->GetGraph();

	return MyGraphObj->GetSchema()->TryCreateConnection(PinA, PinB);
}
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 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
}
Esempio n. 18
0
// Reconcile other pin links:
//   - Links between nodes within the copied set are fine
//   - Links to nodes that were not copied need to be fixed up if the copy-paste was in the same graph or broken completely
// Call PostPasteNode on each node
void FEdGraphUtilities::PostProcessPastedNodes(TSet<UEdGraphNode*>& SpawnedNodes)
{
	// Run thru and fix up the node's pin links; they may point to invalid pins if the paste was to another graph
	for (TSet<UEdGraphNode*>::TIterator It(SpawnedNodes); It; ++It)
	{
		UEdGraphNode* Node = *It;
		UEdGraph* CurrentGraph = Node->GetGraph();

		for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex)
		{
			UEdGraphPin* ThisPin = Node->Pins[PinIndex];

			for (int32 LinkIndex = 0; LinkIndex < ThisPin->LinkedTo.Num(); )
			{
				UEdGraphPin* OtherPin = ThisPin->LinkedTo[LinkIndex];

				if (OtherPin == NULL)
				{
					// Totally bogus link
					ThisPin->LinkedTo.RemoveAtSwap(LinkIndex);
				}
				else if (!SpawnedNodes.Contains(OtherPin->GetOwningNode()))
				{
					// It's a link across the selection set, so it should be broken
					OtherPin->LinkedTo.RemoveSwap(ThisPin);
					ThisPin->LinkedTo.RemoveAtSwap(LinkIndex);
				}
				else if (!OtherPin->LinkedTo.Contains(ThisPin))
				{
					// The link needs to be reciprocal
					check(OtherPin->GetOwningNode()->GetGraph() == CurrentGraph);
					OtherPin->LinkedTo.Add(ThisPin);
					++LinkIndex;
				}
				else
				{
					// Everything seems fine but sanity check the graph
					check(OtherPin->GetOwningNode()->GetGraph() == CurrentGraph);
					++LinkIndex;
				}
			}
		}
	}

	// Give every node a chance to deep copy associated resources, etc...
	for (TSet<UEdGraphNode*>::TIterator It(SpawnedNodes); It; ++It)
	{
		UEdGraphNode* Node = *It;

		Node->PostPasteNode();
		Node->ReconstructNode();

		// Ensure we have RF_Transactional set on all pasted nodes, as its not copied in the T3D format
		Node->SetFlags(RF_Transactional);
	}
}
FReply FKismetVariableDragDropAction::DroppedOnNode(FVector2D ScreenPosition, FVector2D GraphPosition)
{
	UK2Node_Variable* TargetNode = Cast<UK2Node_Variable>(GetHoveredNode());

	if (TargetNode && (VariableName != TargetNode->GetVarName()))
	{
		const FScopedTransaction Transaction( LOCTEXT("ReplacePinVariable", "Replace Pin Variable") );

		UProperty* VariableProperty = GetVariableProperty();

		if(CanVariableBeDropped(VariableProperty, *TargetNode->GetGraph()))
		{
			const FString OldVarName = TargetNode->GetVarNameString();
			const UEdGraphSchema_K2* Schema = Cast<const UEdGraphSchema_K2>(TargetNode->GetSchema());

			TArray<class UEdGraphPin*> BadLinks;
			GetLinksThatWillBreak(TargetNode,VariableProperty,BadLinks);

			// Change the variable name and context
			UBlueprint* DropOnBlueprint = FBlueprintEditorUtils::FindBlueprintForGraph(TargetNode->GetGraph());
			UEdGraphPin* Pin = TargetNode->FindPin(OldVarName);
			DropOnBlueprint->Modify();
			TargetNode->Modify();

			if (Pin != NULL)
			{
				Pin->Modify();
			}

			UEdGraphSchema_K2::ConfigureVarNode(TargetNode, VariableName, VariableSource.Get(), DropOnBlueprint);


			if ((Pin == NULL) || (Pin->LinkedTo.Num() == BadLinks.Num()) || (Schema == NULL))
			{
				TargetNode->GetSchema()->ReconstructNode(*TargetNode);
			}
			else 
			{
				FEdGraphPinType NewPinType;
				Schema->ConvertPropertyToPinType(VariableProperty,NewPinType);

				Pin->PinName = VariableName.ToString();
				Pin->PinType = NewPinType;

				//break bad links
				for(TArray<class UEdGraphPin*>::TIterator OtherPinIt(BadLinks);OtherPinIt;)
				{
					Pin->BreakLinkTo(*OtherPinIt);
				}
			}

			return FReply::Handled();
		}
	}
	return FReply::Unhandled();
}
Esempio n. 20
0
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
	{
		RewireOldPinsToNewPins(OldPins, Pins);
	}


	if (bDestroyOldPins)
	{
		DestroyPinList(OldPins);
	}

	// Let subclasses do any additional work
	PostReconstructNode();

	GetGraph()->NotifyGraphChanged();
}
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 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());
}
Esempio n. 23
0
void FSoundCueEditor::DeleteInput()
{
	UEdGraphPin* SelectedPin = SoundCueGraphEditor->GetGraphPinForMenu();
	
	USoundCueGraphNode* SelectedNode = Cast<USoundCueGraphNode>(SelectedPin->GetOwningNode());

	if (SelectedNode && SelectedNode == SelectedPin->GetOwningNode())
	{
		SelectedNode->RemoveInputPin(SelectedPin);
	}
}
void FScriptExecutionTunnelExit::NavigateToExitSite(const uint32 TracePath) const
{
	UEdGraphPin* Pin = ObservedPin.Get();
	if (const FTunnelExitInstanceData* SearchResult = InstanceExitSiteInfo.Find(TracePath))
	{
		Pin = SearchResult->InstancePin.Get();
	}
	if (Pin)
	{
		FKismetEditorUtilities::BringKismetToFocusAttentionOnObject(Pin->GetOwningNode());
	}
}
void UK2Node_AddComponent::AllocatePinsForExposedVariables()
{
	const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();

	const UActorComponent* TemplateComponent = GetTemplateFromNode();
	const UClass* ComponentClass = TemplateComponent ? TemplateComponent->GetClass() : nullptr;

	if (ComponentClass != nullptr)
	{
		const UObject* ClassDefaultObject = ComponentClass ? ComponentClass->ClassDefaultObject : nullptr;

		for (TFieldIterator<UProperty> PropertyIt(ComponentClass, EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt)
		{
			UProperty* Property = *PropertyIt;
			const bool bNotDelegate = !Property->IsA(UMulticastDelegateProperty::StaticClass());
			const bool bIsExposedToSpawn = UEdGraphSchema_K2::IsPropertyExposedOnSpawn(Property);
			const bool bIsVisible = Property->HasAllPropertyFlags(CPF_BlueprintVisible);
			const bool bNotParam = !Property->HasAllPropertyFlags(CPF_Parm);
			if(bNotDelegate && bIsExposedToSpawn && bIsVisible && bNotParam)
			{
				FEdGraphPinType PinType;
				K2Schema->ConvertPropertyToPinType(Property, /*out*/ PinType);	
				const bool bIsUnique = (NULL == FindPin(Property->GetName()));
				if (K2Schema->FindSetVariableByNameFunction(PinType) && bIsUnique)
				{
					UEdGraphPin* Pin = CreatePin(EGPD_Input, TEXT(""), TEXT(""), NULL, false, false, Property->GetName());
					Pin->PinType = PinType;
					bHasExposedVariable = true;

					if ((ClassDefaultObject != nullptr) && K2Schema->PinDefaultValueIsEditable(*Pin))
					{
						FString DefaultValueAsString;
						const bool bDefaultValueSet = FBlueprintEditorUtils::PropertyValueToString(Property, reinterpret_cast<const uint8*>(ClassDefaultObject), DefaultValueAsString);
						check(bDefaultValueSet);
						K2Schema->TrySetDefaultValue(*Pin, DefaultValueAsString);
					}

					// Copy tooltip from the property.
					K2Schema->ConstructBasicPinTooltip(*Pin, Property->GetToolTipText(), Pin->PinToolTip);
				}
			}
		}
	}

	// Hide transform and attachment pins if it is not a scene component
	const bool bHideTransformPins = (ComponentClass != nullptr) ? !ComponentClass->IsChildOf(USceneComponent::StaticClass()) : false;

	UEdGraphPin* ManualAttachmentPin = GetManualAttachmentPin();
	ManualAttachmentPin->SafeSetHidden(bHideTransformPins);

	UEdGraphPin* TransformPin = GetRelativeTransformPin();
	TransformPin->SafeSetHidden(bHideTransformPins);
}
Esempio n. 26
0
UEdGraphPin* UEdGraphNode::AllocatePinFromPool(UEdGraphNode* OuterNode)
{
	if (PooledPins.Num() > 0)
	{
		UEdGraphPin* Result = PooledPins.Pop();
		Result->Rename(NULL, OuterNode);
		return Result;
	}
	else
	{
		UEdGraphPin* Result = NewObject<UEdGraphPin>(OuterNode);
		return Result;
	}
}
Esempio n. 27
0
ERenamePinResult UK2Node::RenameUserDefinedPin(const FString& OldName, const FString& NewName, bool bTest)
{
	UEdGraphPin* Pin = NULL;
	for (int32 PinIdx=0; PinIdx<Pins.Num(); PinIdx++)
	{
		if (OldName == Pins[PinIdx]->PinName)
		{
			Pin = Pins[PinIdx];
		}
		else if(NewName == Pins[PinIdx]->PinName)
		{
			return ERenamePinResult::ERenamePinResult_NameCollision;
		}
	}

	if(!Pin)
	{
		return ERenamePinResult::ERenamePinResult_NoSuchPin;
	}

	if(!bTest)
	{
		Pin->Modify();
		Pin->PinName = NewName;
		if(!Pin->DefaultTextValue.IsEmpty())
		{
			Pin->GetSchema()->TrySetDefaultText(*Pin, Pin->DefaultTextValue);
		}

		if (Pin->SubPins.Num() > 0)
		{
			TArray<UEdGraphPin*> PinsToUpdate = Pin->SubPins;

			while (PinsToUpdate.Num() > 0)
			{
				UEdGraphPin* PinToRename = PinsToUpdate.Pop(/*bAllowShrinking=*/ false);
				if (PinToRename->SubPins.Num() > 0)
				{
					PinsToUpdate.Append(PinToRename->SubPins);
				}
				PinToRename->Modify();
				PinToRename->PinName = NewName + PinToRename->PinName.RightChop(OldName.Len());
				PinToRename->PinFriendlyName = FText::FromString(NewName + PinToRename->PinFriendlyName.ToString().RightChop(OldName.Len()));
			}
		}
	}

	return ERenamePinResult::ERenamePinResult_Success;
}
void UMaterialGraphNode_Base::ModifyAndCopyPersistentPinData(UEdGraphPin& TargetPin, const UEdGraphPin& SourcePin) const
{
	if (SourcePin.LinkedTo.Num() > 0)
	{
		TargetPin.Modify();

		for (int32 LinkIndex = 0; LinkIndex < SourcePin.LinkedTo.Num(); ++LinkIndex)
		{
			UEdGraphPin* OtherPin = SourcePin.LinkedTo[LinkIndex];
			OtherPin->Modify();
		}
	}

	TargetPin.CopyPersistentDataFromOldPin(SourcePin);
}
/** Find Pin in array that matches pin */
static class UEdGraphPin* FindOtherLink(TArray<class UEdGraphPin*>& Links2, int32 OriginalIndex, class UEdGraphPin* PinToFind)
{
	//sometimes the order of the pins is different between revisions, although the pins themselves are unchanged, so we have to look at all of them
	UEdGraphNode* Node1 = PinToFind->GetOwningNode();
	for(auto It(Links2.CreateIterator());It;++It)
	{
		UEdGraphPin* Other = *It;
		UEdGraphNode* Node2 = Other->GetOwningNode();
		if(IsNodeMatch(Node1, Node2))
		{
			return Other;
		}
	}
	return Links2[OriginalIndex];
}
Esempio n. 30
0
const FSlateBrush* SGraphPin::GetPinStatusIcon() const
{
	UEdGraphPin* WatchedPin = ((GraphPinObj->Direction == EGPD_Input) && (GraphPinObj->LinkedTo.Num() > 0)) ? GraphPinObj->LinkedTo[0] : GraphPinObj;

	UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForNodeChecked(WatchedPin->GetOwningNode());

	if (FKismetDebugUtilities::IsPinBeingWatched(Blueprint, WatchedPin) )
	{
		return FEditorStyle::GetBrush( TEXT("Graph.WatchedPinIcon_Pinned") );
	}
	else
	{
		return NULL;
	}
}