Files
UnrealEngineUWP/Engine/Source/Editor/AnimGraph/Private/AnimGraphNode_SkeletalControlBase.cpp
Martin Wilson ae71a8cca5 Added FCompactPose, contains only the bone transforms needed by RequiredBones. Allows us to do animation evaluation without having to refer to required bones array all the time
API Breaking Changes

Removed Functions:
FA2CSPose::SafeSetCSBoneTransforms
FA2CSPose::LocalBlendCSBoneTransforms

Member Type Changes:
- int32 -> FCompactPoseBoneIndex
--- FBoneTransform::BoneIndex
--- FABRIKChainLink::BoneIndex
- FA2CSPose -> FCSPose<FCompactPose>
--- FAnimNode_SkeletalControlBase::ForwardedPose
--- FComponentSpacePoseContext::Pose
- FA2Pose -> FCompactPose
--- FSlotEvaluationPose::Pose
--- FAnimNode_TransitionPoseEvaluator::CachedPose
--- FAnimNode_SaveCachedPose::CachedPose
--- FPoseContext::Pose

Paramater Changes:
- FA2Pose& -> FCompactPose&
--- UAnimSingleNodeInstance::InternalBlendSpaceEvaluatePose (FA2Pose& Pose -> FCompactPose&)
--- UAnimInstance::SequenceEvaluatePose
--- UAnimInstance::BlendSequences
--- UAnimInstance::CopyPose
--- UAnimInstance::ApplyAdditiveSequence
--- UAnimInstance::BlendSpaceEvaluatePose
--- UAnimInstance::BlendRotationOffset
--- UAnimInstance::GetSlotWeight
--- UAnimInstance::SlotEvaluatePose
- FA2CSPose& -> FCSPose<FCompactPose>&
--- FAnimNode_SkeletalControlBase::EvaluateBoneTransforms
--- UAnimGraphNode_SkeletalControlBase::ConvertCSVectorToBoneSpace
--- UAnimGraphNode_SkeletalControlBase::ConvertCSRotationToBoneSpace
--- UAnimGraphNode_SkeletalControlBase::ConvertWidgetLocation
--- UAnimPreviewInstance::ApplyBoneControllers
- TArray<FTransform> -> FCompactPose
--- UAnimPreviewInstance::SetKeyImplementation
--- UAnimSequence::GetAnimationPose
--- UAnimSequence::GetBonePose
--- UAnimSequence::GetBonePose_Additive
--- UAnimSequence::GetAdditiveBasePose
--- UAnimSequence::GetBonePose_AdditiveMeshRotationOnly
--- FAnimationRuntime::BlendPosesTogether ( + Removed NumPoses and RequiredBones )
--- FAnimationRuntime::BlendPosesTogetherPerBone  ( + Removed NumPoses and RequiredBones )
--- FAnimationRuntime::BlendPosesTogetherPerBoneInMeshSpace ( + Removed NumPoses and RequiredBones )
--- FAnimationRuntime::BlendPosesPerBoneFilter ( + Removed Skeleton and RequiredBones )
--- FAnimationRuntime::GetPoseFromSequence ( + Removed  RequiredBones )
--- FAnimationRuntime::GetPoseFromAnimTrack ( + Removed  RequiredBones )
--- FAnimationRuntime::FillWithRetargetBaseRefPose ( + Removed  RequiredBones )
--- FAnimationRuntime::ConvertPoseToAdditive ( + Removed  RequiredBones )
--- FAnimationRuntime::ConvertPoseToMeshRotation ( + Removed  RequiredBones )
--- FAnimationRuntime::BlendPosesAccumulate ( + Removed  RequiredBones )
--- FAnimationRuntime::BlendAdditivePose ( + Removed  RequiredBones )
--- FAnimationRuntime::GetPoseFromBlendSpace ( + Removed  RequiredBones )
--- FAnimationRuntime::ConvertCSTransformToBoneSpace
--- FAnimationRuntime::ConvertBoneSpaceTransformToCS
--- FAnimationRuntime::BlendMeshPosesPerBoneWeights ( + Removed Skeleton and RequiredBones )
--- FAnimationRuntime::BlendLocalPosesPerBoneWeights ( + Removed Skeleton and RequiredBones )
- TArray<FTransform> -> FTransform
--- UAnimSequence::ResetRootBoneForRootMotion
- int32 -> FCompactPoseBoneIndex
--- UAnimSequence::RetargetBoneTransform

