Here’s a simple example of how to create an animated Slate widget, which slides in from the left when constructed, and slides out to the right when SetAnimateOut
is called.
//.h
DECLARE_MULTICAST_DELEGATE(FUFLoadingScreen_Event);
class UNFURNISHED_API SUFLoadingScreen : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SUFLoadingScreen) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs);
void SetAnimateOut(const bool bOut);
FUFLoadingScreen_Event OnAnimationFinished;
protected:
FCurveSequence Animation;
FCurveHandle CurveHandle;
float PositionOffset = 0;
bool bPositionInitialized = false;
bool bWasAnimating = false;
bool bAnimateOut = false;
virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override;
};
//.cpp
void SUFLoadingScreen::Construct(const FArguments& InArgs)
{
FSlateFontInfo Font = FAppStyle::Get().GetFontStyle("Regular");
Font.Size = 40;
Animation = FCurveSequence(0, 0.5f);
CurveHandle = Animation.AddCurve(0.f, 0.5f, ECurveEaseFunction::QuadInOut);
ChildSlot
[
SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("WhiteBrush"))
.BorderBackgroundColor(FLinearColor::Gray)
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.ColorAndOpacity(FLinearColor::Black)
.Font(Font)
.Text(INVTEXT("Loading"))
]
.RenderTransform_Lambda([this]()
{
return FSlateRenderTransform(FVector2D(PositionOffset, 0));
})
.Visibility_Lambda([this]()
{
//This avoids the widget from flashing on screen before the render transform offset is set
return bPositionInitialized ? EVisibility::Visible : EVisibility::Hidden;
})
];
bWasAnimating = true;
Animation.Play(SharedThis(this), false);
}
void SUFLoadingScreen::SetAnimateOut(const bool bOut)
{
bAnimateOut = bOut;
bWasAnimating = true;
Animation.Play(AsShared());
}
void SUFLoadingScreen::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{
SCompoundWidget::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);
if(bAnimateOut)
{
PositionOffset = CurveHandle.GetLerp() * AllottedGeometry.Size.X;
}
else
{
PositionOffset = -1 * ((1 - CurveHandle.GetLerp()) * AllottedGeometry.Size.X);
}
bPositionInitialized = true;
if(bWasAnimating && !Animation.IsPlaying())
{
bWasAnimating = false;
OnAnimationFinished.Broadcast();
}
}