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; }
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(""); } } }
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(); } }