Upgrade to 5.8

This commit is contained in:
Ado
2026-07-04 21:15:59 +02:00
parent 4cf4176d57
commit 9f3051d68e
55 changed files with 5495 additions and 77 deletions

View File

@@ -10,7 +10,7 @@
"DocsURL": "https://github.com/RLoris/ArrayHelperDoc/blob/master/README.md",
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/813e339b92ad4cf587a4cef56bec7020",
"SupportURL": "https://forms.gle/CpekZfTewGZrUVen7",
"EngineVersion": "5.7.0",
"EngineVersion": "5.8.0",
"CanContainContent": true,
"Installed": true,
"Modules": [

View File

@@ -0,0 +1,30 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.3",
"FriendlyName": "LTween",
"Description": "LTween (Lex-Tween) is a tween animation library",
"Category": "LexPlugin",
"CreatedBy": "LexLiu",
"CreatedByURL": "",
"DocsURL": "https://liufei2008.github.io/LTweenDoc/GetStarted/",
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/efa1b6e762974e48847e029c8ac6c602",
"SupportURL": "707908214@qq.com",
"EngineVersion": "5.8.0",
"CanContainContent": true,
"Installed": true,
"Modules": [
{
"Name": "LTween",
"Type": "Runtime",
"LoadingPhase": "Default",
"PlatformAllowList": [
"Win64",
"Mac",
"Linux",
"IOS",
"Android"
]
}
]
}

Binary file not shown.

View File

@@ -0,0 +1,40 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
using UnrealBuildTool;
public class LTween : ModuleRules
{
public LTween(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"Engine",
// ... add other public dependencies that you statically link with here ...
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"UMG",
"SlateCore",
// ... add private dependencies that you statically link with here ...
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}

View File

@@ -0,0 +1,21 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#include "LTween.h"
#include "Modules/ModuleManager.h"
DEFINE_LOG_CATEGORY(LTween);
void FLTweenModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
}
void FLTweenModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
}
IMPLEMENT_MODULE(FLTweenModule, LTween)//if second param is wrong, an error like "EmptyLinkFunctionForStaticInitialization(XXX)" will occor when package project

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,493 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#include "LTweenManager.h"
#include "Tweener/LTweenerFloat.h"
#include "Tweener/LTweenerDouble.h"
#include "Tweener/LTweenerInteger.h"
#include "Tweener/LTweenerVector.h"
#include "Tweener/LTweenerColor.h"
#include "Tweener/LTweenerLinearColor.h"
#include "Tweener/LTweenerVector2D.h"
#include "Tweener/LTweenerVector4.h"
#include "Tweener/LTweenerPosition.h"
#include "Tweener/LTweenerQuaternion.h"
#include "Tweener/LTweenerRotator.h"
#include "Tweener/LTweenerRotationEuler.h"
#include "Tweener/LTweenerRotationQuat.h"
#include "Tweener/LTweenerMaterialScalar.h"
#include "Tweener/LTweenerMaterialVector.h"
#include "Tweener/LTweenerFrame.h"
#include "Tweener/LTweenerVirtual.h"
#include "Tweener/LTweenerUpdate.h"
#include "LTweenerSequence.h"
#include "Engine/World.h"
#include "Engine/Engine.h"
ULTweenTickHelperComponent::ULTweenTickHelperComponent()
{
PrimaryComponentTick.bCanEverTick = true;
PrimaryComponentTick.bStartWithTickEnabled = true;
PrimaryComponentTick.TickGroup = ETickingGroup::TG_DuringPhysics;
PrimaryComponentTick.bTickEvenWhenPaused = true;
}
void ULTweenTickHelperComponent::BeginPlay()
{
Super::BeginPlay();
}
void ULTweenTickHelperComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (Target.IsValid())
{
Target->Tick((ELTweenTickType)((uint8)PrimaryComponentTick.TickGroup), DeltaTime);
}
}
void ULTweenTickHelperComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
}
ALTweenTickHelperActor::ALTweenTickHelperActor()
{
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = true;
PrimaryActorTick.TickGroup = ETickingGroup::TG_DuringPhysics;
PrimaryActorTick.bTickEvenWhenPaused = true;
SpawnCollisionHandlingMethod = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
}
void ALTweenTickHelperActor::BeginPlay()
{
Super::BeginPlay();
if (auto LTweenManager = ULTweenManager::GetLTweenInstance(this))
{
SetupTick(LTweenManager);
}
else
{
//If GameInstance subsystem not created yet, then register a event to wait it create
OnLTweenManagerCreatedDelegateHandle = ULTweenManager::OnLTweenManagerCreated.AddUObject(this, &ALTweenTickHelperActor::OnLTweenManagerCreated);
}
}
void ALTweenTickHelperActor::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
if (Target.IsValid())
{
Target->Tick(ELTweenTickType::DuringPhysics, DeltaSeconds);
}
}
void ALTweenTickHelperActor::EndPlay(EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
if (OnLTweenManagerCreatedDelegateHandle.IsValid())
{
ULTweenManager::OnLTweenManagerCreated.Remove(OnLTweenManagerCreatedDelegateHandle);
}
}
void ALTweenTickHelperActor::OnLTweenManagerCreated(ULTweenManager* LTweenManager)
{
SetupTick(LTweenManager);
}
void ALTweenTickHelperActor::SetupTick(ULTweenManager* LTweenManager)
{
auto CreateComp = [LTweenManager, this](ETickingGroup TickingGroup, FName Name) {
auto TickComp_DuringPhysics = NewObject<ULTweenTickHelperComponent>(this, Name);
TickComp_DuringPhysics->SetTickGroup(TickingGroup);
TickComp_DuringPhysics->RegisterComponent();
TickComp_DuringPhysics->Target = LTweenManager;
this->AddInstanceComponent(TickComp_DuringPhysics);
};
CreateComp(ETickingGroup::TG_PrePhysics, TEXT("PrePhysics"));
CreateComp(ETickingGroup::TG_PostPhysics, TEXT("PostPhysics"));
CreateComp(ETickingGroup::TG_PostUpdateWork, TEXT("PostUpdateWork"));
this->Target = LTweenManager;
}
bool ULTweenTickHelperWorldSubsystem::ShouldCreateSubsystem(UObject* Outer) const
{
if (auto World = Outer->GetWorld())
{
if (World->IsGameWorld())
{
return true;
}
}
return false;
}
void ULTweenTickHelperWorldSubsystem::PostInitialize()
{
Super::PostInitialize();
if (auto World = GetWorld())
{
if (World->IsGameWorld())
{
World->SpawnActor<ALTweenTickHelperActor>();
}
}
}
DECLARE_CYCLE_STAT(TEXT("LTween Update"), STAT_Update, STATGROUP_LTween);
FLTweenManagerCreated ULTweenManager::OnLTweenManagerCreated;
//~USubsystem interface
void ULTweenManager::Initialize(FSubsystemCollectionBase& Collection)
{
const UGameInstance* LocalGameInstance = GetGameInstance();
check(LocalGameInstance);
}
void ULTweenManager::Deinitialize()
{
tweenerList.Empty();
}
bool ULTweenManager::ShouldCreateSubsystem(UObject* Outer) const
{
return true;
}
//~End of USubsystem interface
void ULTweenManager::Tick(ELTweenTickType TickType, float DeltaTime)
{
if (bTickPaused)return;
if (TickType == ELTweenTickType::Manual)
{
OnTick(TickType, DeltaTime, DeltaTime);
}
else
{
if (auto World = GetWorld())
{
OnTick(TickType, World->DeltaTimeSeconds, World->DeltaRealTimeSeconds);
}
else
{
OnTick(TickType, DeltaTime, DeltaTime);
}
}
}
#include "Kismet/GameplayStatics.h"
#include "Engine/GameInstance.h"
ULTweenManager* ULTweenManager::GetLTweenInstance(UObject* WorldContextObject)
{
if (auto GameInstance = UGameplayStatics::GetGameInstance(WorldContextObject))
return GameInstance->GetSubsystem<ULTweenManager>();
else
return nullptr;
}
void ULTweenManager::OnTick(ELTweenTickType TickType, float DeltaTime, float UnscaledDeltaTime)
{
SCOPE_CYCLE_COUNTER(STAT_Update);
auto count = tweenerList.Num();
for (int32 i = 0; i < count; i++)
{
auto tweener = tweenerList[i];
if (!IsValid(tweener))
{
tweenerList.RemoveAt(i);
i--;
count--;
}
else
{
if (tweener->GetTickType() != TickType)continue;
if (tweener->ToNext(DeltaTime, UnscaledDeltaTime) == false)
{
tweenerList.RemoveAt(i);
tweener->ConditionalBeginDestroy();
i--;
count--;
}
}
}
if (TickType == ELTweenTickType::DuringPhysics)
{
if (updateEvent.IsBound())
updateEvent.Broadcast(DeltaTime);
}
}
void ULTweenManager::CustomTick(float DeltaTime)
{
OnTick(ELTweenTickType::DuringPhysics, DeltaTime, DeltaTime);
}
void ULTweenManager::DisableTick()
{
bTickPaused = true;
}
void ULTweenManager::EnableTick()
{
bTickPaused = false;
}
void ULTweenManager::ManualTick(float DeltaTime)
{
Tick(ELTweenTickType::Manual, DeltaTime);
}
void ULTweenManager::KillAllTweens(bool callComplete)
{
for (auto item : tweenerList)
{
if (IsValid(item))
{
item->Kill(callComplete);
}
}
tweenerList.Reset();
}
bool ULTweenManager::IsTweening(UObject* WorldContextObject, ULTweener* item)
{
if (!IsValid(item))return false;
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return false;
return Instance->tweenerList.Contains(item);
}
void ULTweenManager::KillIfIsTweening(UObject* WorldContextObject, ULTweener* item, bool callComplete)
{
if (IsTweening(WorldContextObject, item))
{
item->Kill(callComplete);
}
}
void ULTweenManager::RemoveTweener(UObject* WorldContextObject, ULTweener* item)
{
if (!IsValid(item))return;
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return;
Instance->tweenerList.Remove(item);
}
//float
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenFloatGetterFunction& getter, const FLTweenFloatSetterFunction& setter, float endValue, float duration)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerFloat>(WorldContextObject);
tweener->SetInitialValue(getter, setter, endValue, duration);
Instance->tweenerList.Add(tweener);
return tweener;
}
//float
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenDoubleGetterFunction& getter, const FLTweenDoubleSetterFunction& setter, double endValue, float duration)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerDouble>(WorldContextObject);
tweener->SetInitialValue(getter, setter, endValue, duration);
Instance->tweenerList.Add(tweener);
return tweener;
}
//interger
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenIntGetterFunction& getter, const FLTweenIntSetterFunction& setter, int endValue, float duration)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerInteger>(WorldContextObject);
tweener->SetInitialValue(getter, setter, endValue, duration);
Instance->tweenerList.Add(tweener);
return tweener;
}
//position
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenPositionGetterFunction& getter, const FLTweenPositionSetterFunction& setter, const FVector& endValue, float duration, bool sweep, FHitResult* sweepHitResult, ETeleportType teleportType)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerPosition>(WorldContextObject);
tweener->SetInitialValue(getter, setter, endValue, duration, sweep, sweepHitResult, teleportType);
Instance->tweenerList.Add(tweener);
return tweener;
}
//vector
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenVectorGetterFunction& getter, const FLTweenVectorSetterFunction& setter, const FVector& endValue, float duration)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerVector>(WorldContextObject);
tweener->SetInitialValue(getter, setter, endValue, duration);
Instance->tweenerList.Add(tweener);
return tweener;
}
//color
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenColorGetterFunction& getter, const FLTweenColorSetterFunction& setter, const FColor& endValue, float duration)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerColor>(WorldContextObject);
tweener->SetInitialValue(getter, setter, endValue, duration);
Instance->tweenerList.Add(tweener);
return tweener;
}
//linearcolor
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenLinearColorGetterFunction& getter, const FLTweenLinearColorSetterFunction& setter, const FLinearColor& endValue, float duration)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerLinearColor>(WorldContextObject);
tweener->SetInitialValue(getter, setter, endValue, duration);
Instance->tweenerList.Add(tweener);
return tweener;
}
//vector2d
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenVector2DGetterFunction& getter, const FLTweenVector2DSetterFunction& setter, const FVector2D& endValue, float duration)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerVector2D>(WorldContextObject);
tweener->SetInitialValue(getter, setter, endValue, duration);
Instance->tweenerList.Add(tweener);
return tweener;
}
//vector4
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenVector4GetterFunction& getter, const FLTweenVector4SetterFunction& setter, const FVector4& endValue, float duration)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerVector4>(WorldContextObject);
tweener->SetInitialValue(getter, setter, endValue, duration);
Instance->tweenerList.Add(tweener);
return tweener;
}
//quaternion
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenQuaternionGetterFunction& getter, const FLTweenQuaternionSetterFunction& setter, const FQuat& endValue, float duration)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerQuaternion>(WorldContextObject);
tweener->SetInitialValue(getter, setter, endValue, duration);
Instance->tweenerList.Add(tweener);
return tweener;
}
//rotator
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenRotatorGetterFunction& getter, const FLTweenRotatorSetterFunction& setter, const FRotator& endValue, float duration)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerRotator>(WorldContextObject);
tweener->SetInitialValue(getter, setter, endValue, duration);
Instance->tweenerList.Add(tweener);
return tweener;
}
//rotation euler
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenRotationQuatGetterFunction& getter, const FLTweenRotationQuatSetterFunction& setter, const FVector& eulerAngle, float duration, bool sweep, FHitResult* sweepHitResult, ETeleportType teleportType)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerRotationEuler>(WorldContextObject);
tweener->SetInitialValue(getter, setter, eulerAngle, duration, sweep, sweepHitResult, teleportType);
Instance->tweenerList.Add(tweener);
return tweener;
}
//rotation quat
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenRotationQuatGetterFunction& getter, const FLTweenRotationQuatSetterFunction& setter, const FQuat& endValue, float duration, bool sweep, FHitResult* sweepHitResult, ETeleportType teleportType)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerRotationQuat>(WorldContextObject);
tweener->SetInitialValue(getter, setter, endValue, duration, sweep, sweepHitResult, teleportType);
Instance->tweenerList.Add(tweener);
return tweener;
}
//material scalar
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenMaterialScalarGetterFunction& getter, const FLTweenMaterialScalarSetterFunction& setter, float endValue, float duration, int32 parameterIndex)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerMaterialScalar>(WorldContextObject);
tweener->SetInitialValue(getter, setter, endValue, duration, parameterIndex);
Instance->tweenerList.Add(tweener);
return tweener;
}
//material vector
ULTweener* ULTweenManager::To(UObject* WorldContextObject, const FLTweenMaterialVectorGetterFunction& getter, const FLTweenMaterialVectorSetterFunction& setter, const FLinearColor& endValue, float duration, int32 parameterIndex)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerMaterialVector>(WorldContextObject);
tweener->SetInitialValue(getter, setter, endValue, duration, parameterIndex);
Instance->tweenerList.Add(tweener);
return tweener;
}
ULTweener* ULTweenManager::VirtualTo(UObject* WorldContextObject, float duration)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerVirtual>(WorldContextObject);
tweener->SetInitialValue(duration);
Instance->tweenerList.Add(tweener);
return tweener;
}
ULTweener* ULTweenManager::DelayFrameCall(UObject* WorldContextObject, int delayFrame)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerFrame>(WorldContextObject);
tweener->SetInitialValue(delayFrame);
Instance->tweenerList.Add(tweener);
return tweener;
}
ULTweener* ULTweenManager::UpdateCall(UObject* WorldContextObject)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerUpdate>(WorldContextObject);
Instance->tweenerList.Add(tweener);
return tweener;
}
ULTweenerSequence* ULTweenManager::CreateSequence(UObject* WorldContextObject)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return nullptr;
auto tweener = NewObject<ULTweenerSequence>(WorldContextObject);
Instance->tweenerList.Add(tweener);
return tweener;
}
FDelegateHandle ULTweenManager::RegisterUpdateEvent(UObject* WorldContextObject, const FLTweenUpdateDelegate& update)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return FDelegateHandle();
return Instance->updateEvent.Add(update);
}
void ULTweenManager::UnregisterUpdateEvent(UObject* WorldContextObject, const FDelegateHandle& delegateHandle)
{
auto Instance = GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return;
Instance->updateEvent.Remove(delegateHandle);
}

View File

@@ -0,0 +1,338 @@
// 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);
}
}

View File

