Files
UnrealEngineUWP/Engine/Source/Runtime/AnimGraphRuntime/Private/AnimNodes/AnimNode_SequenceEvaluator.cpp
Thomas Sarkanen 1dee2903c0 Added schematic view of animation graphs
Initial basic implementation, more features to follow.
Accessed via the context menu of a graph track.
Shows anim graph nodes in a linearized tree similar to ShowDebug ANIMATION.
Select a node to 'pin' all the properties that it traced (multi select supported) to the bottom of the window.
Scrub the timeline to see those properties change over time.
Asset references use clickable hyperlinks to go to the specified asset editor.

#rb Jurre.deBaare

[CL 11041140 by Thomas Sarkanen in Dev-Core branch]
2020-01-17 03:32:34 -05:00

126 lines
4.0 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "AnimNodes/AnimNode_SequenceEvaluator.h"
#include "Animation/AnimInstanceProxy.h"
#include "Animation/AnimTrace.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)
{
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(Initialize_AnyThread)
FAnimNode_AssetPlayerBase::Initialize_AnyThread(Context);
bReinitialized = true;
}
void FAnimNode_SequenceEvaluator::CacheBones_AnyThread(const FAnimationCacheBonesContext& Context)
{
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(CacheBones_AnyThread)
}
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;
TRACE_ANIM_NODE_VALUE(Context, TEXT("Name"), Sequence != nullptr ? Sequence->GetFName() : NAME_None);
TRACE_ANIM_NODE_VALUE(Context, TEXT("Sequence"), Sequence);
TRACE_ANIM_NODE_VALUE(Context, TEXT("InputTime"), ExplicitTime);
TRACE_ANIM_NODE_VALUE(Context, TEXT("Time"), InternalTimeAccumulator);
}
void FAnimNode_SequenceEvaluator::Evaluate_AnyThread(FPoseContext& Output)
{
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(Evaluate_AnyThread)
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)
{
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(GatherDebugData)
FString DebugLine = DebugData.GetNodeName(this);
DebugLine += FString::Printf(TEXT("('%s' InputTime: %.3f, Time: %.3f)"), *GetNameSafe(Sequence), ExplicitTime, InternalTimeAccumulator);
DebugData.AddDebugItem(DebugLine, true);
}