VRTowerDef/Plugins/MetaXR/Source/OculusXRMovement/Private/OculusXRLiveLinkRetargetFac...

83 lines
2.8 KiB
C++

// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRLiveLinkRetargetFaceAsset.h"
#include "LiveLinkTypes.h"
#include "Algo/ForEach.h"
#include "Animation/AnimCurveTypes.h"
#include "BonePose.h"
#include "OculusXRMovement.h"
#include "OculusXRMovementLog.h"
UOculusXRLiveLinkRetargetFaceAsset::UOculusXRLiveLinkRetargetFaceAsset(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
void UOculusXRLiveLinkRetargetFaceAsset::Initialize()
{
LastSkeletonGuid.Invalidate();
#if UE_VERSION_OLDER_THAN(5, 3, 0)
Algo::ForEach(RemappingForLastSkeleton, [](TArray<SmartName::UID_Type>& Arr) { Arr.Reset(); });
#else
Algo::ForEach(RemappingForLastSkeleton, [](TArray<FName>& Arr) { Arr.Reset(); });
#endif
}
void UOculusXRLiveLinkRetargetFaceAsset::BuildPoseAndCurveFromBaseData(float DeltaTime, const FLiveLinkBaseStaticData* InBaseStaticData, const FLiveLinkBaseFrameData* InBaseFrameData, FCompactPose& OutPose, FBlendedCurve& OutCurve)
{
check(InBaseFrameData);
if (static_cast<int32>(EOculusXRFaceExpression::COUNT) != InBaseFrameData->PropertyValues.Num())
{
UE_LOG(LogOculusXRMovement, Error, TEXT("Received wrong data of live link frame. This retargeting asset must be used with Meta MovementSDK Live Link source and Face subject. (received %d face expressions, expected %d)"), InBaseFrameData->PropertyValues.Num(), static_cast<int32>(EOculusXRFaceExpression::COUNT));
return;
}
const USkeleton* Skeleton = OutPose.GetBoneContainer().GetSkeletonAsset();
if (!IsValid(Skeleton))
{
UE_LOG(LogOculusXRMovement, Error, TEXT("No skeleton asset for this retargeting."));
return;
}
if (LastSkeletonGuid != Skeleton->GetGuid())
{
OnSkeletonChanged(Skeleton);
}
for (uint8 ExpressionId = 0; ExpressionId < static_cast<uint8>(EOculusXRFaceExpression::COUNT); ++ExpressionId)
{
#if UE_VERSION_OLDER_THAN(5, 3, 0)
for (const SmartName::UID_Type UID : RemappingForLastSkeleton[ExpressionId])
{
OutCurve.Set(UID, InBaseFrameData->PropertyValues[ExpressionId]);
}
#else
for (const FName Name : RemappingForLastSkeleton[ExpressionId])
{
OutCurve.Set(Name, InBaseFrameData->PropertyValues[ExpressionId]);
}
#endif
}
}
void UOculusXRLiveLinkRetargetFaceAsset::OnSkeletonChanged(const USkeleton* Skeleton)
{
Initialize();
for (const auto& [ExpressionId, CurveMapping] : CurveRemapping)
{
for (const auto& CurveName : CurveMapping.CurveNames)
{
#if UE_VERSION_OLDER_THAN(5, 3, 0)
if (const SmartName::UID_Type UID = Skeleton->GetUIDByName(USkeleton::AnimCurveMappingName, CurveName); UID != SmartName::MaxUID)
{
RemappingForLastSkeleton[static_cast<uint8>(ExpressionId)].Emplace(UID);
}
#else
RemappingForLastSkeleton[static_cast<uint8>(ExpressionId)].Emplace(CurveName);
#endif
}
}
LastSkeletonGuid = Skeleton->GetGuid();
}