// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. #include "BlueprintGraphPrivatePCH.h" #include "Engine/Breakpoint.h" #include "K2Node.h" #include "KismetDebugUtilities.h" // for HasDebuggingData(), GetWatchText() #include "KismetCompiler.h" #include "GraphEditorSettings.h" #define LOCTEXT_NAMESPACE "K2Node" // File-Scoped Globals static const uint32 MaxArrayPinTooltipLineCount = 10; ///////////////////////////////////////////////////// // UK2Node UK2Node::UK2Node(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { } void UK2Node::PostLoad() { Super::PostLoad(); // fix up pin default values FixupPinDefaultValues(); } void UK2Node::FixupPinDefaultValues() { const int32 LinkerUE4Version = GetLinkerUE4Version(); const UEdGraphSchema_K2* K2Schema = GetDefault(); // Swap "new" default error tolerance value with zero on vector/rotator equality nodes, in order to preserve current behavior in existing blueprints. if(LinkerUE4Version < VER_UE4_BP_MATH_VECTOR_EQUALITY_USES_EPSILON) { static const FString VectorsEqualFunctionEpsilonPinName = TEXT("KismetMathLibrary.EqualEqual_VectorVector.ErrorTolerance"); static const FString VectorsNotEqualFunctionEpsilonPinName = TEXT("KismetMathLibrary.NotEqual_VectorVector.ErrorTolerance"); static const FString RotatorsEqualFunctionEpsilonPinName = TEXT("KismetMathLibrary.EqualEqual_RotatorRotator.ErrorTolerance"); static const FString RotatorsNotEqualFunctionEpsilonPinName = TEXT("KismetMathLibrary.NotEqual_RotatorRotator.ErrorTolerance"); bool bFoundPin = false; for(int32 i = 0; i < Pins.Num() && !bFoundPin; ++i) { UEdGraphPin* Pin = Pins[i]; check(Pin); TArray RedirectPinNames; GetRedirectPinNames(*Pin, RedirectPinNames); for(auto PinNameIter = RedirectPinNames.CreateConstIterator(); PinNameIter && !bFoundPin; ++PinNameIter) { if((Pin->DefaultValue == Pin->AutogeneratedDefaultValue) && (*PinNameIter == VectorsEqualFunctionEpsilonPinName || *PinNameIter == VectorsNotEqualFunctionEpsilonPinName || *PinNameIter == RotatorsEqualFunctionEpsilonPinName || *PinNameIter == RotatorsNotEqualFunctionEpsilonPinName)) { bFoundPin = true; K2Schema->TrySetDefaultValue(*Pin, TEXT("0.0")); } } } } } FText UK2Node::GetToolTipHeading() const { FText Heading = FText::GetEmpty(); if (UBreakpoint* ExistingBreakpoint = FKismetDebugUtilities::FindBreakpointForNode(GetBlueprint(), this)) { if (ExistingBreakpoint->IsEnabled()) { Heading = LOCTEXT("EnabledBreakpoint", "Active Breakpoint"); FText ActiveBreakpointToolTipText = GetActiveBreakpointToolTipText(); if (!ActiveBreakpointToolTipText.IsEmpty()) { Heading = FText::Format(FText::FromString("{0} - {1}"), Heading, ActiveBreakpointToolTipText); } } else { Heading = LOCTEXT("DisabledBreakpoint", "Disabled Breakpoint"); } } return Heading; } FText UK2Node::GetActiveBreakpointToolTipText() const { return LOCTEXT("ActiveBreakpointToolTip", "Execution will break at this location."); } bool UK2Node::CreatePinsForFunctionEntryExit(const UFunction* Function, bool bForFunctionEntry) { const UEdGraphSchema_K2* K2Schema = GetDefault(); // Create the inputs and outputs bool bAllPinsGood = true; for (TFieldIterator PropIt(Function); PropIt && (PropIt->PropertyFlags & CPF_Parm); ++PropIt) { UProperty* Param = *PropIt; const bool bIsFunctionInput = !Param->HasAnyPropertyFlags(CPF_OutParm) || Param->HasAnyPropertyFlags(CPF_ReferenceParm); if (bIsFunctionInput == bForFunctionEntry) { const EEdGraphPinDirection Direction = bForFunctionEntry ? EGPD_Output : EGPD_Input; UEdGraphPin* Pin = CreatePin(Direction, TEXT(""), TEXT(""), NULL, false, false, Param->GetName()); const bool bPinGood = K2Schema->ConvertPropertyToPinType(Param, /*out*/ Pin->PinType); K2Schema->SetPinDefaultValueBasedOnType(Pin); UK2Node_CallFunction::GeneratePinTooltipFromFunction(*Pin, Function); bAllPinsGood = bAllPinsGood && bPinGood; } } return bAllPinsGood; } void UK2Node::AutowireNewNode(UEdGraphPin* FromPin) { const UEdGraphSchema_K2* K2Schema = CastChecked(GetSchema()); // Do some auto-connection if (FromPin != NULL) { TSet NodeList; // sometimes we don't always find an ideal connection, but we want to exhaust // all our options first... this stores a secondary less-ideal pin to connect to, if nothing better was found UEdGraphPin* BackupConnection = NULL; // If not dragging an exec pin, auto-connect from dragged pin to first compatible pin on the new node for (int32 i=0; i