I’m trying to create a delegate. The return type will either be: Float, Int, or Vector. I can’t know until it’s ran. I can simply create 3 delegates, but this becomes a hassle.
Is there a way to get the return type to be a Tvariant? I’ve tried numerous different methods, but it appears Delegate definitions can’t handle TypeDefs, nor “<>”, nor structs as return types.
how about returning struct with {float, vector, enum{IsFloat, IsInt, IsVector}}
?
Can’t return a struct. The Delegate macro can’t see structs.
You can pass structs to dynamic delegates, but the structs should be declared as USTRUCT(BlueprintType)
(and don’t forget the GENERATED_BODY()
)
Not as an output.
I have two delegates declared.
One has a struct as an input. Works.
One has the exact same struct as an output. Broken: “use of undefined type ‘FSelectionMaps’”
Oh, got you. Never had to use the delegates which actually returns something.
Since you didn’t specify you need a BP-exposed solution, i’ve just tested a following c++ example:
struct example
//header
USTRUCT(BlueprintType)
struct FMyTestStruct
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite)
int xyz = 123;
};
DECLARE_DELEGATE_RetVal(FMyTestStruct, FTestDelegateQWE);
UCLASS()
class MY_API ABaseCharacter : public ACharacter
{
GENERATED_BODY()
public:
FTestDelegateQWE TestQWE;
virtual void Tick(float DeltaTime) override;
//<...>
}
//implementation
void ABaseCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
TestQWE.BindLambda([]() -> FMyTestStruct {
FMyTestStruct Result;
Result.xyz = 456;
return Result;
});
FMyTestStruct Test;
PrintLog("Before call: " + FString::FromInt(Test.xyz)); // PrintLog() is my custom macro which essencially is `GEngine->AddOnScreenDebugMessage()`
Test = TestQWE.Execute();
PrintLog("After call: " + FString::FromInt(Test.xyz));
}
And according to output it works fine:
So, we having a delegate that can return a struct, is it the thing you looking for? If it is, then use of undefined type ‘FSelectionMaps’
can happen if you declare delegate before actually declaring the FSelectionMaps
: that’s why i put DECLARE_DELEGATE
below the struct declaration (forward declaration should also work).
Hope this helps
upd: using `TVariant` directly also works
though i had to typedef it:
//header
using FMyVariant = TVariant<float, int, FString>;
DECLARE_DELEGATE_RetVal(FMyVariant, FTestDelegateQWE);
//cpp
TestQWE.BindLambda([]() -> FMyVariant {
FMyVariant Result;
Result.Set<FString>("QWE");
return Result;
});
FMyVariant Test;
Test.Set<int>(123);
PrintLog("Before call: " + FString::FromInt(Test.Get<int>()));
Test = TestQWE.Execute();
PrintLog("After call: " + Test.Get<FString>());
Yes, the delegate must be BP exposed.
The struct is also BP exposed, as it works just fine as an input.
Interesting that you used “Using” instead of “typedef”. Wonder if that’d work for me as well.
The Tvariant is the only retval that I’m looking for. For this particular delegate, it’ll either be int, vector, or float, and impossible to know which until it’s ran. The delegate is a function created elsewhere by the user, connected via blueprint.
Thanks for all your help so far!
Tested that. No issues, but not BP accessible.
using FMyVariant = TVariant<float, int, FString>;
DECLARE_DYNAMIC_DELEGATE_RetVal(FMyVariant, FTestDelegateQWE);
BP accessible, but “FMyVariant not found” (Same problem even with BP accessible structs as retval)
I had the answer staring me in the face.
Dynamic delegates do not work if the return value is a struct…
but does work if the exact same struct is a parameter… including a reference.
Well, duh… make the ‘output’ a referenced ‘input’ parameter.
DECLARE_DYNAMIC_DELEGATE_TwoParams(FAttributeDelegate, UBlenderMesh*, TargetMesh, UPARAM(ref) FVariantData&, ReturnValue);
This is false. You can return structures from dynamic delegates just fine. FVector is a structure and I return it from delegates all the time.
Dynamic delegate input/outputs are restricted to the same types as UPROPERTY. In your working example FVariantData is probably a USTRUCT. In your previous example FMyVariant isn’t a USTRUCT (and templates generally can’t be). If the type works as an parameter, it should work just as well as a return value.