UEdGraphNode* FEdGraphSchemaAction_K2AssignDelegate::AssignDelegate(class UK2Node* NodeTemplate, class UEdGraph* ParentGraph, UEdGraphPin* FromPin, const FVector2D Location, bool bSelectNewNode) { UK2Node_AddDelegate* BindNode = NULL; if (UK2Node_AddDelegate* AddDelegateTemplate = Cast<UK2Node_AddDelegate>(NodeTemplate)) { const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "K2_AddNode", "Add Node") ); ParentGraph->Modify(); if (FromPin) { FromPin->Modify(); } BindNode = Cast<UK2Node_AddDelegate>(CreateNode(ParentGraph, FromPin, Location, NodeTemplate, bSelectNewNode)); UMulticastDelegateProperty* DelegateProperty = BindNode ? Cast<UMulticastDelegateProperty>(BindNode->GetProperty()) : NULL; if(DelegateProperty) { const FString FunctionName = FString::Printf(TEXT("%s_Event"), *DelegateProperty->GetName()); UK2Node_CustomEvent* EventNode = UK2Node_CustomEvent::CreateFromFunction( FVector2D(Location.X - 150, Location.Y + 150), ParentGraph, FunctionName, DelegateProperty->SignatureFunction, bSelectNewNode); if(EventNode) { const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); UEdGraphPin* OutDelegatePin = EventNode->FindPinChecked(UK2Node_CustomEvent::DelegateOutputName); UEdGraphPin* InDelegatePin = BindNode->GetDelegatePin(); K2Schema->TryCreateConnection(OutDelegatePin, InDelegatePin); } } UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraphChecked(ParentGraph); FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(Blueprint); } return BindNode; }
UMulticastDelegateProperty* UK2Node_ActorBoundEvent::GetTargetDelegateProperty() { auto ActualEventSignatureClass = FActorBoundEventHelper::GetSignatureClass(this); if (!EventSignatureClass && ActualEventSignatureClass) { EventSignatureClass = ActualEventSignatureClass; } UMulticastDelegateProperty* TargetDelegateProp = Cast<UMulticastDelegateProperty>(FindField<UMulticastDelegateProperty>(EventSignatureClass, DelegatePropertyName)); // If we couldn't find the target delegate, then try to find it in the property remap table if (!TargetDelegateProp) { UMulticastDelegateProperty* NewProperty = Cast<UMulticastDelegateProperty>(FindRemappedField(EventSignatureClass, DelegatePropertyName)); if (NewProperty) { // Found a remapped property, update the node TargetDelegateProp = NewProperty; DelegatePropertyName = NewProperty->GetFName(); EventSignatureClass = Cast<UClass>(NewProperty->GetOuter()); CachedNodeTitle.MarkDirty(); } } return TargetDelegateProp; }
void UComponentDelegateBinding::BindDynamicDelegates(AActor* InInstance) const { for(int32 BindIdx=0; BindIdx<ComponentDelegateBindings.Num(); BindIdx++) { const FBlueprintComponentDelegateBinding& Binding = ComponentDelegateBindings[BindIdx]; // Get the function we want to bind UFunction* FunctionToBind = FindField<UFunction>(InInstance->GetClass(), Binding.FunctionNameToBind); // Get the property that points to the component we want to assign to UObjectProperty* ObjProp = FindField<UObjectProperty>(InInstance->GetClass(), Binding.ComponentPropertyName); // If we have both of those.. if(ObjProp != NULL && FunctionToBind != NULL) { // ..see if there is actually a component assigned UActorComponent* Component = Cast<UActorComponent>(ObjProp->GetObjectPropertyValue_InContainer(InInstance)); if(Component != NULL) { // If there is, find the delegate property on it UMulticastDelegateProperty* DelegateProp = FindField<UMulticastDelegateProperty>(Component->GetClass(), Binding.DelegatePropertyName); if(DelegateProp) { // Found that, finally bind function on the actor to this delegate FMulticastScriptDelegate* TargetDelegate = DelegateProp->GetPropertyValuePtr_InContainer(Component); FScriptDelegate Delegate; Delegate.SetFunctionName(Binding.FunctionNameToBind); Delegate.SetObject(InInstance); TargetDelegate->AddUnique(Delegate); } } } } }
//------------------------------------------------------------------------------ static void BlueprintActionDatabaseImpl::AddClassPropertyActions(UClass const* const Class, FActionList& ActionListOut) { using namespace FBlueprintNodeSpawnerFactory; // for MakeDelegateNodeSpawner() bool const bIsComponent = Class->IsChildOf<UActorComponent>(); bool const bIsActorClass = Class->IsChildOf<AActor>(); // loop over all the properties in the specified class; exclude-super because // we can always get the super properties by looking up that class separateHavely for (TFieldIterator<UProperty> PropertyIt(Class, EFieldIteratorFlags::ExcludeSuper); PropertyIt; ++PropertyIt) { UProperty* Property = *PropertyIt; if (!IsPropertyBlueprintVisible(Property)) { continue; } bool const bIsDelegate = Property->IsA(UMulticastDelegateProperty::StaticClass()); if (bIsDelegate) { UMulticastDelegateProperty* DelegateProperty = CastChecked<UMulticastDelegateProperty>(Property); if (DelegateProperty->HasAnyPropertyFlags(CPF_BlueprintAssignable)) { UBlueprintNodeSpawner* AddSpawner = UBlueprintDelegateNodeSpawner::Create(UK2Node_AddDelegate::StaticClass(), DelegateProperty); ActionListOut.Add(AddSpawner); UBlueprintNodeSpawner* AssignSpawner = MakeAssignDelegateNodeSpawner(DelegateProperty); ActionListOut.Add(AssignSpawner); } if (DelegateProperty->HasAnyPropertyFlags(CPF_BlueprintCallable)) { UBlueprintNodeSpawner* CallSpawner = UBlueprintDelegateNodeSpawner::Create(UK2Node_CallDelegate::StaticClass(), DelegateProperty); ActionListOut.Add(CallSpawner); } UBlueprintNodeSpawner* RemoveSpawner = UBlueprintDelegateNodeSpawner::Create(UK2Node_RemoveDelegate::StaticClass(), DelegateProperty); ActionListOut.Add(RemoveSpawner); UBlueprintNodeSpawner* ClearSpawner = UBlueprintDelegateNodeSpawner::Create(UK2Node_ClearDelegate::StaticClass(), DelegateProperty); ActionListOut.Add(ClearSpawner); if (bIsComponent) { ActionListOut.Add(MakeComponentBoundEventSpawner(DelegateProperty)); } else if (bIsActorClass) { ActionListOut.Add(MakeActorBoundEventSpawner(DelegateProperty)); } } else { UBlueprintVariableNodeSpawner* GetterSpawner = UBlueprintVariableNodeSpawner::Create(UK2Node_VariableGet::StaticClass(), Property); ActionListOut.Add(GetterSpawner); UBlueprintVariableNodeSpawner* SetterSpawner = UBlueprintVariableNodeSpawner::Create(UK2Node_VariableSet::StaticClass(), Property); ActionListOut.Add(SetterSpawner); } } }
static UMulticastDelegateProperty* FindAndCheckDelegateProperty(FKismetFunctionContext& Context, UK2Node_BaseMCDelegate * DelegateNode, FCompilerResultsLog& MessageLog, const UEdGraphSchema_K2* Schema) { check(NULL != DelegateNode); UEdGraphPin* Pin = Schema->FindSelfPin(*DelegateNode, EEdGraphPinDirection::EGPD_Input); UStruct* DelegateScope = Pin ? Context.GetScopeFromPinType(Pin->PinType, Context.NewClass) : NULL; // Early out if we have no pin. That means the delegate is no longer valid, and we need to terminate gracefully if (!Pin || !DelegateScope) { MessageLog.Error(*LOCTEXT("NoDelegateProperty", "Event Dispatcher has no property @@").ToString(), DelegateNode); return NULL; } // Don't use DelegateNode->GetProperty(), because we don't want any property from skeletal class UClass* PropertyOwnerClass = CastChecked<UClass>(DelegateScope); UMulticastDelegateProperty* BoundProperty = NULL; for (TFieldIterator<UMulticastDelegateProperty> It(PropertyOwnerClass); It; ++It) { UMulticastDelegateProperty* Prop = *It; if (DelegateNode->GetPropertyName() == Prop->GetFName()) { BoundProperty = Prop; break; } } if (!BoundProperty) { FString const OwnerName = PropertyOwnerClass->GetName(); FString const PropName = DelegateNode->GetPropertyName().ToString(); FText const ErrorFormat = LOCTEXT("DelegateNotFound", "Could not find an event-dispatcher named \"%s\" in '%s'.\nMake sure '%s' has been compiled for @@"); MessageLog.Error(*FString::Printf(*ErrorFormat.ToString(), *PropName, *OwnerName, *OwnerName), DelegateNode); return NULL; } { // MulticastDelegateProperty from NewClass may have empty signature, but property from skeletal class should have it. const UFunction* OrgSignature = DelegateNode->GetDelegateSignature(); if(const UEdGraphPin* DelegatePin = DelegateNode->GetDelegatePin()) { const UFunction* PinSignature = FMemberReference::ResolveSimpleMemberReference<UFunction>(DelegatePin->PinType.PinSubCategoryMemberReference); if (!OrgSignature || !PinSignature || !OrgSignature->IsSignatureCompatibleWith(PinSignature)) { MessageLog.Error(*LOCTEXT("WrongDelegate", "Wrong Event Dispatcher. Refresh node @@").ToString(), DelegateNode); return NULL; } } CheckOutputsParametersInDelegateSignature(OrgSignature, DelegateNode, MessageLog); } return BoundProperty; }
FText UK2Node_ActorBoundEvent::GetTooltipText() const { UMulticastDelegateProperty* TargetDelegateProp = GetTargetDelegatePropertyConst(); if(TargetDelegateProp) { return TargetDelegateProp->GetToolTipText(); } else { return FText::FromName(DelegatePropertyName); } }
FMulticastScriptDelegate* UK2Node_ActorBoundEvent::GetTargetDelegate() { if( EventOwner ) { UMulticastDelegateProperty* TargetDelegateProp = GetTargetDelegateProperty(); if( TargetDelegateProp ) { return TargetDelegateProp->GetPropertyValuePtr_InContainer(EventOwner); } } return NULL; }
UFunction* UK2Node_DelegateSet::GetDelegateSignature() { UMulticastDelegateProperty* DelegateProperty = FindField<UMulticastDelegateProperty>(DelegatePropertyClass, DelegatePropertyName); if( !DelegateProperty ) { // Attempt to find a remapped delegate property UMulticastDelegateProperty* NewProperty = Cast<UMulticastDelegateProperty>(FMemberReference::FindRemappedField(DelegatePropertyClass, DelegatePropertyName)); if( NewProperty ) { // Found a remapped property, update the node DelegateProperty = NewProperty; DelegatePropertyName = NewProperty->GetFName(); DelegatePropertyClass = Cast<UClass>(NewProperty->GetOuter()); } } return (DelegateProperty != NULL) ? DelegateProperty->SignatureFunction : NULL; }