Can you bind a reflected UFunction* to a FMulticastScriptDelegate* without the concrete delegate type?

I’m working on a custom asset editor, which contains many instances of the following UObject type (or types similar to it).

UCLASS(BlueprintType)
class BOBCAT_API UCustomA : public UObject
{
	GENERATED_BODY()

public:
	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCustomA1Delegate, FContext1, Context);
	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCustomA2Delegate, FContext2, Context);
	
	UPROPERTY()
	FCustomA1Delegate EventWithContext1;

	UPROPERTY())
	FCustomA2Delegate EventWithContext2;

};

For each custom asset instance (essentially fancy data assets), there is a blueprint related to it (not unlike levels and level blueprints in terms of their 1:1 relationship).
Users can create custom events in the blueprint, which should be automatically bound to the related event during editor-time. Below is a sample chunk of the procedure to gather the relevant pointers to bind the event.

Note: Please bear with the obfuscasion of specifics and code mistakes, this is an uncompiled example / pseudo-code based on what I already have compiling.

UClass* BlueprintGeneratedClass = SomeOtherObjectType->GetClass();
UBlueprint* Blueprint = Cast<UBlueprint>(BlueprintGeneratedClass->ClassGeneratedBy);
UCustomA* OutInstance = NewObject(...);

for (TFieldIterator<FMulticastDelegateProperty> PropertyIt(OutInstwnce->GetClass(), EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt)
{
	FMulticastDelegateProperty* Property = *PropertyIt;
    
	/* Specific node in `Blueprint` which is the one and only event generated to handle the Property. Blackbox omitted, but it uses `FBlueprintEditorUtils::GetAllNodesOfClass` on the blueprint with some extra criteria. */
	const UK2Node_Event* GeneratedEventNode = FindBlueprintEventForDelegate(Blueprint, OutInstance, Property);
	UFunction* GeneratedEvent = BlueprintGeneratedClass->FindFunctionByName(GeneratedEventNode->GetFunctionName());
	if (!Property->SignatureFunction->IsSignatureCompatibleWith(GeneratedEvent)) continue;

	FMulticastScriptDelegate* Delegate = Property->ContainerPtrToValuePtr<FMulticastScriptDelegate>(OutInstance);

	/* TODO: Run binding logic here to attach `GeneratedEvent` as a handler when `Delegate` is broadcast. */
}

So my problem/question is how would one bind a generic UFunction* on a specific Blueprint object (i.e. the ClassDefaultObject of a blueprint class) to a generic delegate on a known UObject (non-blueprint)?

All of the normal binding methods are staticly typed (for reasonable and good type safety reasons). In this case, however, I don’t know of a way to get those hard-types when iterating over the reflected property fields (they are often different delegate types). And the only binding method in the currently used types is FMulticastScriptDelegate::Add[Dynamic], which requires some subclass of FScriptDelegate.

Is there some type I can cast one or both of these sides to in order to generate the safely typed structure for binding? If not, are there any recommendations to how one could bind a blueprint-generated function to a delegate, when I only really know the name of both (i.e. the name of the delegate UProperty and the name of the generated function)?

Oh I feel silly. FScriptDelegate has a default constructor, and a method from which you can bind a UObject function by its name.

FScriptDelegate Callback;
Callback.BindUFunction(SomeOtherObjectType, GeneratedEvent->GetFName());
Delegate->AddUnique(Callback);

That properly updates the invocation list on the UCustomA instance (via the delegate pointer).

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.