2020-09-01 14:07:48 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
2021-04-22 04:57:09 -04:00
# include "AnimBlueprintExtension_CachedPose.h"
2020-09-01 14:07:48 -04:00
# include "AnimGraphNode_SaveCachedPose.h"
# include "AnimGraphNode_Root.h"
# include "AnimGraphNode_UseCachedPose.h"
# include "Kismet2/CompilerResultsLog.h"
# include "AnimGraphNode_StateMachine.h"
# include "AnimGraphNode_StateResult.h"
2020-09-09 08:32:25 -04:00
# include "IAnimBlueprintGeneratedClassCompiledData.h"
# include "IAnimBlueprintCompilerCreationContext.h"
# include "IAnimBlueprintCompilationContext.h"
2021-02-17 05:10:10 -04:00
# include "AnimationGraphSchema.h"
2020-09-01 14:07:48 -04:00
2021-04-22 04:57:09 -04:00
void UAnimBlueprintExtension_CachedPose : : HandleStartCompilingClass ( const UClass * InClass , IAnimBlueprintCompilationBracketContext & InCompilationContext , IAnimBlueprintGeneratedClassCompiledData & OutCompiledData )
2020-09-09 08:32:25 -04:00
{
2021-04-22 04:57:09 -04:00
SaveCachedPoseNodes . Empty ( ) ;
2020-09-09 08:32:25 -04:00
}
2021-04-22 04:57:09 -04:00
void UAnimBlueprintExtension_CachedPose : : HandlePreProcessAnimationNodes ( TArrayView < UAnimGraphNode_Base * > InAnimNodes , IAnimBlueprintCompilationContext & InCompilationContext , IAnimBlueprintGeneratedClassCompiledData & OutCompiledData )
2020-09-01 14:07:48 -04:00
{
for ( UAnimGraphNode_Base * Node : InAnimNodes )
{
if ( UAnimGraphNode_SaveCachedPose * SavePoseRoot = Cast < UAnimGraphNode_SaveCachedPose > ( Node ) )
{
//@TODO: Ideally we only add these if there is a UseCachedPose node referencing them, but those can be anywhere and are hard to grab
SaveCachedPoseNodes . Add ( SavePoseRoot - > CacheName , SavePoseRoot ) ;
}
}
}
2021-04-22 04:57:09 -04:00
void UAnimBlueprintExtension_CachedPose : : HandlePostProcessAnimationNodes ( TArrayView < UAnimGraphNode_Base * > InAnimNodes , IAnimBlueprintCompilationContext & InCompilationContext , IAnimBlueprintGeneratedClassCompiledData & OutCompiledData )
2020-09-01 14:07:48 -04:00
{
// Build cached pose map
2020-09-09 08:32:25 -04:00
BuildCachedPoseNodeUpdateOrder ( InCompilationContext , OutCompiledData ) ;
2020-09-01 14:07:48 -04:00
}
TAutoConsoleVariable < int32 > CVarAnimDebugCachePoseNodeUpdateOrder ( TEXT ( " a.Compiler.CachePoseNodeUpdateOrderDebug.Enable " ) , 0 , TEXT ( " Toggle debugging for CacheNodeUpdateOrder debug during AnimBP compilation " ) ) ;
2021-04-22 04:57:09 -04:00
void UAnimBlueprintExtension_CachedPose : : BuildCachedPoseNodeUpdateOrder ( IAnimBlueprintCompilationContext & InCompilationContext , IAnimBlueprintGeneratedClassCompiledData & OutCompiledData )
2020-09-01 14:07:48 -04:00
{
TArray < UAnimGraphNode_Root * > RootNodes ;
2020-09-09 08:32:25 -04:00
InCompilationContext . GetConsolidatedEventGraph ( ) - > GetNodesOfClass < UAnimGraphNode_Root > ( RootNodes ) ;
2020-09-01 14:07:48 -04:00
// State results are also "root" nodes, need to find the true roots
RootNodes . RemoveAll ( [ ] ( UAnimGraphNode_Root * InPossibleRootNode )
{
return InPossibleRootNode - > GetClass ( ) ! = UAnimGraphNode_Root : : StaticClass ( ) ;
} ) ;
const bool bEnableDebug = ( CVarAnimDebugCachePoseNodeUpdateOrder . GetValueOnAnyThread ( ) = = 1 ) ;
for ( UAnimGraphNode_Root * RootNode : RootNodes )
{
TArray < UAnimGraphNode_SaveCachedPose * > OrderedSavePoseNodes ;
TArray < UAnimGraphNode_Base * > VisitedRootNodes ;
UE_CLOG ( bEnableDebug , LogAnimation , Display , TEXT ( " CachePoseNodeOrdering BEGIN " ) ) ;
2020-09-09 08:32:25 -04:00
CachePoseNodeOrdering_StartNewTraversal ( InCompilationContext , RootNode , OrderedSavePoseNodes , VisitedRootNodes ) ;
2020-09-01 14:07:48 -04:00
UE_CLOG ( bEnableDebug , LogAnimation , Display , TEXT ( " CachePoseNodeOrdering END " ) ) ;
if ( bEnableDebug )
{
UE_LOG ( LogAnimation , Display , TEXT ( " Ordered Save Pose Node List: " ) ) ;
for ( UAnimGraphNode_SaveCachedPose * SavedPoseNode : OrderedSavePoseNodes )
{
UE_LOG ( LogAnimation , Display , TEXT ( " \t %s " ) , * SavedPoseNode - > Node . CachePoseName . ToString ( ) )
}
UE_LOG ( LogAnimation , Display , TEXT ( " End List " ) ) ;
}
2021-04-22 04:57:09 -04:00
FCachedPoseIndices & OrderedSavedPoseIndices = OutCompiledData . GetOrderedSavedPoseIndicesMap ( ) . FindOrAdd ( RootNode - > Node . GetName ( ) ) ;
2020-09-01 14:07:48 -04:00
for ( UAnimGraphNode_SaveCachedPose * PoseNode : OrderedSavePoseNodes )
{
2020-09-09 08:32:25 -04:00
if ( const int32 * NodeIndex = InCompilationContext . GetAllocatedAnimNodeIndices ( ) . Find ( PoseNode ) )
2020-09-01 14:07:48 -04:00
{
OrderedSavedPoseIndices . OrderedSavedPoseNodeIndices . Add ( * NodeIndex ) ;
}
else
{
2020-09-09 08:32:25 -04:00
InCompilationContext . GetMessageLog ( ) . Error ( TEXT ( " Failed to find index for a saved pose node while building ordered pose list. " ) ) ;
2020-09-01 14:07:48 -04:00
}
}
}
}
2021-04-22 04:57:09 -04:00
void UAnimBlueprintExtension_CachedPose : : CachePoseNodeOrdering_StartNewTraversal ( IAnimBlueprintCompilationContext & InCompilationContext , UAnimGraphNode_Base * InRootNode , TArray < UAnimGraphNode_SaveCachedPose * > & OrderedSavePoseNodes , TArray < UAnimGraphNode_Base * > VisitedRootNodes )
2020-09-01 14:07:48 -04:00
{
check ( InRootNode ) ;
UAnimGraphNode_SaveCachedPose * RootCacheNode = Cast < UAnimGraphNode_SaveCachedPose > ( InRootNode ) ;
FString RootName = RootCacheNode ? RootCacheNode - > CacheName : InRootNode - > GetName ( ) ;
const bool bEnableDebug = ( CVarAnimDebugCachePoseNodeUpdateOrder . GetValueOnAnyThread ( ) = = 1 ) ;
UE_CLOG ( bEnableDebug , LogAnimation , Display , TEXT ( " StartNewTraversal %s " ) , * RootName ) ;
// Track which root nodes we've visited to prevent infinite recursion.
VisitedRootNodes . Add ( InRootNode ) ;
// Need a list of only what we find here to recurse, we can't do that with the total list
TArray < UAnimGraphNode_SaveCachedPose * > InternalOrderedNodes ;
// Traverse whole graph from root collecting SaveCachePose nodes we've touched.
2020-09-09 08:32:25 -04:00
CachePoseNodeOrdering_TraverseInternal ( InCompilationContext , InRootNode , InternalOrderedNodes ) ;
2020-09-01 14:07:48 -04:00
// Process nodes that we've touched
UE_CLOG ( bEnableDebug , LogAnimation , Display , TEXT ( " Process Queue for %s " ) , * RootName ) ;
for ( UAnimGraphNode_SaveCachedPose * QueuedCacheNode : InternalOrderedNodes )
{
if ( VisitedRootNodes . Contains ( QueuedCacheNode ) )
{
UE_CLOG ( bEnableDebug , LogAnimation , Display , TEXT ( " Process Queue SaveCachePose %s. ALREADY VISITED, INFINITE RECURSION DETECTED! SKIPPING " ) , * QueuedCacheNode - > CacheName ) ;
2020-09-09 08:32:25 -04:00
InCompilationContext . GetMessageLog ( ) . Error ( * FString : : Printf ( TEXT ( " Infinite recursion detected with SaveCachePose %s and %s " ) , * RootName , * QueuedCacheNode - > CacheName ) ) ;
2020-09-01 14:07:48 -04:00
continue ;
}
else
{
OrderedSavePoseNodes . Remove ( QueuedCacheNode ) ;
OrderedSavePoseNodes . Add ( QueuedCacheNode ) ;
2020-09-09 08:32:25 -04:00
CachePoseNodeOrdering_StartNewTraversal ( InCompilationContext , QueuedCacheNode , OrderedSavePoseNodes , VisitedRootNodes ) ;
2020-09-01 14:07:48 -04:00
}
}
UE_CLOG ( bEnableDebug , LogAnimation , Display , TEXT ( " EndNewTraversal %s " ) , * RootName ) ;
}
2021-04-22 04:57:09 -04:00
void UAnimBlueprintExtension_CachedPose : : CachePoseNodeOrdering_TraverseInternal_SubGraph ( IAnimBlueprintCompilationContext & InCompilationContext , UEdGraph * InGraph , TArray < UAnimGraphNode_SaveCachedPose * > & OrderedSavePoseNodes )
2021-02-17 05:10:10 -04:00
{
const bool bEnableDebug = ( CVarAnimDebugCachePoseNodeUpdateOrder . GetValueOnAnyThread ( ) = = 1 ) ;
UE_CLOG ( bEnableDebug , LogAnimation , Display , TEXT ( " ProcessGraph %s " ) , * InGraph - > GetName ( ) ) ;
if ( InGraph - > Schema - > IsChildOf ( UAnimationGraphSchema : : StaticClass ( ) ) )
{
TArray < UAnimGraphNode_Base * > PotentialRootNodes ;
InGraph - > GetNodesOfClass ( PotentialRootNodes ) ;
for ( UAnimGraphNode_Base * PotentialRootNode : PotentialRootNodes )
{
if ( PotentialRootNode - > IsNodeRootSet ( ) )
{
CachePoseNodeOrdering_TraverseInternal ( InCompilationContext , PotentialRootNode , OrderedSavePoseNodes ) ;
}
}
}
else
{
for ( UEdGraph * SubGraph : InGraph - > SubGraphs )
{
CachePoseNodeOrdering_TraverseInternal_SubGraph ( InCompilationContext , SubGraph , OrderedSavePoseNodes ) ;
}
}
}
2021-04-22 04:57:09 -04:00
void UAnimBlueprintExtension_CachedPose : : CachePoseNodeOrdering_TraverseInternal ( IAnimBlueprintCompilationContext & InCompilationContext , UAnimGraphNode_Base * InAnimGraphNode , TArray < UAnimGraphNode_SaveCachedPose * > & OrderedSavePoseNodes )
2020-09-01 14:07:48 -04:00
{
TArray < UAnimGraphNode_Base * > LinkedAnimNodes ;
2020-09-09 08:32:25 -04:00
InCompilationContext . GetLinkedAnimNodes ( InAnimGraphNode , LinkedAnimNodes ) ;
2020-09-01 14:07:48 -04:00
const bool bEnableDebug = ( CVarAnimDebugCachePoseNodeUpdateOrder . GetValueOnAnyThread ( ) = = 1 ) ;
for ( UAnimGraphNode_Base * LinkedNode : LinkedAnimNodes )
{
UE_CLOG ( bEnableDebug , LogAnimation , Display , TEXT ( " \t Processing %s " ) , * LinkedNode - > GetName ( ) ) ;
if ( UAnimGraphNode_UseCachedPose * UsePoseNode = Cast < UAnimGraphNode_UseCachedPose > ( LinkedNode ) )
{
if ( UAnimGraphNode_SaveCachedPose * SaveNode = UsePoseNode - > SaveCachedPoseNode . Get ( ) )
{
UE_CLOG ( bEnableDebug , LogAnimation , Display , TEXT ( " \t Queueing SaveCachePose %s " ) , * SaveNode - > CacheName ) ;
// Requeue the node we found
OrderedSavePoseNodes . Remove ( SaveNode ) ;
OrderedSavePoseNodes . Add ( SaveNode ) ;
}
}
2021-02-11 11:50:48 -04:00
else
{
2021-02-17 05:10:10 -04:00
TArray < UEdGraph * > SubGraphs = LinkedNode - > GetSubGraphs ( ) ;
if ( SubGraphs . Num ( ) > 0 )
{
for ( UEdGraph * SubGraph : SubGraphs )
{
CachePoseNodeOrdering_TraverseInternal_SubGraph ( InCompilationContext , SubGraph , OrderedSavePoseNodes ) ;
}
}
else
{
CachePoseNodeOrdering_TraverseInternal ( InCompilationContext , LinkedNode , OrderedSavePoseNodes ) ;
}
2020-09-01 14:07:48 -04:00
}
}
}
2021-04-22 04:57:09 -04:00
const TMap < FString , UAnimGraphNode_SaveCachedPose * > & UAnimBlueprintExtension_CachedPose : : GetSaveCachedPoseNodes ( ) const
2020-09-01 14:07:48 -04:00
{
return SaveCachedPoseNodes ;
2020-09-09 08:32:25 -04:00
}