예제 #1
0
void UK2Node_VariableGet::Serialize(FArchive& Ar)
{
	// The following code is to attempt to log info related to UE-19729
	if (Ar.IsSaving() && !Ar.IsTransacting())
	{
		if (UEdGraph* Graph = Cast<UEdGraph>(GetOuter()))
		{
			if (UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraph(Graph))
			{
				if (!Blueprint->bBeingCompiled)
				{
					FString VariableName = GetVarNameString();
					FString BlueprintPath = Blueprint->GetPathName();
					FString SetupStyle = bIsPureGet? TEXT("pure") : TEXT("validated");
					UE_LOG(LogBlueprintUserMessages, Log, TEXT("Serialization for Get node for variable '%s' in Blueprint '%s' which is setup as %s"), *VariableName, *BlueprintPath, *SetupStyle);

					// The following line may spur the crash noted in UE-19729 and will confirm that the crash happens before the FiB gather.
					GetNodeTitle(ENodeTitleType::ListView);
				}
			}
			
		}
	}
	Super::Serialize(Ar);
}
void UK2Node_VariableGet::CreateNonPurePins(TArray<UEdGraphPin*>* InOldPinsPtr)
{
	const UEdGraphSchema_K2* K2Schema = Cast<UEdGraphSchema_K2>(GetSchema());
	check(K2Schema != nullptr);
	if (!K2Schema->DoesGraphSupportImpureFunctions(GetGraph()))
	{
		bIsPureGet = true;
	}

	if (!bIsPureGet)
	{
		FEdGraphPinType PinType;
		UProperty* VariableProperty = GetPropertyForVariable();

		// We need the pin's type, to both see if it's an array and if it is of the correct types to remain an impure node
		if (VariableProperty)
		{
			K2Schema->ConvertPropertyToPinType(GetPropertyForVariable(), PinType);
		}
		// If there is no property and we are given some old pins to look at, find the old value pin and use the type there
		// This allows nodes to be pasted into other BPs without access to the property
		else if(InOldPinsPtr)
		{
			// find old variable pin and use the type.
			const FString PinName = GetVarNameString();
			for(auto Iter = InOldPinsPtr->CreateConstIterator(); Iter; ++Iter)
			{
				if(const UEdGraphPin* Pin = *Iter)
				{
					if(PinName == Pin->PinName)
					{
						PinType = Pin->PinType;
						break;
					}
				}
			}

		}

		if (IsValidTypeForNonPure(PinType))
		{
			// Input - Execution Pin
			CreatePin(EGPD_Input, K2Schema->PC_Exec, TEXT(""), NULL, false, false, K2Schema->PN_Execute);

			// Output - Execution Pins
			UEdGraphPin* ValidPin = CreatePin(EGPD_Output, K2Schema->PC_Exec, TEXT(""), NULL, false, false, K2Schema->PN_Then);
			ValidPin->PinFriendlyName = LOCTEXT("Valid", "Is Valid");

			UEdGraphPin* InvalidPin = CreatePin(EGPD_Output, K2Schema->PC_Exec, TEXT(""), NULL, false, false, K2Schema->PN_Else);
			InvalidPin->PinFriendlyName = LOCTEXT("Invalid", "Is Not Valid");
		}
		else
		{
			bIsPureGet = true;
		}
	}
}
FText UK2Node_StructMemberGet::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
	if (CachedNodeTitle.IsOutOfDate(this))
	{
		FFormatNamedArguments Args;
		Args.Add(TEXT("VariableName"), FText::FromString(GetVarNameString()));
		// FText::Format() is slow, so we cache this to save on performance
		CachedNodeTitle.SetCachedText(FText::Format(LOCTEXT("GetMembersInVariable", "Get members in {VariableName}"), Args), this);
	}
	return CachedNodeTitle;
}
FText UK2Node_StructMemberGet::GetTooltipText() const
{
	if (CachedTooltip.IsOutOfDate(this))
	{
		FFormatNamedArguments Args;
		Args.Add(TEXT("VariableName"), FText::FromString(GetVarNameString()));
		// FText::Format() is slow, so we cache this to save on performance
		CachedTooltip.SetCachedText(FText::Format(LOCTEXT("K2Node_StructMemberGet_Tooltip", "Get member variables of {VariableName}"), Args), this);
	}
	return CachedTooltip;
}
UProperty* UK2Node_Variable::GetPropertyForVariable() const
{
	const FName VarName = GetVarName();
	UEdGraphPin* VariablePin = FindPin(GetVarNameString());

	UProperty* VariableProperty = nullptr;

	// Need to look at parent Blueprint's skeleton classes to see if the variable property can resolve there.
	UClass* CurrentGeneratedClass = GetBlueprint()->GeneratedClass;
	while(CurrentGeneratedClass && VariableProperty == nullptr)
	{
		if(UBlueprint* CurrentBlueprint = Cast<UBlueprint>(CurrentGeneratedClass->ClassGeneratedBy))
		{
			VariableProperty = VariableReference.ResolveMember<UProperty>(CurrentBlueprint->SkeletonGeneratedClass);
			CurrentGeneratedClass = CurrentBlueprint->ParentClass;
		}
		else
		{
			break;
		}
	}

	// if the variable has been deprecated, don't use it
	if(VariableProperty != NULL)
	{
		if (VariableProperty->HasAllPropertyFlags(CPF_Deprecated))
		{
			VariableProperty = NULL;
		}
		// If the variable has been remapped update the pin
		else if (VariablePin && VarName != GetVarName())
		{
			VariablePin->PinName = GetVarNameString();
		}
	}

	return VariableProperty;
}
예제 #6
0
UProperty* UK2Node_Variable::GetPropertyForVariable() const
{
	const FName VarName = GetVarName();
	UEdGraphPin* VariablePin = FindPin(GetVarNameString());

	UProperty* VariableProperty = VariableReference.ResolveMember<UProperty>(GetBlueprintClassFromNode());

	// if the variable has been deprecated, don't use it
	if(VariableProperty != NULL)
	{
		if (VariableProperty->HasAllPropertyFlags(CPF_Deprecated))
		{
			VariableProperty = NULL;
		}
		// If the variable has been remapped update the pin
		else if (VariablePin && VarName != GetVarName())
		{
			VariablePin->PinName = GetVarNameString();
		}
	}

	return VariableProperty;
}
예제 #7
0
bool UK2Node_Variable::CreatePinForVariable(EEdGraphPinDirection Direction, FString InPinName/* = FString()*/)
{
	const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();

	UProperty* VariableProperty = GetPropertyForVariable();
	// favor the skeleton property if possible (in case the property type has 
	// been changed, and not yet compiled).
	if (!VariableReference.IsSelfContext())
	{
		UClass* VariableClass = VariableReference.GetMemberParentClass(GetBlueprint()->GeneratedClass);
		if (UBlueprintGeneratedClass* BpClassOwner = Cast<UBlueprintGeneratedClass>(VariableClass))
		{
			// this variable could currently only be a part of some skeleton 
			// class (the blueprint has not be compiled with it yet), so let's 
			// check the skeleton class as well, see if we can pull pin data 
			// from there...
			UBlueprint* VariableBlueprint = CastChecked<UBlueprint>(BpClassOwner->ClassGeneratedBy, ECastCheckedType::NullAllowed);
			if (VariableBlueprint)
			{
				if (UProperty* SkelProperty = FindField<UProperty>(VariableBlueprint->SkeletonGeneratedClass, VariableReference.GetMemberName()))
				{
					VariableProperty = SkelProperty;
				}
			}
		}
	}

	if (VariableProperty != NULL)
	{
		const FString PinName = InPinName.IsEmpty()? GetVarNameString() : InPinName;
		// Create the pin
		UEdGraphPin* VariablePin = CreatePin(Direction, TEXT(""), TEXT(""), NULL, false, false, PinName);
		K2Schema->ConvertPropertyToPinType(VariableProperty, /*out*/ VariablePin->PinType);
		K2Schema->SetPinDefaultValueBasedOnType(VariablePin);
	}
	else
	{
		if (!VariableReference.IsLocalScope())
		{
			Message_Warn(*FString::Printf(TEXT("CreatePinForVariable: '%s' variable not found. Base class was probably changed."), *GetVarNameString()));
		}
		return false;
	}

	return true;
}
FText UK2Node_VariableGet::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
	// If there is only one variable being read, the title can be made the variable name
	FString OutputPinName;
	int32 NumOutputsFound = 0;

	for (int32 PinIndex = 0; PinIndex < Pins.Num(); ++PinIndex)
	{
		UEdGraphPin* Pin = Pins[PinIndex];

		// The following code is to attempt to log info related to UE-19729
		if (TitleType == ENodeTitleType::ListView)
		{
			if (UEdGraph* Graph = Cast<UEdGraph>(GetOuter()))
			{
				FString VariableName = GetVarNameString();
				FString BlueprintPath = FBlueprintEditorUtils::FindBlueprintForGraph(Graph)->GetPathName();
				FString SetupStyle = bIsPureGet? TEXT("pure") : TEXT("validated");
				FString VariableResolves = (VariableReference.ResolveMember<UProperty>(GetBlueprintClassFromNode()) != nullptr)? TEXT("resolves") : TEXT("does not resolve");
				checkf(Pin, TEXT("Get node for variable '%s' in Blueprint '%s' which is setup as %s and has %d pins. Variable %s"), *VariableName, *BlueprintPath, *SetupStyle, Pins.Num(), *VariableResolves);
			}
		}

		if (Pin->Direction == EGPD_Output)
		{
			++NumOutputsFound;
			OutputPinName = Pin->PinName;
		}
	}

	if (NumOutputsFound != 1)
	{
		return LOCTEXT("Get", "Get");
	}
	else if (CachedNodeTitle.IsOutOfDate(this))
	{
		FFormatNamedArguments Args;
		Args.Add(TEXT("PinName"), FText::FromString(OutputPinName));
		// FText::Format() is slow, so we cache this to save on performance
		CachedNodeTitle.SetCachedText(FText::Format(LOCTEXT("GetPinName", "Get {PinName}"), Args), this);
	}
	return CachedNodeTitle;
}
예제 #9
0
bool UK2Node_Variable::RecreatePinForVariable(EEdGraphPinDirection Direction, TArray<UEdGraphPin*>& OldPins, FString InPinName/* = FString()*/)
{
	// probably the node was pasted to a blueprint without the variable
	// we don't want to beak any connection, so the pin will be recreated from old one, but compiler will throw error

	// find old variable pin
	const UEdGraphPin* OldVariablePin = NULL;
	const FString PinName = InPinName.IsEmpty()? GetVarNameString() : InPinName;
	for(auto Iter = OldPins.CreateConstIterator(); Iter; ++Iter)
	{
		if(const UEdGraphPin* Pin = *Iter)
		{
			if(PinName == Pin->PinName)
			{
				OldVariablePin = Pin;
				break;
			}
		}
	}

	if(NULL != OldVariablePin)
	{
		// create new pin from old one
		UEdGraphPin* VariablePin = CreatePin(Direction, TEXT(""), TEXT(""), NULL, false, false, PinName);
		VariablePin->PinType = OldVariablePin->PinType;
		
		const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
		K2Schema->SetPinDefaultValueBasedOnType(VariablePin);

		Message_Note(*FString::Printf(TEXT("Pin for variable '%s' recreated, but the variable is missing."), *PinName));
		return true;
	}
	else
	{
		Message_Warn(*FString::Printf(TEXT("RecreatePinForVariable: '%s' pin not found"), *PinName));
		return false;
	}
}
예제 #10
0
UEdGraphPin* UK2Node_Variable::GetValuePin() const
{
	UEdGraphPin* Pin = FindPin(GetVarNameString());
	check(Pin == NULL || Pin->Direction == EGPD_Output);
	return Pin;
}