176 lines
5.6 KiB
C++
176 lines
5.6 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "AnimGraphNode_Constraint.h"
|
|
#include "Kismet2/CompilerResultsLog.h"
|
|
#include "AnimNodeEditModes.h"
|
|
#include "Animation/AnimInstance.h"
|
|
#include "Components/SkeletalMeshComponent.h"
|
|
|
|
/////////////////////////////////////////////////////
|
|
// UAnimGraphNode_Constraint
|
|
|
|
#define LOCTEXT_NAMESPACE "UAnimGraphNode_Constraint"
|
|
|
|
/* Utility function that gives transform type string for UI */
|
|
//////////////////////////////////////////////////
|
|
FString GetTransformTypeString(const ETransformConstraintType& TransformType, bool bSimple = false)
|
|
{
|
|
switch (TransformType)
|
|
{
|
|
case ETransformConstraintType::Parent:
|
|
return (bSimple) ? TEXT("P") : TEXT("Parent");
|
|
case ETransformConstraintType::Translation:
|
|
return (bSimple) ? TEXT("T") : TEXT("Translation");
|
|
case ETransformConstraintType::Rotation:
|
|
return (bSimple) ? TEXT("R") : TEXT("Rotation");
|
|
case ETransformConstraintType::Scale:
|
|
return (bSimple) ? TEXT("S") : TEXT("Scale");
|
|
}
|
|
|
|
return (bSimple) ? TEXT("U") : TEXT("Unknown");
|
|
};
|
|
//////////////////////////////////////////////////////
|
|
|
|
UAnimGraphNode_Constraint::UAnimGraphNode_Constraint(const FObjectInitializer& ObjectInitializer)
|
|
: Super(ObjectInitializer)
|
|
{
|
|
}
|
|
|
|
void UAnimGraphNode_Constraint::ValidateAnimNodeDuringCompilation(USkeleton* ForSkeleton, FCompilerResultsLog& MessageLog)
|
|
{
|
|
if (ForSkeleton && ForSkeleton->GetReferenceSkeleton().FindBoneIndex(Node.BoneToModify.BoneName) == INDEX_NONE)
|
|
{
|
|
if (Node.BoneToModify.BoneName == NAME_None)
|
|
{
|
|
MessageLog.Warning(*LOCTEXT("NoBoneSelectedToModify", "@@ - You must pick a bone to modify").ToString(), this);
|
|
}
|
|
else
|
|
{
|
|
FFormatNamedArguments Args;
|
|
Args.Add(TEXT("BoneName"), FText::FromName(Node.BoneToModify.BoneName));
|
|
|
|
FText Msg = FText::Format(LOCTEXT("NoBoneFoundToModify", "@@ - Bone {BoneName} not found in Skeleton"), Args);
|
|
|
|
MessageLog.Warning(*Msg.ToString(), this);
|
|
}
|
|
}
|
|
|
|
float OverallWeight = 0.f;
|
|
for (UEdGraphPin* Pin : Pins)
|
|
{
|
|
if (Pin->GetName().StartsWith(TEXT("ConstraintWeights")))
|
|
{
|
|
OverallWeight += FCString::Atof(*(Pin->DefaultValue));
|
|
}
|
|
}
|
|
if (Node.ConstraintWeights.Num() > 0 && !FMath::IsNearlyEqual(OverallWeight, 1.f, ZERO_ANIMWEIGHT_THRESH * float(Node.ConstraintWeights.Num())))
|
|
{
|
|
MessageLog.Note(*LOCTEXT("WeightsDontSumToOne", "@@ - The weights don't add up to 1.0").ToString(), this);
|
|
}
|
|
|
|
Super::ValidateAnimNodeDuringCompilation(ForSkeleton, MessageLog);
|
|
}
|
|
|
|
FText UAnimGraphNode_Constraint::GetControllerDescription() const
|
|
{
|
|
return LOCTEXT("Constraint", "Constraint");
|
|
}
|
|
|
|
FText UAnimGraphNode_Constraint::GetTooltipText() const
|
|
{
|
|
return LOCTEXT("AnimGraphNode_Constraint_Tooltip", "Constraint to another joint per transform component");
|
|
}
|
|
|
|
FText UAnimGraphNode_Constraint::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
|
{
|
|
// get simple transform type
|
|
auto GetSimpleTransformString = [this]() -> FString
|
|
{
|
|
FString Ret;
|
|
for (const FConstraint& Constraint : Node.ConstraintSetup)
|
|
{
|
|
Ret += GetTransformTypeString(Constraint.TransformType, true);
|
|
}
|
|
return Ret;
|
|
};
|
|
|
|
if ((TitleType == ENodeTitleType::ListView || TitleType == ENodeTitleType::MenuTitle) && (Node.BoneToModify.BoneName == NAME_None))
|
|
{
|
|
return GetControllerDescription();
|
|
}
|
|
else
|
|
{
|
|
FFormatNamedArguments Args;
|
|
Args.Add(TEXT("ControllerDescription"), GetControllerDescription());
|
|
Args.Add(TEXT("BoneName"), FText::FromName(Node.BoneToModify.BoneName));
|
|
Args.Add(TEXT("TransformComponents"), FText::FromString(GetSimpleTransformString()));
|
|
|
|
// FText::Format() is slow, so we cache this to save on performance
|
|
CachedNodeTitles.SetCachedTitle(TitleType, FText::Format(LOCTEXT("AnimGraphNode_Constraint_ListTitle", "{ControllerDescription} - {BoneName} ({TransformComponents})"), Args), this);
|
|
}
|
|
return CachedNodeTitles[TitleType];
|
|
}
|
|
|
|
void UAnimGraphNode_Constraint::Draw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* SkelMeshComp) const
|
|
{
|
|
if (SkelMeshComp)
|
|
{
|
|
if (FAnimNode_Constraint* ActiveNode = GetActiveInstanceNode<FAnimNode_Constraint>(SkelMeshComp->GetAnimInstance()))
|
|
{
|
|
ActiveNode->ConditionalDebugDraw(PDI, SkelMeshComp);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UAnimGraphNode_Constraint::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent)
|
|
{
|
|
Super::PostEditChangeProperty(PropertyChangedEvent);
|
|
|
|
if (PropertyChangedEvent.Property)
|
|
{
|
|
static const FName NAME_ConstraintSetup = GET_MEMBER_NAME_CHECKED(FAnimNode_Constraint, ConstraintSetup);
|
|
const FName PropName = PropertyChangedEvent.Property->GetFName();
|
|
|
|
if (PropName == NAME_ConstraintSetup)
|
|
{
|
|
int32 CurrentNum = Node.ConstraintWeights.Num();
|
|
Node.ConstraintWeights.SetNumZeroed(Node.ConstraintSetup.Num());
|
|
int32 NewNum = Node.ConstraintWeights.Num();
|
|
|
|
// we want to fill up 1, not 0.
|
|
for (int32 Index = CurrentNum; Index < NewNum; ++Index)
|
|
{
|
|
Node.ConstraintWeights[Index] = 1.f;
|
|
}
|
|
|
|
ReconstructNode();
|
|
}
|
|
}
|
|
}
|
|
|
|
void UAnimGraphNode_Constraint::PostProcessPinName(const UEdGraphPin* Pin, FString& DisplayName) const
|
|
{
|
|
Super::PostProcessPinName(Pin, DisplayName);
|
|
|
|
if (Pin->Direction == EGPD_Input)
|
|
{
|
|
const FString ConstraintWeightPrefix = TEXT("ConstraintWeights_");
|
|
const FString PinName = Pin->PinName.ToString();
|
|
FString IndexString;
|
|
if (PinName.Split(ConstraintWeightPrefix, nullptr, &IndexString))
|
|
{
|
|
// convert index and display better name
|
|
const int32 Index = FCString::Atoi(*IndexString);
|
|
if (Node.ConstraintSetup.IsValidIndex(Index))
|
|
{
|
|
const FConstraint& Constraint = Node.ConstraintSetup[Index];
|
|
DisplayName = Constraint.TargetBone.BoneName.ToString();
|
|
DisplayName += TEXT(" : ");
|
|
DisplayName += GetTransformTypeString(Constraint.TransformType);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|