You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
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]
116 lines
4.2 KiB
C++
116 lines
4.2 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "AnimNodes/AnimNode_Slot.h"
|
|
#include "Animation/AnimInstanceProxy.h"
|
|
#include "Animation/AnimTrace.h"
|
|
|
|
/////////////////////////////////////////////////////
|
|
// FAnimNode_Slot
|
|
|
|
void FAnimNode_Slot::Initialize_AnyThread(const FAnimationInitializeContext& Context)
|
|
{
|
|
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(Initialize_AnyThread)
|
|
FAnimNode_Base::Initialize_AnyThread(Context);
|
|
|
|
Source.Initialize(Context);
|
|
WeightData.Reset();
|
|
|
|
// If this node has not already been registered with the AnimInstance, do it.
|
|
if (!SlotNodeInitializationCounter.IsSynchronized_Counter(Context.AnimInstanceProxy->GetSlotNodeInitializationCounter()))
|
|
{
|
|
SlotNodeInitializationCounter.SynchronizeWith(Context.AnimInstanceProxy->GetSlotNodeInitializationCounter());
|
|
Context.AnimInstanceProxy->RegisterSlotNodeWithAnimInstance(SlotName);
|
|
}
|
|
}
|
|
|
|
void FAnimNode_Slot::CacheBones_AnyThread(const FAnimationCacheBonesContext& Context)
|
|
{
|
|
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(CacheBones_AnyThread)
|
|
Source.CacheBones(Context);
|
|
}
|
|
|
|
void FAnimNode_Slot::Update_AnyThread(const FAnimationUpdateContext& Context)
|
|
{
|
|
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(Update_AnyThread)
|
|
// Update weights.
|
|
Context.AnimInstanceProxy->GetSlotWeight(SlotName, WeightData.SlotNodeWeight, WeightData.SourceWeight, WeightData.TotalNodeWeight);
|
|
|
|
// Update cache in AnimInstance.
|
|
Context.AnimInstanceProxy->UpdateSlotNodeWeight(SlotName, WeightData.SlotNodeWeight, Context.GetFinalBlendWeight());
|
|
|
|
const bool bUpdateSource = bAlwaysUpdateSourcePose || FAnimWeight::IsRelevant(WeightData.SourceWeight);
|
|
if (bUpdateSource)
|
|
{
|
|
const float SourceWeight = FMath::Max(FAnimWeight::GetSmallestRelevantWeight(), WeightData.SourceWeight);
|
|
Source.Update(Context.FractionalWeight(SourceWeight));
|
|
}
|
|
|
|
#if ANIM_TRACE_ENABLED
|
|
TRACE_ANIM_NODE_VALUE(Context, TEXT("Name"), SlotName);
|
|
TRACE_ANIM_NODE_VALUE(Context, TEXT("Slot Weight"), WeightData.SlotNodeWeight);
|
|
TRACE_ANIM_NODE_VALUE(Context, TEXT("Pose Source"), (WeightData.SourceWeight <= ZERO_ANIMWEIGHT_THRESH));
|
|
|
|
Context.AnimInstanceProxy->TraceMontageEvaluationData(Context, SlotName);
|
|
#endif
|
|
}
|
|
|
|
void FAnimNode_Slot::Evaluate_AnyThread(FPoseContext & Output)
|
|
{
|
|
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(Evaluate_AnyThread)
|
|
// If not playing a montage, just pass through
|
|
if (WeightData.SlotNodeWeight <= ZERO_ANIMWEIGHT_THRESH)
|
|
{
|
|
Source.Evaluate(Output);
|
|
}
|
|
else
|
|
{
|
|
FPoseContext SourceContext(Output);
|
|
if (WeightData.SourceWeight > ZERO_ANIMWEIGHT_THRESH)
|
|
{
|
|
Source.Evaluate(SourceContext);
|
|
}
|
|
|
|
Output.AnimInstanceProxy->SlotEvaluatePose(SlotName, SourceContext.Pose, SourceContext.Curve, WeightData.SourceWeight, Output.Pose, Output.Curve, WeightData.SlotNodeWeight, WeightData.TotalNodeWeight);
|
|
|
|
checkSlow(!Output.ContainsNaN());
|
|
checkSlow(Output.IsNormalized());
|
|
}
|
|
}
|
|
|
|
void FAnimNode_Slot::GatherDebugData(FNodeDebugData& DebugData)
|
|
{
|
|
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(GatherDebugData)
|
|
FString DebugLine = DebugData.GetNodeName(this);
|
|
DebugLine += FString::Printf(TEXT("(Slot Name: '%s' Weight:%.1f%%)"), *SlotName.ToString(), WeightData.SlotNodeWeight*100.f);
|
|
|
|
bool const bIsPoseSource = (WeightData.SourceWeight <= ZERO_ANIMWEIGHT_THRESH);
|
|
DebugData.AddDebugItem(DebugLine, bIsPoseSource);
|
|
Source.GatherDebugData(DebugData.BranchFlow(WeightData.SourceWeight));
|
|
|
|
for (FAnimMontageInstance* MontageInstance : DebugData.AnimInstance->MontageInstances)
|
|
{
|
|
if (MontageInstance->IsValid() && MontageInstance->Montage->IsValidSlot(SlotName))
|
|
{
|
|
if (const FAnimTrack* const Track = MontageInstance->Montage->GetAnimationData(SlotName))
|
|
{
|
|
if (const FAnimSegment* const Segment = Track->GetSegmentAtTime(MontageInstance->GetPosition()))
|
|
{
|
|
float CurrentAnimPos;
|
|
if (UAnimSequenceBase* Anim = Segment->GetAnimationData(MontageInstance->GetPosition(), CurrentAnimPos))
|
|
{
|
|
FString MontageLine = FString::Printf(TEXT("Montage('%s') Anim('%s') P(%.2f) W(%.0f%%)"), *MontageInstance->Montage->GetName(), *Anim->GetName(), CurrentAnimPos, WeightData.SlotNodeWeight*100.f);
|
|
DebugData.BranchFlow(1.0f).AddDebugItem(MontageLine, true);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
FAnimNode_Slot::FAnimNode_Slot()
|
|
: SlotName(FAnimSlotGroup::DefaultSlotName)
|
|
, bAlwaysUpdateSourcePose(false)
|
|
{
|
|
}
|