#include "ScriptedAnimation.h" #include "Engine/Engine.h" #include "Animation/AnimSequenceBase.h" void FlxScriptedAnimation::InitiateFadeOut(double CurrentTime, double AllowedFade) { // We only need to truncate if we aren't already fading out, // or if the in-progress fadeout isn't sufficiently fast. // double FadeOutAlpha = CalcFadeOutAlpha(CurrentTime); if ((FadeOutAlpha >= 1.0) || (FadeOutDuration > AllowedFade)) { double CurrentAlpha = FMath::Min(CalcFadeInAlpha(CurrentTime), FadeOutAlpha); double NewFadeOutDuration = FMath::Min(AllowedFade, FadeOutDuration); double NewTimeLeft = NewFadeOutDuration * CurrentAlpha; EndTime = CurrentTime + NewTimeLeft; FadeOutDuration = NewFadeOutDuration; } } void UlxScriptedAnimations::Keep(int n) { if (n < 0) n = 0; if (Animations.Num() > n) { Animations.SetNum(n); } } void UlxScriptedAnimations::AddAnimation( UObject* WorldContextObject, UAnimSequenceBase* Sequence, double FadeInTime, double FadeOutTime, int64 AnimationStepID, bool ContinueWhenPaused) { check(KeepCount >= 1); FlxScriptedAnimation Result; // Get World Time FlxWorldClocks Clocks = UlxScriptedAnimationLibrary::GetAllWorldClocks(WorldContextObject); double CurrentTime = ContinueWhenPaused ? Clocks.RealTime : Clocks.WorldTime; // Get the animation Length. double Length = (Sequence ? static_cast(Sequence->GetPlayLength()) : 0.0); // Fill the static setup fields Result.Sequence = Sequence; Result.ContinueWhenPaused = ContinueWhenPaused; Result.AnimationStepID = AnimationStepID; Result.FadeInDuration = FadeInTime; Result.FadeOutDuration = FadeOutTime; Result.StartTime = CurrentTime; Result.EndTime = CurrentTime + Length; Keep(KeepCount - 1); Animations.Insert(Result, 0); } double UlxScriptedAnimations::CalculateTimeLeft(UObject *WorldContextObject, int64 AnimationID) { double max = 0.0; FlxWorldClocks Clocks = UlxScriptedAnimationLibrary::GetAllWorldClocks(WorldContextObject); for (int i = 0; i < Animations.Num(); i++) { const FlxScriptedAnimation &Anim = Animations[i]; if (Anim.AnimationStepID == AnimationID) { double Current = Anim.ChooseCorrectClock(Clocks); double TimeLeft = Anim.ClampedTimeLeft(Current); if (TimeLeft > max) max = TimeLeft; } } return max; } void UlxScriptedAnimations::FadeGarbage(const UObject *WorldContextObject, TArray KeepIDs) { FlxWorldClocks Clocks = UlxScriptedAnimationLibrary::GetAllWorldClocks(WorldContextObject); for (int i = 0; i < Animations.Num(); i++) { FlxScriptedAnimation &Anim = Animations[i]; if ((Anim.AnimationStepID > 0) && (!KeepIDs.Contains(Anim.AnimationStepID))) { Anim.InitiateFadeOut(Anim.ChooseCorrectClock(Clocks), 0.2); } } } void UlxScriptedAnimationLibrary::ScriptedAnimationEvaluatorData( const UlxScriptedAnimations *Animations, const FlxWorldClocks &WorldClocks, UAnimSequenceBase *&Sequence0, float &ExplicitTime0, UAnimSequenceBase *&Sequence1, float &ExplicitTime1, UAnimSequenceBase *&Sequence2, float &ExplicitTime2, float &BaseAlpha, float &Sequence0Alpha, float &Sequence1Alpha, float &Sequence2Alpha) { Sequence0 = nullptr; Sequence1 = nullptr; Sequence2 = nullptr; ExplicitTime0 = 0.0; ExplicitTime1 = 0.0; ExplicitTime2 = 0.0; BaseAlpha = 0.0; Sequence0Alpha = 0.0; Sequence1Alpha = 0.0; Sequence2Alpha = 0.0; if (Animations != nullptr) { const TArray &Anims = Animations->GetAnimations(); if (Anims.Num() > 0) { const FlxScriptedAnimation &Anim = Anims[0]; double CurrentTime = Anim.ChooseCorrectClock(WorldClocks); Sequence0 = Anim.Sequence; ExplicitTime0 = Anim.ClampedElapsedTime(CurrentTime); Sequence0Alpha = Anim.CalcFadeInOutAlpha(CurrentTime); } if (Anims.Num() > 1) { const FlxScriptedAnimation &Anim = Anims[1]; double CurrentTime = Anim.ChooseCorrectClock(WorldClocks); Sequence1 = Anim.Sequence; ExplicitTime1 = Anim.ClampedElapsedTime(CurrentTime); Sequence1Alpha = Anim.CalcFadeInOutAlpha(CurrentTime); } if (Anims.Num() > 2) { const FlxScriptedAnimation &Anim = Anims[2]; double CurrentTime = Anim.ChooseCorrectClock(WorldClocks); Sequence2 = Anim.Sequence; ExplicitTime2 = Anim.ClampedElapsedTime(CurrentTime); Sequence2Alpha = Anim.CalcFadeInOutAlpha(CurrentTime); } } double AlphaTotal = Sequence0Alpha + Sequence1Alpha + Sequence2Alpha; if (AlphaTotal > 1.0) { double Scale = 1.0 / AlphaTotal; Sequence0Alpha *= Scale; Sequence1Alpha *= Scale; Sequence2Alpha *= Scale; BaseAlpha = 0.0; } else { BaseAlpha = 1.0 - AlphaTotal; } } 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; }