Refactor Scripted Animations to provide an option for which clock to use
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -30,7 +30,7 @@ public:
|
|||||||
|
|
||||||
// The hash of the animation step, a 63-bit unique identifier.
|
// The hash of the animation step, a 63-bit unique identifier.
|
||||||
//
|
//
|
||||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
UPROPERTY()
|
||||||
int64 Hash;
|
int64 Hash;
|
||||||
|
|
||||||
// The Body contains all the key-value pairs in an encoded form. To
|
// The Body contains all the key-value pairs in an encoded form. To
|
||||||
@@ -74,7 +74,7 @@ class INTEGRATION_API UlxAnimationStepLibrary : public UBlueprintFunctionLibrary
|
|||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Animation Step")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Animation Step")
|
||||||
static FString AnimationStepDebugString(const FlxAnimationStep& step);
|
static FString AnimationStepDebugString(const FlxAnimationStep& step);
|
||||||
|
|
||||||
// Stores the key-value pairs in properties of the target object.
|
// Stores the key-value pairs in properties of the target object.
|
||||||
@@ -101,26 +101,29 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = "Luprex|Animation Step")
|
UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = "Luprex|Animation Step")
|
||||||
static void UnpackAnimationStep(bool &bChanged, FString &Action, const FlxAnimationStep& step, UObject* target, const FString& VariableNamePrefix = TEXT("aq"));
|
static void UnpackAnimationStep(bool &bChanged, FString &Action, const FlxAnimationStep& step, UObject* target, const FString& VariableNamePrefix = TEXT("aq"));
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Animation Step")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Animation Step")
|
||||||
static bool AnimationStepEqual(const FlxAnimationStep &StepA, const FlxAnimationStep &StepB);
|
static bool AnimationStepEqual(const FlxAnimationStep &StepA, const FlxAnimationStep &StepB);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Animation Step")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Animation Step")
|
||||||
static bool AnimationStepIsIdle(const FlxAnimationStep &step);
|
static bool AnimationStepIsIdle(const FlxAnimationStep &step);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Animation Step")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Animation Step")
|
||||||
static FVector AnimationStepGetVector(const FlxAnimationStep& step, const FString& name);
|
static FVector AnimationStepGetVector(const FlxAnimationStep& step, const FString& name);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Animation Step")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Animation Step")
|
||||||
static double AnimationStepGetFloat(const FlxAnimationStep& step, const FString& name);
|
static double AnimationStepGetFloat(const FlxAnimationStep& step, const FString& name);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Animation Step")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Animation Step")
|
||||||
static FString AnimationStepGetString(const FlxAnimationStep& step, const FString& name);
|
static FString AnimationStepGetString(const FlxAnimationStep& step, const FString& name);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Animation Step")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Animation Step")
|
||||||
static FName AnimationStepGetName(const FlxAnimationStep& step, const FString& name);
|
static FName AnimationStepGetName(const FlxAnimationStep& step, const FString& name);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Luprex|Animation Step")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Animation Step")
|
||||||
static bool AnimationStepGetBool(const FlxAnimationStep& step, const FString& name);
|
static bool AnimationStepGetBool(const FlxAnimationStep& step, const FString& name);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, meta = (BlueprintAutocast), Category = "Luprex|Animation Step")
|
||||||
|
static int64 AnimationStepID(const FlxAnimationStep& step) { return step.Hash; }
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////
|
////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -1,59 +1,5 @@
|
|||||||
#include "ScriptedAnimation.h"
|
#include "ScriptedAnimation.h"
|
||||||
|
#include "Engine/Engine.h"
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Routines to calculate the current state of an FlxScriptedAnimation.
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
double FlxScriptedAnimation::CalculateFade(double Offset, double Fade)
|
|
||||||
{
|
|
||||||
if (Offset < 0.0)
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
if (Fade > 0.001)
|
|
||||||
{
|
|
||||||
return FMath::Min(Offset / Fade, 1.0);
|
|
||||||
}
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double FlxScriptedAnimation::UnclampedElapsedTime(double CurrentTime) const
|
|
||||||
{
|
|
||||||
return CurrentTime - StartTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
double FlxScriptedAnimation::UnclampedTimeLeft(double CurrentTime) const
|
|
||||||
{
|
|
||||||
return EndTime - CurrentTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
double FlxScriptedAnimation::ClampedElapsedTime(double CurrentTime) const
|
|
||||||
{
|
|
||||||
return FMath::Max(0.0, CurrentTime - StartTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
double FlxScriptedAnimation::ClampedTimeLeft(double CurrentTime) const
|
|
||||||
{
|
|
||||||
return FMath::Max(0.0, EndTime - CurrentTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
double FlxScriptedAnimation::CalcFadeInAlpha(double CurrentTime) const
|
|
||||||
{
|
|
||||||
return CalculateFade(UnclampedElapsedTime(CurrentTime), FadeInDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
double FlxScriptedAnimation::CalcFadeOutAlpha(double CurrentTime) const
|
|
||||||
{
|
|
||||||
return CalculateFade(UnclampedTimeLeft(CurrentTime), FadeOutDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
double FlxScriptedAnimation::CalcFadeInOutAlpha(double CurrentTime) const
|
|
||||||
{
|
|
||||||
return FMath::Min(CalcFadeInAlpha(CurrentTime), CalcFadeOutAlpha(CurrentTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlxScriptedAnimation::InitiateFadeOut(double CurrentTime, double AllowedFade)
|
void FlxScriptedAnimation::InitiateFadeOut(double CurrentTime, double AllowedFade)
|
||||||
{
|
{
|
||||||
@@ -81,43 +27,48 @@ void UlxScriptedAnimations::Keep(int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UlxScriptedAnimations::AddAnimation(
|
void UlxScriptedAnimations::AddAnimation(
|
||||||
UObject* WorldContextObject, UAnimSequenceBase* Sequence, double FadeInTime, double FadeOutTime, int64 AqHash)
|
UObject* WorldContextObject, UAnimSequenceBase* Sequence, double FadeInTime, double FadeOutTime,
|
||||||
|
int64 AnimationStepID, bool ContinueWhenPaused)
|
||||||
{
|
{
|
||||||
check(KeepCount >= 1);
|
check(KeepCount >= 1);
|
||||||
FlxScriptedAnimation Result;
|
FlxScriptedAnimation Result;
|
||||||
|
|
||||||
// Get World Time
|
// Get World Time
|
||||||
UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject);
|
FlxWorldClocks Clocks = UlxScriptedAnimationLibrary::GetAllWorldClocks(WorldContextObject);
|
||||||
double WorldTime = World ? World->GetTimeSeconds() : 0.0;
|
double CurrentTime = ContinueWhenPaused ? Clocks.RealTime : Clocks.WorldTime;
|
||||||
|
|
||||||
// Get the animation Length.
|
// Get the animation Length.
|
||||||
double Length = (Sequence ? static_cast<double>(Sequence->GetPlayLength()) : 0.0);
|
double Length = (Sequence ? static_cast<double>(Sequence->GetPlayLength()) : 0.0);
|
||||||
|
|
||||||
// Fill the static setup fields
|
// Fill the static setup fields
|
||||||
Result.Sequence = Sequence;
|
Result.Sequence = Sequence;
|
||||||
Result.AqHash = AqHash;
|
Result.ContinueWhenPaused = ContinueWhenPaused;
|
||||||
|
Result.AnimationStepID = AnimationStepID;
|
||||||
Result.FadeInDuration = FadeInTime;
|
Result.FadeInDuration = FadeInTime;
|
||||||
Result.FadeOutDuration = FadeOutTime;
|
Result.FadeOutDuration = FadeOutTime;
|
||||||
Result.StartTime = WorldTime;
|
Result.StartTime = CurrentTime;
|
||||||
Result.EndTime = WorldTime + Length;
|
Result.EndTime = CurrentTime + Length;
|
||||||
|
|
||||||
Keep(KeepCount - 1);
|
Keep(KeepCount - 1);
|
||||||
Animations.Insert(Result, 0);
|
Animations.Insert(Result, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxScriptedAnimations::FadeGarbage(TArray<int32> Hashes, double CurrentTime)
|
void UlxScriptedAnimations::FadeGarbage(const UObject *WorldContextObject, TArray<int64> KeepIDs)
|
||||||
{
|
{
|
||||||
|
FlxWorldClocks Clocks = UlxScriptedAnimationLibrary::GetAllWorldClocks(WorldContextObject);
|
||||||
for (int i = 0; i < Animations.Num(); i++)
|
for (int i = 0; i < Animations.Num(); i++)
|
||||||
{
|
{
|
||||||
FlxScriptedAnimation &Anim = Animations[i];
|
FlxScriptedAnimation &Anim = Animations[i];
|
||||||
if ((Anim.AqHash != 0) && (!Hashes.Contains(Anim.AqHash)))
|
if ((Anim.AnimationStepID > 0) && (!KeepIDs.Contains(Anim.AnimationStepID)))
|
||||||
{
|
{
|
||||||
Anim.InitiateFadeOut(CurrentTime, 0.2);
|
Anim.InitiateFadeOut(Anim.ChooseCorrectClock(Clocks), 0.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxScriptedAnimationLibrary::ScriptedAnimationEvaluatorData(const UlxScriptedAnimations *Animations, double CurrentTime,
|
void UlxScriptedAnimationLibrary::ScriptedAnimationEvaluatorData(
|
||||||
|
const UlxScriptedAnimations *Animations,
|
||||||
|
const FlxWorldClocks &WorldClocks,
|
||||||
UAnimSequenceBase *&Sequence0, float &ExplicitTime0,
|
UAnimSequenceBase *&Sequence0, float &ExplicitTime0,
|
||||||
UAnimSequenceBase *&Sequence1, float &ExplicitTime1,
|
UAnimSequenceBase *&Sequence1, float &ExplicitTime1,
|
||||||
UAnimSequenceBase *&Sequence2, float &ExplicitTime2,
|
UAnimSequenceBase *&Sequence2, float &ExplicitTime2,
|
||||||
@@ -140,6 +91,7 @@ void UlxScriptedAnimationLibrary::ScriptedAnimationEvaluatorData(const UlxScript
|
|||||||
if (Anims.Num() > 0)
|
if (Anims.Num() > 0)
|
||||||
{
|
{
|
||||||
const FlxScriptedAnimation &Anim = Anims[0];
|
const FlxScriptedAnimation &Anim = Anims[0];
|
||||||
|
double CurrentTime = Anim.ChooseCorrectClock(WorldClocks);
|
||||||
Sequence0 = Anim.Sequence;
|
Sequence0 = Anim.Sequence;
|
||||||
ExplicitTime0 = Anim.ClampedElapsedTime(CurrentTime);
|
ExplicitTime0 = Anim.ClampedElapsedTime(CurrentTime);
|
||||||
Sequence0Alpha = Anim.CalcFadeInOutAlpha(CurrentTime);
|
Sequence0Alpha = Anim.CalcFadeInOutAlpha(CurrentTime);
|
||||||
@@ -147,6 +99,7 @@ void UlxScriptedAnimationLibrary::ScriptedAnimationEvaluatorData(const UlxScript
|
|||||||
if (Anims.Num() > 1)
|
if (Anims.Num() > 1)
|
||||||
{
|
{
|
||||||
const FlxScriptedAnimation &Anim = Anims[1];
|
const FlxScriptedAnimation &Anim = Anims[1];
|
||||||
|
double CurrentTime = Anim.ChooseCorrectClock(WorldClocks);
|
||||||
Sequence1 = Anim.Sequence;
|
Sequence1 = Anim.Sequence;
|
||||||
ExplicitTime1 = Anim.ClampedElapsedTime(CurrentTime);
|
ExplicitTime1 = Anim.ClampedElapsedTime(CurrentTime);
|
||||||
Sequence1Alpha = Anim.CalcFadeInOutAlpha(CurrentTime);
|
Sequence1Alpha = Anim.CalcFadeInOutAlpha(CurrentTime);
|
||||||
@@ -154,6 +107,7 @@ void UlxScriptedAnimationLibrary::ScriptedAnimationEvaluatorData(const UlxScript
|
|||||||
if (Anims.Num() > 2)
|
if (Anims.Num() > 2)
|
||||||
{
|
{
|
||||||
const FlxScriptedAnimation &Anim = Anims[2];
|
const FlxScriptedAnimation &Anim = Anims[2];
|
||||||
|
double CurrentTime = Anim.ChooseCorrectClock(WorldClocks);
|
||||||
Sequence2 = Anim.Sequence;
|
Sequence2 = Anim.Sequence;
|
||||||
ExplicitTime2 = Anim.ClampedElapsedTime(CurrentTime);
|
ExplicitTime2 = Anim.ClampedElapsedTime(CurrentTime);
|
||||||
Sequence2Alpha = Anim.CalcFadeInOutAlpha(CurrentTime);
|
Sequence2Alpha = Anim.CalcFadeInOutAlpha(CurrentTime);
|
||||||
@@ -175,3 +129,14 @@ void UlxScriptedAnimationLibrary::ScriptedAnimationEvaluatorData(const UlxScript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlxWorldClocks UlxScriptedAnimationLibrary::GetAllWorldClocks(const UObject *WorldContextObject)
|
||||||
|
{
|
||||||
|
UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject);
|
||||||
|
FlxWorldClocks Result;
|
||||||
|
if (World != nullptr)
|
||||||
|
{
|
||||||
|
Result.WorldTime = World->GetTimeSeconds();
|
||||||
|
Result.RealTime = World->GetRealTimeSeconds();
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
|
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||||
// #include "Kismet/KismetSystemLibrary.h"
|
// #include "Kismet/KismetSystemLibrary.h"
|
||||||
// #include "CommonTypes.h"
|
// #include "CommonTypes.h"
|
||||||
// #include "Kismet/BlueprintFunctionLibrary.h"
|
|
||||||
|
|
||||||
#include "ScriptedAnimation.generated.h"
|
#include "ScriptedAnimation.generated.h"
|
||||||
|
|
||||||
@@ -12,6 +12,18 @@ class UEnhancedInputLocalPlayerSubsystem;
|
|||||||
class UAnimSequenceBase;
|
class UAnimSequenceBase;
|
||||||
|
|
||||||
|
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct INTEGRATION_API FlxWorldClocks
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||||
|
double WorldTime = 0.0;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||||
|
double RealTime = 0.0;
|
||||||
|
};
|
||||||
|
|
||||||
USTRUCT(BlueprintType)
|
USTRUCT(BlueprintType)
|
||||||
struct INTEGRATION_API FlxScriptedAnimation
|
struct INTEGRATION_API FlxScriptedAnimation
|
||||||
{
|
{
|
||||||
@@ -20,13 +32,16 @@ struct INTEGRATION_API FlxScriptedAnimation
|
|||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||||
UAnimSequenceBase *Sequence = nullptr;
|
UAnimSequenceBase *Sequence = nullptr;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay)
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||||
int64 AqHash = 0;
|
bool ContinueWhenPaused = false;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay)
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||||
|
int64 AnimationStepID = 0;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||||
double FadeInDuration = 0.0;
|
double FadeInDuration = 0.0;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay)
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||||
double FadeOutDuration = 0.0;
|
double FadeOutDuration = 0.0;
|
||||||
|
|
||||||
// StartTime and EndTime.
|
// StartTime and EndTime.
|
||||||
@@ -38,55 +53,94 @@ struct INTEGRATION_API FlxScriptedAnimation
|
|||||||
// may be reduced to implement the truncation.
|
// may be reduced to implement the truncation.
|
||||||
//
|
//
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay)
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||||
double StartTime = 0.0;
|
double StartTime = 0.0;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay)
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||||
double EndTime = 0.0;
|
double EndTime = 0.0;
|
||||||
|
|
||||||
// Calculate the progress of a fade.
|
// Calculate the progress of a fade.
|
||||||
//
|
//
|
||||||
static double CalculateFade(double Offset, double Fade);
|
inline static double CalculateFade(double Offset, double Fade)
|
||||||
|
{
|
||||||
|
if (Offset < 0.0)
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
if (Fade > 0.001)
|
||||||
|
{
|
||||||
|
return FMath::Min(Offset / Fade, 1.0);
|
||||||
|
}
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given an FGameTime, extract the correct clock to use for this animation.
|
||||||
|
//
|
||||||
|
inline double ChooseCorrectClock(const FlxWorldClocks &WorldClocks) const
|
||||||
|
{
|
||||||
|
return ContinueWhenPaused ? WorldClocks.RealTime : WorldClocks.WorldTime;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate Elapsed Time (unclamped)
|
// Calculate Elapsed Time (unclamped)
|
||||||
//
|
//
|
||||||
// If current time is before the animation's start time, then
|
// If current time is before the animation's start time, then
|
||||||
// elapsed time will be negative.
|
// elapsed time will be negative.
|
||||||
//
|
//
|
||||||
double UnclampedElapsedTime(double CurrentTime) const;
|
inline double UnclampedElapsedTime(double CurrentTime) const
|
||||||
|
{
|
||||||
|
return CurrentTime - StartTime;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate Time Left (unclamped)
|
// Calculate Time Left (unclamped)
|
||||||
//
|
//
|
||||||
// If current time is after the animation's end time, then
|
// If current time is after the animation's end time, then
|
||||||
// time left will be negative.
|
// time left will be negative.
|
||||||
//
|
//
|
||||||
double UnclampedTimeLeft(double CurrentTime) const;
|
inline double UnclampedTimeLeft(double CurrentTime) const
|
||||||
|
{
|
||||||
|
return EndTime - CurrentTime;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate Elapsed Time (clamped)
|
// Calculate Elapsed Time (clamped)
|
||||||
//
|
//
|
||||||
// If current time is before the animation's start time, then
|
// If current time is before the animation's start time, then
|
||||||
// elapsed time will be zero.
|
// elapsed time will be zero.
|
||||||
//
|
//
|
||||||
double ClampedElapsedTime(double CurrentTime) const;
|
inline double ClampedElapsedTime(double CurrentTime) const
|
||||||
|
{
|
||||||
|
return FMath::Max(0.0, CurrentTime - StartTime);
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate Time Left (clamped)
|
// Calculate Time Left (clamped)
|
||||||
//
|
//
|
||||||
// If current time is after the animation's end time, then
|
// If current time is after the animation's end time, then
|
||||||
// time left will be zero.
|
// time left will be zero.
|
||||||
//
|
//
|
||||||
double ClampedTimeLeft(double CurrentTime) const;
|
inline double ClampedTimeLeft(double CurrentTime) const
|
||||||
|
{
|
||||||
|
return FMath::Max(0.0, EndTime - CurrentTime);
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the progress of the fadein.
|
// Calculate the progress of the fadein.
|
||||||
//
|
//
|
||||||
double CalcFadeInAlpha(double CurrentTime) const;
|
inline double CalcFadeInAlpha(double CurrentTime) const
|
||||||
|
{
|
||||||
|
return CalculateFade(UnclampedElapsedTime(CurrentTime), FadeInDuration);
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the progress of the fadeout.
|
// Calculate the progress of the fadeout.
|
||||||
//
|
//
|
||||||
double CalcFadeOutAlpha(double CurrentTime) const;
|
inline double CalcFadeOutAlpha(double CurrentTime) const
|
||||||
|
{
|
||||||
|
return CalculateFade(UnclampedTimeLeft(CurrentTime), FadeOutDuration);
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the combined alpha of the fade-in-out.
|
// Calculate the combined alpha of the fade-in-out.
|
||||||
//
|
//
|
||||||
double CalcFadeInOutAlpha(double CurrentTime) const;
|
inline double CalcFadeInOutAlpha(double CurrentTime) const
|
||||||
|
{
|
||||||
|
return FMath::Min(CalcFadeInAlpha(CurrentTime), CalcFadeOutAlpha(CurrentTime));
|
||||||
|
}
|
||||||
|
|
||||||
// Cause an animation to start fading right away.
|
// Cause an animation to start fading right away.
|
||||||
//
|
//
|
||||||
@@ -130,25 +184,38 @@ public:
|
|||||||
// in the array is always the most recent. All other steps are shifted
|
// in the array is always the most recent. All other steps are shifted
|
||||||
// back. If the array size exceeds the KeepCount, it is truncated.
|
// back. If the array size exceeds the KeepCount, it is truncated.
|
||||||
//
|
//
|
||||||
// The Aq Hash parameter can be used to associate a scripted animation
|
// The AnimationStepID parameter can be used to associate a scripted
|
||||||
// with a step in the animation queue. This makes it feasible to garbage
|
// animation with a step in the animation queue. Typically, you would
|
||||||
// collect the scripted animation if the animation queue step disappears.
|
// set the scripted animation ID equal to the animation queue step ID.
|
||||||
|
// This makes it feasible to garbage collect the scripted animation
|
||||||
|
// if the animation queue step disappears.
|
||||||
|
//
|
||||||
|
// If 'ContinueWhenPaused' is true, then the animation keeps playing
|
||||||
|
// even when the game is paused. Otherwise, it freezes when the game
|
||||||
|
// is paused.
|
||||||
//
|
//
|
||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Scripted Animations", meta=(WorldContext = "WorldContextObject"))
|
UFUNCTION(BlueprintCallable, Category = "Luprex|Scripted Animations", meta=(WorldContext = "WorldContextObject"))
|
||||||
void AddAnimation(
|
void AddAnimation(
|
||||||
UObject *WorldContextObject, UAnimSequenceBase* Sequence, double FadeInTime = 0.2, double FadeOutTime = 0.2, int64 AqHash=0);
|
UObject *WorldContextObject, UAnimSequenceBase* Sequence, double FadeInTime = 0.2, double FadeOutTime = 0.2,
|
||||||
|
int64 AnimationStepID=0, bool ContinueWhenPaused=false);
|
||||||
|
|
||||||
// Fade animations whose corresponding animation queue step is dead.
|
// Fade all animations whose IDs are not in the 'Keep' list.
|
||||||
//
|
//
|
||||||
// Sometimes, predictive reexecution causes an animation step to
|
// Sometimes, predictive reexecution causes an animation step to
|
||||||
// vanish from the animation queue. When that happens, it is usually
|
// vanish from the animation queue. When that happens, it is
|
||||||
// desirable to terminate any scripted animations that were launched
|
// desirable to terminate any scripted animations that were launched
|
||||||
// by that animation step. You don't want to cut them off abruptly,
|
// by that animation step. You don't want to cut them off abruptly,
|
||||||
// you want to fade them out. This function causes all animations that
|
// you want to fade them out.
|
||||||
// are owned by a dead animation step to begin fading.
|
|
||||||
//
|
//
|
||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Scripted Animations", meta=(WorldContext = "WorldContextObject"))
|
// Whenever luprex calls 'Animation Queue Changed' in a blueprint,
|
||||||
void FadeGarbage(TArray<int32> Hashes, double CurrentTime);
|
// it also automatically runs this garbage collection routine on the
|
||||||
|
// scripted animations.
|
||||||
|
//
|
||||||
|
// Scripted animations with nonpositive IDs are immune to garbage
|
||||||
|
// collection. So if you want an animation step to be not affected,
|
||||||
|
// give it an ID of zero or a negative number.
|
||||||
|
//
|
||||||
|
void FadeGarbage(const UObject *WorldContextObject, TArray<int64> KeepIDs);
|
||||||
};
|
};
|
||||||
|
|
||||||
UCLASS()
|
UCLASS()
|
||||||
@@ -156,10 +223,12 @@ class INTEGRATION_API UlxScriptedAnimationLibrary : public UBlueprintFunctionLib
|
|||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// Get all the major 'World Clocks' in a single struct.
|
||||||
|
//
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Utilities|Time", meta=(WorldContext = "WorldContextObject"))
|
||||||
|
static FlxWorldClocks GetAllWorldClocks(const UObject *WorldContextObject);
|
||||||
|
|
||||||
// Get the data to drive Sequence Evaluators and Multi Blend
|
// Get the data to drive Sequence Evaluators and Multi Blend
|
||||||
//
|
//
|
||||||
// To apply scripted animations in an Anim Graph, you will need
|
// To apply scripted animations in an Anim Graph, you will need
|
||||||
@@ -167,7 +236,8 @@ public:
|
|||||||
// function outputs the input parameters for all of those nodes.
|
// function outputs the input parameters for all of those nodes.
|
||||||
//
|
//
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Scripted Animations", meta=(BlueprintThreadSafe))
|
UFUNCTION(BlueprintPure, Category = "Luprex|Scripted Animations", meta=(BlueprintThreadSafe))
|
||||||
static void ScriptedAnimationEvaluatorData(const UlxScriptedAnimations *Animations, double CurrentTime,
|
static void ScriptedAnimationEvaluatorData(const UlxScriptedAnimations *Animations,
|
||||||
|
const FlxWorldClocks &WorldClocks,
|
||||||
UAnimSequenceBase *&Sequence0, float &ExplicitTime0,
|
UAnimSequenceBase *&Sequence0, float &ExplicitTime0,
|
||||||
UAnimSequenceBase *&Sequence1, float &ExplicitTime1,
|
UAnimSequenceBase *&Sequence1, float &ExplicitTime1,
|
||||||
UAnimSequenceBase *&Sequence2, float &ExplicitTime2,
|
UAnimSequenceBase *&Sequence2, float &ExplicitTime2,
|
||||||
|
|||||||
@@ -123,7 +123,8 @@ void UlxTangible::MaybeExecuteAnimStateChanged() {
|
|||||||
|
|
||||||
bool AnyChange = AnimTracker.IsChanged();
|
bool AnyChange = AnimTracker.IsChanged();
|
||||||
|
|
||||||
while (AnimTracker.IsChanged()) {
|
while (AnimTracker.IsChanged())
|
||||||
|
{
|
||||||
if (limit == 0) break;
|
if (limit == 0) break;
|
||||||
limit -= 1;
|
limit -= 1;
|
||||||
AnimTracker.ClearChanged();
|
AnimTracker.ClearChanged();
|
||||||
@@ -164,11 +165,22 @@ void UlxTangible::MaybeExecuteAnimStateChanged() {
|
|||||||
FString DS = UlxAnimationStepLibrary::AnimationStepDebugString(*Step);
|
FString DS = UlxAnimationStepLibrary::AnimationStepDebugString(*Step);
|
||||||
UE_LOG(LogLuprex, Warning, TEXT("Timeout - blueprint didn't finish animation: %s"), *DS);
|
UE_LOG(LogLuprex, Warning, TEXT("Timeout - blueprint didn't finish animation: %s"), *DS);
|
||||||
AnimTracker.FinishedAnimation(PendingAnimationHash);
|
AnimTracker.FinishedAnimation(PendingAnimationHash);
|
||||||
|
AnyChange = true;
|
||||||
}
|
}
|
||||||
AutoUpdatePosition();
|
AutoUpdatePosition();
|
||||||
PendingAnimationHash = 0;
|
PendingAnimationHash = 0;
|
||||||
PendingAnimationTimeout = 0.0;
|
PendingAnimationTimeout = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The following code garbage collects any scripted animations that
|
||||||
|
// were created by animation steps that are no longer in the animation
|
||||||
|
// queue. This is intended to handle the case that predictive reexecution
|
||||||
|
// incorrectly predicts an animation step, and then the animation step
|
||||||
|
// goes away during of difference transmission.
|
||||||
|
if (AnyChange && (ScriptedAnimations != nullptr))
|
||||||
|
{
|
||||||
|
ScriptedAnimations->FadeGarbage(this, AnimTracker.GetHashes());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FVector UlxTangible::GetLocation() const
|
FVector UlxTangible::GetLocation() const
|
||||||
@@ -233,7 +245,8 @@ void UlxTangible::AutoUpdatePosition()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxTangible::FinishedAnimation(AActor *target, const FlxAnimationStep &step, bool AutoUpdate) {
|
void UlxTangible::FinishedAnimation(AActor *target, const FlxAnimationStep &step, bool AutoUpdate)
|
||||||
|
{
|
||||||
UlxTangible *tan = GetActorTangibleOrLog(target);
|
UlxTangible *tan = GetActorTangibleOrLog(target);
|
||||||
if (tan == nullptr) return;
|
if (tan == nullptr) return;
|
||||||
tan->AnimTracker.FinishedAnimation(step.Hash);
|
tan->AnimTracker.FinishedAnimation(step.Hash);
|
||||||
@@ -242,7 +255,8 @@ void UlxTangible::FinishedAnimation(AActor *target, const FlxAnimationStep &step
|
|||||||
UE_LOG(LogLuprex, Display, TEXT("Animation Finished: %s"), *DebugString);
|
UE_LOG(LogLuprex, Display, TEXT("Animation Finished: %s"), *DebugString);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UlxTangible::AnimationStepIsFinished(AActor *target, const FlxAnimationStep &step) {
|
bool UlxTangible::AnimationStepIsFinished(AActor *target, const FlxAnimationStep &step)
|
||||||
|
{
|
||||||
UlxTangible *tan = GetActorTangibleOrLog(target);
|
UlxTangible *tan = GetActorTangibleOrLog(target);
|
||||||
if (tan == nullptr) return true;
|
if (tan == nullptr) return true;
|
||||||
return tan->AnimTracker.IsFinished(step.Hash);
|
return tan->AnimTracker.IsFinished(step.Hash);
|
||||||
|
|||||||
Reference in New Issue
Block a user