Files
UnrealEngineUWP/Engine/Source/Runtime/AnimGraphRuntime/Private/AnimNodes/AnimNode_SequenceEvaluator.cpp
max chen 5cb47f6cf5 Jittery Sequencer Animations with RateScale > 0.0
Two changes fixed this. First we invert out the RateScale when calculating the PlayRate inside  FAnimNode_SequenceEvaluator::UpdateAssetPlayer, since it get's multiplied back in the CreateTickRecordForNode function.   This stops the jittering but the animation playback isn't scaled. To fix that we modify the Sequencer sections PlayRate by the asset'ss RateScale.

#jira UE-63636
#rb max.chen, martin.wilson

#ROBOMERGE-OWNER: ryan.vance
#ROBOMERGE-AUTHOR: max.chen
#ROBOMERGE-SOURCE: CL 4896912 in //UE4/Release-4.22/... via CL 4896913
#ROBOMERGE-BOT: DEVVR (Main -> Dev-VR)

[CL 4912523 by max chen in Dev-VR branch]
2019-02-05 18:49:16 -05:00

116 lines
3.4 KiB
C++

// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "AnimNodes/AnimNode_SequenceEvaluator.h"
#include "Animation/AnimInstanceProxy.h"
float FAnimNode_SequenceEvaluator::GetCurrentAssetTime()
{
return ExplicitTime;
}
float FAnimNode_SequenceEvaluator::GetCurrentAssetLength()
{
return Sequence ? Sequence->SequenceLength : 0.0f;
}
/////////////////////////////////////////////////////
// FAnimSequenceEvaluatorNode
void FAnimNode_SequenceEvaluator::Initialize_AnyThread(const FAnimationInitializeContext& Context)
{
FAnimNode_AssetPlayerBase::Initialize_AnyThread(Context);
bReinitialized = true;
}
void FAnimNode_SequenceEvaluator::CacheBones_AnyThread(const FAnimationCacheBonesContext& Context)
{
}
void FAnimNode_SequenceEvaluator::UpdateAssetPlayer(const FAnimationUpdateContext& Context)
{
GetEvaluateGraphExposedInputs().Execute(Context);
if (Sequence)
{
// Clamp input to a valid position on this sequence's time line.
ExplicitTime = FMath::Clamp(ExplicitTime, 0.f, Sequence->SequenceLength);
if ((!bTeleportToExplicitTime || (GroupIndex != INDEX_NONE)) && (Context.AnimInstanceProxy->IsSkeletonCompatible(Sequence->GetSkeleton())))
{
if (bReinitialized)
{
switch (ReinitializationBehavior)
{
case ESequenceEvalReinit::StartPosition: InternalTimeAccumulator = StartPosition; break;
case ESequenceEvalReinit::ExplicitTime: InternalTimeAccumulator = ExplicitTime; break;
}
InternalTimeAccumulator = FMath::Clamp(InternalTimeAccumulator, 0.f, Sequence->SequenceLength);
}
float TimeJump = ExplicitTime - InternalTimeAccumulator;
if (bShouldLoop)
{
if (FMath::Abs(TimeJump) > (Sequence->SequenceLength * 0.5f))
{
if (TimeJump > 0.f)
{
TimeJump -= Sequence->SequenceLength;
}
else
{
TimeJump += Sequence->SequenceLength;
}
}
}
// if you jump from front to end or end to front, your time jump is 0.f, so nothing moves
// to prevent that from happening, we set current accumulator to explicit time
if (TimeJump == 0.f)
{
InternalTimeAccumulator = ExplicitTime;
}
const float DeltaTime = Context.GetDeltaTime();
const float RateScale = Sequence->RateScale;
const float PlayRate = FMath::IsNearlyZero(DeltaTime) || FMath::IsNearlyZero(RateScale) ? 0.f : (TimeJump / (DeltaTime * RateScale));
CreateTickRecordForNode(Context, Sequence, bShouldLoop, PlayRate);
}
else
{
InternalTimeAccumulator = ExplicitTime;
}
}
bReinitialized = false;
}
void FAnimNode_SequenceEvaluator::Evaluate_AnyThread(FPoseContext& Output)
{
check(Output.AnimInstanceProxy != nullptr);
if ((Sequence != nullptr) && (Output.AnimInstanceProxy->IsSkeletonCompatible(Sequence->GetSkeleton())))
{
Sequence->GetAnimationPose(Output.Pose, Output.Curve, FAnimExtractContext(InternalTimeAccumulator, Output.AnimInstanceProxy->ShouldExtractRootMotion()));
}
else
{
Output.ResetToRefPose();
}
}
void FAnimNode_SequenceEvaluator::OverrideAsset(UAnimationAsset* NewAsset)
{
if(UAnimSequenceBase* NewSequence = Cast<UAnimSequenceBase>(NewAsset))
{
Sequence = NewSequence;
}
}
void FAnimNode_SequenceEvaluator::GatherDebugData(FNodeDebugData& DebugData)
{
FString DebugLine = DebugData.GetNodeName(this);
DebugLine += FString::Printf(TEXT("('%s' InputTime: %.3f, Time: %.3f)"), *GetNameSafe(Sequence), ExplicitTime, InternalTimeAccumulator);
DebugData.AddDebugItem(DebugLine, true);
}