You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Runtime notes: - Removes 'smart name' usage across the animation systems. - Changed curve blending from a uniform array (sized per skeleton) to a sparse array of sorted named values. Blends and other combiners are performed using a dual iteration 'tape merge'. - Skeleton curves are no longer guaranteed to cover all curve names that can be found at runtime. Editor notes: - Curve metadata (flags, bone links etc.) is still present on the skeleton, but can also now exist on a skeletal mesh - Curve metadata (for morph targets) is still populated on import - Curves can now be used arbitrarily at runtime New features: - New Find/Replace dialog that allows for batch-replacing curves and notifies across all of a project's assets - New curve debugger tab in various Persona editors that allows for viewing curve values live. This also now allows viewing curves for specific pose watches. - Pose watches now output curve tracks to the Rewind Debugger #rb Jurre.deBaare,Nicholas.Frechette,Sara.Schvartzman,Helge.Mathee,Kiaran.Ritchie,Jaime.Cifuentes,Martin.Wilson,Keith.Yerex,Andrean.Franc (and more!) #jira UE-167776 #jira UE-173716 #jira UE-110407 #preflight 63fc98c81206d91a2bc3ab90 #preflight 63f3ad4f81646f1f24c240c2 [CL 24421496 by Thomas Sarkanen in ue5-main branch]
114 lines
3.6 KiB
C++
114 lines
3.6 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "AnimNodes/AnimNode_PoseHandler.h"
|
|
#include "Animation/AnimInstanceProxy.h"
|
|
#include "Animation/AnimTrace.h"
|
|
|
|
#include UE_INLINE_GENERATED_CPP_BY_NAME(AnimNode_PoseHandler)
|
|
|
|
/////////////////////////////////////////////////////
|
|
// FAnimPoseByNameNode
|
|
|
|
void FAnimNode_PoseHandler::Initialize_AnyThread(const FAnimationInitializeContext& Context)
|
|
{
|
|
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(Initialize_AnyThread)
|
|
FAnimNode_AssetPlayerBase::Initialize_AnyThread(Context);
|
|
|
|
UpdatePoseAssetProperty(Context.AnimInstanceProxy);
|
|
}
|
|
|
|
void FAnimNode_PoseHandler::CacheBoneBlendWeights(FAnimInstanceProxy* InstanceProxy)
|
|
{
|
|
BoneBlendWeights.Reset();
|
|
|
|
const FBoneContainer& BoneContainer = InstanceProxy->GetRequiredBones();
|
|
|
|
// this has to update bone blending weight
|
|
if (CurrentPoseAsset.IsValid() && BoneContainer.IsValid())
|
|
{
|
|
const UPoseAsset* CurrentAsset = CurrentPoseAsset.Get();
|
|
const TArray<FName>& TrackNames = CurrentAsset->GetTrackNames();
|
|
const TArray<FBoneIndexType>& RequiredBoneIndices = BoneContainer.GetBoneIndicesArray();
|
|
BoneBlendWeights.AddZeroed(RequiredBoneIndices.Num());
|
|
|
|
for (const auto& TrackName : TrackNames)
|
|
{
|
|
int32 MeshBoneIndex = BoneContainer.GetPoseBoneIndexForBoneName(TrackName);
|
|
FCompactPoseBoneIndex CompactBoneIndex = BoneContainer.MakeCompactPoseIndex(FMeshPoseBoneIndex(MeshBoneIndex));
|
|
if (CompactBoneIndex != INDEX_NONE)
|
|
{
|
|
BoneBlendWeights[CompactBoneIndex.GetInt()] = 1.f;
|
|
}
|
|
}
|
|
|
|
RebuildPoseList(BoneContainer, CurrentAsset);
|
|
}
|
|
else
|
|
{
|
|
PoseExtractContext.PoseCurves.Reset();
|
|
}
|
|
}
|
|
|
|
void FAnimNode_PoseHandler::CacheBones_AnyThread(const FAnimationCacheBonesContext& Context)
|
|
{
|
|
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(CacheBones_AnyThread)
|
|
FAnimNode_AssetPlayerBase::CacheBones_AnyThread(Context);
|
|
|
|
CacheBoneBlendWeights(Context.AnimInstanceProxy);
|
|
}
|
|
|
|
void FAnimNode_PoseHandler::RebuildPoseList(const FBoneContainer& InBoneContainer, const UPoseAsset* InPoseAsset)
|
|
{
|
|
PoseExtractContext.PoseCurves.Reset();
|
|
const TArray<FName>& PoseNames = InPoseAsset->GetPoseFNames();
|
|
const int32 TotalPoseNum = PoseNames.Num();
|
|
if (TotalPoseNum > 0)
|
|
{
|
|
for (int32 PoseIndex = 0; PoseIndex < PoseNames.Num(); ++PoseIndex)
|
|
{
|
|
const FName& PoseName = PoseNames[PoseIndex];
|
|
|
|
// we keep pose index as that is the fastest way to search when extracting pose asset
|
|
PoseExtractContext.PoseCurves.Add(FPoseCurve(PoseIndex, PoseName, 0.f));
|
|
}
|
|
}
|
|
}
|
|
|
|
void FAnimNode_PoseHandler::UpdateAssetPlayer(const FAnimationUpdateContext& Context)
|
|
{
|
|
GetEvaluateGraphExposedInputs().Execute(Context);
|
|
|
|
// update pose asset if it's not valid
|
|
if (CurrentPoseAsset.IsValid() == false || CurrentPoseAsset.Get() != PoseAsset)
|
|
{
|
|
UpdatePoseAssetProperty(Context.AnimInstanceProxy);
|
|
}
|
|
|
|
TRACE_ANIM_NODE_VALUE(Context, TEXT("Name"), CurrentPoseAsset.IsValid() ? *CurrentPoseAsset.Get()->GetName() : TEXT("None"));
|
|
TRACE_ANIM_NODE_VALUE(Context, TEXT("Pose Asset"), CurrentPoseAsset.IsValid() ? *CurrentPoseAsset.Get()->GetName() : TEXT("None"));
|
|
}
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
void FAnimNode_PoseHandler::SetPoseAsset(UPoseAsset* InPoseAsset)
|
|
{
|
|
PoseAsset = InPoseAsset;
|
|
}
|
|
#endif
|
|
|
|
void FAnimNode_PoseHandler::GatherDebugData(FNodeDebugData& DebugData)
|
|
{
|
|
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(GatherDebugData)
|
|
FString DebugLine = DebugData.GetNodeName(this);
|
|
|
|
DebugLine += FString::Printf(TEXT("('%s')"), *GetNameSafe(PoseAsset));
|
|
DebugData.AddDebugItem(DebugLine, true);
|
|
}
|
|
|
|
void FAnimNode_PoseHandler::UpdatePoseAssetProperty(struct FAnimInstanceProxy* InstanceProxy)
|
|
{
|
|
CurrentPoseAsset = PoseAsset;
|
|
CacheBoneBlendWeights(InstanceProxy);
|
|
}
|
|
|
|
|