@@ -0,0 +1,326 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#include "LTweenerSequence.h"
#include "LTween.h"
#include "LTweenManager.h"
#include "Tweener/LTweenerFrame.h"
#include "Tweener/LTweenerVirtual.h"
ULTweenerSequence* ULTweenerSequence::Append(UObject* WorldContextObject, ULTweener* tweener)
{
return this->Insert(WorldContextObject, duration, tweener);
}
ULTweenerSequence* ULTweenerSequence::AppendInterval(UObject* WorldContextObject, float interval)
{
if (elapseTime > 0 || startToTween)
{
UE_LOG(LTween, Error, TEXT("[%s].%d can't do this because this tween already started"), ANSI_TO_TCHAR(__FUNCTION__), __LINE__);
return this;
}
duration += interval;
return this;
}
ULTweenerSequence* ULTweenerSequence::Insert(UObject* WorldContextObject, float timePosition, ULTweener* tweener)
{
if (!IsValid(tweener))
{
UE_LOG(LTween, Error, TEXT("[%s].%d tweener is null"), ANSI_TO_TCHAR(__FUNCTION__), __LINE__);
return this;
}
if (tweener->IsA<ULTweenerFrame>() || tweener->IsA<ULTweenerVirtual>())
{
UE_LOG(LTween, Error, TEXT("[%s].%d sequence not support this tweener type: %s"), ANSI_TO_TCHAR(__FUNCTION__), __LINE__, *(tweener->GetClass()->GetName()));
return this;
}
if (elapseTime > 0 || startToTween)
{
UE_LOG(LTween, Error, TEXT("[%s].%d can't do this because this tween already started"), ANSI_TO_TCHAR(__FUNCTION__), __LINE__);
return this;
}
if (tweenerList.Contains(tweener))
{
UE_LOG(LTween, Error, TEXT("[%s].%d tweener already contains in the list"), ANSI_TO_TCHAR(__FUNCTION__), __LINE__);
return this;
}
if (tweener->loopType != ELTweenLoop::Once && tweener->maxLoopCount == -1)
{
UE_LOG(LTween, Error, TEXT("[%s].%d infinite tweener is not supported in sequence, will convert to 1"), ANSI_TO_TCHAR(__FUNCTION__), __LINE__);
tweener->maxLoopCount = 1;
}
ULTweenManager::RemoveTweener(WorldContextObject, tweener);
int loopCount = tweener->loopType == ELTweenLoop::Once ? 1 : tweener->maxLoopCount;
float tweenerTime = tweener->delay + tweener->duration * loopCount;
tweener->SetDelay(tweener->delay + timePosition);
tweenerList.Add(tweener);
lastTweenStartTime = timePosition;
float inputDuration = tweenerTime + timePosition;
if (duration < inputDuration)
{
duration = inputDuration;
}
return this;
}
ULTweenerSequence* ULTweenerSequence::Prepend(UObject* WorldContextObject, ULTweener* tweener)
{
if (!IsValid(tweener))
{
UE_LOG(LTween, Error, TEXT("[%s].%d tweener is null"), ANSI_TO_TCHAR(__FUNCTION__), __LINE__);
return this;
}
if (tweener->IsA<ULTweenerFrame>() || tweener->IsA<ULTweenerVirtual>())
{
UE_LOG(LTween, Error, TEXT("[%s].%d sequence not support this tweener type: %s"), ANSI_TO_TCHAR(__FUNCTION__), __LINE__, *(tweener->GetClass()->GetName()));
return this;
}
if (elapseTime > 0 || startToTween)
{
UE_LOG(LTween, Error, TEXT("[%s].%d can't do this because this tween already started"), ANSI_TO_TCHAR(__FUNCTION__), __LINE__);
return this;
}
if (tweenerList.Contains(tweener))
{
UE_LOG(LTween, Error, TEXT("[%s].%d tweener already contains in the list"), ANSI_TO_TCHAR(__FUNCTION__), __LINE__);
return this;
}
if (tweener->loopType != ELTweenLoop::Once && tweener->maxLoopCount == -1)
{
UE_LOG(LTween, Error, TEXT("[%s].%d infinite tweener is not supported in sequence, will convert to 1"), ANSI_TO_TCHAR(__FUNCTION__), __LINE__);
tweener->maxLoopCount = 1;
}
ULTweenManager::RemoveTweener(WorldContextObject, tweener);
int loopCount = tweener->loopType == ELTweenLoop::Once ? 1 : tweener->maxLoopCount;
float inputDuration = tweener->delay + tweener->duration * loopCount;
//offset others
for (auto& item : tweenerList)
{
item->SetDelay(item->delay + inputDuration);
}
tweenerList.Insert(tweener, 0);
duration += inputDuration;
lastTweenStartTime = 0;
return this;
}
ULTweenerSequence* ULTweenerSequence::PrependInterval(UObject* WorldContextObject, float interval)
{
if (elapseTime > 0 || startToTween)
{
UE_LOG(LTween, Error, TEXT("[%s].%d can't do this because this tween already started"), ANSI_TO_TCHAR(__FUNCTION__), __LINE__);
return this;
}
//offset others
for (auto& item : tweenerList)
{
item->SetDelay(item->delay + interval);
}
duration += interval;
lastTweenStartTime += interval;
return this;
}
ULTweenerSequence* ULTweenerSequence::Join(UObject* WorldContextObject, ULTweener* tweener)
{
if (!IsValid(tweener))
{
UE_LOG(LTween, Error, TEXT("[%s].%d tweener is null"), ANSI_TO_TCHAR(__FUNCTION__), __LINE__);
return this;
}
if (tweener->IsA<ULTweenerFrame>() || tweener->IsA<ULTweenerVirtual>())
{
UE_LOG(LTween, Error, TEXT("[%s].%d sequence not support this tweener type: %s"), ANSI_TO_TCHAR(__FUNCTION__), __LINE__, *(tweener->GetClass()->GetName()));
return this;
}
if (tweenerList.Num() == 0)return this;
return this->Insert(WorldContextObject, lastTweenStartTime, tweener);
}
void ULTweenerSequence::TweenAndApplyValue(float currentTime)
{
for(int i = 0; i < tweenerList.Num(); i++)
{
auto& item = tweenerList[i];
if (!item->ToNextWithElapsedTime(currentTime))
{
finishedTweenerList.Add(item);
tweenerList.RemoveAt(i);
i--;
}
}
}
void ULTweenerSequence::SetOriginValueForRestart()
{
for (auto& item : finishedTweenerList)
{
//add tweener to tweenerList
tweenerList.Add(item);
}
finishedTweenerList.Reset();
for (auto& item : tweenerList)
{
if (item->elapseTime > 0 || item->startToTween)
{
item->SetOriginValueForRestart();//if tween already start, then we can call "SetOriginValueForRestart"
item->TweenAndApplyValue(0);
}
//set parameter to initial
item->elapseTime = 0;
item->loopCycleCount = 0;
item->reverseTween = false;
}
}
void ULTweenerSequence::SetValueForIncremental()
{
for (auto& item : finishedTweenerList)
{
item->SetValueForIncremental();
//set parameter to initial
item->elapseTime = 0;
item->loopCycleCount = 0;
item->reverseTween = false;
item->TweenAndApplyValue(0);
//add tweener to tweenerList
tweenerList.Add(item);
}
finishedTweenerList.Reset();
}
void ULTweenerSequence::SetValueForYoyo()
{
this->reverseTween = !this->reverseTween;//reverse it again, so it will keep value false, because we only need to reverse tweenerList
for (auto& item : finishedTweenerList)
{
if (item->loopType != ELTweenLoop::Yoyo)//if it is already yoyo, then we no need to change reverseTween for it
{
item->reverseTween = !item->reverseTween;
}
//set parameter to initial
item->elapseTime = 0;
item->loopCycleCount = 0;
//flip tweener
int loopCount = item->loopType == ELTweenLoop::Once ? 1 : item->maxLoopCount;
float tweenerDelay = duration - (item->delay + item->duration * loopCount);
item->delay = tweenerDelay;
//add tweener to tweenerList
tweenerList.Add(item);
}
finishedTweenerList.Reset();
}
void ULTweenerSequence::SetValueForRestart()
{
for (auto& item : finishedTweenerList)
{
//set parameter to initial
item->elapseTime = 0;
item->loopCycleCount = 0;
item->reverseTween = false;
item->TweenAndApplyValue(0);
//add tweener to tweenerList
tweenerList.Add(item);
}
finishedTweenerList.Reset();
}
void ULTweenerSequence::Restart()
{
if (elapseTime == 0)
{
return;
}
this->isMarkedPause = false;//incase it is paused.
//reset parameter and value to start
{
//reset parameter to initial
if (this->loopType == ELTweenLoop::Yoyo)
{
if (loopCycleCount % 2 != 0)//this means current is yoyo back, then we should reverse it
{
this->reverseTween = true;
for (auto& item : tweenerList)
{
finishedTweenerList.Add(item);
}
tweenerList.Reset();
this->SetValueForYoyo();
}
}
for (auto& item : finishedTweenerList)
{
tweenerList.Add(item);
}
finishedTweenerList.Reset();
this->loopCycleCount = 0;
//sort it, so later tweener can do "SetOriginValueForRestart" ealier, so ealier tweener will get correct start state
tweenerList.Sort([=](const ULTweener& A, const ULTweener& B) {
return A.delay > B.delay;
});
for (int i = 0; i < tweenerList.Num(); i++)
{
auto& item = tweenerList[i];
if (item->startToTween)
{
item->SetOriginValueForRestart();
item->TweenAndApplyValue(0);
}
//set parameter to initial
item->elapseTime = 0;
item->loopCycleCount = 0;
item->reverseTween = false;
}
}
this->ToNextWithElapsedTime(0);
}
void ULTweenerSequence::Goto(float timePoint)
{
timePoint = FMath::Clamp(timePoint, 0.0f, duration);
//reset parameter to start, then goto timepoint. these line should be same as lines in "Restart"
{
//reset parameter to initial
if (this->loopType == ELTweenLoop::Yoyo)
{
if (loopCycleCount % 2 != 0)//mean current is yoyo back, should reverse it
{
this->reverseTween = true;
for (auto& item : tweenerList)
{
finishedTweenerList.Add(item);
}
tweenerList.Reset();
this->SetValueForYoyo();
}
}
for (auto& item : finishedTweenerList)
{
tweenerList.Add(item);
}
finishedTweenerList.Reset();
this->loopCycleCount = 0;
//sort it, so later tweener can do "SetOriginValueForRestart" ealier, so ealier tweener will get correct start state
tweenerList.Sort([=](const ULTweener& A, const ULTweener& B) {
return A.delay > B.delay;
});
for (int i = 0; i < tweenerList.Num(); i++)
{
auto& item = tweenerList[i];
if (item->startToTween)
{
item->SetOriginValueForRestart();
item->TweenAndApplyValue(0);
}
//set parameter to initial
item->elapseTime = 0;
item->loopCycleCount = 0;
item->reverseTween = false;
}
}
this->ToNextWithElapsedTime(timePoint);
}

View File

@@ -0,0 +1,66 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerColor.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerColor :public ULTweener
{
GENERATED_BODY()
public:
float startFloat = 0.0f;//b
float changeFloat = 1.0f;//c
FColor startValue;
FColor endValue;
FLTweenColorGetterFunction getter;
FLTweenColorSetterFunction setter;
FColor originStartValue;
FColor originEndValue;
void SetInitialValue(const FLTweenColorGetterFunction& newGetter, const FLTweenColorSetterFunction& newSetter, const FColor& newEndValue, float newDuration)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->endValue = newEndValue;
this->startFloat = 0.0f;
this->changeFloat = 1.0f;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
this->startValue = getter.Execute();
this->originStartValue = this->startValue;
this->originEndValue = this->endValue;
}
virtual void TweenAndApplyValue(float currentTime) override
{
float lerpValue = tweenFunc.Execute(changeFloat, startFloat, currentTime, duration);
FColor value;
value.R = FMath::Lerp(startValue.R, endValue.R, lerpValue);
value.G = FMath::Lerp(startValue.G, endValue.G, lerpValue);
value.B = FMath::Lerp(startValue.B, endValue.B, lerpValue);
value.A = FMath::Lerp(startValue.A, endValue.A, lerpValue);
setter.ExecuteIfBound(value);
}
virtual void SetValueForIncremental() override
{
FColor diffValue;
diffValue.R = endValue.R - startValue.R;
diffValue.G = endValue.G - startValue.G;
diffValue.B = endValue.B - startValue.B;
diffValue.A = endValue.A - startValue.A;
startValue = endValue;
endValue += diffValue;
}
virtual void SetOriginValueForRestart() override
{
startValue = originStartValue;
endValue = originEndValue;
}
};

View File

@@ -0,0 +1,57 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerDouble.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerDouble:public ULTweener
{
GENERATED_BODY()
public:
float startFloat = 0.0f;//b
float changeFloat = 1.0f;//c
double startValue;
double endValue;
FLTweenDoubleGetterFunction getter;
FLTweenDoubleSetterFunction setter;
double originStartValue;
void SetInitialValue(const FLTweenDoubleGetterFunction& newGetter, const FLTweenDoubleSetterFunction& newSetter, const double& newEndValue, float newDuration)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->endValue = newEndValue;
this->startFloat = 0.0f;
this->changeFloat = 1.0f;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
this->startValue = getter.Execute();
this->originStartValue = this->startValue;
}
virtual void TweenAndApplyValue(float currentTime) override
{
float lerpValue = tweenFunc.Execute(changeFloat, startFloat, currentTime, duration);
auto value = FMath::Lerp(startValue, endValue, lerpValue);
setter.ExecuteIfBound(value);
}
virtual void SetValueForIncremental() override
{
auto diffValue = endValue - startValue;
startValue = endValue;
endValue += diffValue;
}
virtual void SetOriginValueForRestart() override
{
auto diffValue = endValue - startValue;
startValue = originStartValue;
endValue = originStartValue + diffValue;
}
};

View File

@@ -0,0 +1,51 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerFloat.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerFloat:public ULTweener
{
GENERATED_BODY()
public:
float startValue = 0.0f;//b
float changeValue = 0.0f;//c
float endValue = 0.0f;
FLTweenFloatGetterFunction getter;
FLTweenFloatSetterFunction setter;
float originStartValue = 0.0f;
void SetInitialValue(const FLTweenFloatGetterFunction& newGetter, const FLTweenFloatSetterFunction& newSetter, float newEndValue, float newDuration)
{
this->duration = newDuration;
this->endValue = newEndValue;
this->getter = newGetter;
this->setter = newSetter;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
this->startValue = getter.Execute();
this->originStartValue = this->startValue;
this->changeValue = endValue - startValue;
}
virtual void TweenAndApplyValue(float currentTime) override
{
auto value = tweenFunc.Execute(changeValue, startValue, currentTime, duration);
setter.ExecuteIfBound(value);
}
virtual void SetValueForIncremental() override
{
startValue = endValue;
endValue += changeValue;
}
virtual void SetOriginValueForRestart() override
{
startValue = originStartValue;
endValue = startValue + changeValue;
}
};

View File

@@ -0,0 +1,77 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTween.h"
#include "Engine/World.h"
#include "LTweenerFrame.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerFrame:public ULTweener
{
GENERATED_BODY()
public:
uint32 startFrameNumber = 0;//b
uint32 endFrameNumber = 0;//c
void SetInitialValue(int newEndValue)
{
this->startFrameNumber = GFrameNumber;
this->endFrameNumber = GFrameNumber + newEndValue;
}
protected:
virtual void OnStartGetValue() override
{
}
virtual bool ToNext(float deltaTime, float unscaledDeltaTime) override
{
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
if (!startToTween)
{
startToTween = true;
onStartCpp.ExecuteIfBound();
}
if (GFrameNumber >= endFrameNumber)
{
onUpdateCpp.ExecuteIfBound(1.0f);
onCompleteCpp.ExecuteIfBound();
return false;
}
else
{
onUpdateCpp.ExecuteIfBound((float)(GFrameNumber - startFrameNumber) / (endFrameNumber - startFrameNumber));
return true;
}
}
virtual void TweenAndApplyValue(float currentTime) override
{
}
virtual ULTweener* SetDelay(float newDelay)override
{
UE_LOG(LTween, Error, TEXT("[LTweenerFrame::SetDelay]LTweenerFrame does not support delay!"));
return this;
}
virtual ULTweener* SetLoop(ELTweenLoop newLoopType, int32 newLoopCount)override
{
UE_LOG(LTween, Error, TEXT("[LTweenerFrame::SetLoop]LTweenerFrame does not support loop!"));
return this;
}
virtual void SetValueForIncremental() override
{
}
virtual void SetOriginValueForRestart() override
{
auto changeValue = endFrameNumber - startFrameNumber;
startFrameNumber = GFrameNumber;
endFrameNumber = GFrameNumber + changeValue;
}
};

