You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Added validation and visual error functionality to AnimNode_SkeletalControlBase, which can be used to check referenced bones and show errors on the AnimGraph nodes that use them (so it is clear if the setup does not work due to a bone missing)
#rb thomas.sarkanen #jira UE-160111 #preflight 63b85453c927e34482895de4 [CL 23599353 by jaime cifuentes in ue5-main branch]
This commit is contained in:
+3
-11
@@ -1773,17 +1773,9 @@ void FAnimNode_RigidBody::InitializeBoneReferences(const FBoneContainer& Require
|
||||
BaseBoneRef.BoneName = RefSkeleton.GetBoneName(0);
|
||||
}
|
||||
|
||||
if (BaseBoneRef.BoneName != NAME_None)
|
||||
{
|
||||
BaseBoneRef.Initialize(RequiredBones);
|
||||
}
|
||||
|
||||
if (!BaseBoneRef.HasValidSetup())
|
||||
{
|
||||
// If the user specified a simulation root that is not used by the skelmesh, issue a warning
|
||||
// (FAnimNode_RigidBody::IsValidToEvaluate will return false and the simulation will not run)
|
||||
UE_LOG(LogRBAN, Log, TEXT("FAnimNode_RigidBody: RBAN Simulation Base Bone \'%s\' does not exist on SkeletalMesh %s."), *BaseBoneRef.BoneName.ToString(), *GetNameSafe(RequiredBones.GetSkeletalMeshAsset()));
|
||||
}
|
||||
// If the user specified a simulation root that is not used by the skelmesh, issue a warning
|
||||
// (FAnimNode_RigidBody::IsValidToEvaluate will return false and the simulation will not run)
|
||||
InitializeAndValidateBoneRef(BaseBoneRef, RequiredBones);
|
||||
|
||||
bool bHasInvalidBoneReference = false;
|
||||
for (int32 Index = 0; Index < NumRequiredBoneIndices; ++Index)
|
||||
|
||||
+76
@@ -1,11 +1,21 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "BoneControllers/AnimNode_SkeletalControlBase.h"
|
||||
#include "Engine/SkeletalMesh.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Engine/SkeletalMeshSocket.h"
|
||||
|
||||
#include UE_INLINE_GENERATED_CPP_BY_NAME(AnimNode_SkeletalControlBase)
|
||||
|
||||
#define LOCTEXT_NAMESPACE "AnimNode_SkeletalControlBase"
|
||||
|
||||
#if UE_BUILD_SHIPPING || UE_BUILD_TEST
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogSkeletalControlBase, Log, Warning);
|
||||
#else
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogSkeletalControlBase, Log, All);
|
||||
#endif
|
||||
DEFINE_LOG_CATEGORY(LogSkeletalControlBase);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// FAnimNode_SkeletalControlBase
|
||||
|
||||
@@ -22,6 +32,10 @@ void FAnimNode_SkeletalControlBase::Initialize_AnyThread(const FAnimationInitial
|
||||
|
||||
void FAnimNode_SkeletalControlBase::CacheBones_AnyThread(const FAnimationCacheBonesContext& Context)
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
ClearValidationVisualWarnings();
|
||||
#endif
|
||||
|
||||
DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(CacheBones_AnyThread)
|
||||
FAnimNode_Base::CacheBones_AnyThread(Context);
|
||||
InitializeBoneReferences(Context.AnimInstanceProxy->GetRequiredBones());
|
||||
@@ -160,3 +174,65 @@ float FAnimNode_SkeletalControlBase::GetAlpha() const
|
||||
{
|
||||
return ActualAlpha;
|
||||
}
|
||||
|
||||
void FAnimNode_SkeletalControlBase::InitializeAndValidateBoneRef(FBoneReference& BoneRef, const FBoneContainer& RequiredBones)
|
||||
{
|
||||
if (BoneRef.BoneName != NAME_None)
|
||||
{
|
||||
BoneRef.Initialize(RequiredBones);
|
||||
}
|
||||
|
||||
if (!BoneRef.HasValidSetup())
|
||||
{
|
||||
const FText ErrorText = FText::Format(LOCTEXT("SkeletalControlBoneError", "Referenced Bone {0} does not exist on SkeletalMesh {1}."),
|
||||
FText::AsCultureInvariant(BoneRef.BoneName.ToString()),
|
||||
FText::AsCultureInvariant(GetNameSafe(RequiredBones.GetSkeletalMeshAsset())));
|
||||
|
||||
#if WITH_EDITOR
|
||||
AddValidationVisualWarning(ErrorText);
|
||||
#endif // WITH_EDITOR
|
||||
|
||||
// If the user specified a simulation root that is not used by the skelmesh, issue a warning
|
||||
UE_LOG(LogSkeletalControlBase, Log, TEXT("%s"), *ErrorText.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
void FAnimNode_SkeletalControlBase::AddBoneRefMissingVisualWarning(const FString& BoneName, const FString& SkeletalMeshName)
|
||||
{
|
||||
const FText ErrorText = FText::Format(LOCTEXT("SkeletalControlBoneError", "Simulation Base Bone {0} does not exist on SkeletalMesh {1}."), FText::FromString(BoneName), FText::FromString(SkeletalMeshName));
|
||||
|
||||
AddValidationVisualWarning(ErrorText);
|
||||
}
|
||||
|
||||
void FAnimNode_SkeletalControlBase::AddValidationVisualWarning(FText ValidationVisualWarning)
|
||||
{
|
||||
#if WITH_EDITORONLY_DATA
|
||||
if (ValidationVisualWarningMessage.IsEmpty())
|
||||
{
|
||||
ValidationVisualWarningMessage = ValidationVisualWarning;
|
||||
}
|
||||
else
|
||||
{
|
||||
ValidationVisualWarningMessage = FText::Format(FText::FromString(TEXT("{0}\n{1}")), ValidationVisualWarningMessage, ValidationVisualWarning);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FAnimNode_SkeletalControlBase::ClearValidationVisualWarnings()
|
||||
{
|
||||
ValidationVisualWarningMessage = FText::GetEmpty();
|
||||
}
|
||||
|
||||
bool FAnimNode_SkeletalControlBase::HasValidationVisualWarnings() const
|
||||
{
|
||||
return ValidationVisualWarningMessage.IsEmpty() == false;
|
||||
}
|
||||
|
||||
FText FAnimNode_SkeletalControlBase::GetValidationVisualWarningMessage() const
|
||||
{
|
||||
return ValidationVisualWarningMessage;
|
||||
}
|
||||
#endif // WITH_EDITOR
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
+20
-2
@@ -90,7 +90,19 @@ public:
|
||||
|
||||
// Get the alpha of this node
|
||||
float GetAlpha() const;
|
||||
|
||||
|
||||
void InitializeAndValidateBoneRef(FBoneReference& BoneRef, const FBoneContainer& RequiredBones);
|
||||
|
||||
// Visual warnings are shown on the node but not logged as an error for build system, use with care
|
||||
// The warnigns are cleared at CacheBones_AnyThread and should be added during InitializeBoneReferences
|
||||
#if WITH_EDITOR
|
||||
void AddBoneRefMissingVisualWarning(const FString& BoneName, const FString& SkeletalMeshName);
|
||||
void AddValidationVisualWarning(FText ValidationVisualWarning);
|
||||
bool HasValidationVisualWarnings() const;
|
||||
void ClearValidationVisualWarnings();
|
||||
FText GetValidationVisualWarningMessage() const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Interface for derived skeletal controls to implement
|
||||
// use this function to update for skeletal control base
|
||||
@@ -113,8 +125,14 @@ protected:
|
||||
|
||||
/** Allow base to add info to the node debug output */
|
||||
void AddDebugNodeData(FString& OutDebugData);
|
||||
private:
|
||||
|
||||
private:
|
||||
// Resused bone transform array to avoid reallocating in skeletal controls
|
||||
TArray<FBoneTransform> BoneTransforms;
|
||||
|
||||
#if WITH_EDITORONLY_DATA
|
||||
UPROPERTY(transient)
|
||||
FText ValidationVisualWarningMessage;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user