// Copyright (c) Samuel Kahn (samuel@kahncode.com). All Rights Reserved. #include "K2Node_BlobOperation.h" #include "Blob.h" #include "BlueprintActionDatabaseRegistrar.h" #include "BlueprintFieldNodeSpawner.h" #include "EdGraphSchema_K2.h" #include "EdGraphUtilities.h" #include "EditorCategoryUtils.h" #include "K2Node_CallFunction.h" #include "KismetCompiler.h" #define LOCTEXT_NAMESPACE "K2Node_BlobOperation" ////////////////////////////////////////////////////////////////////////// // UK2Node_BlobOperation void UK2Node_BlobOperation::AllocateDefaultPins() { CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute); CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then); AdvancedPinDisplay = ENodeAdvancedPins::Hidden; } void UK2Node_BlobOperation::AllocateBehaviorPin() { UEdGraphPin* BehaviorPin = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Byte, FName(TEXT("Behavior"))); BehaviorPin->bAdvancedView = true; static UEnum* ArchiveTypeEnum = FindObjectChecked(ANY_PACKAGE, TEXT("EBlobArchivetype"), /*ExactClass*/ true); BehaviorPin->PinType.PinSubCategoryObject = ArchiveTypeEnum; BehaviorPin->DefaultValue = ArchiveTypeEnum->GetNameStringByValue((int8)EBlobArchiveType::Default); BehaviorPin->bAdvancedView = true; } void UK2Node_BlobOperation::AllocateNetContextPin() { UEdGraphPin* Pin = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Object, FName(TEXT("NetContext"))); Pin->PinType.PinSubCategoryObject = UObject::StaticClass(); Pin->bAdvancedView = true; } void UK2Node_BlobOperation::PreloadRequiredAssets() { if (StructType) PreloadObject(StructType); Super::PreloadRequiredAssets(); } void UK2Node_BlobOperation::ValidateNodeDuringCompilation(class FCompilerResultsLog& MessageLog) const { Super::ValidateNodeDuringCompilation(MessageLog); if (!StructType) { MessageLog.Error(*LOCTEXT("NoStruct_Error", "No Struct connected to @@").ToString(), this); } else if (StructType == FBlob::StaticStruct()) { MessageLog.Error(*LOCTEXT("BlobToBlob_Error", "@@ cannot convert BinaryBlob into a BinaryBlob").ToString(), this); } } FLinearColor UK2Node_BlobOperation::GetNodeTitleColor() const { if (const UEdGraphSchema_K2* K2Schema = GetDefault()) { FEdGraphPinType PinType; PinType.PinCategory = UEdGraphSchema_K2::PC_Struct; PinType.PinSubCategoryObject = StructType; return K2Schema->GetPinTypeColor(PinType); } return UK2Node::GetNodeTitleColor(); } void UK2Node_BlobOperation::ConvertDeprecatedNode(UEdGraph* Graph, bool bOnlySafeChanges) { // User may have since deleted the struct type if (StructType == nullptr) { return; } } bool UK2Node_BlobOperation::HasExternalDependencies(TArray* OptionalOutput /*= nullptr*/) const { const bool bResult = nullptr != StructType; if (bResult && OptionalOutput) { OptionalOutput->AddUnique(StructType); } const bool bSuperResult = Super::HasExternalDependencies(OptionalOutput); return bSuperResult || bResult; } void UK2Node_BlobOperation::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const { // actions get registered under specific object-keys; the idea is that // actions might have to be updated (or deleted) if their object-key is // mutated (or removed)... here we use the node's class (so if the node // type disappears, then the action should go with it) UClass* ActionKey = GetClass(); // to keep from needlessly instantiating a UBlueprintNodeSpawner, first // check to make sure that the registrar is looking for actions of this type // (could be regenerating actions for a specific asset, and therefore the // registrar would only accept actions corresponding to that asset) if (ActionRegistrar.IsOpenForRegistration(ActionKey)) { UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create(GetClass()); check(NodeSpawner != nullptr); ActionRegistrar.AddBlueprintAction(ActionKey, NodeSpawner); } } void UK2Node_BlobOperation::PostReconstructNode() { Super::PostReconstructNode(); RefreshStructPinType(); } FText UK2Node_BlobOperation::GetMenuCategory() const { return FText::FromString(TEXT("BlobSerialization")); } void UK2Node_BlobOperation::RefreshStructPinType() { UEdGraphPin* StructPin = GetStructPin(); if (StructPin->LinkedTo.Num() == 1) { UEdGraphPin* ConnectedPin = StructPin->LinkedTo[0]; StructType = Cast(ConnectedPin->PinType.PinSubCategoryObject); } else { StructType = nullptr; } StructPin->PinType.PinSubCategoryObject = StructType; StructPin->PinType.PinCategory = (StructType == nullptr) ? UEdGraphSchema_K2::PC_Wildcard : UEdGraphSchema_K2::PC_Struct; } void UK2Node_BlobOperation::NotifyPinConnectionListChanged(UEdGraphPin* Pin) { Super::NotifyPinConnectionListChanged(Pin); if (Pin == GetStructPin()) { RefreshStructPinType(); } } void UK2Node_BlobOperation::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) { Super::ExpandNode(CompilerContext, SourceGraph); if (!StructType) { RefreshStructPinType(); } } UEdGraphPin* UK2Node_BlobOperation::GetThenPin() const { UEdGraphPin* Pin = FindPin(UEdGraphSchema_K2::PN_Then); check(Pin == nullptr || Pin->Direction == EGPD_Output); // If pin exists, it must be output return Pin; } UEdGraphPin* UK2Node_BlobOperation::GetStructPin() const { return FindPin(TEXT("Struct")); } UEdGraphPin* UK2Node_BlobOperation::GetBlobPin() const { return FindPin(TEXT("Blob")); } UEdGraphPin* UK2Node_BlobOperation::GetBehaviorPin() const { return FindPin(TEXT("Behavior")); } UEdGraphPin* UK2Node_BlobOperation::GetNetContextPin() const { return FindPin(TEXT("NetContext")); } #undef LOCTEXT_NAMESPACE