View File

@@ -0,0 +1,53 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerInteger.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerInteger :public ULTweener
{
GENERATED_BODY()
public:
float startFloat = 0.0f;//b
float changeFloat = 1.0f;//c
int startValue;
int endValue;
FLTweenIntGetterFunction getter;
FLTweenIntSetterFunction setter;
int originStartValue = 0;
void SetInitialValue(const FLTweenIntGetterFunction& newGetter, const FLTweenIntSetterFunction& newSetter, int newEndValue, float newDuration)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->endValue = newEndValue;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
this->startValue = getter.Execute();
this->originStartValue = this->startValue;
}
virtual void TweenAndApplyValue(float currentTime) override
{
auto lerpValue = tweenFunc.Execute(changeFloat, startFloat, currentTime, duration);
setter.ExecuteIfBound(FMath::Lerp(startValue, endValue, lerpValue));
}
virtual void SetValueForIncremental() override
{
auto diffValue = endValue - startValue;
startValue = endValue;
endValue += diffValue;
}
virtual void SetOriginValueForRestart() override
{
auto diffValue = endValue - startValue;
startValue = GFrameNumber;
endValue = GFrameNumber + diffValue;
}
};

View File

@@ -0,0 +1,61 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerLinearColor.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerLinearColor :public ULTweener
{
GENERATED_BODY()
public:
float startFloat = 0.0f;//b
float changeFloat = 1.0f;//c
FLinearColor startValue;
FLinearColor endValue;
FLTweenLinearColorGetterFunction getter;
FLTweenLinearColorSetterFunction setter;
FLinearColor originStartValue;
void SetInitialValue(const FLTweenLinearColorGetterFunction& newGetter, const FLTweenLinearColorSetterFunction& newSetter, const FLinearColor& newEndValue, float newDuration)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->endValue = newEndValue;
this->startFloat = 0.0f;
this->changeFloat = 1.0f;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
this->startValue = getter.Execute();
this->originStartValue = this->startValue;
}
virtual void TweenAndApplyValue(float currentTime) override
{
float lerpValue = tweenFunc.Execute(changeFloat, startFloat, currentTime, duration);
FLinearColor value;
value.R = FMath::Lerp(startValue.R, endValue.R, lerpValue);
value.G = FMath::Lerp(startValue.G, endValue.G, lerpValue);
value.B = FMath::Lerp(startValue.B, endValue.B, lerpValue);
value.A = FMath::Lerp(startValue.A, endValue.A, lerpValue);
setter.ExecuteIfBound(value);
}
virtual void SetValueForIncremental() override
{
auto diffValue = endValue - startValue;
startValue = endValue;
endValue += diffValue;
}
virtual void SetOriginValueForRestart() override
{
auto diffValue = endValue - startValue;
startValue = originStartValue;
endValue = originStartValue + diffValue;
}
};

View File

@@ -0,0 +1,64 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTween.h"
#include "LTweenerMaterialScalar.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerMaterialScalar:public ULTweener
{
GENERATED_BODY()
public:
float startValue = 0.0f;//b
float changeValue = 0.0f;//c
int32 parameterIndex;
float endValue = 0.0f;
FLTweenMaterialScalarGetterFunction getter;
FLTweenMaterialScalarSetterFunction setter;
float originStartValue = 0.0f;
void SetInitialValue(const FLTweenMaterialScalarGetterFunction& newGetter, const FLTweenMaterialScalarSetterFunction& newSetter, float newEndValue, float newDuration, int32 newParameterIndex)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->endValue = newEndValue;
this->parameterIndex = newParameterIndex;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
{
if (getter.Execute(startValue))
{
this->changeValue = endValue - startValue;
this->originStartValue = this->changeValue;
}
else
{
UE_LOG(LTween, Error, TEXT("[ULTweenerMaterialScalar/OnStartGetValue]Get paramter value error!"));
}
}
}
virtual void TweenAndApplyValue(float currentTime) override
{
auto value = tweenFunc.Execute(changeValue, startValue, currentTime, duration);
if (setter.Execute(parameterIndex, value) == false)
{
UE_LOG(LTween, Warning, TEXT("[ULTweenerMaterialScalar/TweenAndApplyValue]Set paramter value error!"));
}
}
virtual void SetValueForIncremental() override
{
startValue = endValue;
endValue += changeValue;
}
virtual void SetOriginValueForRestart() override
{
startValue = originStartValue;
endValue = originStartValue + changeValue;
}
};

View File

@@ -0,0 +1,76 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTween.h"
#include "LTweenerMaterialVector.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerMaterialVector :public ULTweener
{
GENERATED_BODY()
public:
float startFloat = 0.0f;//b
float changeFloat = 1.0f;//c
FLinearColor startValue;
FLinearColor endValue;
int32 parameterIndex;
FLTweenMaterialVectorGetterFunction getter;
FLTweenMaterialVectorSetterFunction setter;
FLinearColor originStartValue;
void SetInitialValue(const FLTweenMaterialVectorGetterFunction& newGetter, const FLTweenMaterialVectorSetterFunction& newSetter, const FLinearColor& newEndValue, float newDuration, int32 newParameterIndex)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->parameterIndex = newParameterIndex;
this->endValue = newEndValue;
this->startFloat = 0.0f;
this->changeFloat = 1.0f;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
{
if (getter.Execute(startValue))
{
this->originStartValue = startValue;
}
else
{
UE_LOG(LTween, Error, TEXT("[ULTweenerMaterialVector/OnStartGetValue]Get paramter value error!"));
}
}
}
virtual void TweenAndApplyValue(float currentTime) override
{
float lerpValue = tweenFunc.Execute(changeFloat, startFloat, currentTime, duration);
FLinearColor value;
value.R = FMath::Lerp(startValue.R, endValue.R, lerpValue);
value.G = FMath::Lerp(startValue.G, endValue.G, lerpValue);
value.B = FMath::Lerp(startValue.B, endValue.B, lerpValue);
value.A = FMath::Lerp(startValue.A, endValue.A, lerpValue);
if (setter.IsBound())
if (setter.Execute(parameterIndex, value) == false)
{
UE_LOG(LTween, Warning, TEXT("[ULTweenerMaterialScalar/TweenAndApplyValue]Set paramter value error!"));
}
}
virtual void SetValueForIncremental() override
{
auto diffValue = endValue - startValue;
startValue = endValue;
endValue += diffValue;
}
virtual void SetOriginValueForRestart() override
{
auto diffValue = endValue - startValue;
startValue = originStartValue;
endValue = originStartValue + diffValue;
}
};

View File

@@ -0,0 +1,65 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerPosition.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerPosition :public ULTweener
{
GENERATED_BODY()
public:
float startFloat = 0.0f;//b
float changeFloat = 1.0f;//c
FVector startValue;
FVector endValue;
bool sweep = false;
FHitResult* sweepHitResult = nullptr;
ETeleportType teleportType = ETeleportType::None;
FLTweenPositionGetterFunction getter;
FLTweenPositionSetterFunction setter;
FVector originStartValue;
void SetInitialValue(const FLTweenPositionGetterFunction& newGetter, const FLTweenPositionSetterFunction& newSetter, const FVector& newEndValue, float newDuration, bool newSweep = false, FHitResult* newSweepHitResult = nullptr, ETeleportType newTeleportType = ETeleportType::None)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->endValue = newEndValue;
this->startFloat = 0.0f;
this->changeFloat = 1.0f;
this->sweep = newSweep;
this->sweepHitResult = newSweepHitResult;
this->teleportType = newTeleportType;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
this->startValue = getter.Execute();
this->originStartValue = this->startValue;
}
virtual void TweenAndApplyValue(float currentTime) override
{
float lerpValue = tweenFunc.Execute(changeFloat, startFloat, currentTime, duration);
FVector value = FMath::Lerp(startValue, endValue, lerpValue);
setter.ExecuteIfBound(value, sweep, sweepHitResult, teleportType);
}
virtual void SetValueForIncremental() override
{
auto diffValue = endValue - startValue;
startValue = endValue;
endValue += diffValue;
}
virtual void SetOriginValueForRestart() override
{
auto diffValue = endValue - startValue;
startValue = originStartValue;
endValue = originStartValue + diffValue;
}
};

View File

@@ -0,0 +1,57 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerQuaternion.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerQuaternion :public ULTweener
{
GENERATED_BODY()
public:
float startFloat = 0.0f;//b
float changeFloat = 1.0f;//c
FQuat startValue;
FQuat endValue;
FLTweenQuaternionGetterFunction getter;
FLTweenQuaternionSetterFunction setter;
FQuat originStartValue;
void SetInitialValue(const FLTweenQuaternionGetterFunction& newGetter, const FLTweenQuaternionSetterFunction& newSetter, const FQuat& newEndValue, float newDuration)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->endValue = newEndValue;
this->startFloat = 0.0f;
this->changeFloat = 1.0f;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
this->startValue = getter.Execute();
this->originStartValue = this->startValue;
}
virtual void TweenAndApplyValue(float currentTime) override
{
float lerpValue = tweenFunc.Execute(changeFloat, startFloat, currentTime, duration);
FQuat value = FQuat::Slerp(startValue, endValue, lerpValue);
setter.ExecuteIfBound(value);
}
virtual void SetValueForIncremental() override
{
auto diffValue = endValue - startValue;
startValue = endValue;
endValue += diffValue;
}
virtual void SetOriginValueForRestart() override
{
auto diffValue = endValue - startValue;
startValue = originStartValue;
endValue = originStartValue + diffValue;
}
};

View File

@@ -0,0 +1,61 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerRotationEuler.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerRotationEuler :public ULTweener
{
GENERATED_BODY()
public:
float startFloat = 0.0f;//b
float changeFloat = 1.0f;//c
FQuat startValue;
FVector eulerAngle;
bool sweep = false;
FHitResult* sweepHitResult = nullptr;
ETeleportType teleportType = ETeleportType::None;
FLTweenRotationQuatGetterFunction getter;
FLTweenRotationQuatSetterFunction setter;
FQuat originStartValue;
void SetInitialValue(const FLTweenRotationQuatGetterFunction& newGetter, const FLTweenRotationQuatSetterFunction& newSetter, const FVector& newEulerAngle, float newDuration, bool newSweep = false, FHitResult* newSweepHitResult = nullptr, ETeleportType newTeleportType = ETeleportType::None)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->eulerAngle = newEulerAngle;
this->startFloat = 0.0f;
this->changeFloat = 1.0f;
this->sweep = newSweep;
this->sweepHitResult = newSweepHitResult;
this->teleportType = newTeleportType;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
this->startValue = getter.Execute();
this->originStartValue = this->startValue;
}
virtual void TweenAndApplyValue(float currentTime) override
{
float lerpValue = tweenFunc.Execute(changeFloat, startFloat, currentTime, duration);
auto value = startValue * FQuat::MakeFromEuler(eulerAngle * lerpValue);
setter.ExecuteIfBound(value, sweep, sweepHitResult, teleportType);
}
virtual void SetValueForIncremental() override
{
startValue = startValue * FQuat::MakeFromEuler(eulerAngle);
}
virtual void SetOriginValueForRestart() override
{
startValue = originStartValue;
}
};

View File

@@ -0,0 +1,65 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerRotationQuat.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerRotationQuat :public ULTweener
{
GENERATED_BODY()
public:
float startFloat = 0.0f;//b
float changeFloat = 1.0f;//c
FQuat startValue;
FQuat endValue;
bool sweep = false;
FHitResult* sweepHitResult = nullptr;
ETeleportType teleportType = ETeleportType::None;
FLTweenRotationQuatGetterFunction getter;
FLTweenRotationQuatSetterFunction setter;
FQuat originStartValue;
void SetInitialValue(const FLTweenRotationQuatGetterFunction& newGetter, const FLTweenRotationQuatSetterFunction& newSetter, const FQuat& newEndValue, float newDuration, bool newSweep = false, FHitResult* newSweepHitResult = nullptr, ETeleportType newTeleportType = ETeleportType::None)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->endValue = newEndValue;
this->startFloat = 0.0f;
this->changeFloat = 1.0f;
this->sweep = newSweep;
this->sweepHitResult = newSweepHitResult;
this->teleportType = newTeleportType;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
this->startValue = getter.Execute();
this->originStartValue = this->startValue;
}
virtual void TweenAndApplyValue(float currentTime) override
{
float lerpValue = tweenFunc.Execute(changeFloat, startFloat, currentTime, duration);
auto value = FQuat::Slerp(startValue, endValue, lerpValue);
setter.ExecuteIfBound(value, sweep, sweepHitResult, teleportType);
}
virtual void SetValueForIncremental() override
{
auto diffValue = endValue * startValue.Inverse();
startValue = endValue;
endValue = endValue * diffValue;
}
virtual void SetOriginValueForRestart() override
{
auto diffValue = endValue - startValue;
startValue = originStartValue;
endValue = originStartValue + diffValue;
}
};

View File

@@ -0,0 +1,58 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerRotator.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerRotator :public ULTweener
{
GENERATED_BODY()
public:
float startFloat = 0.0f;//b
float changeFloat = 1.0f;//c
FRotator startValue;
FRotator endValue;
FLTweenRotatorGetterFunction getter;
FLTweenRotatorSetterFunction setter;
FRotator originStartValue;
void SetInitialValue(const FLTweenRotatorGetterFunction& newGetter, const FLTweenRotatorSetterFunction& newSetter, const FRotator& newEndValue, float newDuration)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->endValue = newEndValue;
this->startFloat = 0.0f;
this->changeFloat = 1.0f;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
this->startValue = getter.Execute();
this->originStartValue = this->startValue;
}
virtual void TweenAndApplyValue(float currentTime) override
{
float lerpValue = tweenFunc.Execute(changeFloat, startFloat, currentTime, duration);
FRotator value;
value = startValue + lerpValue * (endValue - startValue);
setter.ExecuteIfBound(value);
}
virtual void SetValueForIncremental() override
{
auto diffValue = endValue - startValue;
startValue = endValue;
endValue += diffValue;
}
virtual void SetOriginValueForRestart() override
{
auto diffValue = endValue - startValue;
startValue = originStartValue;
endValue = originStartValue + diffValue;
}
};

View File

@@ -0,0 +1,57 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerScale.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerScale :public ULTweener
{
GENERATED_BODY()
public:
float startFloat = 0.0f;//b
float changeFloat = 1.0f;//c
FVector startValue;
FVector endValue;
FLTweenVectorGetterFunction getter;
FLTweenVectorSetterFunction setter;
FVector originStartValue;
void SetInitialValue(const FLTweenVectorGetterFunction& newGetter, const FLTweenVectorSetterFunction& newSetter, const FVector& newEndValue, float newDuration)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->endValue = newEndValue;
this->startFloat = 0.0f;
this->changeFloat = 1.0f;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
this->startValue = getter.Execute();
this->originStartValue = this->startValue;
}
virtual void TweenAndApplyValue(float currentTime) override
{
float lerpValue = tweenFunc.Execute(changeFloat, startFloat, currentTime, duration);
auto value = FMath::Lerp(startValue, endValue, lerpValue);
setter.ExecuteIfBound(value);
}
virtual void SetValueForIncremental() override
{
auto diffValue = endValue - startValue;
startValue = endValue;
endValue += diffValue;
}
virtual void SetOriginValueForRestart() override
{
auto diffValue = endValue - startValue;
startValue = originStartValue;
endValue = originStartValue + diffValue;
}
};

View File

@@ -0,0 +1,56 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTween.h"
#include "Engine/World.h"
#include "LTweenerUpdate.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerUpdate :public ULTweener
{
GENERATED_BODY()
public:
void SetInitialValue(int newEndValue)
{
}
protected:
virtual void OnStartGetValue() override
{
}
virtual bool ToNext(float deltaTime, float unscaledDeltaTime) override
{
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
onUpdateCpp.ExecuteIfBound(affectByTimeDilation ? deltaTime : unscaledDeltaTime);
return true;
}
virtual void TweenAndApplyValue(float currentTime) override
{
}
virtual ULTweener* SetDelay(float newDelay)override
{
UE_LOG(LTween, Error, TEXT("[LTweenerFrame::SetDelay]LTweenerUpdate does not support delay!"));
return this;
}
virtual ULTweener* SetLoop(ELTweenLoop newLoopType, int32 newLoopCount)override
{
UE_LOG(LTween, Error, TEXT("[LTweenerFrame::SetLoop]LTweenerUpdate does not support loop!"));
return this;
}
virtual void SetValueForIncremental() override
{
}
virtual void SetOriginValueForRestart() override
{
}
};

