You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Fixed issue with sync group collisions when syncing with 'component' scope This change moves sync group management to use a name->group map instead of indices. Staying with indices cannot work across multiple instances as they are simply allocated at the point the single anim BP is compiled, so can easily collide in anything other than simple configurations. Deprecated all index based access to sync groups in the runtime. Sync groups can still be enumerated on the generated class. #jira UE-101030 - Sync groups with non-local scope can collide, causing incorrect behaviour #rb Martin.Wilson,Jurre.deBaare [CL 14521985 by Thomas Sarkanen in ue5-main branch]
127 lines
4.0 KiB
C++
127 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->GetPlayLength() : 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->GetPlayLength());
|
|
|
|
if ((!bTeleportToExplicitTime || (GroupName != NAME_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->GetPlayLength());
|
|
}
|
|
|
|
float TimeJump = ExplicitTime - InternalTimeAccumulator;
|
|
if (bShouldLoop)
|
|
{
|
|
if (FMath::Abs(TimeJump) > (Sequence->GetPlayLength() * 0.5f))
|
|
{
|
|
if (TimeJump > 0.f)
|
|
{
|
|
TimeJump -= Sequence->GetPlayLength();
|
|
}
|
|
else
|
|
{
|
|
TimeJump += Sequence->GetPlayLength();
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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())))
|
|
{
|
|
FAnimationPoseData AnimationPoseData(Output);
|
|
Sequence->GetAnimationPose(AnimationPoseData, 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);
|
|
}
|