예제 #1
0
void UK2Node_Variable::CreatePinForSelf()
{
	const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
	// Create the self pin
	if (!K2Schema->FindSelfPin(*this, EGPD_Input))
	{
		// Do not create a self pin for locally scoped variables
		if( !VariableReference.IsLocalScope() )
		{
			bool bSelfTarget = VariableReference.IsSelfContext() && (ESelfContextInfo::NotSelfContext != SelfContextInfo);
			UClass* MemberParentClass = VariableReference.GetMemberParentClass(GetBlueprintClassFromNode());
			UClass* TargetClass = MemberParentClass;
			
			// Self Target pins should always make the class be the owning class of the property,
			// so if the node is from a Macro Blueprint, it will hook up as self in any placed Blueprint
			if(bSelfTarget)
			{
				if(UProperty* Property = VariableReference.ResolveMember<UProperty>(GetBlueprintClassFromNode()))
				{
					TargetClass = Property->GetOwnerClass()->GetAuthoritativeClass();
				}
				else
				{
					TargetClass = GetBlueprint()->SkeletonGeneratedClass->GetAuthoritativeClass();
				}
			}
			else if(MemberParentClass && MemberParentClass->ClassGeneratedBy)
			{
				TargetClass = MemberParentClass->GetAuthoritativeClass();
			}

			UEdGraphPin* TargetPin = CreatePin(EGPD_Input, K2Schema->PC_Object, TEXT(""), TargetClass, false, false, K2Schema->PN_Self);
			TargetPin->PinFriendlyName =  LOCTEXT("Target", "Target");

			if (bSelfTarget)
			{
				TargetPin->bHidden = true; // don't show in 'self' context
			}
		}
	}
	else
	{
		//@TODO: Check that the self pin types match!
	}
}
FText UK2Node_CallFunctionOnMember::GetFunctionContextString() const
{
	UClass* MemberVarClass = MemberVariableToCallOn.GetMemberParentClass(GetBlueprintClassFromNode());
	FText CallFunctionClassName = (MemberVarClass != NULL) ? MemberVarClass->GetDisplayNameText() : FText::GetEmpty();
	FFormatNamedArguments Args;
	Args.Add(TEXT("TargetName"), CallFunctionClassName);
	Args.Add(TEXT("MemberVariableName"), FText::FromName(MemberVariableToCallOn.GetMemberName()));
	return FText::Format(LOCTEXT("CallFunctionOnMemberDifferentContext", "Target is {TargetName} ({MemberVariableName})"), Args);
}
예제 #3
0
FName UK2Node_Variable::GetCornerIcon() const
{
	const UProperty* VariableProperty = VariableReference.ResolveMember<UProperty>(GetBlueprintClassFromNode());
	if (VariableProperty && VariableProperty->HasAllPropertyFlags(CPF_Net))
	{
		return TEXT("Graph.Replication.Replicated");
	}

	return Super::GetCornerIcon();
}
예제 #4
0
void UK2Node_Variable::CheckForErrors(const UEdGraphSchema_K2* Schema, FCompilerResultsLog& MessageLog)
{
	if(!VariableReference.IsSelfContext() && VariableReference.GetMemberParentClass(GetBlueprintClassFromNode()) != NULL)
	{
		// Check to see if we're not a self context, if we have a valid context.  It may have been purged because of a dead execution chain
		UEdGraphPin* ContextPin = Schema->FindSelfPin(*this, EGPD_Input);
		if((ContextPin != NULL) && (ContextPin->LinkedTo.Num() == 0) && (ContextPin->DefaultObject == NULL))
		{
			MessageLog.Error(*LOCTEXT("VarNodeError_InvalidVarTarget", "Variable node @@ uses an invalid target.  It may depend on a node that is not connected to the execution chain, and got purged.").ToString(), this);
		}
	}
}
예제 #5
0
void UK2Node_Variable::AutowireNewNode(UEdGraphPin* FromPin)
{
	const UEdGraphSchema_K2* K2Schema = CastChecked<UEdGraphSchema_K2>(GetSchema());

	// Do some auto-connection
	if (FromPin != NULL)
	{
		bool bConnected = false;
		if(FromPin->Direction == EGPD_Output)
		{
			// If the source pin has a valid PinSubCategoryObject, we might be doing BP Comms, so check if it is a class
			if(FromPin->PinType.PinSubCategoryObject.IsValid() && FromPin->PinType.PinSubCategoryObject->IsA(UClass::StaticClass()))
			{
				UProperty* VariableProperty = VariableReference.ResolveMember<UProperty>(GetBlueprintClassFromNode());
				if(VariableProperty)
				{
					UClass* PropertyOwner = VariableProperty->GetOwnerClass();
					if (PropertyOwner != nullptr)
					{
						PropertyOwner = PropertyOwner->GetAuthoritativeClass();
					}

					// BP Comms is highly likely at this point, if the source pin's type is a child of the variable's owner class, let's conform the "Target" pin
					if(FromPin->PinType.PinSubCategoryObject == PropertyOwner || dynamic_cast<UClass*>(FromPin->PinType.PinSubCategoryObject.Get())->IsChildOf(PropertyOwner))
					{
						UEdGraphPin* TargetPin = FindPin(K2Schema->PN_Self);
						if (TargetPin)
						{
							TargetPin->PinType.PinSubCategoryObject = PropertyOwner;

							if(K2Schema->TryCreateConnection(FromPin, TargetPin))
							{
								bConnected = true;

								// Setup the VariableReference correctly since it may no longer be a self member
								VariableReference.SetFromField<UProperty>(GetPropertyForVariable(), false);
								TargetPin->bHidden = false;
								FromPin->GetOwningNode()->NodeConnectionListChanged();
								this->NodeConnectionListChanged();
							}
						}
					}
				}
			}
		}

		if(!bConnected)
		{
			Super::AutowireNewNode(FromPin);
		}
	}
}
예제 #6
0
FName UK2Node_Variable::GetPaletteIcon(FLinearColor& ColorOut) const
{
	FName ReturnIconName;

	if(VariableReference.IsLocalScope())
	{
		ReturnIconName = GetVariableIconAndColor(VariableReference.GetMemberScope(GetBlueprintClassFromNode()), GetVarName(), ColorOut);
	}
	else
	{
		ReturnIconName = GetVariableIconAndColor(GetVariableSourceClass(), GetVarName(), ColorOut);
	}

	return ReturnIconName;
}
bool UK2Node_CallFunctionOnMember::HasExternalDependencies(TArray<class UStruct*>* OptionalOutput) const
{
	const UBlueprint* SourceBlueprint = GetBlueprint();

	auto VarProperty = MemberVariableToCallOn.ResolveMember<UProperty>(GetBlueprintClassFromNode());
	UClass* SourceClass = VarProperty ? VarProperty->GetOwnerClass() : nullptr;
	const bool bResult = (SourceClass != NULL) && (SourceClass->ClassGeneratedBy != SourceBlueprint);
	if (bResult && OptionalOutput)
	{
		OptionalOutput->AddUnique(SourceClass);
	}

	const bool bSuperResult = Super::HasExternalDependencies(OptionalOutput);
	return bSuperResult || bResult;
}
예제 #8
0
bool UK2Node_Variable::CanPasteHere(const UEdGraph* TargetGraph) const
{
	// Do not allow pasting of variables in BPs that cannot handle them
	if ( FBlueprintEditorUtils::FindBlueprintForGraph(TargetGraph)->BlueprintType == BPTYPE_MacroLibrary && VariableReference.IsSelfContext() )
	{
		// Self variables must be from a parent class to the macro BP
		if(UProperty* Property = VariableReference.ResolveMember<UProperty>(GetBlueprintClassFromNode()))
		{
			const UClass* CurrentClass = GetBlueprint()->SkeletonGeneratedClass->GetAuthoritativeClass();
			const UClass* PropertyClass = Property->GetOwnerClass()->GetAuthoritativeClass();
			const bool bIsChildOf = CurrentClass->IsChildOf(PropertyClass);
			return bIsChildOf;
		}
		return false;
	}
	return true;
}
FText UK2Node_CallParentFunction::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
	UFunction* Function = FunctionReference.ResolveMember<UFunction>(GetBlueprintClassFromNode());
	FText FunctionName;

	if (Function)
	{
		FunctionName = GetUserFacingFunctionName( Function );
	}
	else if ( GEditor && GetDefault<UEditorStyleSettings>()->bShowFriendlyNames )
	{
		FunctionName = FText::FromString(FName::NameToDisplayString(FunctionReference.GetMemberName().ToString(), false));
	}

	FFormatNamedArguments Args;
	Args.Add(TEXT("FunctionName"), FunctionName);
	return FText::Format( LOCTEXT( "CallSuperFunction", "Parent: {FunctionName}" ), Args);
}
void UK2Node_CommutativeAssociativeBinaryOperator::AllocateDefaultPins()
{
	Super::AllocateDefaultPins();

	const UFunction* Function = GetTargetFunction();
	if(NULL != Function)
	{
		check(Function->HasAnyFunctionFlags(FUNC_BlueprintPure));
	
#if DO_CHECK
		ensure(FindOutPin());
		ensure((FindSelfPin() ? 4 : 3) ==  Pins.Num());
		{
			//VALIDATION
			const FEdGraphPinType InputType = GetType();
			int32 NativeInputPinsNum = 0;
			for (int32 PinIt = 0; PinIt < Pins.Num(); PinIt++)
			{
				const UEdGraphPin* Pin = Pins[PinIt];
				if (Pin != FindSelfPin())
				{
					ensure(InputType == Pin->PinType);
					NativeInputPinsNum += (EEdGraphPinDirection::EGPD_Input ==  Pin->Direction) ? 1 : 0;
				}
			}
			ensure(BinaryOperatorInputsNum == NativeInputPinsNum);
		}
#endif // DO_CHECK

		for (int32 i = 0; i < NumAdditionalInputs; ++i)
		{
			AddInputPinInner(i);
		}
	}
	else
	{
		const UClass* FunctionParentClass = FunctionReference.GetMemberParentClass(GetBlueprintClassFromNode());
		Message_Error(FString::Printf(
			*LOCTEXT("NoFunction_Error", "CommutativeAssociativeBinaryOperator has no function: '%s' class: '%s'").ToString(), 
			*FunctionReference.GetMemberName().ToString(),
			(FunctionParentClass ? *FunctionParentClass->GetName() : TEXT("None"))
			));
	}
}
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;
}
예제 #12
0
FText UK2Node_Variable::GetToolTipHeading() const
{
	FText Heading = Super::GetToolTipHeading();

	UProperty const* VariableProperty = VariableReference.ResolveMember<UProperty>(GetBlueprintClassFromNode());
	if (VariableProperty && VariableProperty->HasAllPropertyFlags(CPF_Net))
	{
		FText ReplicatedTag = LOCTEXT("ReplicatedVar", "Replicated");
		if (Heading.IsEmpty())
		{
			Heading = ReplicatedTag;
		}
		else 
		{
			Heading = FText::Format(FText::FromString("{0}\n{1}"), ReplicatedTag, Heading);
		}
	}

	return Heading;
}
예제 #13
0
FBPVariableDescription const* UK2Node_Variable::GetBlueprintVarDescription() const
{
	FName const& VarName = VariableReference.GetMemberName();
	UStruct const* VariableScope = VariableReference.GetMemberScope(GetBlueprintClassFromNode());

	bool const bIsLocalVariable = (VariableScope != nullptr);
	if (bIsLocalVariable)
	{
		return FBlueprintEditorUtils::FindLocalVariable(GetBlueprint(), VariableScope, VarName);
	}
	else if (UProperty const* VarProperty = GetPropertyForVariable())
	{
		UClass const* SourceClass = VarProperty->GetOwnerClass();
		UBlueprint const* SourceBlueprint = (SourceClass != nullptr) ? Cast<UBlueprint>(SourceClass->ClassGeneratedBy) : nullptr;

		if (SourceBlueprint != nullptr)
		{
			int32 const VarIndex = FBlueprintEditorUtils::FindNewVariableIndex(SourceBlueprint, VarName);
			return &SourceBlueprint->NewVariables[VarIndex];
		}
	}
	return nullptr;
}
예제 #14
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;
}
예제 #15
0
UClass* UK2Node_Variable::GetVariableSourceClass() const
{
	UClass* Result = VariableReference.GetMemberParentClass(GetBlueprintClassFromNode());
	return Result;
}
예제 #16
0
void UK2Node_Variable::PostPasteNode()
{
	Super::PostPasteNode();

	UBlueprint* Blueprint = GetBlueprint();
	bool bInvalidateVariable = false;

	if (VariableReference.ResolveMember<UProperty>(Blueprint) == nullptr)
	{
		bInvalidateVariable = true;
	}
	else if (VariableReference.IsLocalScope())
	{
		// Local scoped variables should always validate whether they are being placed in the same graph as their scope
		// ResolveMember will not return nullptr when the graph changes but the Blueprint remains the same.
		UEdGraph* ScopeGraph = FBlueprintEditorUtils::FindScopeGraph(Blueprint, VariableReference.GetMemberScope(GetBlueprintClassFromNode()));
		if(ScopeGraph != GetGraph())
		{
			bInvalidateVariable = true;
		}
	}
		
	if (bInvalidateVariable)
	{
		// This invalidates the local scope
		VariableReference.InvalidateScope();

		// If the current graph is a Function graph, look to see if there is a compatible local variable (same name)
		if (GetGraph()->GetSchema()->GetGraphType(GetGraph()) == GT_Function)
		{
			FBPVariableDescription* VariableDescription = FBlueprintEditorUtils::FindLocalVariable(Blueprint, GetGraph(), VariableReference.GetMemberName());
			if(VariableDescription)
			{
				VariableReference.SetLocalMember(VariableReference.GetMemberName(), GetGraph()->GetName(), VariableReference.GetMemberGuid());
			}
		}
		// If no variable was found, ResolveMember should automatically find a member variable with the same name in the current Blueprint and hook up to it as expected
	}
}
UEdGraphPin* UK2Node_CallFunctionOnMember::CreateSelfPin(const UFunction* Function) 
{
	const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();

	UEdGraphPin* SelfPin = NULL;
	if (MemberVariableToCallOn.IsSelfContext())
	{
		// This means the function is defined within the blueprint, so the pin should be a true "self" pin
		SelfPin = CreatePin(EGPD_Input, K2Schema->PC_Object, K2Schema->PSC_Self, NULL, false, false, K2Schema->PN_Self);
	}
	else
	{
		// This means that the function is declared in an external class, and should reference that class
		SelfPin = CreatePin(EGPD_Input, K2Schema->PC_Object, TEXT(""), MemberVariableToCallOn.GetMemberParentClass(GetBlueprintClassFromNode()), false, false, K2Schema->PN_Self);
	}
	check(SelfPin != NULL);

	return SelfPin;
}