View File

@@ -0,0 +1,57 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerVector.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerVector :public ULTweener
{
GENERATED_BODY()
public:
float startFloat = 0.0f;//b
float changeFloat = 1.0f;//c
FVector startValue;
FVector endValue;
FLTweenVectorGetterFunction getter;
FLTweenVectorSetterFunction setter;
FVector originStartValue;
void SetInitialValue(const FLTweenVectorGetterFunction& newGetter, const FLTweenVectorSetterFunction& newSetter, const FVector& newEndValue, float newDuration)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->endValue = newEndValue;
this->startFloat = 0.0f;
this->changeFloat = 1.0f;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
this->startValue = getter.Execute();
this->originStartValue = this->startValue;
}
virtual void TweenAndApplyValue(float currentTime) override
{
float lerpValue = tweenFunc.Execute(changeFloat, startFloat, currentTime, duration);
auto value = FMath::Lerp(startValue, endValue, lerpValue);
setter.ExecuteIfBound(value);
}
virtual void SetValueForIncremental() override
{
auto diffValue = endValue - startValue;
startValue = endValue;
endValue += diffValue;
}
virtual void SetOriginValueForRestart() override
{
auto diffValue = endValue - startValue;
startValue = originStartValue;
endValue = originStartValue + diffValue;
}
};

View File

@@ -0,0 +1,57 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerVector2D.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerVector2D :public ULTweener
{
GENERATED_BODY()
public:
float startFloat = 0.0f;//b
float changeFloat = 1.0f;//c
FVector2D startValue;
FVector2D endValue;
FLTweenVector2DGetterFunction getter;
FLTweenVector2DSetterFunction setter;
FVector2D originStartValue;
void SetInitialValue(const FLTweenVector2DGetterFunction& newGetter, const FLTweenVector2DSetterFunction& newSetter, const FVector2D& newEndValue, float newDuration)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->endValue = newEndValue;
this->startFloat = 0.0f;
this->changeFloat = 1.0f;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
this->startValue = getter.Execute();
this->originStartValue = this->startValue;
}
virtual void TweenAndApplyValue(float currentTime) override
{
float lerpValue = tweenFunc.Execute(changeFloat, startFloat, currentTime, duration);
auto value = FMath::Lerp(startValue, endValue, lerpValue);
setter.ExecuteIfBound(value);
}
virtual void SetValueForIncremental() override
{
auto diffValue = endValue - startValue;
startValue = endValue;
endValue += diffValue;
}
virtual void SetOriginValueForRestart() override
{
auto diffValue = endValue - startValue;
startValue = originStartValue;
endValue = originStartValue + diffValue;
}
};

View File

@@ -0,0 +1,57 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerVector4.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerVector4 :public ULTweener
{
GENERATED_BODY()
public:
float startFloat = 0.0f;//b
float changeFloat = 1.0f;//c
FVector4 startValue;
FVector4 endValue;
FLTweenVector4GetterFunction getter;
FLTweenVector4SetterFunction setter;
FVector4 originStartValue;
void SetInitialValue(const FLTweenVector4GetterFunction& newGetter, const FLTweenVector4SetterFunction& newSetter, const FVector4& newEndValue, float newDuration)
{
this->duration = newDuration;
this->getter = newGetter;
this->setter = newSetter;
this->endValue = newEndValue;
this->startFloat = 0.0f;
this->changeFloat = 1.0f;
}
protected:
virtual void OnStartGetValue() override
{
if (getter.IsBound())
this->startValue = getter.Execute();
this->originStartValue = this->startValue;
}
virtual void TweenAndApplyValue(float currentTime) override
{
float lerpValue = tweenFunc.Execute(changeFloat, startFloat, currentTime, duration);
auto value = FMath::Lerp(startValue, endValue, lerpValue);
setter.ExecuteIfBound(value);
}
virtual void SetValueForIncremental() override
{
auto diffValue = endValue - startValue;
startValue = endValue;
endValue += diffValue;
}
virtual void SetOriginValueForRestart() override
{
auto diffValue = endValue - startValue;
startValue = originStartValue;
endValue = originStartValue + diffValue;
}
};

View File

@@ -0,0 +1,34 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerVirtual.generated.h"
UCLASS(NotBlueprintType)
class LTWEEN_API ULTweenerVirtual:public ULTweener
{
GENERATED_BODY()
public:
void SetInitialValue(float newDuration)
{
this->duration = newDuration;
}
protected:
virtual void OnStartGetValue() override
{
}
virtual void TweenAndApplyValue(float currentTime) override
{
}
virtual void SetValueForIncremental() override
{
}
virtual void SetOriginValueForRestart() override
{
}
};

View File

@@ -0,0 +1,15 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "Stats/Stats.h"
#include "Modules/ModuleInterface.h"
DECLARE_LOG_CATEGORY_EXTERN(LTween, Log, All);
DECLARE_STATS_GROUP(TEXT("LTween"), STATGROUP_LTween, STATCAT_Advanced);
class FLTweenModule : public IModuleInterface
{
public:
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};

View File

