Hi, just looking through the code, I don’t think that we’ve ever supported sockets on the warp target. We get the target bone index in CalculateRootTransformRelativeToWarpPointAtTime with the following code:
const FBoneContainer& FullBoneContainer = AnimInstance->GetRequiredBones();
const int32 BoneIndex = FullBoneContainer.GetPoseBoneIndexForBoneName(WarpPointBoneName);
And that will only return bone indices, not sockets. Looking back in P4, it seems the code has always been that way.
Having said that, I don’t think there’s any reason why we shouldn’t add socket support for this. To do this properly, I would look at adding a new EWarpPointAnimProvider type and then specifying the socket via a FBoneSocketTarget since that has an API for getting the warp offset nicely. But if you just want a quick fix for this, something like the following should get sockets working for you:
FTransform UMotionWarpingUtilities::CalculateRootTransformRelativeToWarpPointAtTime(const UMotionWarpingBaseAdapter& WarpingAdapter, const UAnimSequenceBase* Animation, float Time, const FName& WarpPointBoneName)
{
if (const USkeletalMeshComponent* Mesh = WarpingAdapter.GetMesh())
{
if (const UAnimInstance* AnimInstance = Mesh->GetAnimInstance())
{
FTransform WarpPointLocalOffset = FTransform::Identity;
FName WarpPointOwningBoneName = WarpPointBoneName;
if (const USkeletalMeshSocket* Socket = Mesh->GetSocketByName(WarpPointBoneName))
{
WarpPointLocalOffset = Socket->GetSocketLocalTransform();
WarpPointOwningBoneName = Socket->BoneName;
}
const FBoneContainer& FullBoneContainer = AnimInstance->GetRequiredBones();
const int32 BoneIndex = FullBoneContainer.GetPoseBoneIndexForBoneName(WarpPointOwningBoneName);
if (BoneIndex != INDEX_NONE)
{
TArray<FBoneIndexType> RequiredBoneIndexArray = { 0, (FBoneIndexType)BoneIndex };
FullBoneContainer.GetReferenceSkeleton().EnsureParentsExistAndSort(RequiredBoneIndexArray);
FBoneContainer LimitedBoneContainer(RequiredBoneIndexArray, UE::Anim::FCurveFilterSettings(UE::Anim::ECurveFilterMode::DisallowAll), *FullBoneContainer.GetAsset());
FCSPose<FCompactPose> Pose;
UMotionWarpingUtilities::ExtractComponentSpacePose(Animation, LimitedBoneContainer, Time, false, Pose);
const FCompactPoseBoneIndex WarpPointBoneIndex = LimitedBoneContainer.MakeCompactPoseIndex(FMeshPoseBoneIndex(BoneIndex));
// Inverse of mesh's relative rotation. Used to convert root and warp point in the animation from Y forward to X forward
const FTransform MeshCompRelativeRotInverse = FTransform(WarpingAdapter.GetBaseVisualRotationOffset().Inverse());
const FTransform RootTransform = MeshCompRelativeRotInverse * Pose.GetComponentSpaceTransform(FCompactPoseBoneIndex(0));
const FTransform WarpPointTransform = MeshCompRelativeRotInverse * (WarpPointLocalOffset * Pose.GetComponentSpaceTransform(WarpPointBoneIndex));
return RootTransform.GetRelativeTransform(WarpPointTransform);
}
}
}
return FTransform::Identity;
}
Note that there’s an extra change in there. Previously, we were extracting the warp target transform by doing this:
onst FTransform WarpPointTransform = MeshCompRelativeRotInverse * Pose.GetComponentSpaceTransform(FCompactPoseBoneIndex(1));But that assumes the warp target is a child of the root. So the code snippet above changes that to use the target bone index. You’d also need to make similar changes to the other overload of CalculateRootTransformRelativeToWarpPointAtTime.
Let me know if you’ve got any questions
[Attachment Removed]