Alright so incase anyone else stumbles upon this posting. I want to point out a couple things.
- I recently found this talk posted on EPIC’s YouTube channel that essentially showcases a version of what I wanted to achieve:
- https://youtu.be/S6iT1p7tm2Q?si=QPJQzgi4uK7GgtTi
Now with that said, the above is focused on a programmer authored solution. Which wasn’t my personal goal, mine was more oriented towards allowing content creators OR programmers to setup their OWN delegates/event dispatchers and removing the “middle man” scripting between actors and objects in the world.
What I landed on was something I’m happy with. I can’t post the solution but what I will say is the following things were useful:
The following code lets you parse through functions by comparing it with a provided UFunction
TArray<FString> SomeComponent::FindFunctionNamesWithFunctionSignature(AActor* ObjectToLookAt, UFunction* FunctionForSignature)
{
for (TFieldIterator<UFunction> func(ObjectToLookAt->GetClass()); func; ++func) {
if (!func->GetName().Contains(NamingConvention, ESearchCase::IgnoreCase))
{
continue;
}
if (!IsValid(FunctionForSignature))
{
continue;
}
//Make sure to add other code here for verification and error checking
ArrayToReturn.Add(func->GetName());
}
The following code can get you all of the Event dispatchers or Delegates from a provided class
void SomeComponent::SetEventDispatchersBasedOnParent()
{
AActor* Parent = GetOwner();
if (!IsValid(Parent))
{
return;
}
for (TFieldIterator<FMulticastDelegateProperty> func(Parent->GetClass()); func; ++func) {
if (!func->GetName().Contains(NamingConvention, ESearchCase::IgnoreCase))
{
continue;
}
EventDispatcherToFunctionMap.FindOrAdd(*func->GetName());
}
}
Now that you have a list of functions from some object, and a list of event dispatchers/ delegates from another, you can tie them together by doing something like this (This is pseudocode):
//To get a FMulticastScriptDelegate
for (TFieldIterator<FMulticastDelegateProperty> CurrentDelegateProperty(Parent->GetClass()); CurrentDelegateProperty; ++CurrentDelegateProperty) {
//This line grabs the actual value of a delegate property.
FMulticastScriptDelegate* CurrentScriptDelegate = CurrentDelegateProperty->ContainerPtrToValuePtr<FMulticastScriptDelegate>(Parent);
//This line grabs a function by name
UFunction* CurrentFunction = CurrentActorKey->FindFunction(*FunctionsToCallPair.Key);
//Once the above is done youll want to do some comparisons and make sure the two are compatible otherwise you could crash your game
//finally bind the two together
DelegateToAddToParentActor.BindUFunction(CurrentActor, FName(FunctionsToCallPair.Key));
CurrentScriptDelegate->Add(DelegateToAddToParentActor);
}
Anyway sorry about the vagueness, but those are all functions that essentially already available through Unreal and I thought I just share my findings and what was useful for me.
One last note, this line is very helpful when trying to compare and validate UFunctions that have the same signature (more pseudocode):
//Collect Properties from UFunctions
TArray<FProperty*> DelegateParams;
for (TFieldIterator<FProperty> It(DelegateFunction); It; ++It)
{
if ((It->PropertyFlags & CPF_Parm) && !(It->PropertyFlags & CPF_OutParm))
{
DelegateParams.Add(*It);
}
}
TArray<FProperty*> FunctionParams;
for (TFieldIterator<FProperty> It(FirstFunction); It; ++It)
{
if (It->PropertyFlags & CPF_OutParm)
{
return false;
}
if ((It->PropertyFlags & CPF_Parm) && !(It->PropertyFlags & CPF_OutParm))
{
FunctionParams.Add(*It);
}
}
//Make sure your parameters are matching between functions and delegates
FStructUtils::ArePropertiesTheSame(CurrentParam, CurrentDelegateParam, false)
Anyway, those are my findings and the pieces that need to be put together, apologies if someone out there wanted actual code. I cannot provide that but all of those functions above would have helped me get to a solution