FAnimationRuntime: Many changes to animation operation functions, removal of NumPoses and RequiredBones, conversion of TArray<FTransform> to FCompactPose

Removed USTRUCT markup from FBoneTransform
Removed UPROPERTY markup from FAnimNode_TransitionPoseEvaluator::CachedPose

[CL 2556671 by Martin Wilson in Main branch]
2015-05-19 06:19:22 -04:00

339 lines
9.7 KiB
C++

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#include "AnimGraphPrivatePCH.h"
#include "AnimGraphNode_SkeletalControlBase.h"
#include "AnimationGraphSchema.h"
/////////////////////////////////////////////////////
// UAnimGraphNode_SkeletalControlBase
#define LOCTEXT_NAMESPACE "A3Nodes"
UAnimGraphNode_SkeletalControlBase::UAnimGraphNode_SkeletalControlBase(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
// returns int32 instead of EWidgetMode because of compiling issue on Mac
int32 UAnimGraphNode_SkeletalControlBase::GetWidgetMode(const USkeletalMeshComponent* SkelComp)
{
return (int32)FWidget::EWidgetMode::WM_None;
}
int32 UAnimGraphNode_SkeletalControlBase::ChangeToNextWidgetMode(const USkeletalMeshComponent* SkelComp, int32 CurWidgetMode)
{
return GetWidgetMode(SkelComp);
}
//
FName UAnimGraphNode_SkeletalControlBase::FindSelectedBone()
{
return NAME_None;
}
FLinearColor UAnimGraphNode_SkeletalControlBase::GetNodeTitleColor() const
{
return FLinearColor(0.75f, 0.75f, 0.10f);
}
FString UAnimGraphNode_SkeletalControlBase::GetNodeCategory() const
{
return TEXT("Skeletal Controls");
}
FText UAnimGraphNode_SkeletalControlBase::GetControllerDescription() const
{
return LOCTEXT("ImplementMe", "Implement me");
}
FText UAnimGraphNode_SkeletalControlBase::GetTooltipText() const
{
return GetControllerDescription();
}
void UAnimGraphNode_SkeletalControlBase::CreateOutputPins()
{
const UAnimationGraphSchema* Schema = GetDefault<UAnimationGraphSchema>();
CreatePin(EGPD_Output, Schema->PC_Struct, TEXT(""), FComponentSpacePoseLink::StaticStruct(), /*bIsArray=*/ false, /*bIsReference=*/ false, TEXT("Pose"));
}
void UAnimGraphNode_SkeletalControlBase::ConvertToComponentSpaceTransform(const USkeletalMeshComponent* SkelComp, const FTransform & InTransform, FTransform & OutCSTransform, int32 BoneIndex, EBoneControlSpace Space) const
{
USkeleton * Skeleton = SkelComp->SkeletalMesh->Skeleton;
switch (Space)
{
case BCS_WorldSpace:
{
OutCSTransform = InTransform;
OutCSTransform.SetToRelativeTransform(SkelComp->ComponentToWorld);
}
break;
case BCS_ComponentSpace:
{
// Component Space, no change.
OutCSTransform = InTransform;
}
break;
case BCS_ParentBoneSpace:
if (BoneIndex != INDEX_NONE)
{
const int32 ParentIndex = Skeleton->GetReferenceSkeleton().GetParentIndex(BoneIndex);
if (ParentIndex != INDEX_NONE)
{
const int32 MeshParentIndex = Skeleton->GetMeshBoneIndexFromSkeletonBoneIndex(SkelComp->SkeletalMesh, ParentIndex);
if (MeshParentIndex != INDEX_NONE)
{
const FTransform ParentTM = SkelComp->GetBoneTransform(MeshParentIndex);
OutCSTransform = InTransform * ParentTM;
}
else
{
OutCSTransform = InTransform;
}
}
}
break;
case BCS_BoneSpace:
if (BoneIndex != INDEX_NONE)
{
const int32 MeshBoneIndex = Skeleton->GetMeshBoneIndexFromSkeletonBoneIndex(SkelComp->SkeletalMesh, BoneIndex);
if (MeshBoneIndex != INDEX_NONE)
{
const FTransform BoneTM = SkelComp->GetBoneTransform(MeshBoneIndex);
OutCSTransform = InTransform * BoneTM;
}
else
{
OutCSTransform = InTransform;
}
}
break;
default:
if (SkelComp->SkeletalMesh)
{
UE_LOG(LogAnimation, Warning, TEXT("ConvertToComponentSpaceTransform: Unknown BoneSpace %d for Mesh: %s"), (uint8)Space, *SkelComp->SkeletalMesh->GetFName().ToString());
}
else
{
UE_LOG(LogAnimation, Warning, TEXT("ConvertToComponentSpaceTransform: Unknown BoneSpace %d for Skeleton: %s"), (uint8)Space, *Skeleton->GetFName().ToString());
}
break;
}
}
FVector UAnimGraphNode_SkeletalControlBase::ConvertCSVectorToBoneSpace(const USkeletalMeshComponent* SkelComp, FVector& InCSVector, FCSPose<FCompactPose>& MeshBases, const FName& BoneName, const EBoneControlSpace Space)
{
FVector OutVector = InCSVector;
if (MeshBases.GetPose().IsValid())
{
const FMeshPoseBoneIndex MeshBoneIndex(SkelComp->GetBoneIndex(BoneName));
const FCompactPoseBoneIndex BoneIndex = MeshBases.GetPose().GetBoneContainer().MakeCompactPoseIndex(MeshBoneIndex);
switch (Space)
{
// World Space, no change in preview window
case BCS_WorldSpace:
case BCS_ComponentSpace:
// Component Space, no change.
break;
case BCS_ParentBoneSpace:
{
const FCompactPoseBoneIndex ParentIndex = MeshBases.GetPose().GetParentBoneIndex(BoneIndex);
if (ParentIndex != INDEX_NONE)
{
const FTransform& ParentTM = MeshBases.GetComponentSpaceTransform(ParentIndex);
OutVector = ParentTM.InverseTransformVector(InCSVector);
}
}
break;
case BCS_BoneSpace:
{
const FTransform& BoneTM = MeshBases.GetComponentSpaceTransform(BoneIndex);
OutVector = BoneTM.InverseTransformVector(InCSVector);
}
break;
}
}
return OutVector;
}
FQuat UAnimGraphNode_SkeletalControlBase::ConvertCSRotationToBoneSpace(const USkeletalMeshComponent* SkelComp, FRotator& InCSRotator, FCSPose<FCompactPose>& MeshBases, const FName& BoneName, const EBoneControlSpace Space)
{
FQuat OutQuat = FQuat::Identity;
if (MeshBases.GetPose().IsValid())
{
const FMeshPoseBoneIndex MeshBoneIndex(SkelComp->GetBoneIndex(BoneName));
const FCompactPoseBoneIndex BoneIndex = MeshBases.GetPose().GetBoneContainer().MakeCompactPoseIndex(MeshBoneIndex);
FVector RotAxis;
float RotAngle;
InCSRotator.Quaternion().ToAxisAndAngle(RotAxis, RotAngle);
switch (Space)
{
// World Space, no change in preview window
case BCS_WorldSpace:
case BCS_ComponentSpace:
// Component Space, no change.
OutQuat = InCSRotator.Quaternion();
break;
case BCS_ParentBoneSpace:
{
const FCompactPoseBoneIndex ParentIndex = MeshBases.GetPose().GetParentBoneIndex(BoneIndex);
if (ParentIndex != INDEX_NONE)
{
const FTransform& ParentTM = MeshBases.GetComponentSpaceTransform(ParentIndex);
FTransform InverseParentTM = ParentTM.Inverse();
//Calculate the new delta rotation
FVector4 BoneSpaceAxis = InverseParentTM.TransformVector(RotAxis);
FQuat DeltaQuat(BoneSpaceAxis, RotAngle);
DeltaQuat.Normalize();
OutQuat = DeltaQuat;
}
}
break;
case BCS_BoneSpace:
{
const FTransform& BoneTM = MeshBases.GetComponentSpaceTransform(BoneIndex);
FTransform InverseBoneTM = BoneTM.Inverse();
FVector4 BoneSpaceAxis = InverseBoneTM.TransformVector(RotAxis);
//Calculate the new delta rotation
FQuat DeltaQuat(BoneSpaceAxis, RotAngle);
DeltaQuat.Normalize();
OutQuat = DeltaQuat;
}
break;
}
}
return OutQuat;
}
FVector UAnimGraphNode_SkeletalControlBase::ConvertWidgetLocation(const USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, const FName& BoneName, const FVector& Location, const EBoneControlSpace Space)
{
FVector WidgetLoc = FVector::ZeroVector;
if (MeshBases.GetPose().IsValid())
{
USkeleton * Skeleton = SkelComp->SkeletalMesh->Skeleton;
const FMeshPoseBoneIndex MeshBoneIndex(SkelComp->GetBoneIndex(BoneName));
const FCompactPoseBoneIndex CompactBoneIndex = MeshBases.GetPose().GetBoneContainer().MakeCompactPoseIndex(MeshBoneIndex);
switch (Space)
{
// ComponentToWorld must be Identity in preview window so same as ComponentSpace
case BCS_WorldSpace:
case BCS_ComponentSpace:
{
// Component Space, no change.
WidgetLoc = Location;
}
break;
case BCS_ParentBoneSpace:
if (CompactBoneIndex != INDEX_NONE)
{
const FCompactPoseBoneIndex CompactParentIndex = MeshBases.GetPose().GetParentBoneIndex(CompactBoneIndex);
if (CompactParentIndex != INDEX_NONE)
{
const FTransform& ParentTM = MeshBases.GetComponentSpaceTransform(CompactParentIndex);
WidgetLoc = ParentTM.TransformPosition(Location);
}
}
break;
case BCS_BoneSpace:
if (CompactBoneIndex != INDEX_NONE)
{
const FTransform& BoneTM = MeshBases.GetComponentSpaceTransform(CompactBoneIndex);
WidgetLoc = BoneTM.TransformPosition(Location);
}
}
}
return WidgetLoc;
}
void UAnimGraphNode_SkeletalControlBase::GetDefaultValue(const FString& UpdateDefaultValueName, FVector& OutVec)
{
for (UEdGraphPin* Pin : Pins)
{
if (Pin->PinName == UpdateDefaultValueName)
{
if (GetSchema()->IsCurrentPinDefaultValid(Pin).IsEmpty())
{
FString DefaultString = Pin->GetDefaultAsString();
// Existing nodes (from older versions) might have an empty default value string; in that case we just fall through and return the zero vector below (which is the default value in that case).
if(!DefaultString.IsEmpty())
{
TArray<FString> ResultString;
//Parse string to split its contents separated by ','
DefaultString.Trim();
DefaultString.TrimTrailing();
DefaultString.ParseIntoArray(ResultString, TEXT(","), true);
check(ResultString.Num() == 3);
OutVec.Set(
FCString::Atof(*ResultString[0]),
FCString::Atof(*ResultString[1]),
FCString::Atof(*ResultString[2])
);
return;
}
}
}
}
OutVec = FVector::ZeroVector;
}
void UAnimGraphNode_SkeletalControlBase::SetDefaultValue(const FString& UpdateDefaultValueName, const FVector& Value)
{
for (UEdGraphPin* Pin : Pins)
{
if (Pin->PinName == UpdateDefaultValueName)
{
if (GetSchema()->IsCurrentPinDefaultValid(Pin).IsEmpty())
{
FString Str = FString::Printf(TEXT("%.3f,%.3f,%.3f"), Value.X, Value.Y, Value.Z);
if (Pin->DefaultValue != Str)
{
PreEditChange(NULL);
GetSchema()->TrySetDefaultValue(*Pin, Str);
PostEditChange();
break;
}
}
}
}
}
bool UAnimGraphNode_SkeletalControlBase::IsPinShown(const FString& PinName) const
{
for (const FOptionalPinFromProperty& Pin : ShowPinForProperties)
{
if (Pin.PropertyName.ToString() == PinName)
{
return Pin.bShowPin;
}
}
return false;
}
#undef LOCTEXT_NAMESPACE