Esempio n. 1
0
bool UK2Node_Select::CanChangePinType(UEdGraphPin* Pin) const
{
	// If this is the index pin, only allow type switching if nothing is linked to the pin
	if (Pin == GetIndexPin())
	{
		if (Pin->LinkedTo.Num() > 0)
		{
			return false;
		}
	}
	// Else it's one of the wildcard pins that share their type, so make sure none of them have a link
	else
	{
		if (GetReturnValuePin()->LinkedTo.Num() > 0)
		{
			return false;
		}
		else
		{
			TArray<UEdGraphPin*> OptionPins;
			GetOptionPins(OptionPins);
			for (auto It = OptionPins.CreateConstIterator(); It; It++)
			{
				UEdGraphPin* OptionPin = (*It);
				if (OptionPin && OptionPin->LinkedTo.Num() > 0)
				{
					return false;
				}
			}
		}
	}
	return true;
}
Esempio n. 2
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_EnumEquality::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);

	const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();

	// Get the enum equality node and the KismetMathLibrary function info for use when we build those nodes
	FName ConditionalFunctionName = "";
	UClass* ConditionalFunctionClass = NULL;
	GetConditionalFunction(ConditionalFunctionName, &ConditionalFunctionClass);

	// Create the conditional node we're replacing the enum node for
	UK2Node_CallFunction* ConditionalNode = SourceGraph->CreateBlankNode<UK2Node_CallFunction>();
	ConditionalNode->FunctionReference.SetExternalMember(ConditionalFunctionName, ConditionalFunctionClass);
	ConditionalNode->AllocateDefaultPins();
	CompilerContext.MessageLog.NotifyIntermediateObjectCreation(ConditionalNode, this);

	// Rewire the enum pins to the new conditional node
	UEdGraphPin* LeftSideConditionalPin = ConditionalNode->FindPinChecked(TEXT("A"));
	UEdGraphPin* RightSideConditionalPin = ConditionalNode->FindPinChecked(TEXT("B"));
	UEdGraphPin* ReturnConditionalPin = ConditionalNode->FindPinChecked(Schema->PN_ReturnValue);
	UEdGraphPin* Input1Pin = GetInput1Pin();
	UEdGraphPin* Input2Pin = GetInput2Pin();
	LeftSideConditionalPin->PinType = Input1Pin->PinType;
	RightSideConditionalPin->PinType = Input2Pin->PinType;
	CompilerContext.MovePinLinksToIntermediate(*Input1Pin, *LeftSideConditionalPin);
	CompilerContext.MovePinLinksToIntermediate(*Input2Pin, *RightSideConditionalPin);
	CompilerContext.MovePinLinksToIntermediate(*GetReturnValuePin(), *ReturnConditionalPin);

	// Break all links to the Select node so it goes away for at scheduling time
	BreakAllNodeLinks();
}
void UK2Node_AddComponent::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);

	auto TransformPin = GetRelativeTransformPin();
	if (TransformPin && !TransformPin->LinkedTo.Num())
	{
		FString DefaultValue;

		// Try and find the template and get relative transform from it
		UEdGraphPin* TemplateNamePin = GetTemplateNamePinChecked();
		const FString TemplateName = TemplateNamePin->DefaultValue;
		check(CompilerContext.Blueprint);
		USceneComponent* SceneCompTemplate = Cast<USceneComponent>(CompilerContext.Blueprint->FindTemplateByName(FName(*TemplateName)));
		if (SceneCompTemplate)
		{
			FTransform TemplateTransform = FTransform(SceneCompTemplate->RelativeRotation, SceneCompTemplate->RelativeLocation, SceneCompTemplate->RelativeScale3D);
			DefaultValue = TemplateTransform.ToString();
		}

		auto ValuePin = InnerHandleAutoCreateRef(this, TransformPin, CompilerContext, SourceGraph, !DefaultValue.IsEmpty());
		if (ValuePin)
		{
			ValuePin->DefaultValue = DefaultValue;
		}
	}

	if (bHasExposedVariable)
	{
		static FString ObjectParamName = FString(TEXT("Object"));
		static FString ValueParamName = FString(TEXT("Value"));
		static FString PropertyNameParamName = FString(TEXT("PropertyName"));

		UK2Node_AddComponent* NewNode = CompilerContext.SpawnIntermediateNode<UK2Node_AddComponent>(this, SourceGraph); 
		NewNode->SetFromFunction(GetTargetFunction());
		NewNode->AllocateDefaultPinsWithoutExposedVariables();

		// function parameters
		const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
		CompilerContext.MovePinLinksToIntermediate(*FindPin(K2Schema->PN_Self), *NewNode->FindPin(K2Schema->PN_Self));
		CompilerContext.MovePinLinksToIntermediate(*GetTemplateNamePinChecked(), *NewNode->GetTemplateNamePinChecked());
		CompilerContext.MovePinLinksToIntermediate(*GetRelativeTransformPin(), *NewNode->GetRelativeTransformPin());
		CompilerContext.MovePinLinksToIntermediate(*GetManualAttachmentPin(), *NewNode->GetManualAttachmentPin());

		UEdGraphPin* ReturnPin = NewNode->GetReturnValuePin();
		UEdGraphPin* OriginalReturnPin = GetReturnValuePin();
		check((NULL != ReturnPin) && (NULL != OriginalReturnPin));
		ReturnPin->PinType = OriginalReturnPin->PinType;
		CompilerContext.MovePinLinksToIntermediate(*OriginalReturnPin, *ReturnPin);
		// exec in
		CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *NewNode->GetExecPin());

		UEdGraphPin* LastThen = FKismetCompilerUtilities::GenerateAssignmentNodes( CompilerContext, SourceGraph, NewNode, this, ReturnPin, GetSpawnedType() );

		CompilerContext.MovePinLinksToIntermediate(*GetThenPin(), *LastThen);
		BreakAllNodeLinks();
	}
}
void UK2Node_AddComponent::PostPasteNode()
{
	Super::PostPasteNode();

	// There is a template associated with this node that should be unique, but after a node is pasted, it either points to a
	// template shared by the copied node, or to nothing (when pasting into a different blueprint)
	const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
	UBlueprint* Blueprint = GetBlueprint();

	// Find the template name and return type pins
	UEdGraphPin* TemplateNamePin = GetTemplateNamePin();
	UEdGraphPin* ReturnPin = GetReturnValuePin();
	if ((TemplateNamePin != NULL) && (ReturnPin != NULL))
	{
		// Find the current template if it exists
		FString TemplateName = TemplateNamePin->DefaultValue;
		UActorComponent* SourceTemplate = Blueprint->FindTemplateByName(FName(*TemplateName));

		// Determine the type of the component needed
		UClass* ComponentClass = Cast<UClass>(ReturnPin->PinType.PinSubCategoryObject.Get());
			
		if (ComponentClass)
		{
			ensure(NULL != Cast<UBlueprintGeneratedClass>(Blueprint->GeneratedClass));
			// Create a new template object and update the template pin to point to it
			UActorComponent* NewTemplate = NewObject<UActorComponent>(Blueprint->GeneratedClass, ComponentClass, NAME_None, RF_ArchetypeObject|RF_Public);
			Blueprint->ComponentTemplates.Add(NewTemplate);

			TemplateNamePin->DefaultValue = NewTemplate->GetName();

			// Copy the old template data over to the new template if it's compatible
			if ((SourceTemplate != NULL) && (SourceTemplate->GetClass()->IsChildOf(ComponentClass)))
			{
				TArray<uint8> SavedProperties;
				FObjectWriter Writer(SourceTemplate, SavedProperties);
				FObjectReader(NewTemplate, SavedProperties);
			}
			else if(TemplateBlueprint.Len() > 0)
			{
				// try to find/load our blueprint to copy the template
				UBlueprint* SourceBlueprint = FindObject<UBlueprint>(NULL, *TemplateBlueprint);
				if(SourceBlueprint != NULL)
				{
					SourceTemplate = SourceBlueprint->FindTemplateByName(FName(*TemplateName));
					if ((SourceTemplate != NULL) && (SourceTemplate->GetClass()->IsChildOf(ComponentClass)))
					{
						TArray<uint8> SavedProperties;
						FObjectWriter Writer(SourceTemplate, SavedProperties);
						FObjectReader(NewTemplate, SavedProperties);
					}
				}

				TemplateBlueprint.Empty();
			}
		}
		else
		{
			// Clear the template connection; can't resolve the type of the component to create
			ensure(false);
			TemplateNamePin->DefaultValue = TEXT("");
		}
	}
}
Esempio n. 6
0
void UK2Node_Select::PinTypeChanged(UEdGraphPin* Pin)
{
	const UEdGraphSchema_K2* Schema = GetDefault<UEdGraphSchema_K2>();

	if (Pin == GetIndexPin())
	{
		if (IndexPinType != Pin->PinType)
		{
			IndexPinType = Pin->PinType;

			if (IndexPinType.PinSubCategoryObject.IsValid())
			{
				SetEnum(Cast<UEnum>(IndexPinType.PinSubCategoryObject.Get()));
			}
			else if (Enum)
			{
				SetEnum(NULL);
			}

			// Remove all but two options if we switched to a bool index
			if (IndexPinType.PinCategory == Schema->PC_Boolean)
			{
				if (NumOptionPins > 2)
				{
					NumOptionPins = 2;
					bReconstructNode = true;
				}
			}

			// Reset the default value
			Schema->SetPinDefaultValueBasedOnType(Pin);
		}
	}
	else
	{
		// Set the return value
		UEdGraphPin* ReturnPin = GetReturnValuePin();
		if (ReturnPin->PinType != Pin->PinType)
		{
			ReturnPin->PinType = Pin->PinType;
			Schema->SetPinDefaultValueBasedOnType(ReturnPin);
		}

		// Set the options
		TArray<UEdGraphPin*> OptionPins;
		GetOptionPins(OptionPins);
		for (auto It = OptionPins.CreateConstIterator(); It; It++)
		{
			UEdGraphPin* OptionPin = (*It);
			if (OptionPin->PinType != Pin->PinType ||
				OptionPin == Pin)
			{
				OptionPin->PinType = Pin->PinType;
				Schema->SetPinDefaultValueBasedOnType(OptionPin);
			}
		}
	}


	// Reconstruct the node since the options could change
	if (bReconstructNode)
	{
		ReconstructNode();
	}

	// Let the graph know to refresh
	GetGraph()->NotifyGraphChanged();

	UBlueprint* Blueprint = GetBlueprint();
	if(!Blueprint->bBeingCompiled)
	{
		FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
		Blueprint->BroadcastChanged();
	}
}
void UK2Node_ConvertAsset::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);
	const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();
	
	UClass* TargetType = GetTargetClass();
	if (TargetType && Schema && (2 == Pins.Num()))
	{
		const bool bIsAssetClass = IsAssetClassType();

		//Create Convert Function
		auto ConvertToObjectFunc = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
		const FName ConvertFunctionName = bIsAssetClass 
			? GET_FUNCTION_NAME_CHECKED(UKismetSystemLibrary, Conv_AssetClassToClass) 
			: GET_FUNCTION_NAME_CHECKED(UKismetSystemLibrary, Conv_AssetToObject);
		ConvertToObjectFunc->FunctionReference.SetExternalMember(ConvertFunctionName, UKismetSystemLibrary::StaticClass());
		ConvertToObjectFunc->AllocateDefaultPins();

		//Connect input to convert
		auto InputPin = FindPin(UK2Node_ConvertAssetImpl::InputPinName);
		const FString ConvertInputName = bIsAssetClass
			? FString(TEXT("AssetClass"))
			: FString(TEXT("Asset"));
		auto ConvertInput = ConvertToObjectFunc->FindPin(ConvertInputName);
		bool bIsErrorFree = InputPin && ConvertInput && CompilerContext.MovePinLinksToIntermediate(*InputPin, *ConvertInput).CanSafeConnect();

		auto ConvertOutput = ConvertToObjectFunc->GetReturnValuePin();
		UEdGraphPin* InnerOutput = nullptr;
		if (UObject::StaticClass() != TargetType)
		{
			//Create Cast Node
			UK2Node_DynamicCast* CastNode = bIsAssetClass
				? CompilerContext.SpawnIntermediateNode<UK2Node_ClassDynamicCast>(this, SourceGraph)
				: CompilerContext.SpawnIntermediateNode<UK2Node_DynamicCast>(this, SourceGraph);
			CastNode->SetPurity(true);
			CastNode->TargetType = TargetType;
			CastNode->AllocateDefaultPins();

			// Connect Object/Class to Cast
			auto CastInput = CastNode->GetCastSourcePin();
			bIsErrorFree &= ConvertOutput && CastInput && Schema->TryCreateConnection(ConvertOutput, CastInput);

			// Connect output to cast
			InnerOutput = CastNode->GetCastResultPin();
		}
		else
		{
			InnerOutput = ConvertOutput;
		}

		auto OutputPin = FindPin(UK2Node_ConvertAssetImpl::OutputPinName);
		bIsErrorFree &= OutputPin && InnerOutput && CompilerContext.MovePinLinksToIntermediate(*OutputPin, *InnerOutput).CanSafeConnect();

		if (!bIsErrorFree)
		{
			CompilerContext.MessageLog.Error(*LOCTEXT("InternalConnectionError", "K2Node_ConvertAsset: Internal connection error. @@").ToString(), this);
		}

		BreakAllNodeLinks();
	}
}