October3d55/M/LGUI/Source/LTween/Private/LTweener.cpp

338 lines
7.6 KiB
C++

// Copyright 2019-Present LexLiu. All Rights Reserved.
#include "LTweener.h"
#include "Curves/CurveFloat.h"
#include "LTween.h"
#include "Engine/World.h"
ULTweener::ULTweener()
{
tweenFunc.BindStatic(&ULTweener::OutCubic);//OutCubic default animation curve function
}
ULTweener* ULTweener::SetEase(ELTweenEase easetype)
{
if (elapseTime > 0 || startToTween)return this;
switch (easetype)
{
case ELTweenEase::Linear:
tweenFunc.BindStatic(&ULTweener::Linear);
break;
case ELTweenEase::InQuad:
tweenFunc.BindStatic(&ULTweener::InQuad);
break;
case ELTweenEase::OutQuad:
tweenFunc.BindStatic(&ULTweener::OutQuad);
break;
case ELTweenEase::InOutQuad:
tweenFunc.BindStatic(&ULTweener::InOutQuad);
break;
case ELTweenEase::InCubic:
tweenFunc.BindStatic(&ULTweener::InCubic);
break;
case ELTweenEase::OutCubic:
tweenFunc.BindStatic(&ULTweener::OutCubic);
break;
case ELTweenEase::InOutCubic:
tweenFunc.BindStatic(&ULTweener::InOutCubic);
break;
case ELTweenEase::InQuart:
tweenFunc.BindStatic(&ULTweener::InQuart);
break;
case ELTweenEase::OutQuart:
tweenFunc.BindStatic(&ULTweener::OutQuart);
break;
case ELTweenEase::InOutQuart:
tweenFunc.BindStatic(&ULTweener::InOutQuart);
break;
case ELTweenEase::InSine:
tweenFunc.BindStatic(&ULTweener::InSine);
break;
case ELTweenEase::OutSine:
tweenFunc.BindStatic(&ULTweener::OutSine);
break;
case ELTweenEase::InOutSine:
tweenFunc.BindStatic(&ULTweener::InOutSine);
break;
case ELTweenEase::InExpo:
tweenFunc.BindStatic(&ULTweener::InExpo);
break;
case ELTweenEase::OutExpo:
tweenFunc.BindStatic(&ULTweener::OutExpo);
break;
case ELTweenEase::InOutExpo:
tweenFunc.BindStatic(&ULTweener::InOutExpo);
break;
case ELTweenEase::InCirc:
tweenFunc.BindStatic(&ULTweener::InCirc);
break;
case ELTweenEase::OutCirc:
tweenFunc.BindStatic(&ULTweener::OutCirc);
break;
case ELTweenEase::InOutCirc:
tweenFunc.BindStatic(&ULTweener::InOutCirc);
break;
case ELTweenEase::InElastic:
tweenFunc.BindStatic(&ULTweener::InElastic);
break;
case ELTweenEase::OutElastic:
tweenFunc.BindStatic(&ULTweener::OutElastic);
break;
case ELTweenEase::InOutElastic:
tweenFunc.BindStatic(&ULTweener::InOutElastic);
break;
case ELTweenEase::InBack:
tweenFunc.BindStatic(&ULTweener::InBack);
break;
case ELTweenEase::OutBack:
tweenFunc.BindStatic(&ULTweener::OutBack);
break;
case ELTweenEase::InOutBack:
tweenFunc.BindStatic(&ULTweener::InOutBack);
break;
case ELTweenEase::InBounce:
tweenFunc.BindStatic(&ULTweener::InBounce);
break;
case ELTweenEase::OutBounce:
tweenFunc.BindStatic(&ULTweener::OutBounce);
break;
case ELTweenEase::InOutBounce:
tweenFunc.BindStatic(&ULTweener::InOutBounce);
break;
case ELTweenEase::CurveFloat:
tweenFunc.BindUObject(this, &ULTweener::CurveFloat);
break;
}
return this;
}
ULTweener* ULTweener::SetDelay(float newDelay)
{
if (elapseTime > 0 || startToTween)return this;
this->delay = newDelay;
if (this->delay < 0)
{
this->delay = 0;
}
return this;
}
ULTweener* ULTweener::SetLoop(ELTweenLoop newLoopType, int32 newLoopCount)
{
if (elapseTime > 0 || startToTween)return this;
this->loopType = newLoopType;
this->maxLoopCount = newLoopCount;
return this;
}
ULTweener* ULTweener::SetEaseCurve(UCurveFloat* newCurve)
{
if (IsValid(newCurve))
{
SetEase(ELTweenEase::CurveFloat);
curveFloat = newCurve;
}
else
{
UE_LOG(LTween, Error, TEXT("[ULTweener::SetEaseCurve]newCurve is not valid!"));
}
return this;
}
ULTweener* ULTweener::SetCurveFloat(UCurveFloat* newCurveFloat)
{
if (elapseTime > 0 || startToTween)return this;
curveFloat = newCurveFloat;
return this;
}
ULTweener* ULTweener::SetAffectByGamePause(bool value)
{
affectByGamePause = value;
return this;
}
ULTweener* ULTweener::SetAffectByTimeDilation(bool value)
{
affectByTimeDilation = value;
return this;
}
bool ULTweener::ToNext(float deltaTime, float unscaledDeltaTime)
{
if (auto world = GetWorld())
{
if (world->IsPaused() && affectByGamePause)return true;
}
if (isMarkedToKill)return false;
if (isMarkedPause)return true;//no need to tick time if pause
return this->ToNextWithElapsedTime(elapseTime + (affectByTimeDilation ? deltaTime : unscaledDeltaTime));
}
bool ULTweener::ToNextWithElapsedTime(float InElapseTime)
{
this->elapseTime = InElapseTime;
if (elapseTime > delay)//if elapseTime bigger than delay, do animation
{
if (!startToTween)
{
startToTween = true;
//set initialize value
OnStartGetValue();
//execute callback
onCycleStartCpp.ExecuteIfBound();
onStartCpp.ExecuteIfBound();
}
float elapseTimeWithoutDelay = elapseTime - delay;
float currentTime = elapseTimeWithoutDelay - duration * loopCycleCount;
if (currentTime >= duration)
{
bool returnValue = true;
loopCycleCount++;
TweenAndApplyValue(reverseTween ? 0 : duration);
onUpdateCpp.ExecuteIfBound(1.0f);
onCycleCompleteCpp.ExecuteIfBound();
if (loopType == ELTweenLoop::Once)
{
onCompleteCpp.ExecuteIfBound();
returnValue = false;
}
else if (maxLoopCount <= -1)//infinite loop
{
onCycleStartCpp.ExecuteIfBound();//start new cycle callback
returnValue = true;
}
else
{
if (loopCycleCount >= maxLoopCount)//reach end cycle
{
onCompleteCpp.ExecuteIfBound();
returnValue = false;
}
else//not reach end cycle
{
onCycleStartCpp.ExecuteIfBound();//start new cycle callback
returnValue = true;
}
}
switch (loopType)
{
case ELTweenLoop::Restart:
{
SetValueForRestart();
}
break;
case ELTweenLoop::Yoyo:
{
reverseTween = !reverseTween;
SetValueForYoyo();
}
break;
case ELTweenLoop::Incremental:
{
SetValueForIncremental();
}
break;
}
return returnValue;
}
else
{
if (reverseTween)
{
currentTime = duration - currentTime;
}
TweenAndApplyValue(currentTime);
onUpdateCpp.ExecuteIfBound(currentTime / duration);
return true;
}
}
else
{
return true;//waiting delay
}
}
void ULTweener::Kill(bool callComplete)
{
if (callComplete)
{
onCompleteCpp.ExecuteIfBound();
}
isMarkedToKill = true;
}
void ULTweener::ForceComplete()
{
isMarkedToKill = true;
elapseTime = delay + duration;
TweenAndApplyValue(duration);
onUpdateCpp.ExecuteIfBound(1.0f);
onCompleteCpp.ExecuteIfBound();
}
void ULTweener::Restart()
{
if (elapseTime == 0)
{
return;
}
isMarkedPause = false;//incase it is paused.
//reset parameter to initial
loopCycleCount = 0;
reverseTween = false;
SetOriginValueForRestart();
this->ToNextWithElapsedTime(0);
}
void ULTweener::Goto(float timePoint)
{
timePoint = FMath::Clamp(timePoint, 0.0f, duration);
//reset parameter to initial
loopCycleCount = 0;
reverseTween = false;
this->ToNextWithElapsedTime(timePoint);
}
float ULTweener::GetProgress()const
{
if (elapseTime > delay)
{
float elapseTimeWithoutDelay = elapseTime - delay;
float currentTime = elapseTimeWithoutDelay - duration * loopCycleCount;
if (currentTime >= duration)
{
return 1;
}
else
{
if (reverseTween)
{
currentTime = duration - currentTime;
}
return currentTime / duration;
}
}
else
{
return 0;
}
}
ULTweener* ULTweener::SetTickType(ELTweenTickType value)
{
if (elapseTime > 0 || startToTween)return this;
this->tickType = value;
return this;
}
float ULTweener::CurveFloat(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
if (curveFloat.IsValid())
{
return curveFloat->GetFloatValue(t / d) * c + b;
}
else
{
UE_LOG(LTween, Warning, TEXT("[ULTweener::CurveFloat]CurveFloat not valid! Fallback to linear. You should always call SetCurveFloat(and pass a valid curve) if set Easetype to CurveFloat."));
return Linear(c, b, t, d);
}
}