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. 2
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);
}
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());
		}
	}
}
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. 6
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 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 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 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();
	}
}
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. 11
0
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 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();
}
Esempio n. 13
0
/** Determine if any pins are connected, if so make all the other pins the same type, if not, make sure pins are switched back to wildcards */
void UK2Node_Select::NotifyPinConnectionListChanged(UEdGraphPin* Pin)
{
	Super::NotifyPinConnectionListChanged(Pin);

	const UEdGraphSchema_K2* Schema = GetDefault<UEdGraphSchema_K2>();

	// If this is the Enum pin we need to set the enum and reconstruct the node
	if (Pin == GetIndexPin())
	{
		// If the index pin was just linked to another pin
		if (Pin->LinkedTo.Num() > 0)
		{
			UEdGraphPin* LinkPin = Pin->LinkedTo[0];
			IndexPinType = LinkPin->PinType;
			Pin->PinType = IndexPinType;

			// See if it was an enum pin
			if (LinkPin->PinType.PinCategory == Schema->PC_Byte &&
				LinkPin->PinType.PinSubCategoryObject != NULL &&
				LinkPin->PinType.PinSubCategoryObject->IsA(UEnum::StaticClass()))
			{
				UEnum* EnumPtr = Cast<UEnum>(LinkPin->PinType.PinSubCategoryObject.Get());
				SetEnum(EnumPtr);
			}
			else
			{
				SetEnum(NULL);
			}

			Schema->SetPinDefaultValueBasedOnType(Pin);

			GetGraph()->NotifyGraphChanged();
			UBlueprint* Blueprint = GetBlueprint();
			if(!Blueprint->bBeingCompiled)
			{
				FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
				Blueprint->BroadcastChanged();
			}

			// If the index pin is a boolean, we need to remove all but 2 options
			if (IndexPinType.PinCategory == Schema->PC_Boolean &&
				NumOptionPins != 2)
			{
				NumOptionPins = 2;
				bReconstructNode = true;
			}
		}
	}
	else
	{
		// Grab references to all option pins and the return pin
		TArray<UEdGraphPin*> OptionPins;
		GetOptionPins(OptionPins);
		UEdGraphPin* ReturnPin = FindPin(Schema->PN_ReturnValue);

		// See if this pin is one of the wildcard pins
		bool bIsWildcardPin = (Pin == ReturnPin || OptionPins.Find(Pin) != INDEX_NONE) && Pin->PinType.PinCategory == Schema->PC_Wildcard;

		// If the pin was one of the wildcards we have to handle it specially
		if (bIsWildcardPin)
		{
			// If the pin is linked, make sure the other wildcard pins match
			if (Pin->LinkedTo.Num() > 0)
			{
				// Set pin type on the pin
				Pin->PinType = Pin->LinkedTo[0]->PinType;

				// Make sure the return pin is the same pin type
				if (ReturnPin != Pin)
				{
					ReturnPin->Modify();

					ReturnPin->PinType = Pin->PinType;
					UEdGraphSchema_K2::ValidateExistingConnections(ReturnPin);
				}

				// Make sure all options are of the same pin type
				for (auto It = OptionPins.CreateConstIterator(); It; It++)
				{
					UEdGraphPin* OptionPin = (*It);
					if (*It && *It != Pin)
					{
						(*It)->Modify();

						(*It)->PinType = Pin->PinType;
						UEdGraphSchema_K2::ValidateExistingConnections(*It);
					}
				}

				bReconstructNode = true;
			}
		}
	}
}
Esempio n. 14
0
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();
}
Esempio n. 15
0
void FEnumEditorUtils::BroadcastChanges(const UUserDefinedEnum* Enum, const TArray<TPair<FName, int8>>& OldNames, bool bResolveData)
{
	check(NULL != Enum);
	if (bResolveData)
	{
		FArchiveEnumeratorResolver EnumeratorResolver(Enum, OldNames);

		TArray<UClass*> ClassesToCheck;
		for (TObjectIterator<UByteProperty> PropertyIter; PropertyIter; ++PropertyIter)
		{
			const UByteProperty* ByteProperty = *PropertyIter;
			if (ByteProperty && (Enum == ByteProperty->GetIntPropertyEnum()))
			{
				UClass* OwnerClass = ByteProperty->GetOwnerClass();
				if (OwnerClass)
				{
					ClassesToCheck.Add(OwnerClass);
				}
			}
		}

		for (FObjectIterator ObjIter; ObjIter; ++ObjIter)
		{
			for (auto ClassIter = ClassesToCheck.CreateConstIterator(); ClassIter; ++ClassIter)
			{
				if (ObjIter->IsA(*ClassIter))
				{
					ObjIter->Serialize(EnumeratorResolver);
					break;
				}
			}
		}
	}

	struct FNodeValidatorHelper
	{
		static bool IsValid(UK2Node* Node)
		{
			return Node
				&& (NULL != Cast<UEdGraph>(Node->GetOuter()))
				&& !Node->HasAnyFlags(RF_Transient | RF_PendingKill);
		}
	};

	TSet<UBlueprint*> BlueprintsToRefresh;

	{
		//CUSTOM NODES DEPENTENT ON ENUM

		for (TObjectIterator<UK2Node> It(RF_Transient); It; ++It)
		{
			UK2Node* Node = *It;
			INodeDependingOnEnumInterface* NodeDependingOnEnum = Cast<INodeDependingOnEnumInterface>(Node);
			if (FNodeValidatorHelper::IsValid(Node) && NodeDependingOnEnum && (Enum == NodeDependingOnEnum->GetEnum()))
			{
				if (UBlueprint* Blueprint = Node->GetBlueprint())
				{
					if (NodeDependingOnEnum->ShouldBeReconstructedAfterEnumChanged())
					{
						Node->ReconstructNode();
					}
					BlueprintsToRefresh.Add(Blueprint);
				}
			}
		}
	}

	for (TObjectIterator<UEdGraphPin> It(RF_Transient); It; ++It)
	{
		UEdGraphPin* Pin = *It;
		if (Pin && (Enum == Pin->PinType.PinSubCategoryObject.Get()) && (EEdGraphPinDirection::EGPD_Input == Pin->Direction))
		{
			UK2Node* Node = Cast<UK2Node>(Pin->GetOuter());
			if (FNodeValidatorHelper::IsValid(Node))
			{
				if (UBlueprint* Blueprint = Node->GetBlueprint())
				{
					if (INDEX_NONE == Enum->FindEnumIndex(*Pin->DefaultValue))
					{
						Pin->Modify();
						if (Blueprint->BlueprintType == BPTYPE_Interface)
						{
							Pin->DefaultValue = Enum->GetEnumName(0);
						}
						else
						{
							Pin->DefaultValue = FEnumEditorUtilsHelper::InvalidName();
						}
						Node->PinDefaultValueChanged(Pin);
						BlueprintsToRefresh.Add(Blueprint);
					}
				}
			}
		}
	}

	for (auto It = BlueprintsToRefresh.CreateIterator(); It; ++It)
	{
		FBlueprintEditorUtils::MarkBlueprintAsModified(*It);
		(*It)->BroadcastChanged();
	}

	FEnumEditorManager::Get().PostChange(Enum, EEnumEditorChangeInfo::Changed);
}
Esempio n. 16
0
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();
}
Esempio n. 17
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
	{
		// 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();
}
Esempio n. 18
0
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)
	{
		DefaultObject = SourcePin.DefaultObject;
		DefaultValue = SourcePin.DefaultValue;
	}

	const bool bTextValueWasModified = (SourcePin.DefaultTextValue.ToString() != SourcePin.AutogeneratedDefaultValue);
	if (bTextValueWasModified)
	{
		DefaultTextValue = SourcePin.DefaultTextValue;
	}

	// In K2 schemas the wildcard pins need to have their type copied before we get to pin splitting
	// TODO: Better less hacky way of this?
	if (PinType.PinCategory == TEXT("wildcard"))
	{
		PinType = SourcePin.PinType;
	}

	// 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
	if (SourcePin.SubPins.Num() > 0)
	{
		GetSchema()->SplitPin(this);
	}

#if WITH_EDITORONLY_DATA
	// Copy advanced visibility property, since it can be changed by user
	bAdvancedView = SourcePin.bAdvancedView;
#endif // WITH_EDITORONLY_DATA
}