I have a question regarding the proper use of TScriptInterface. Say, I have two interfaces, IMyInterface1 and IMyInterface2, and an actor AMyActor which implements both interfaces. If I now have a variable of type TScriptInterface(IMyInterface1) (can’t use angular brackets in normal text…), how would I go about obtaining a variable of type TScriptInterface(IMyInterface2) of the same underlying object, without having to do an intermediate cast to AMyActor? I know it is possible doing the following:
TScriptInterface<IMyInterface1> x;
AMyActor* myActor = Cast<AMyActor>(x.GetObject());
TScriptInterface<IMyInterface2> y = TScriptInterface<IMyInterface2>(myActor);
If I were using raw pointers, I would simply do
IMyInterface1* x;
IMyInterface2* y = Cast<IMyInterface2>(x);
What I’d love to be able to do, would be:
TScriptInterface<IMyInterface1> x;
TScriptInterface<IMyInterface2> y = TScriptInterface<IMyInterface2>(x.GetObject());
The reason I can’t use raw pointers, is that passing raw pointers to an RPC is not possible, and raw interface pointers also cannot be used as UPROPERTYs. I don’t want to cast to AMyActor, because I also have other actor-types that implement both interfaces, so I would have to try to cast to each of these actor types to obtain a valid pointer, that I can pass to the TScriptInterface constructor.
Am I missing something here, or is this simply not possible? The way I’m doing it right now, is that I use raw interface pointers, and simply cast to AActor* when passing the pointer to an RPC and then cast back to the interface type on the server (which obviously isn’t optimal, since I’m losing the type safety of the interface type).
That’s odd, my last reply didn’t appear. Yeah, I realised that earlier and posted this alternate solution which at least doesn’t involve an intermediate type:
template <typename To, typename From>
TScriptInterface<To> CastScriptInterface(const TScriptInterface<From>& Interface)
{
TScriptInterface<To> Result;
To* Temp = Cast<To>(&*Interface);
Result.SetInterface(Temp);
Result.SetObject(Cast<UObject>(Temp));
return Result;
}
TScriptInterface<IMyInterface1> x;
auto y = CastScriptInterface<IMyInterface2>(x);
But I’ve raised a ticket to improve TScriptInterface as it’s quite deficient in a number of areas.
Is TScriptInterface still on the list for getting some love? Trying to pass a TScriptInterface pointer as a parameter is disturbing as it always fails with the same error message as the OP (cannot convert from IInterface* to UObject*). Having to manually setup the TScriptInterface to pass an interface pointer around is just not very nice. I pass my interface pointers like so:
void IComponentEventListener::SomeFunction()
{
// Prevents the cast to UObject* error
TScriptInterface<IComponentEventListener> TS;
TS.SetObject(Cast<UObject>(this));
TS.SetInterface(this);
SomeClassObj->TalkToMe(TS);
// What I would really like to see is:
SomeClassObj->TalkToMe(this);
}
void SomeClass::TalkToMe(TScriptInterface<IComponentEventListener> EvL)
{
}
Anyways, I hope there will be more transparency with interfaces in the near future.