You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
208 lines
5.8 KiB
C++
208 lines
5.8 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "AnimNodes/AnimNode_BlendSpacePlayer.h"
|
|
#include "Animation/BlendSpaceBase.h"
|
|
#include "Animation/AnimSequence.h"
|
|
#include "Animation/AnimInstanceProxy.h"
|
|
#include "AnimGraphRuntimeTrace.h"
|
|
#include "Animation/AnimSync.h"
|
|
#include "Animation/AnimSyncScope.h"
|
|
|
|
/////////////////////////////////////////////////////
|
|
// FAnimNode_BlendSpacePlayer
|
|
|
|
FAnimNode_BlendSpacePlayer::FAnimNode_BlendSpacePlayer()
|
|
: X(0.0f)
|
|
, Y(0.0f)
|
|
, Z(0.0f)
|
|
, PlayRate(1.0f)
|
|
, bLoop(true)
|
|
, bResetPlayTimeWhenBlendSpaceChanges(true)
|
|
, StartPosition(0.f)
|
|
, BlendSpace(nullptr)
|
|
, PreviousBlendSpace(nullptr)
|
|
{
|
|
}
|
|
|
|
float FAnimNode_BlendSpacePlayer::GetCurrentAssetTime()
|
|
{
|
|
if(const FBlendSampleData* HighestWeightedSample = GetHighestWeightedSample())
|
|
{
|
|
return HighestWeightedSample->Time;
|
|
}
|
|
|
|
// No sample
|
|
return 0.0f;
|
|
}
|
|
|
|
float FAnimNode_BlendSpacePlayer::GetCurrentAssetTimePlayRateAdjusted()
|
|
{
|
|
float Length = GetCurrentAssetLength();
|
|
return PlayRate < 0.0f ? Length - InternalTimeAccumulator * Length : Length * InternalTimeAccumulator;
|
|
}
|
|
|
|
float FAnimNode_BlendSpacePlayer::GetCurrentAssetLength()
|
|
{
|
|
if(const FBlendSampleData* HighestWeightedSample = GetHighestWeightedSample())
|
|
{
|
|
if (BlendSpace != nullptr)
|
|
{
|
|
const FBlendSample& Sample = BlendSpace->GetBlendSample(HighestWeightedSample->SampleDataIndex);
|
|
return Sample.Animation->GetPlayLength();
|
|
}
|
|
}
|
|
|
|
// No sample
|
|
return 0.0f;
|
|
}
|
|
|
|
void FAnimNode_BlendSpacePlayer::Initialize_AnyThread(const FAnimationInitializeContext& Context)
|
|
{
|
|
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(Initialize_AnyThread)
|
|
FAnimNode_AssetPlayerBase::Initialize_AnyThread(Context);
|
|
|
|
GetEvaluateGraphExposedInputs().Execute(Context);
|
|
|
|
Reinitialize();
|
|
|
|
PreviousBlendSpace = BlendSpace;
|
|
}
|
|
|
|
void FAnimNode_BlendSpacePlayer::CacheBones_AnyThread(const FAnimationCacheBonesContext& Context)
|
|
{
|
|
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(CacheBones_AnyThread)
|
|
}
|
|
|
|
void FAnimNode_BlendSpacePlayer::UpdateAssetPlayer(const FAnimationUpdateContext& Context)
|
|
{
|
|
GetEvaluateGraphExposedInputs().Execute(Context);
|
|
|
|
UpdateInternal(Context);
|
|
}
|
|
|
|
void FAnimNode_BlendSpacePlayer::UpdateInternal(const FAnimationUpdateContext& Context)
|
|
{
|
|
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(UpdateInternal)
|
|
if ((BlendSpace != nullptr) && (Context.AnimInstanceProxy->IsSkeletonCompatible(BlendSpace->GetSkeleton())))
|
|
{
|
|
if (PreviousBlendSpace != BlendSpace)
|
|
{
|
|
Reinitialize(bResetPlayTimeWhenBlendSpaceChanges);
|
|
}
|
|
|
|
const FVector Position(X, Y, Z);
|
|
|
|
// Create a tick record and push into the closest scope
|
|
UE::Anim::FAnimSyncGroupScope& SyncScope = Context.GetMessageChecked<UE::Anim::FAnimSyncGroupScope>();
|
|
|
|
FAnimTickRecord TickRecord(BlendSpace, Position, BlendSampleDataCache, BlendFilter, bLoop, PlayRate, Context.GetFinalBlendWeight(), /*inout*/ InternalTimeAccumulator, MarkerTickRecord);
|
|
TickRecord.RootMotionWeightModifier = Context.GetRootMotionWeightModifier();
|
|
UE::Anim::FAnimSyncParams SyncParams(GroupName, GroupRole, Method);
|
|
|
|
SyncScope.AddTickRecord(TickRecord, SyncParams, UE::Anim::FAnimSyncDebugInfo(Context));
|
|
|
|
TRACE_ANIM_TICK_RECORD(Context, TickRecord);
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
if (FAnimBlueprintDebugData* DebugData = Context.AnimInstanceProxy->GetAnimBlueprintDebugData())
|
|
{
|
|
DebugData->RecordBlendSpacePlayer(Context.GetCurrentNodeId(), BlendSpace, Position, BlendFilter.GetFilterLastOutput());
|
|
}
|
|
#endif
|
|
|
|
PreviousBlendSpace = BlendSpace;
|
|
}
|
|
|
|
TRACE_BLENDSPACE_PLAYER(Context, *this);
|
|
TRACE_ANIM_NODE_VALUE(Context, TEXT("Name"), BlendSpace ? *BlendSpace->GetName() : TEXT("None"));
|
|
TRACE_ANIM_NODE_VALUE(Context, TEXT("Blend Space"), BlendSpace);
|
|
TRACE_ANIM_NODE_VALUE(Context, TEXT("Playback Time"), InternalTimeAccumulator);
|
|
}
|
|
|
|
void FAnimNode_BlendSpacePlayer::Evaluate_AnyThread(FPoseContext& Output)
|
|
{
|
|
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(Evaluate_AnyThread)
|
|
if ((BlendSpace != nullptr) && (Output.AnimInstanceProxy->IsSkeletonCompatible(BlendSpace->GetSkeleton())))
|
|
{
|
|
FAnimationPoseData AnimationPoseData(Output);
|
|
BlendSpace->GetAnimationPose(BlendSampleDataCache, AnimationPoseData);
|
|
}
|
|
else
|
|
{
|
|
Output.ResetToRefPose();
|
|
}
|
|
}
|
|
|
|
void FAnimNode_BlendSpacePlayer::OverrideAsset(UAnimationAsset* NewAsset)
|
|
{
|
|
if(UBlendSpaceBase* NewBlendSpace = Cast<UBlendSpaceBase>(NewAsset))
|
|
{
|
|
BlendSpace = NewBlendSpace;
|
|
}
|
|
}
|
|
|
|
void FAnimNode_BlendSpacePlayer::GatherDebugData(FNodeDebugData& DebugData)
|
|
{
|
|
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(GatherDebugData)
|
|
FString DebugLine = DebugData.GetNodeName(this);
|
|
if (BlendSpace)
|
|
{
|
|
DebugLine += FString::Printf(TEXT("('%s' Play Time: %.3f)"), *BlendSpace->GetName(), InternalTimeAccumulator);
|
|
|
|
DebugData.AddDebugItem(DebugLine, true);
|
|
|
|
//BlendSpace->GetBlendSamples();
|
|
}
|
|
}
|
|
|
|
float FAnimNode_BlendSpacePlayer::GetTimeFromEnd(float CurrentTime)
|
|
{
|
|
// Blend-spaces use normalized time value
|
|
const float PlayLength = 1.0f;
|
|
return BlendSpace != nullptr ? PlayLength - CurrentTime : 0.0f;
|
|
}
|
|
|
|
UAnimationAsset* FAnimNode_BlendSpacePlayer::GetAnimAsset()
|
|
{
|
|
return BlendSpace;
|
|
}
|
|
|
|
const FBlendSampleData* FAnimNode_BlendSpacePlayer::GetHighestWeightedSample() const
|
|
{
|
|
if(BlendSampleDataCache.Num() == 0)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
const FBlendSampleData* HighestSample = &BlendSampleDataCache[0];
|
|
|
|
for(int32 Idx = 1; Idx < BlendSampleDataCache.Num(); ++Idx)
|
|
{
|
|
if(BlendSampleDataCache[Idx].TotalWeight > HighestSample->TotalWeight)
|
|
{
|
|
HighestSample = &BlendSampleDataCache[Idx];
|
|
}
|
|
}
|
|
|
|
return HighestSample;
|
|
}
|
|
|
|
void FAnimNode_BlendSpacePlayer::Reinitialize(bool bResetTime)
|
|
{
|
|
BlendSampleDataCache.Empty();
|
|
if(bResetTime)
|
|
{
|
|
InternalTimeAccumulator = FMath::Clamp(StartPosition, 0.f, 1.0f);
|
|
if (StartPosition == 0.f && PlayRate < 0.0f)
|
|
{
|
|
// Blend spaces run between 0 and 1
|
|
InternalTimeAccumulator = 1.0f;
|
|
}
|
|
}
|
|
|
|
if (BlendSpace != nullptr)
|
|
{
|
|
BlendSpace->InitializeFilter(&BlendFilter);
|
|
}
|
|
}
|