Sure, the changes that I did were:
- Turned OnTweenStart and OnTweenComplete a BlueprintNativeEvent in iTInterface.h.
class IiTInterface
{
GENERATED_IINTERFACE_BODY()
public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, meta = (FriendlyName = "On Tween Start"), Category = "iTween|Interface Events")
void OnTweenStart(AiTweenEvent* eventOperator, AActor* actorTweening = nullptr, USceneComponent* componentTweening = nullptr, UWidget* widgetTweening = nullptr, FName tweenName = "");
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, meta = (FriendlyName = "On Tween Tick", DeprecatedFunction, DeprecationMessage = "Interface Event deprecated, use On Tween Update instead."), Category = "iTween|Interface Events")
void OnTweenTick(AiTweenEvent* eventOperator, AActor* actorTweening = nullptr, USceneComponent* componentTweening = nullptr, UWidget* widgetTweening = nullptr, FName tweenName = "", float alphaCompletion = 0.f);
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, meta = (FriendlyName = "On Tween Data Tick", DeprecatedFunction, DeprecationMessage = "Interface Event deprecated, use On Tween Update instead. Data values are now stored in 'Data Type Values' struct. Break that to get float value, vector value, etc."), Category = "iTween|Interface Events")
void OnTweenDataTick(AiTweenEvent* eventOperator, FName tweenName = "", float floatValue = 0.f, FLinearColor linearColorValue = FLinearColor::Black, FRotator rotatorValue = FRotator::ZeroRotator, FVector vectorValue = FVector::ZeroVector, FVector2D vector2DValue = FVector2D::ZeroVector, float alphaCompletion = 0.f);
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, meta = (FriendlyName = "On Tween Loop"), Category = "iTween|Interface Events")
void OnTweenLoop(AiTweenEvent* eventOperator, AActor* actorTweening = nullptr, USceneComponent* componentTweening = nullptr, UWidget* widgetTweening = nullptr, FName tweenName = "", int32 numberOfLoopSections = 0, ELoopType::LoopType loopType = once, bool playingBackward = false);
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, meta = (FriendlyName = "On Tween Complete"), Category = "iTween|Interface Events")
void OnTweenComplete(AiTweenEvent* eventOperator, AActor* actorTweening, USceneComponent* componentTweening, UWidget* widgetTweening, FName tweenName, FHitResult sweepHitResultForMoveEvents, bool successfulTransform);
};
- Changed iTweenEvent.cpp, making AiTweenEvent::RunInterface to use only the static version with the Execute_ prefix. (somehow the cast version was crashing with c++). Double checked the changed version and it was still working with blueprints.
void AiTweenEvent::RunInterface(UObject* target, FString type)
{
/* Little hack to work with c++
IiTInterface* interf = Cast<IiTInterface>(target);
if (interf)
{
if (type == "start")
{
interf->OnTweenStart(this, actorTweening, componentTweening, widgetTweening, tweenName);
}
else if (type == "update")
{
//interf->OnTweenUpdate(this, actorTweening, componentTweening, widgetTweening, tweenName, dtv, alpha);
if (IsEventDataType())
{
interf->OnTweenDataTick(this, tweenName, dtv.floatCurrent, dtv.linearColorCurrent, dtv.rotatorCurrent, dtv.vectorCurrent, dtv.vector2DCurrent, alpha);
}
else
{
interf->OnTweenTick(this, actorTweening, componentTweening, widgetTweening, tweenName, alpha);
}
}
else if (type == "loop")
{
interf->OnTweenLoop(this, actorTweening, componentTweening, widgetTweening, tweenName, numberOfLoopSections, loopType, playingBackward);
}
else if (type == "complete")
{
interf->OnTweenComplete(this, actorTweening, componentTweening, widgetTweening, tweenName, sweepResult, successfulTransform);
}
else
{
UiTween::Print("Target is not defined as iTweenEvent message-accepting type.", "error");
}
}
else
{
*/
if (target && target->GetClass()->ImplementsInterface(UiTInterface::StaticClass()))
{
if (type == "start")
{
IiTInterface::Execute_OnTweenStart(target, this, actorTweening, componentTweening, widgetTweening, tweenName);
}
else if (type == "update")
{
//IiTInterface::Execute_OnTweenUpdate(target, this, actorTweening, componentTweening, widgetTweening, tweenName, dtv, alpha);
if (IsEventDataType())
{
IiTInterface::Execute_OnTweenDataTick(target, this, tweenName, dtv.floatCurrent, dtv.linearColorCurrent, dtv.rotatorCurrent, dtv.vectorCurrent, dtv.vector2DCurrent, alpha);
}
else
{
IiTInterface::Execute_OnTweenTick(target, this, actorTweening, componentTweening, widgetTweening, tweenName, alpha);
}
}
else if (type == "loop")
{
IiTInterface::Execute_OnTweenLoop(target, this, actorTweening, componentTweening, widgetTweening, tweenName, numberOfLoopSections, loopType, playingBackward);
}
else if (type == "complete")
{
IiTInterface::Execute_OnTweenComplete(target, this, actorTweening, componentTweening, widgetTweening, tweenName, sweepResult, successfulTransform);
}
else
{
UiTween::Print("Target is not defined as iTweenEvent message-accepting type.", "error");
}
}
else
{
/*if (target)
{
UiTween::Print("Cannot send Interface message to" + target->GetFName().ToString(), "error");
}
else
{
UiTween::Print("Cannot send Interface message.", "error");
}*/
}
//}
}
- Then, in my actor class I extended IiTInterface;
class RUBIKSUNREAL_API ARubiksCube : public AActor, public IiTInterface
and set to override the _Implementation version of OnTweenComplete (Needed for BlueprintNativeEvents).
...
public:
virtual void OnTweenComplete_Implementation(AiTweenEvent* eventOperator, AActor* actorTweening, USceneComponent* componentTweening, UWidget* widgetTweening, FName tweenName, FHitResult sweepHitResultForMoveEvents, bool successfulTransform) override;
...
- this way, if I not implement the callback in blueprints it will use the c++ version.
Did you get it? If not I can send you the project after I finish it.
Best Regards,
Daniel