@@ -0,0 +1,428 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "LTweenManager.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "LTweenDelegateHandleWrapper.h"
#include "LTweenBPLibrary.generated.h"
DECLARE_DYNAMIC_DELEGATE_OneParam(FLTweenFloatSetterDynamic, float, value);
DECLARE_DYNAMIC_DELEGATE_OneParam(FLTweenDoubleSetterDynamic, double, value);
DECLARE_DYNAMIC_DELEGATE_OneParam(FLTweenIntSetterDynamic, int, value);
DECLARE_DYNAMIC_DELEGATE_OneParam(FLTweenVector2SetterDynamic, const FVector2D&, value);
DECLARE_DYNAMIC_DELEGATE_OneParam(FLTweenVector3SetterDynamic, const FVector&, value);
DECLARE_DYNAMIC_DELEGATE_OneParam(FLTweenVector4SetterDynamic, const FVector4&, value);
DECLARE_DYNAMIC_DELEGATE_OneParam(FLTweenColorSetterDynamic, const FColor&, value);
DECLARE_DYNAMIC_DELEGATE_OneParam(FLTweenLinearColorSetterDynamic, const FLinearColor&, value);
DECLARE_DYNAMIC_DELEGATE_OneParam(FLTweenQuaternionSetterDynamic, const FQuat&, value);
DECLARE_DYNAMIC_DELEGATE_OneParam(FLTweenRotatorSetterDynamic, const FRotator&, value);
UCLASS()
class LTWEEN_API ULTweenBPLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = LTween, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = "LTween")
static ULTweener* FloatTo(UObject* WorldContextObject, const FLTweenFloatSetterDynamic& setter, float startValue = 0.0f, float endValue = 1.0f, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, Category = LTween, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = "LTween")
static ULTweener* DoubleTo(UObject* WorldContextObject, const FLTweenDoubleSetterDynamic& setter, double startValue = 0.0f, double endValue = 1.0f, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, Category = LTween, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = "LTween")
static ULTweener* IntTo(UObject* WorldContextObject, const FLTweenIntSetterDynamic& setter, int startValue, int endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, Category = LTween, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = "LTween")
static ULTweener* Vector2To(UObject* WorldContextObject, const FLTweenVector2SetterDynamic& setter, FVector2D startValue, FVector2D endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, Category = LTween, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = "LTween")
static ULTweener* Vector3To(UObject* WorldContextObject, const FLTweenVector3SetterDynamic& setter, FVector startValue, FVector endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, Category = LTween, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = "LTween")
static ULTweener* Vector4To(UObject* WorldContextObject, const FLTweenVector4SetterDynamic& setter, FVector4 startValue, FVector4 endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, Category = LTween, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = "LTween")
static ULTweener* ColorTo(UObject* WorldContextObject, const FLTweenColorSetterDynamic& setter, FColor startValue, FColor endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, Category = LTween, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = "LTween")
static ULTweener* LinearColorTo(UObject* WorldContextObject, const FLTweenLinearColorSetterDynamic& setter, FLinearColor startValue, FLinearColor endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, Category = LTween, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = "LTween")
static ULTweener* QuaternionTo(UObject* WorldContextObject, const FLTweenQuaternionSetterDynamic& setter, FQuat startValue, FQuat endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, Category = LTween, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = "LTween")
static ULTweener* RotatorTo(UObject* WorldContextObject, const FLTweenRotatorSetterDynamic& setter, FRotator startValue, FRotator endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
#pragma region PositionXYZ
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "Local Position X To"), Category = "LTween")
static ULTweener* LocalPositionXTo(USceneComponent* target, double endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "Local Position Y To"), Category = "LTween")
static ULTweener* LocalPositionYTo(USceneComponent* target, double endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "Local Position Z To"), Category = "LTween")
static ULTweener* LocalPositionZTo(USceneComponent* target, double endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "Local Position X To (Sweep)"), Category = LTween)
static ULTweener* LocalPositionXTo_Sweep(USceneComponent* target, double endValue, FHitResult& sweepHitResult, bool sweep, bool teleport, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "Local Position Y To (Sweep)"), Category = LTween)
static ULTweener* LocalPositionYTo_Sweep(USceneComponent* target, double endValue, FHitResult& sweepHitResult, bool sweep, bool teleport, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "Local Position Z To (Sweep)"), Category = LTween)
static ULTweener* LocalPositionZTo_Sweep(USceneComponent* target, double endValue, FHitResult& sweepHitResult, bool sweep, bool teleport, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "World Position X To"), Category = "LTween")
static ULTweener* WorldPositionXTo(USceneComponent* target, double endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "World Position Y To"), Category = "LTween")
static ULTweener* WorldPositionYTo(USceneComponent* target, double endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "World Position Z To"), Category = "LTween")
static ULTweener* WorldPositionZTo(USceneComponent* target, double endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "World Position X To (Sweep)"), Category = LTween)
static ULTweener* WorldPositionXTo_Sweep(USceneComponent* target, double endValue, FHitResult& sweepHitResult, bool sweep, bool teleport, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "World Position Y To (Sweep)"), Category = LTween)
static ULTweener* WorldPositionYTo_Sweep(USceneComponent* target, double endValue, FHitResult& sweepHitResult, bool sweep, bool teleport, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "World Position Z To (Sweep)"), Category = LTween)
static ULTweener* WorldPositionZTo_Sweep(USceneComponent* target, double endValue, FHitResult& sweepHitResult, bool sweep, bool teleport, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
#pragma endregion
#pragma region Position
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease"), Category = "LTween")
static ULTweener* LocalPositionTo(USceneComponent* target, FVector endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "Local Position To (Sweep)"), Category = LTween)
static ULTweener* LocalPositionTo_Sweep(USceneComponent* target, FVector endValue, FHitResult& sweepHitResult, bool sweep, bool teleport, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease"), Category = "LTween")
static ULTweener* WorldPositionTo(USceneComponent* target, FVector endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "World Position To (Sweep)"), Category = LTween)
static ULTweener* WorldPositionTo_Sweep(USceneComponent* target, FVector endValue, FHitResult& sweepHitResult, bool sweep, bool teleport, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
#pragma endregion Position
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease"), Category = LTween)
static ULTweener* LocalScaleTo(USceneComponent* target, FVector endValue = FVector(1.0f, 1.0f, 1.0f), float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
#pragma region Rotation
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", ToolTip = "Rotate eulerAngle relative to current rotation value"), Category = "LTween")
static ULTweener* LocalRotateEulerAngleTo(USceneComponent* target, FVector eulerAngle, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", ToolTip = "Rotate absolute quaternion rotation value"), Category = "LTween")
static ULTweener* LocalRotationQuaternionTo(USceneComponent* target, const FQuat& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", ToolTip = "Rotate absolute rotator value"), Category = "LTween")
static ULTweener* LocalRotatorTo(USceneComponent* target, FRotator endValue, bool shortestPath, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "Local Rotate Euler Angle To (Sweep)", ToolTip = "Rotate eulerAngle relative to current rotation value"), Category = "LTween")
static ULTweener* LocalRotateEulerAngleTo_Sweep(USceneComponent* target, FVector eulerAngle, FHitResult& sweepHitResult, bool sweep, bool teleport, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "Local Rotation Quaternion To (Sweep)", ToolTip = "Rotate absolute quaternion rotation value"), Category = "LTween")
static ULTweener* LocalRotationQuaternionTo_Sweep(USceneComponent* target, const FQuat& endValue, FHitResult& sweepHitResult, bool sweep, bool teleport, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "Local Rotator To (Sweep)", ToolTip = "Rotate absolute rotator value"), Category = "LTween")
static ULTweener* LocalRotatorTo_Sweep(USceneComponent* target, FRotator endValue, bool shortestPath, FHitResult& sweepHitResult, bool sweep, bool teleport, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", ToolTip = "Rotate eulerAngle relative to current rotation value"), Category = "LTween")
static ULTweener* WorldRotateEulerAngleTo(USceneComponent* target, FVector eulerAngle, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", ToolTip = "Rotate absolute quaternion rotation value"), Category = "LTween")
static ULTweener* WorldRotationQuaternionTo(USceneComponent* target, const FQuat& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", ToolTip = "Rotate absolute rotator value"), Category = "LTween")
static ULTweener* WorldRotatorTo(USceneComponent* target, FRotator endValue, bool shortestPath, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "World Rotate Euler Angle To (Sweep)", ToolTip = "Rotate eulerAngle relative to current rotation value"), Category = "LTween")
static ULTweener* WorldRotateEulerAngleTo_Sweep(USceneComponent* target, FVector eulerAngle, FHitResult& sweepHitResult, bool sweep, bool teleport, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "World Rotation Quaternion To (Sweep)", ToolTip = "Rotate absolute quaternion rotation value"), Category = "LTween")
static ULTweener* WorldRotationQuaternionTo_Sweep(USceneComponent* target, const FQuat& endValue, FHitResult& sweepHitResult, bool sweep, bool teleport, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", DisplayName = "World Rotator To (Sweep)", ToolTip = "Rotate absolute rotator value"), Category = "LTween")
static ULTweener* WorldRotatorTo_Sweep(USceneComponent* target, FRotator endValue, bool shortestPath, FHitResult& sweepHitResult, bool sweep, bool teleport, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
#pragma endregion Rotation
#pragma region Material
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* MaterialScalarParameterTo(UObject* WorldContextObject, class UMaterialInstanceDynamic* target, FName parameterName, float endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* MaterialVectorParameterTo(UObject* WorldContextObject, class UMaterialInstanceDynamic* target, FName parameterName, FLinearColor endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease"), Category = LTween)
static ULTweener* MeshMaterialScalarParameterTo(class UPrimitiveComponent* target, int materialIndex, FName parameterName, float endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease"), Category = LTween)
static ULTweener* MeshMaterialVectorParameterTo(class UPrimitiveComponent* target, int materialIndex, FName parameterName, FLinearColor endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
#pragma endregion
#pragma region UMG
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_CanvasPanelSlot_PositionTo(UObject* WorldContextObject, class UCanvasPanelSlot* target, const FVector2D& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_CanvasPanelSlot_SizeTo(UObject* WorldContextObject, class UCanvasPanelSlot* target, const FVector2D& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_HorizontalBoxSlot_PaddingTo(UObject* WorldContextObject, class UHorizontalBoxSlot* target, const FMargin& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_VerticalBoxSlot_PaddingTo(UObject* WorldContextObject, class UVerticalBoxSlot* target, const FMargin& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_OverlaySlot_PaddingTo(UObject* WorldContextObject, class UOverlaySlot* target, const FMargin& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_ButtonSlot_PaddingTo(UObject* WorldContextObject, class UButtonSlot* target, const FMargin& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_BorderSlot_PaddingTo(UObject* WorldContextObject, class UBorderSlot* target, const FMargin& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_RenderTransform_TranslationTo(UObject* WorldContextObject, class UWidget* target, const FVector2D& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_RenderTransform_AngleTo(UObject* WorldContextObject, class UWidget* target, float endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_RenderTransform_ScaleTo(UObject* WorldContextObject, class UWidget* target, const FVector2D& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_RenderTransform_ShearTo(UObject* WorldContextObject, class UWidget* target, const FVector2D& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_RenderOpacityTo(UObject* WorldContextObject, class UWidget* target, float endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_UserWidget_ColorAndOpacityTo(UObject* WorldContextObject, class UUserWidget* target, const FLinearColor& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_Image_ColorAndOpacityTo(UObject* WorldContextObject, class UImage* target, const FLinearColor& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_Button_ColorAndOpacityTo(UObject* WorldContextObject, class UButton* target, const FLinearColor& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "delay,ease", WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* UMG_Border_ContentColorAndOpacityTo(UObject* WorldContextObject, class UBorder* target, const FLinearColor& endValue, float duration = 0.5f, float delay = 0.0f, ELTweenEase ease = ELTweenEase::OutCubic);
#pragma endregion
UFUNCTION(BlueprintCallable, meta = (ToolTip = "Assign start or update or omplete functions", WorldContext = "WorldContextObject", AutoCreateRefTerm="start,update,complete"), Category = LTween)
static ULTweener* VirtualCall(UObject* WorldContextObject, float duration, float delay, const FLTweenerSimpleDynamicDelegate& start, const FLTweenerFloatDynamicDelegate& update, const FLTweenerSimpleDynamicDelegate& complete)
{
auto Tweener = ULTweenManager::VirtualTo(WorldContextObject, duration);
if (Tweener)
{
Tweener->SetDelay(delay)->OnStart(start)->OnUpdate(update)->OnComplete(complete);
}
return Tweener;
}
static ULTweener* VirtualCall(UObject* WorldContextObject, float duration, float delay, FSimpleDelegate start, FLTweenUpdateDelegate update, FSimpleDelegate complete)
{
auto Tweener = ULTweenManager::VirtualTo(WorldContextObject, duration);
if (Tweener)
{
Tweener->SetDelay(delay)->OnStart(start)->OnUpdate(update)->OnComplete(complete);
};
return Tweener;
}
static ULTweener* VirtualCall(UObject* WorldContextObject, float duration, float delay, const TFunction<void()>& start, const TFunction<void(float)>& update, const TFunction<void()>& complete)
{
auto Tweener = ULTweenManager::VirtualTo(WorldContextObject, duration);
if (Tweener)
{
Tweener->SetDelay(delay)->OnStart(start)->OnUpdate(update)->OnComplete(complete);
}
return Tweener;
}
static ULTweener* VirtualCall(UObject* WorldContextObject, float duration)
{
return ULTweenManager::VirtualTo(WorldContextObject, duration);
}
UFUNCTION(BlueprintCallable, meta = (ToolTip = "MainThread delay call function, Assign delayComplete to call", WorldContext = "WorldContextObject", AdvancedDisplay="affectByGamePause,affectByTimeDilation"), Category = LTween)
static ULTweener* DelayCall(UObject* WorldContextObject, float delayTime, const FLTweenerSimpleDynamicDelegate& delayComplete, bool affectByGamePause = true, bool affectByTimeDilation = true)
{
auto Tweener = ULTweenManager::VirtualTo(WorldContextObject, delayTime);
if (Tweener)
{
Tweener->OnComplete(delayComplete)->SetAffectByGamePause(affectByGamePause)->SetAffectByTimeDilation(affectByTimeDilation);
}
return Tweener;
}
static ULTweener* DelayCall(UObject* WorldContextObject, float delayTime, FSimpleDelegate delayComplete, bool affectByGamePause = true, bool affectByTimeDilation = true)
{
auto Tweener = ULTweenManager::VirtualTo(WorldContextObject, delayTime);
if (Tweener)
{
Tweener->OnComplete(delayComplete)->SetAffectByGamePause(affectByGamePause)->SetAffectByTimeDilation(affectByTimeDilation);
}
return Tweener;
}
static ULTweener* DelayCall(UObject* WorldContextObject, float delayTime, const TFunction<void()>& delayComplete, bool affectByGamePause = true, bool affectByTimeDilation = true)
{
auto Tweener = ULTweenManager::VirtualTo(WorldContextObject, delayTime);
if (Tweener)
{
Tweener->OnComplete(delayComplete)->SetAffectByGamePause(affectByGamePause)->SetAffectByTimeDilation(affectByTimeDilation);
}
return Tweener;
}
UFUNCTION(BlueprintCallable, meta = (ToolTip = "MainThread delay frame call function, Assign delayComplete to call", WorldContext = "WorldContextObject", AdvancedDisplay = "affectByGamePause"), Category = LTween)
static ULTweener* DelayFrameCall(UObject* WorldContextObject, int frameCount, const FLTweenerSimpleDynamicDelegate& delayComplete, bool affectByGamePause = true)
{
auto Tweener = ULTweenManager::DelayFrameCall(WorldContextObject, frameCount);
if (Tweener)
{
Tweener->OnComplete(delayComplete)->SetAffectByGamePause(affectByGamePause);
}
return Tweener;
}
static ULTweener* DelayFrameCall(UObject* WorldContextObject, int frameCount, FSimpleDelegate delayComplete, bool affectByGamePause = true)
{
auto Tweener = ULTweenManager::DelayFrameCall(WorldContextObject, frameCount);
if (Tweener)
{
Tweener->OnComplete(delayComplete)->SetAffectByGamePause(affectByGamePause);
}
return Tweener;
}
static ULTweener* DelayFrameCall(UObject* WorldContextObject, int frameCount, const TFunction<void()>& delayComplete, bool affectByGamePause = true)
{
auto Tweener = ULTweenManager::DelayFrameCall(WorldContextObject, frameCount);
if (Tweener)
{
Tweener->OnComplete(delayComplete)->SetAffectByGamePause(affectByGamePause);
}
return Tweener;
}
UFUNCTION(BlueprintCallable, meta = (ToolTip = "Assign start or update or omplete functions", WorldContext = "WorldContextObject", AutoCreateRefTerm = "start,update,complete"), Category = LTween)
static ULTweener* UpdateCall(UObject* WorldContextObject, const FLTweenerFloatDynamicDelegate& update)
{
auto Tweener = ULTweenManager::UpdateCall(WorldContextObject);
if (Tweener)
{
Tweener->OnUpdate(update);
}
return Tweener;
}
static ULTweener* UpdateCall(UObject* WorldContextObject, FLTweenUpdateDelegate update)
{
auto Tweener = ULTweenManager::UpdateCall(WorldContextObject);
if (Tweener)
{
Tweener->OnUpdate(update);
};
return Tweener;
}
static ULTweener* UpdateCall(UObject* WorldContextObject, const TFunction<void(float)>& update)
{
auto Tweener = ULTweenManager::UpdateCall(WorldContextObject);
if (Tweener)
{
Tweener->OnUpdate(update);
}
return Tweener;
}
UFUNCTION(BlueprintPure, Category = LTween, meta = (WorldContext = "WorldContextObject"))
static bool IsTweening(UObject* WorldContextObject, ULTweener* inTweener)
{
return ULTweenManager::IsTweening(WorldContextObject, inTweener);
}
/**
* Force stop this animation. if callComplete = true, OnComplete will call after stop.
* This method will check if the tweener is valid.
*/
UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay = "callComplete", WorldContext = "WorldContextObject"), Category = LTween)
static void KillIfIsTweening(UObject* WorldContextObject, ULTweener* inTweener, bool callComplete = false)
{
ULTweenManager::KillIfIsTweening(WorldContextObject, inTweener, callComplete);
}
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Kill If Is Tweening (Array)", AdvancedDisplay = "callComplete", WorldContext = "WorldContextObject"), Category = LTween)
static void ArrayKillIfIsTweening(UObject* WorldContextObject, const TArray<ULTweener*>& inTweenerArray, bool callComplete = false)
{
auto Instance = ULTweenManager::GetLTweenInstance(WorldContextObject);
if (!IsValid(Instance))return;
for (auto tweener : inTweenerArray)
{
Instance->KillIfIsTweening(WorldContextObject, tweener, callComplete);
}
}
UE_DEPRECATED(5.2, "Use UpdateCall instead.")
static FDelegateHandle RegisterUpdateEvent(UObject* WorldContextObject, const FLTweenUpdateDelegate& update)
{
// Disable deprecation warnings so we can call the deprecated function to support this function (which is also deprecated)
PRAGMA_DISABLE_DEPRECATION_WARNINGS
auto delegateHandle = ULTweenManager::RegisterUpdateEvent(WorldContextObject, update);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
return delegateHandle;
}
UE_DEPRECATED(5.2, "Use UpdateCall instead.")
static FDelegateHandle RegisterUpdateEvent(UObject* WorldContextObject, const TFunction<void(float)>& update)
{
FLTweenUpdateDelegate updateDelegate = FLTweenUpdateDelegate::CreateLambda(update);
// Disable deprecation warnings so we can call the deprecated function to support this function (which is also deprecated)
PRAGMA_DISABLE_DEPRECATION_WARNINGS
ULTweenManager::RegisterUpdateEvent(WorldContextObject, updateDelegate);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
return updateDelegate.GetHandle();
}
UE_DEPRECATED(5.2, "Use UpdateCall instead.")
UFUNCTION(BlueprintCallable, meta = (ToolTip = "Registerred update function will be called every frame from mainthread.", WorldContext = "WorldContextObject", DeprecatedFunction, DeprecationMessage = "Use UpdateCall instead."), Category = LTween)
static FLTweenDelegateHandleWrapper RegisterUpdateEvent(UObject* WorldContextObject, const FLTweenerFloatDynamicDelegate& update)
{
FLTweenUpdateDelegate updateDelegate = FLTweenUpdateDelegate::CreateLambda([update](float deltaTime) {update.ExecuteIfBound(deltaTime); });
FLTweenDelegateHandleWrapper delegateHandle(updateDelegate.GetHandle());
// Disable deprecation warnings so we can call the deprecated function to support this function (which is also deprecated)
PRAGMA_DISABLE_DEPRECATION_WARNINGS
ULTweenManager::RegisterUpdateEvent(WorldContextObject, updateDelegate);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
return delegateHandle;
}
UE_DEPRECATED(5.2, "Use UpdateCall instead of RegisterUpdateEvent, and KillIfIsTweening for returned tweener instead of this UnregisterUpdateEvent.")
static void UnregisterUpdateEvent(UObject* WorldContextObject, const FDelegateHandle& handle)
{
// Disable deprecation warnings so we can call the deprecated function to support this function (which is also deprecated)
PRAGMA_DISABLE_DEPRECATION_WARNINGS
ULTweenManager::UnregisterUpdateEvent(WorldContextObject, handle);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
UE_DEPRECATED(5.2, "Use UpdateCall instead of RegisterUpdateEvent, and KillIfIsTweening for returned tweener instead of this UnregisterUpdateEvent.")
UFUNCTION(BlueprintCallable, meta = (ToolTip = "Unregister the update function. \"delegateHandle\" is the return value when use RegisterUpdateEvent.", WorldContext = "WorldContextObject", DeprecatedFunction, DeprecationMessage = "Use UpdateCall instead of RegisterUpdateEvent, and KillIfIsTweening for returned tweener instead of this UnregisterUpdateEvent."), Category = LTween)
static void UnregisterUpdateEvent(UObject* WorldContextObject, const FLTweenDelegateHandleWrapper& delegateHandle)
{
// Disable deprecation warnings so we can call the deprecated function to support this function (which is also deprecated)
PRAGMA_DISABLE_DEPRECATION_WARNINGS
ULTweenManager::UnregisterUpdateEvent(WorldContextObject, delegateHandle.DelegateHandle);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
/**
* Repeatedly call function.
* @param delayTime delay time before the first call
* @param interval interval time between every call
* @param repeatCount repeat count, -1 means infinite
* @return tweener
*/
static ULTweener* RepeatCall(UObject* WorldContextObject, const TFunction<void()>& callFunction, float delayTime, float interval, int repeatCount = 1)
{
auto Tweener = ULTweenManager::VirtualTo(WorldContextObject, interval);
if (Tweener)
{
Tweener
->SetDelay(delayTime)
->SetLoop(repeatCount == 1 || repeatCount == 0 ? ELTweenLoop::Once : ELTweenLoop::Restart, repeatCount)
->OnCycleStart(callFunction)
;
}
return Tweener;
}
/**
* Repeatedly call function.
* @param delayTime delay time before the first call
* @param interval interval time between every call
* @param repeatCount repeat count, -1 means infinite
* \return tweener
*/
static ULTweener* RepeatCall(UObject* WorldContextObject, const FSimpleDelegate& callFunction, float delayTime, float interval, int repeatCount = 1)
{
auto Tweener = ULTweenManager::VirtualTo(WorldContextObject, interval);
if (Tweener)
{
Tweener
->SetDelay(delayTime)
->SetLoop(repeatCount == 1 || repeatCount == 0 ? ELTweenLoop::Once : ELTweenLoop::Restart, repeatCount)
->OnCycleStart(callFunction)
;
}
return Tweener;
}
/**
* Repeatedly call function.
* @param delayTime delay time before the first call
* @param interval interval time between every call
* @param repeatCount repeat count, -1 means infinite
* @return tweener
*/
UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"), Category = LTween)
static ULTweener* RepeatCall(UObject* WorldContextObject, FLTweenerSimpleDynamicDelegate callFunction, float delayTime, float interval = 1.0f, int repeatCount = 1)
{
auto Tweener = ULTweenManager::VirtualTo(WorldContextObject, interval);
if (Tweener)
{
Tweener
->SetDelay(delayTime)
->SetLoop(repeatCount == 1 || repeatCount == 0 ? ELTweenLoop::Once : ELTweenLoop::Restart, repeatCount)
->OnCycleStart(callFunction)
;
}
return Tweener;
}
UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"), Category = LTween)
static class ULTweenerSequence* CreateSequence(UObject* WorldContextObject)
{
return ULTweenManager::CreateSequence(WorldContextObject);
}
};

View File

@@ -0,0 +1,19 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "LTweenDelegateHandleWrapper.generated.h"
/** Just a wrapper for blueprint to store a delegate handle */
USTRUCT(BlueprintType)
struct LTWEEN_API FLTweenDelegateHandleWrapper
{
GENERATED_BODY()
public:
FLTweenDelegateHandleWrapper() {}
FLTweenDelegateHandleWrapper(FDelegateHandle InDelegateHandle)
{
DelegateHandle = InDelegateHandle;
}
FDelegateHandle DelegateHandle;
};

View File

@@ -0,0 +1,7 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweenManager.h"
#include "LTweenBPLibrary.h"
#include "LTweenerSequence.h"

View File

@@ -0,0 +1,154 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/ActorComponent.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "Subsystems/WorldSubsystem.h"
#include "LTweener.h"
#include "LTweenManager.generated.h"
UCLASS(NotBlueprintable, NotBlueprintType, Transient)
class LTWEEN_API ULTweenTickHelperComponent : public UActorComponent
{
GENERATED_BODY()
public:
ULTweenTickHelperComponent();
UPROPERTY() TWeakObjectPtr<class ULTweenManager> Target = nullptr;
protected:
virtual void BeginPlay() override;
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason)override;
};
UCLASS(NotBlueprintable, NotBlueprintType, Transient, NotPlaceable)
class LTWEEN_API ALTweenTickHelperActor : public AActor
{
GENERATED_BODY()
public:
ALTweenTickHelperActor();
virtual void BeginPlay()override;
virtual void Tick(float DeltaSeconds)override;
virtual void EndPlay(EEndPlayReason::Type EndPlayReason)override;
UPROPERTY() TWeakObjectPtr<class ULTweenManager> Target = nullptr;
private:
void OnLTweenManagerCreated(class ULTweenManager* LTweenManager);
FDelegateHandle OnLTweenManagerCreatedDelegateHandle;
void SetupTick(ULTweenManager* LTweenManager);
};
// This class is only for spawn ALTweenTickHelperActor for game world
UCLASS(NotBlueprintable, NotBlueprintType, Transient)
class LTWEEN_API ULTweenTickHelperWorldSubsystem : public UWorldSubsystem
{
GENERATED_BODY()
public:
virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
virtual void PostInitialize()override;
};
DECLARE_EVENT_OneParam(ULTweenManager, FLTweenManagerCreated, class ULTweenManager*);
UCLASS(NotBlueprintable, BlueprintType, Transient)
class LTWEEN_API ULTweenManager : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
//~USubsystem interface
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
//~End of USubsystem interface
//~FTickableObjectBase interface
void Tick(ELTweenTickType TickType, float DeltaTime);
UFUNCTION(BlueprintPure, Category = LTween, meta = (WorldContext = "WorldContextObject", DisplayName = "Get LTween Instance"))
static ULTweenManager* GetLTweenInstance(UObject* WorldContextObject);
static FLTweenManagerCreated OnLTweenManagerCreated;
private:
/** current active tweener collection*/
UPROPERTY(VisibleAnywhere, Category=LTween)TArray<TObjectPtr<ULTweener>> tweenerList;
void OnTick(ELTweenTickType TickType, float DeltaTime, float UnscaledDeltaTime);
FLTweenUpdateMulticastDelegate updateEvent;
bool bTickPaused = false;
public:
UE_DEPRECATED(5.1, "Use Tweener->SetTickType(ELTweenTickType::Manual) then call this->ManualTick.")
/** Use "CustomTick" instead of UE4's default Tick to control your tween animations. Call "DisableTick" function to disable UE4's default Tick function, then call this CustomTick function.*/
UFUNCTION(BlueprintCallable, Category = LTween, meta=(DeprecatedFunction, DeprecationMessage = "Use Tweener->SetTickType(ELTweenTickType::Manual) then call this->ManualTick."))
void CustomTick(float DeltaTime);
UE_DEPRECATED(5.1, "Use Tweener->SetTickType(ELTweenTickType::Manual) then call this->ManualTick.")
/**
* Disable default Tick function, so you can pause all tween or use CustomTick to do your own tick and use your own DeltaTime.
* This will only pause the tick with current LTweenManager instance, so after load a new level, default Tick will work again, and you need to call DisableTick again if you want to disable tick.
*/
UFUNCTION(BlueprintCallable, Category = LTween, meta = (DeprecatedFunction, DeprecationMessage = "Use Tweener->SetTickType(ELTweenTickType::Manual) then call this->ManualTick."))
void DisableTick();
UE_DEPRECATED(5.1, "Use Tweener->SetTickType(ELTweenTickType::Manual) then call this->ManualTick.")
/**
* Enable default Tick if it is disabled.
*/
UFUNCTION(BlueprintCallable, Category = LTween, meta = (DeprecatedFunction, DeprecationMessage = "Use Tweener->SetTickType(ELTweenTickType::Manual) then call this->ManualTick."))
void EnableTick();
UFUNCTION(BlueprintCallable, Category = LTween)
void ManualTick(float DeltaTime);
/**
* Kill all tweens
*/
UFUNCTION(BlueprintCallable, Category = LTween)
void KillAllTweens(bool callComplete = false);
/**
* Is the tweener is currently tweening?
* @param item tweener item
*/
static bool IsTweening(UObject* WorldContextObject, ULTweener* item);
/**
* Kill the tweener if it is tweening.
* @param item tweener item
* @param callComplete true-execute onComplete event.
*/
static void KillIfIsTweening(UObject* WorldContextObject, ULTweener* item, bool callComplete);
/**
* Remove tweener from list, so the tweener will not be managed by this LTweenManager.
* @param item tweener item
*/
static void RemoveTweener(UObject* WorldContextObject, ULTweener* item);
static ULTweener* To(UObject* WorldContextObject, const FLTweenFloatGetterFunction& getter, const FLTweenFloatSetterFunction& setter, float endValue, float duration);
static ULTweener* To(UObject* WorldContextObject, const FLTweenDoubleGetterFunction& getter, const FLTweenDoubleSetterFunction& setter, double endValue, float duration);
static ULTweener* To(UObject* WorldContextObject, const FLTweenIntGetterFunction& getter, const FLTweenIntSetterFunction& setter, int endValue, float duration);
static ULTweener* To(UObject* WorldContextObject, const FLTweenPositionGetterFunction& getter, const FLTweenPositionSetterFunction& setter, const FVector& endValue, float duration, bool sweep = false, FHitResult* sweepHitResult = nullptr, ETeleportType teleportType = ETeleportType::None);
static ULTweener* To(UObject* WorldContextObject, const FLTweenVectorGetterFunction& getter, const FLTweenVectorSetterFunction& setter, const FVector& endValue, float duration);
static ULTweener* To(UObject* WorldContextObject, const FLTweenColorGetterFunction& getter, const FLTweenColorSetterFunction& setter, const FColor& endValue, float duration);
static ULTweener* To(UObject* WorldContextObject, const FLTweenLinearColorGetterFunction& getter, const FLTweenLinearColorSetterFunction& setter, const FLinearColor& endValue, float duration);
static ULTweener* To(UObject* WorldContextObject, const FLTweenVector2DGetterFunction& getter, const FLTweenVector2DSetterFunction& setter, const FVector2D& endValue, float duration);
static ULTweener* To(UObject* WorldContextObject, const FLTweenVector4GetterFunction& getter, const FLTweenVector4SetterFunction& setter, const FVector4& endValue, float duration);
static ULTweener* To(UObject* WorldContextObject, const FLTweenQuaternionGetterFunction& getter, const FLTweenQuaternionSetterFunction& setter, const FQuat& endValue, float duration);
static ULTweener* To(UObject* WorldContextObject, const FLTweenRotatorGetterFunction& getter, const FLTweenRotatorSetterFunction& setter, const FRotator& endValue, float duration);
static ULTweener* To(UObject* WorldContextObject, const FLTweenRotationQuatGetterFunction& getter, const FLTweenRotationQuatSetterFunction& setter, const FVector& eulerAngle, float duration, bool sweep = false, FHitResult* sweepHitResult = nullptr, ETeleportType teleportType = ETeleportType::None);
static ULTweener* To(UObject* WorldContextObject, const FLTweenRotationQuatGetterFunction& getter, const FLTweenRotationQuatSetterFunction& setter, const FQuat& endValue, float duration, bool sweep = false, FHitResult* sweepHitResult = nullptr, ETeleportType teleportType = ETeleportType::None);
static ULTweener* To(UObject* WorldContextObject, const FLTweenMaterialScalarGetterFunction& getter, const FLTweenMaterialScalarSetterFunction& setter, float endValue, float duration, int32 parameterIndex);
static ULTweener* To(UObject* WorldContextObject, const FLTweenMaterialVectorGetterFunction& getter, const FLTweenMaterialVectorSetterFunction& setter, const FLinearColor& endValue, float duration, int32 parameterIndex);
static ULTweener* VirtualTo(UObject* WorldContextObject, float duration);
static ULTweener* DelayFrameCall(UObject* WorldContextObject, int delayFrame);
static ULTweener* UpdateCall(UObject* WorldContextObject);
static class ULTweenerSequence* CreateSequence(UObject* WorldContextObject);
UE_DEPRECATED(5.2, "Use LTweenBPLibrary.UpdateCall instead.")
static FDelegateHandle RegisterUpdateEvent(UObject* WorldContextObject, const FLTweenUpdateDelegate& update);
UE_DEPRECATED(5.2, "Use LTweenBPLibrary.UpdateCall instead of RegisterUpdateEvent, and KillIfIsTweening for returned tweener instead of this UnregisterUpdateEvent.")
static void UnregisterUpdateEvent(UObject* WorldContextObject, const FDelegateHandle& delegateHandle);
};

View File

@@ -0,0 +1,701 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Engine/EngineTypes.h"
#include "Engine/EngineBaseTypes.h"
#include "Engine/HitResult.h"
#include "LTweener.generated.h"
DECLARE_DELEGATE_RetVal_FourParams(float, FLTweenFunction, float, float, float, float);
DECLARE_DELEGATE_OneParam(FLTweenUpdateDelegate, float);
DECLARE_MULTICAST_DELEGATE_OneParam(FLTweenUpdateMulticastDelegate, float);
#ifndef LTweenUpdateDelegate
#define LTweenUpdateDelegate UE_DEPRECATED_MACRO(5.0, "LTweenUpdateDelegate has been renamed to FLTweenUpdateDelegate") FLTweenUpdateDelegate
#endif
#ifndef LTweenUpdateMulticastDelegate
#define LTweenUpdateMulticastDelegate UE_DEPRECATED_MACRO(5.0, "LTweenUpdateMulticastDelegate has been renamed to FLTweenUpdateMulticastDelegate") FLTweenUpdateMulticastDelegate
#endif
DECLARE_DELEGATE_RetVal(float, FLTweenFloatGetterFunction);
DECLARE_DELEGATE_OneParam(FLTweenFloatSetterFunction, float);
DECLARE_DELEGATE_RetVal(double, FLTweenDoubleGetterFunction);
DECLARE_DELEGATE_OneParam(FLTweenDoubleSetterFunction, double);
DECLARE_DELEGATE_RetVal(int, FLTweenIntGetterFunction);
DECLARE_DELEGATE_OneParam(FLTweenIntSetterFunction, int);
DECLARE_DELEGATE_RetVal(FVector, FLTweenVectorGetterFunction);
DECLARE_DELEGATE_OneParam(FLTweenVectorSetterFunction, FVector);
DECLARE_DELEGATE_RetVal(FColor, FLTweenColorGetterFunction);
DECLARE_DELEGATE_OneParam(FLTweenColorSetterFunction, FColor);
DECLARE_DELEGATE_RetVal(FLinearColor, FLTweenLinearColorGetterFunction);
DECLARE_DELEGATE_OneParam(FLTweenLinearColorSetterFunction, FLinearColor);
DECLARE_DELEGATE_RetVal(FVector2D, FLTweenVector2DGetterFunction);
DECLARE_DELEGATE_OneParam(FLTweenVector2DSetterFunction, FVector2D);
DECLARE_DELEGATE_RetVal(FVector4, FLTweenVector4GetterFunction);
DECLARE_DELEGATE_OneParam(FLTweenVector4SetterFunction, FVector4);
DECLARE_DELEGATE_RetVal(FQuat, FLTweenQuaternionGetterFunction);
DECLARE_DELEGATE_OneParam(FLTweenQuaternionSetterFunction, const FQuat&);
DECLARE_DELEGATE_RetVal(FRotator, FLTweenRotatorGetterFunction);
DECLARE_DELEGATE_OneParam(FLTweenRotatorSetterFunction, FRotator);
DECLARE_DELEGATE_RetVal(FVector, FLTweenPositionGetterFunction);
DECLARE_DELEGATE_FourParams(FLTweenPositionSetterFunction, FVector, bool, FHitResult*, ETeleportType);
DECLARE_DELEGATE_RetVal(FQuat, FLTweenRotationQuatGetterFunction);
DECLARE_DELEGATE_FourParams(FLTweenRotationQuatSetterFunction, const FQuat&, bool, FHitResult*, ETeleportType);
DECLARE_DELEGATE_RetVal_OneParam(bool, FLTweenMaterialScalarGetterFunction, float&);
DECLARE_DELEGATE_RetVal_TwoParams(bool, FLTweenMaterialScalarSetterFunction, int32, float);
DECLARE_DELEGATE_RetVal_OneParam(bool, FLTweenMaterialVectorGetterFunction, FLinearColor&);
DECLARE_DELEGATE_RetVal_TwoParams(bool, FLTweenMaterialVectorSetterFunction, int32, const FLinearColor&);
/** simple delegate */
DECLARE_DYNAMIC_DELEGATE(FLTweenerSimpleDynamicDelegate);
/** @param InProgress Progress of this tween, from 0 to 1 */
DECLARE_DYNAMIC_DELEGATE_OneParam(FLTweenerFloatDynamicDelegate, float, InProgress);
/** */
UENUM(BlueprintType, Category = LTween)
enum class ELTweenTickType:uint8
{
PrePhysics = ETickingGroup::TG_PrePhysics UMETA(DisplayName = "Pre Physics"),
DuringPhysics = ETickingGroup::TG_DuringPhysics UMETA(DisplayName = "During Physics"),
PostPhysics = ETickingGroup::TG_PostPhysics UMETA(DisplayName = "Post Physics"),
PostUpdateWork = ETickingGroup::TG_PostUpdateWork UMETA(DisplayName = "Post Update Work"),
/** This tween will use manual tick. You need to call LTweenManager::ManualTick to make it work. */
Manual,
};
/**
* Animation curve type
*/
UENUM(BlueprintType, Category = LTween)
enum class ELTweenEase :uint8
{
Linear,
InQuad,
OutQuad,
InOutQuad,
InCubic,
OutCubic,
InOutCubic,
InQuart,
OutQuart,
InOutQuart,
InSine,
OutSine,
InOutSine,
InExpo,
OutExpo,
InOutExpo,
InCirc,
OutCirc,
InOutCirc,
InElastic,
OutElastic,
InOutElastic,
InBack,
OutBack,
InOutBack,
InBounce,
OutBounce,
InOutBounce,
/** Use CurveFloat to animate, only range 0-1 is valid. If use this you must assign curveFloat, or fallback to Linear. */
CurveFloat,
};
#ifndef LTweenEase
#define LTweenEase UE_DEPRECATED_MACRO(5.0, "LTweenEase has been renamed to ELTweenEase") ELTweenEase
#endif
/**
* Loop type
*/
UENUM(BlueprintType, Category = LGUI)
enum class ELTweenLoop :uint8
{
/** Play once, not loop */
Once,
/** Each loop cycle restarts from beginning */
Restart,
/** The tween move forward and backward at alternate cycles */
Yoyo,
/** Continuously increments the tween at the end of each loop cycle (A to B, B to B+(A-B), and so on). */
Incremental,
};
#ifndef LTweenLoop
#define LTweenLoop UE_DEPRECATED_MACRO(5.0, "LTweenLoop has been renamed to ELTweenLoop") ELTweenLoop
#endif
class UCurveFloat;
/** Class for manage single tween */
UCLASS(BlueprintType, Abstract)
class LTWEEN_API ULTweener : public UObject
{
GENERATED_BODY()
public:
ULTweener();
protected:
friend class ULTweenerSequence;
/** animation duration */
float duration = 0.0f;
/** delay time before animation start */
float delay = 0.0f;
/** total elapse time, include delay */
float elapseTime = 0.0f;
/** use CurveFloat as animation function,horizontal is time (0-1),vertical is value (0-1) */
TWeakObjectPtr<UCurveFloat> curveFloat = nullptr;
/** loop type */
ELTweenLoop loopType = ELTweenLoop::Once;
/** max loop count when loop type is Restart/Yoyo/Incremental */
int32 maxLoopCount = 0;
/** current completed cycle count */
int32 loopCycleCount = 0;
/** how this tween update */
ELTweenTickType tickType = ELTweenTickType::DuringPhysics;
/** reverse animation */
bool reverseTween = false;
/** if animation start play */
bool startToTween = false;
/** mark this tween for kill, so when the next update came, the tween will be killed */
bool isMarkedToKill = false;
/** mark this tween as pause, it will keep pause until call Resume() */
bool isMarkedPause = false;
/** will this tween be affected when GamePause? usually set to false for UI */
bool affectByGamePause = true;
/** will this tween use dilation-time or real-time? */
bool affectByTimeDilation = true;
/** tween function */
FLTweenFunction tweenFunc;
/** call once after animation complete */
FSimpleDelegate onCompleteCpp;
/** if use loop, this will call every time when begin tween in every cycle */
FSimpleDelegate onCycleStartCpp;
/** if use loop, this will call every time after tween complete in every cycle */
FSimpleDelegate onCycleCompleteCpp;
/** call every frame after animation starts */
FLTweenUpdateDelegate onUpdateCpp;
/** call once when animation starts */
FSimpleDelegate onStartCpp;
public:
/**
* Set animation curve type.
* Has no effect if the Tween has already started.
*/
UFUNCTION(BlueprintCallable, Category = "LTween")
ULTweener* SetEase(ELTweenEase easetype);
/** set ease to CurveFloat and use CurveFloat as animation function, horizontal is time (0-1),vertical is value (0-1) */
UE_DEPRECATED(4.23, "SetEaseCurve is not valid anymore, use SetEase and SetCurveFloat instead.")
UFUNCTION(BlueprintCallable, Category = "LTween", meta = (DeprecatedFunction, DeprecationMessage = "SetEaseCurve is not valid anymore, use SetEase and SetCurveFloat instead."))
ULTweener* SetEaseCurve(UCurveFloat* newCurve);
/**
* Set delay time before start animation.
* Has no effect if the Tween has already started.
*/
UFUNCTION(BlueprintCallable, Category = "LTween")
virtual ULTweener* SetDelay(float newDelay);
UE_DEPRECATED(4.23, "SetLoopType not valid anymore, use SetLoop instead.")
UFUNCTION(BlueprintCallable, Category = "LTween", meta = (DeprecatedFunction, DeprecationMessage = "SetLoopType not valid anymore, use SetLoop instead."))
virtual ULTweener* SetLoopType(ELTweenLoop newLoopType)
{
return SetLoop(newLoopType, -1);
}
/**
* Set loop of tween.
* Has no effect if the Tween has already started.
* @param newLoopType loop type
* @param newLoopCount number of cycles to play (-1 for infinite)
*/
UFUNCTION(BlueprintCallable, Category = "LTween")
virtual ULTweener* SetLoop(ELTweenLoop newLoopType, int32 newLoopCount = 1);
UE_DEPRECATED(4.23, "GetLoopCount not valid anymore, use GetLoopCycleCount instead.")
UFUNCTION(BlueprintCallable, Category = "LTween", meta = (DeprecatedFunction, DeprecationMessage = "GetLoopCount not valid anymore, use GetLoopCycleCount instead."))
int32 GetLoopCount() { return loopCycleCount; }
/** curently completed loop cycle count */
UFUNCTION(BlueprintCallable, Category = "LTween")
int32 GetLoopCycleCount()const { return loopCycleCount; }
/** execute when animation complete */
ULTweener* OnComplete(const FSimpleDelegate& newComplete)
{
this->onCompleteCpp = newComplete;
return this;
}
/** execute when animation complete */
ULTweener* OnComplete(const TFunction<void()>& newComplete)
{
if (newComplete != nullptr)
{
this->onCompleteCpp.BindLambda(newComplete);
}
return this;
}
/** execute when animation complete */
UFUNCTION(BlueprintCallable, Category = "LTween")
ULTweener* OnComplete(const FLTweenerSimpleDynamicDelegate& newComplete)
{
this->onCompleteCpp.BindLambda([newComplete] {
newComplete.ExecuteIfBound();
});
return this;
}
/** if use loop, this will call every time after tween complete in every cycle */
ULTweener* OnCycleComplete(const FSimpleDelegate& newCycleComplete)
{
this->onCycleCompleteCpp = newCycleComplete;
return this;
}
/** if use loop, this will call every time after tween complete in every cycle */
ULTweener* OnCycleComplete(const TFunction<void()>& newCycleComplete)
{
if (newCycleComplete != nullptr)
{
this->onCycleCompleteCpp.BindLambda(newCycleComplete);
}
return this;
}
/** if use loop, this will call every time after tween complete in every cycle */
UFUNCTION(BlueprintCallable, Category = "LTween")
ULTweener* OnCycleComplete(const FLTweenerSimpleDynamicDelegate& newCycleComplete)
{
this->onCycleCompleteCpp.BindLambda([newCycleComplete] {
newCycleComplete.ExecuteIfBound();
});
return this;
}
/** if use loop, this will call every time when begin tween in every cycle */
ULTweener* OnCycleStart(const FSimpleDelegate& newCycleStart)
{
this->onCycleStartCpp = newCycleStart;
return this;
}
/** if use loop, this will call every time when begin tween in every cycle */
ULTweener* OnCycleStart(const TFunction<void()>& newCycleStart)
{
if (newCycleStart != nullptr)
{
this->onCycleStartCpp.BindLambda(newCycleStart);
}
return this;
}
/** if use loop, this will call every time when begin tween in every cycle */
UFUNCTION(BlueprintCallable, Category = "LTween")
ULTweener* OnCycleStart(const FLTweenerSimpleDynamicDelegate& newCycleStart)
{
this->onCycleStartCpp.BindLambda([newCycleStart] {
newCycleStart.ExecuteIfBound();
});
return this;
}
/** execute every frame if animation is playing */
ULTweener* OnUpdate(const FLTweenUpdateDelegate& newUpdate)
{
this->onUpdateCpp = newUpdate;
return this;
}
/** execute every frame if animation is playing */
ULTweener* OnUpdate(const TFunction<void(float)>& newUpdate)
{
if (newUpdate != nullptr)
{
this->onUpdateCpp.BindLambda(newUpdate);
}
return this;
}
/** execute every frame if animation is playing */
UFUNCTION(BlueprintCallable, Category = "LTween")
ULTweener* OnUpdate(const FLTweenerFloatDynamicDelegate& newUpdate)
{
this->onUpdateCpp.BindLambda([newUpdate](float progress) {
newUpdate.ExecuteIfBound(progress);
});
return this;
}
/** execute when animation start*/
ULTweener* OnStart(const FSimpleDelegate& newStart)
{
this->onStartCpp = newStart;
return this;
}
/** execute when animation start, blueprint version*/
UFUNCTION(BlueprintCallable, Category = "LTween")
ULTweener* OnStart(const FLTweenerSimpleDynamicDelegate& newStart)
{
this->onStartCpp.BindLambda([newStart] {
newStart.ExecuteIfBound();
});
return this;
}
/** execute when animation start, lambda version*/
ULTweener* OnStart(const TFunction<void()>& newStart)
{
if (newStart != nullptr)
{
this->onStartCpp.BindLambda(newStart);
}
return this;
}
/**
* Set CurveFloat as animation curve. Make sure ease type is CurveFloat. (Call SetEase function to set ease type)
* Has no effect if the Tween has already started.
*/
UFUNCTION(BlueprintCallable, Category = "LTween")
ULTweener* SetCurveFloat(UCurveFloat* newCurveFloat);
/**
* @return false: the tween is complete and need to be killed. true: the tween is still processing.
*/
virtual bool ToNext(float deltaTime, float unscaledDeltaTime);
/**
* @return false: the tween is complete and need to be killed. true: the tween is still processing.
*/
bool ToNextWithElapsedTime(float InElapseTime);
/** Force stop this animation. if callComplete = true, will call OnComplete after stop*/
UFUNCTION(BlueprintCallable, Category = "LTween")
virtual void Kill(bool callComplete = false);
/** Force stop this animation at this frame, set value to end, call OnComplete. */
UFUNCTION(BlueprintCallable, Category = "LTween")
virtual void ForceComplete();
/** Pause this animation. */
UFUNCTION(BlueprintCallable, Category = "LTween")
void Pause()
{
isMarkedPause = true;
}
/** Continue play animation if is paused. */
UFUNCTION(BlueprintCallable, Category = "LTween")
void Resume()
{
isMarkedPause = false;
}
/** Will this tween be affected when GamePause? Default is true, usually set to false for UI. */
UFUNCTION(BlueprintCallable, Category = "LTween")
bool GetAffectByGamePause()const { return affectByGamePause; }
/** Will this tween be affected when GamePause? Default is true, usually set to false for UI. */
UFUNCTION(BlueprintCallable, Category = "LTween")
ULTweener* SetAffectByGamePause(bool value);
/** will this tween use dilated-time or real-time? */
UFUNCTION(BlueprintCallable, Category = "LTween")
bool GetAffectByTimeDilation()const { return affectByTimeDilation; }
/** will this tween use dilated-time or real-time? */
UFUNCTION(BlueprintCallable, Category = "LTween")
ULTweener* SetAffectByTimeDilation(bool value);
/**
* Restart animation.
* Has no effect if the Tween is not started.
*/
UFUNCTION(BlueprintCallable, Category = "LTween")
virtual void Restart();
/**
* Send the tween to the given position in time.
* @param timePoint Time position to reach (if higher than the whole tween duration the tween will simply reach its end).
*/
UFUNCTION(BlueprintCallable, Category = "LTween")
virtual void Goto(float timePoint);
/** Return progress 0-1 */
UFUNCTION(BlueprintCallable, Category = "LTween")
virtual float GetProgress()const;
UFUNCTION(BlueprintCallable, Category = "LTween")
float GetElapsedTime()const { return elapseTime; }
UFUNCTION(BlueprintCallable, Category = "LTween")
float GetDuration()const { return duration; }
/** Return tickType of this tween, default is DuringPhysics. */
UFUNCTION(BlueprintCallable, Category = "LTween")
ELTweenTickType GetTickType()const { return tickType; }
/**
* Set TickType of this tween.
* Has no effect if the Tween has already started.
*/
UFUNCTION(BlueprintCallable, Category = "LTween")
ULTweener* SetTickType(ELTweenTickType value = ELTweenTickType::DuringPhysics);
protected:
/** get value when start. child class must override this, check LTweenerFloat for reference */
virtual void OnStartGetValue() PURE_VIRTUAL(ULTweener::OnStartGetValue, );
/** set value when tweening. child class must override this, check LTweenerFloat for reference */
virtual void TweenAndApplyValue(float currentTime) PURE_VIRTUAL(ULTweener::TweenAndApplyValue, );
/** set start and end value if looptype is Incremental. */
virtual void SetValueForIncremental() PURE_VIRTUAL(ULTweener::SetValueForIncremental, );
/** set start and end value before the animation wan't to restart */
virtual void SetOriginValueForRestart() PURE_VIRTUAL(ULTweener::SetOriginValueForRestart, );
virtual void SetValueForYoyo() {};
virtual void SetValueForRestart() {};
#pragma region tweenFunctions
public:
/**
* @param c Change needed in value.
* @param b Starting value.
* @param t Current time (in frames or seconds).
* @param d Expected eaSing duration (in frames or seconds).
* @return The correct value.
*/
static float Linear(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
return c*t / d + b;
}
static float InQuad(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
t /= d;
return c*t*t + b;
}
static float OutQuad(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
t /= d;
return -c*t*(t - 2) + b;
}
static float InOutQuad(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
t /= d * 0.5f;
if (t < 1)
{
return c * 0.5f * t*t + b;
}
else
{
--t;
return -c * 0.5f * (t*(t - 2) - 1) + b;
}
}
static float InCubic(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
t /= d;
return c*t*t*t + b;
}
static float OutCubic(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
t = t / d - 1.0f;
return c*(t*t*t + 1) + b;
}
static float InOutCubic(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
t /= d * 0.5f;
if (t < 1)
{
return c * 0.5f * t*t*t + b;
}
else
{
t -= 2;
return c * 0.5f * (t*t*t + 2) + b;
}
}
static float InQuart(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
t /= d;
return c*t*t*t*t + b;
}
static float OutQuart(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
t = t / d - 1.0f;
return -c * (t*t*t*t - 1) + b;
}
static float InOutQuart(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
t /= d * 0.5f;
if (t < 1)
{
return c * 0.5f * t*t*t*t + b;
}
else
{
t -= 2;
return -c * 0.5f * (t*t*t*t - 2) + b;
}
}
static float InSine(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
return -c * FMath::Cos(t / d * HALF_PI) + c + b;
}
static float OutSine(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
return c * FMath::Sin(t / d * HALF_PI) + b;
}
static float InOutSine(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
return -c * 0.5f * (FMath::Cos(PI * t / d) - 1) + b;
}
static float InExpo(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
return (t == 0.0f) ? b : c * FMath::Pow(2.0f, 10.0f * (t / d - 1.0f)) + b - c * 0.001f;
}
static float OutExpo(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
return (t == d) ? b + c : c * 1.001f * (-FMath::Pow(2.0f, -10.0f * t / d) + 1.0f) + b;
}
static float InOutExpo(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
if (t == 0) return b;
if (t == d) return b + c;
t /= d * 0.5f;
if (t < 1.0f)
{
return c * 0.5f * FMath::Pow(2.0f, 10.0f * (t - 1.0f)) + b - c * 0.0005f;
}
else
{
return c * 0.5f * 1.0005f * (-FMath::Pow(2.0f, -10.0f * (t - 1.0f)) + 2.0f) + b;
}
}
static float InCirc(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
t /= d;
return -c * (FMath::Sqrt(1.0f - t*t) - 1.0f) + b;
}
static float OutCirc(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
t = t / d - 1.0f;
return c * FMath::Sqrt(1.0f - t*t) + b;
}
static float InOutCirc(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
t /= d * 0.5f;
if (t < 1)
{
return -c * 0.5f * (FMath::Sqrt(1 - t * t) - 1) + b;
}
else
{
t -= 2.0f;
return c * 0.5f * (FMath::Sqrt(1.0f - t*t) + 1.0f) + b;
}
}
static float InElastic(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
if (t == 0) return b;
t /= d;
if (t == 1) return b + c;
float p = d*0.3f;
float s = p / 4;
float a = c;
t -= 1.0f;
return -(a*FMath::Pow(2.0f, 10.0f * t) * FMath::Sin((t*d - s)*(2.0f * PI) / p)) + b;
}
static float OutElastic(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
if (t == 0) return b;
t /= d;
if (t == 1) return b + c;
float p = d*0.3f;
float s = p / 4;
float a = c;
return (a*FMath::Pow(2.0f, -10.0f * t) * FMath::Sin((t*d - s)*(2.0f * PI) / p) + c + b);
}
static float InOutElastic(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
if (t == 0) return b;
t /= d * 0.5f;
if (t == 2) return b + c;
float p = d*0.3f;
float s = p / 4;
float a = c;
if (t < 1.0f)
{
t -= 1.0f;
return -0.5f*(a*FMath::Pow(2.0f, 10.0f * t) * FMath::Sin((t*d - s)*(2.0f * PI) / p)) + b;
}
else
{
t -= 1.0f;
return a * FMath::Pow(2.0f, -10.0f * t) * FMath::Sin((t*d - s)*(2.0f * PI) / p)*0.5f + c + b;
}
}
static float InBack(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
static float s = 1.70158f;
t /= d;
return c*t*t*((s + 1)*t - s) + b;
}
static float OutBack(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
static float s = 1.70158f;
t = t / d - 1;
return c*(t*t*((s + 1)*t + s) + 1) + b;
}
static float InOutBack(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
if (t < d * 0.5f) return InBack(c, 0, t * 2, d) * .5f + b;
else return OutBack(c, 0, t * 2 - d, d) * .5f + c * .5f + b;
}
static float OutBounce(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
t /= d;
if (t < (1.0f / 2.75f)) {
return c*(7.5625f*t*t) + b;
}
else if (t < (2.0f / 2.75f)) {
t -= (1.5f / 2.75f);
return c*(7.5625f*t*t + .75f) + b;
}
else if (t < (2.5f / 2.75f)) {
t -= (2.25f / 2.75f);
return c*(7.5625f*t*t + .9375f) + b;
}
else {
t -= (2.625f / 2.75f);
return c*(7.5625f*t*t + .984375f) + b;
}
}
static float InBounce(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
return c - OutBounce(c, 0, d - t, d) + b;
}
static float InOutBounce(float c, float b, float t, float d)
{
if (d < KINDA_SMALL_NUMBER)return c + b;
if (t < d * 0.5f) return InBounce(c, 0, t * 2, d) * .5f + b;
else return OutBounce(c, 0, t * 2 - d, d) * .5f + c * .5f + b;
}
/** Tween use CurveFloat, in range of 0-1. if curveFloat is null, fallback to Linear */
float CurveFloat(float c, float b, float t, float d);
#pragma endregion
};

View File

@@ -0,0 +1,71 @@
// Copyright 2019-Present LexLiu. All Rights Reserved.
#pragma once
#include "LTweener.h"
#include "LTweenerSequence.generated.h"
UCLASS(BlueprintType)
class LTWEEN_API ULTweenerSequence:public ULTweener
{
GENERATED_BODY()
private:
UPROPERTY(VisibleAnywhere, Category = LTween)TArray<TObjectPtr<ULTweener>> tweenerList;
UPROPERTY(VisibleAnywhere, Category = LTween)TArray<TObjectPtr<ULTweener>> finishedTweenerList;
float lastTweenStartTime = 0;
public:
/**
* Adds the given tween to the end of the Sequence.
* Not support Tweener type: Delay/ DelayFrame/ Virtual.
* Has no effect if the Sequence has already started.
*/
UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"), Category = LTween)
ULTweenerSequence* Append(UObject* WorldContextObject, ULTweener* tweener);
/**
* Adds the given interval to the end of the Sequence.
* Has no effect if the Sequence has already started.
* @param interval The interval duration
*/
UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"), Category = LTween)
ULTweenerSequence* AppendInterval(UObject* WorldContextObject, float interval);
/**
* Inserts the given tween at the given time position in the Sequence, automatically adding an interval if needed.
* Not support Tweener type: Delay/ DelayFrame/ Virtual.
* Has no effect if the Sequence has already started.
* @param timePosition The time position where the tween will be placed
*/
UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"), Category = LTween)
ULTweenerSequence* Insert(UObject* WorldContextObject, float timePosition, ULTweener* tweener);
/**
* Adds the given tween to the beginning of the Sequence, pushing forward the other nested content.
* Not support Tweener type: Delay/ DelayFrame/ Virtual.
* Has no effect if the Sequence has already started.
*/
UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"), Category = LTween)
ULTweenerSequence* Prepend(UObject* WorldContextObject, ULTweener* tweener);
/**
* Adds the given interval to the beginning of the Sequence, pushing forward the other nested content.
* Has no effect if the Sequence has already started.
* @param interval The interval duration
*/
UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"), Category = LTween)
ULTweenerSequence* PrependInterval(UObject* WorldContextObject, float interval);
/**
* Inserts the given tween at the same time position of the last tween added to the Sequence.
* Note that, in case of a Join after an interval, the insertion time will be the time where the interval starts, not where it finishes.
* Not support Tweener type: Delay/ DelayFrame/ Virtual.
* Has no effect if the Sequence has already started.
*/
UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"), Category = LTween)
ULTweenerSequence* Join(UObject* WorldContextObject, ULTweener* tweener);
protected:
virtual void OnStartGetValue() override {};
virtual void TweenAndApplyValue(float currentTime) override;
virtual void SetValueForIncremental() override;
virtual void SetValueForYoyo() override;
virtual void SetValueForRestart() override;
virtual void SetOriginValueForRestart() override;
virtual void Restart()override;
virtual void Goto(float timePoint)override;
};

View File

@@ -0,0 +1,6 @@
{
"cSpell.words": [
"speakerline",
"squarebrackets"
]
}

View File

@@ -0,0 +1,12 @@
from setuptools import setup, find_packages
setup (
name='sudslexer',
packages=find_packages(),
version="0.4.0",
entry_points =
"""
[pygments.lexers]
sudslexer = sudslexer.lexer:SudsLexer
""",
)

View File

@@ -0,0 +1,71 @@
from pygments.lexer import RegexLexer, bygroups
from pygments.token import *
class SudsLexer(RegexLexer):
name = 'SUDS'
aliases = ['suds']
filenames = ['*.sud']
tokens = {
'root': [
(r'===\s*\n', Generic.Heading),
# Choices
(r'\s*\*\-?\s+[^\@\n]+[\@\n]', Generic.Subheading),
(r'\s*#.*\n', Comment),
# Speaker lines
(r'\s*\S+\:', Name.Class, 'speakerline'),
# Open brackets for special functions
(r'\[', Operator, 'squarebrackets'),
# Variables
(r'(\{)([\w\.]+)(\})', bygroups(Operator, Name.Variable, Operator)),
(r'(\|)(plural|gender)(\()(.*?)(\))', bygroups(Operator, Keyword, Operator, Keyword, Operator)),
(r'\b([tT]rue|[fF]alse|[mM]asculine|[fF]eminine|[nN]euter)\b', Name.Constant),
# Line IDs
(r'\@[0-9a-fA-F]+\@', Comment.Special),
# Embedded markup
(r'\<\w+\>', Name.Decorator),
(r'\<\/\>', Name.Decorator),
# Goto labels
(r'\s*:\S+\n', Name.Label),
# Comments
(r'\s*\#[\=\+\%]?.*\n', Comment.Special),
# Fallback for all other text
# Needs an optional \n on the end to finish lines correctly
(r'\s+[\n]?', Text),
(r'\S+?[\n]?', Text), # non-greedy so we don't consume all non-whitespace
],
# While in a speaker line, we ignore everything else except variables & markup
'speakerline' : [
# Variables
(r'(\{)([\w\.]+)(\})', bygroups(Operator, Name.Variable, Operator)),
(r'(\|)(plural|gender)(\()(.*?)(\))', bygroups(Operator, Keyword, Operator, Keyword, Operator)),
(r'[\@\n]', Text, '#pop'),
# Embedded markup
(r'\<\w+\>', Name.Decorator),
(r'\<\/\>', Name.Decorator),
(r'[^\@\n\<\{]+', Text),
],
# While in a [] block, highlight operators etc (don't do it elsewhere)
'squarebrackets' : [
# Close bracket finishes
(r'\]\s*[\n]?', Operator, '#pop'),
# Variables
(r'(\{)([\w\.]+)(\})', bygroups(Operator, Name.Variable, Operator)),
(r'\+\/\-\*\!\%', Operator),
(r'\"[^\"]*\"', String.Double),
(r'\`[^\`]*\`', String.Escape),
(r'\d+(\.\d+)?', Number),
(r'\b([tT]rue|[fF]alse|[mM]asculine|[fF]eminine|[nN]euter)\b', Name.Constant),
# Set, event commands so we can highlight variable/event differently
(r'\s*(set|event)(\s+)([^\]\s]+)', bygroups(Keyword, Text, Name.Variable)),
(r'\s*(if|else|elseif|endif|event|return|goto|gosub|go to|go sub|random|endrandom)\b', Keyword),
(r'\b(and|or|&&|\|\||not)\b', Operator),
(r'[,]', Punctuation),
(r'\s+', Text), # whitespace OK
]
}

View File

@@ -2,6 +2,9 @@
// Released under the MIT license https://opensource.org/license/MIT/
#include "SUDSValue.h"
#include "UObject/Class.h"
#include "Internationalization/Text.h"
FArchive& operator<<(FArchive& Ar, FSUDSValue& Value)
{
// Custom serialisation since we can't auto-serialise union, TOptional
@@ -62,7 +65,11 @@ FString FSUDSValue::ToString() const
case ESUDSValueType::Boolean:
return GetBooleanValue() ? "True" : "False";
case ESUDSValueType::Gender:
return StaticEnum<ETextGender>()->GetNameStringByValue((int64)GetGenderValue());
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
return LexToString(GetGenderValue());
#else
return *StaticEnum<ETextGender>()->GetNameStringByValue((int64)GetGenderValue());
#endif
case ESUDSValueType::Name:
return GetNameValue().ToString();
case ESUDSValueType::Variable:

View File

@@ -706,7 +706,11 @@ void FSUDSEditorToolkit::OnDialogueChoice(USUDSDialogue* D, int ChoiceIndex, int
void FSUDSEditorToolkit::OnDialogueEvent(USUDSDialogue* D, FName EventName, const TArray<FSUDSValue>& Args, int LineNo)
{
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
TStringBuilder<256> B;
#else
FStringBuilderBase B;
#endif
if (Args.Num() > 0)
{
for (auto& Arg : Args)
@@ -1372,6 +1376,24 @@ TSharedRef<SWidget> SSUDSEditorVariableItem::GetGenderMenu()
{
FMenuBuilder MenuBuilder(true, NULL);
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
// StaticEnum<ETextGender>() doesn't exist anymore so we have to do this manually
const FUIAction Action0(FExecuteAction::CreateSP(this, &SSUDSEditorVariableItem::OnGenderSelected, ETextGender::Feminine));
MenuBuilder.AddMenuEntry(FText::FromString(LexToString(ETextGender::Feminine)),
FText(),
FSlateIcon(),
Action0);
const FUIAction Action1(FExecuteAction::CreateSP(this, &SSUDSEditorVariableItem::OnGenderSelected, ETextGender::Masculine));
MenuBuilder.AddMenuEntry(FText::FromString(LexToString(ETextGender::Masculine)),
FText(),
FSlateIcon(),
Action1);
const FUIAction Action2(FExecuteAction::CreateSP(this, &SSUDSEditorVariableItem::OnGenderSelected, ETextGender::Neuter));
MenuBuilder.AddMenuEntry(FText::FromString(LexToString(ETextGender::Neuter)),
FText(),
FSlateIcon(),
Action2);
#else
// NumEnums() - 1 because the last value is the autogen _MAX value
for (int i = 0; i < StaticEnum<ETextGender>()->NumEnums() - 1; ++i)
{
@@ -1383,6 +1405,7 @@ TSharedRef<SWidget> SSUDSEditorVariableItem::GetGenderMenu()
Action);
}
#endif
return MenuBuilder.MakeWidget();

View File

@@ -1772,7 +1772,11 @@ FString FSUDSScriptImporter::GetCurrentTreePath(const FSUDSScriptImporter::Parse
// Do NOT fallthrough to here
// Fallthrough to here instead (/)
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
TStringBuilder<256> B;
#else
FStringBuilderBase B;
#endif
for (auto Indent : Tree.IndentLevelStack)
{
B.Appendf(TEXT("%s%s"), *Indent.PathEntry, *TreePathSeparator);
@@ -1784,7 +1788,11 @@ FString FSUDSScriptImporter::GetCurrentTreeConditionalPath(const FSUDSScriptImpo
{
// Like GetCurrentTreePath, but for conditional blocks
// Cannot fall through to blocks that aren't on the same conditional path
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
TStringBuilder<256> B;
#else
FStringBuilderBase B;
#endif
int BlockIdx = Tree.CurrentConditionalBlockIdx;
B.Append(TreePathSeparator);
// work backwards, hence prepend
@@ -1803,7 +1811,11 @@ FString FSUDSScriptImporter::GetCurrentTreeConditionalPath(const FSUDSScriptImpo
FString FSUDSScriptImporter::GetTreeConditionalPath(const FSUDSScriptImporter::ParsedTree& Tree, int NodeIndex)
{
// Like GetCurrentTreeConditionalPath, but we're not in the block context. Follow the nodes back up
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
TStringBuilder<256> B;
#else
FStringBuilderBase B;
#endif
B.Append(TreePathSeparator);
while (Tree.Nodes.IsValidIndex(NodeIndex))
@@ -2543,7 +2555,11 @@ void FSUDSScriptImporter::PopulateAssetFromTree(USUDSScript* Asset,
{
case ESUDSParsedNodeType::Text:
{
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
StringTable->GetMutableStringTable()->SetSourceString(InNode.TextID, InNode.Text, "");
#else
StringTable->GetMutableStringTable()->SetSourceString(InNode.TextID, InNode.Text);
#endif
// Always include speaker metadata
StringTable->GetMutableStringTable()->SetMetaData(InNode.TextID, FName("Speaker"), InNode.Identifier);
// Other metadata
@@ -2579,7 +2595,11 @@ void FSUDSScriptImporter::PopulateAssetFromTree(USUDSScript* Asset,
FSUDSExpression Expr = InNode.Expression;
if (Expr.IsTextLiteral())
{
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
StringTable->GetMutableStringTable()->SetSourceString(InNode.TextID, Expr.GetTextLiteralValue().ToString(), "");
#else
StringTable->GetMutableStringTable()->SetSourceString(InNode.TextID, Expr.GetTextLiteralValue().ToString());
#endif
Expr.SetTextLiteralValue(FText::FromStringTable (StringTable->GetStringTableId(), InNode.TextID));
}
SetNode->Init(InNode.Identifier, Expr, InNode.SourceLineNo);
@@ -2707,7 +2727,11 @@ void FSUDSScriptImporter::PopulateAssetFromTree(USUDSScript* Asset,
if (!InEdge.TextID.IsEmpty() && !InEdge.Text.IsEmpty())
{
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
StringTable->GetMutableStringTable()->SetSourceString(InEdge.TextID, InEdge.Text, "");
#else
StringTable->GetMutableStringTable()->SetSourceString(InEdge.TextID, InEdge.Text);
#endif
NewEdge.SetText(FText::FromStringTable(StringTable->GetStringTableId(), InEdge.TextID));
// Always include speaker metadata, always the player in a choice
// Identify that it's a choice so translators know that there may be more limited space

View File

@@ -3,7 +3,7 @@
#include "StevesBPL.h"
#include "Misc/ConfigCacheIni.h"
#include "StevesUiHelpers.h"
#include "StevesUI/StevesUI.h"
#include "ContentStreaming.h"

View File

@@ -8,7 +8,7 @@ float UStevesEasings::EaseAlpha(float InAlpha, EStevesEaseFunction Func)
constexpr float BackC2 = BackC1 * 1.525f;
constexpr float BackC3 = BackC1 + 1.f;
constexpr float ElasticC4 = UE_TWO_PI / 3.f;
constexpr float ElasticC5 = UE_TWO_PI / 4.5;
constexpr float ElasticC5 = UE_TWO_PI / 4.5f;
switch(Func)
{

View File

@@ -110,7 +110,7 @@ void UStevesGameSubsystem::NotifyEnhancedInputMappingsChanged()
OnEnhancedInputMappingsChanged.Broadcast();
};
FTimerHandle TempHandle;
GetWorld()->GetTimerManager().SetTimer(TempHandle, FTimerDelegate::CreateLambda(DelayedFunc), 0.05, false);
GetWorld()->GetTimerManager().SetTimer(TempHandle, FTimerDelegate::CreateLambda(DelayedFunc), 0.05f, false);
}
TSoftObjectPtr<UInputAction> UStevesGameSubsystem::FindEnhancedInputAction(const FString& Name)

View File

@@ -262,13 +262,13 @@ public:
*/
uint32 GetCurrentSeed() const
{
return InitialSeed;
return Seed;
}
FString ToString() const
{
return FString::Printf(TEXT("FStevesBalancedRandomStream(InitialSeed=%i, Seed=%u)"), InitialSeed, InitialSeed);
return FString::Printf(TEXT("FStevesBalancedRandomStream(InitialSeed=%u, Seed=%u)"), InitialSeed, Seed);
}
@@ -407,13 +407,13 @@ public:
*/
FORCEINLINE uint32 GetCurrentSeed() const
{
return InitialSeed;
return Seed;
}
FString ToString() const
{
return FString::Printf(TEXT("FStevesBalancedRandomStream1D(InitialSeed=%i, Seed=%u)"), InitialSeed, InitialSeed);
return FString::Printf(TEXT("FStevesBalancedRandomStream1D(InitialSeed=%u, Seed=%u)"), InitialSeed, Seed);
}
};
@@ -650,13 +650,13 @@ public:
*/
uint32 GetCurrentSeed() const
{
return InitialSeed;
return Base2Seed;
}
FString ToString() const
{
return FString::Printf(TEXT("FStevesBalancedRandomStream2D(InitialSeed=%i, Seed=%u)"), InitialSeed, InitialSeed);
return FString::Printf(TEXT("FStevesBalancedRandomStream2D(InitialSeed=%u, Seed=%u)"), InitialSeed, Base2Seed);
}
};
@@ -775,7 +775,7 @@ public:
uint32 GetInitialSeed() const
{
return InitialSeed;
return Base2Seed;
}
/**
@@ -922,7 +922,7 @@ public:
FString ToString() const
{
return FString::Printf(TEXT("FStevesBalancedRandomStream(InitialSeed=%i, Seed=%u)"), InitialSeed, InitialSeed);
return FString::Printf(TEXT("FStevesBalancedRandomStream(InitialSeed=%u, Seed=%u)"), InitialSeed, Base2Seed);
}

View File

@@ -103,7 +103,7 @@ protected:
const EInputMode DefaultButtonInputMode = EInputMode::Keyboard;
const EInputMode DefaultAxisInputMode = EInputMode::Mouse;
const float MouseMoveThreshold = 1;
const float GamepadAxisThreshold = 0.2;
const float GamepadAxisThreshold = 0.2f;
bool ShouldProcessInputEvents() const;
public:

View File

@@ -1,40 +1,38 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.1.1.0",
"EngineVersion": "",
"FriendlyName": "Steve's UE Helpers",
"Description": "A set of common helper classes for UE projects by Steve Streeting",
"Category": "Code Utilities",
"CreatedBy": "Steve Streeting",
"CreatedByURL": "https://www.stevestreeting.com",
"DocsURL": "https://github.com/sinbad/StevesUEHelpers/blob/master/ReadMe.md",
"MarketplaceURL": "com.epicgames.launcher://ue/Fab/product/6a48c58c-1771-42f6-b46f-2b09e31b1699",
"SupportURL": "https://github.com/sinbad/StevesUEHelpers",
"EnabledByDefault": true,
"CanContainContent": false,
"IsBetaVersion": false,
"Installed": false,
"Modules": [
{
"Name": "StevesUEHelpers",
"Type": "Runtime",
"LoadingPhase": "PreDefault",
"PlatformAllowList": [
"Win64",
"Linux",
"Mac"
]
},
{
"Name": "StevesUEHelpersEd",
"Type": "Editor",
"LoadingPhase": "PostDefault",
"PlatformAllowList": [
"Win64",
"Linux",
"Mac"
]
}
]
}
"FileVersion": 3,
"Version": 1,
"VersionName": "1.2.1.0",
"FriendlyName": "Steve's UE Helpers",
"Description": "A set of common helper classes for UE projects by Steve Streeting",
"Category": "Code Utilities",
"CreatedBy": "Steve Streeting",
"CreatedByURL": "https://www.stevestreeting.com",
"DocsURL": "https://github.com/sinbad/StevesUEHelpers/blob/master/ReadMe.md",
"MarketplaceURL": "com.epicgames.launcher://ue/Fab/product/6a48c58c-1771-42f6-b46f-2b09e31b1699",
"SupportURL": "https://github.com/sinbad/StevesUEHelpers",
"EngineVersion": "5.8.0",
"CanContainContent": false,
"Installed": true,
"Modules": [
{
"Name": "StevesUEHelpers",
"Type": "Runtime",
"LoadingPhase": "PreDefault",
"PlatformAllowList": [
"Win64",
"Linux",
"Mac"
]
},
{
"Name": "StevesUEHelpersEd",
"Type": "Editor",
"LoadingPhase": "PostDefault",
"PlatformAllowList": [
"Win64",
"Linux",
"Mac"
]
}
]
}