2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
# include "AnimGraphPrivatePCH.h"
2014-04-24 14:34:01 -04:00
# include "AnimGraphNode_SequencePlayer.h"
2014-03-14 14:13:41 -04:00
# include "CompilerResultsLog.h"
# include "GraphEditorActions.h"
# include "AssetRegistryModule.h"
2014-04-24 14:34:01 -04:00
# include "AnimationGraphSchema.h"
2014-09-26 11:31:34 -04:00
# include "BlueprintActionDatabaseRegistrar.h"
# include "BlueprintActionFilter.h"
# include "EditorCategoryUtils.h"
2014-09-29 14:31:25 -04:00
# include "BlueprintNodeSpawner.h"
2014-09-26 11:31:34 -04:00
2014-03-14 14:13:41 -04:00
# define LOCTEXT_NAMESPACE "A3Nodes"
/////////////////////////////////////////////////////
// FNewSequencePlayerAction
// Action to add a sequence player node to the graph
struct FNewSequencePlayerAction : public FEdGraphSchemaAction_K2NewNode
{
protected :
FAssetData AssetInfo ;
public :
2014-04-23 18:30:37 -04:00
FNewSequencePlayerAction ( const FAssetData & InAssetInfo , FText Title )
2014-03-14 14:13:41 -04:00
{
AssetInfo = InAssetInfo ;
UAnimGraphNode_SequencePlayer * Template = NewObject < UAnimGraphNode_SequencePlayer > ( ) ;
NodeTemplate = Template ;
MenuDescription = Title ;
TooltipDescription = TEXT ( " Evaluates an animation sequence to produce a pose " ) ;
Category = TEXT ( " Animations " ) ;
// Grab extra keywords
2015-04-20 12:25:37 -04:00
Keywords = FText : : FromName ( InAssetInfo . ObjectPath ) ;
2014-03-14 14:13:41 -04:00
}
2014-06-13 06:14:46 -04:00
virtual UEdGraphNode * PerformAction ( class UEdGraph * ParentGraph , UEdGraphPin * FromPin , const FVector2D Location , bool bSelectNewNode = true ) override
2014-03-14 14:13:41 -04:00
{
UAnimGraphNode_SequencePlayer * SpawnedNode = CastChecked < UAnimGraphNode_SequencePlayer > ( FEdGraphSchemaAction_K2NewNode : : PerformAction ( ParentGraph , FromPin , Location , bSelectNewNode ) ) ;
SpawnedNode - > Node . Sequence = Cast < UAnimSequence > ( AssetInfo . GetAsset ( ) ) ;
return SpawnedNode ;
}
} ;
/////////////////////////////////////////////////////
// UAnimGraphNode_SequencePlayer
2014-10-14 10:29:11 -04:00
UAnimGraphNode_SequencePlayer : : UAnimGraphNode_SequencePlayer ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
}
void UAnimGraphNode_SequencePlayer : : PreloadRequiredAssets ( )
{
PreloadObject ( Node . Sequence ) ;
Super : : PreloadRequiredAssets ( ) ;
}
FLinearColor UAnimGraphNode_SequencePlayer : : GetNodeTitleColor ( ) const
{
if ( ( Node . Sequence ! = NULL ) & & Node . Sequence - > IsValidAdditive ( ) )
{
return FLinearColor ( 0.10f , 0.60f , 0.12f ) ;
}
else
{
return FColor ( 200 , 100 , 100 ) ;
}
}
2014-09-03 18:14:09 -04:00
FText UAnimGraphNode_SequencePlayer : : GetTooltipText ( ) const
2014-03-14 14:13:41 -04:00
{
const bool bAdditive = ( ( Node . Sequence ! = NULL ) & & Node . Sequence - > IsValidAdditive ( ) ) ;
2014-09-03 18:14:09 -04:00
return GetTitleGivenAssetInfo ( FText : : FromString ( Node . Sequence - > GetPathName ( ) ) , bAdditive ) ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 18:30:37 -04:00
FText UAnimGraphNode_SequencePlayer : : GetNodeTitle ( ENodeTitleType : : Type TitleType ) const
2014-03-14 14:13:41 -04:00
{
2014-09-04 11:25:05 -04:00
if ( Node . Sequence = = nullptr )
2014-03-14 14:13:41 -04:00
{
2014-09-04 11:25:05 -04:00
return LOCTEXT ( " SequenceNullTitle " , " Play (None) " ) ;
2014-03-14 14:13:41 -04:00
}
2015-03-04 08:31:40 -05:00
else
2014-09-04 11:25:05 -04:00
{
2015-03-04 08:31:40 -05:00
const bool bAdditive = Node . Sequence - > IsValidAdditive ( ) ;
const FText BasicTitle = GetTitleGivenAssetInfo ( FText : : FromName ( Node . Sequence - > GetFName ( ) ) , bAdditive ) ;
2014-03-14 14:13:41 -04:00
2015-03-04 08:31:40 -05:00
if ( SyncGroup . GroupName = = NAME_None )
{
return BasicTitle ;
}
else
{
const FText SyncGroupName = FText : : FromName ( SyncGroup . GroupName ) ;
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " Title " ) , BasicTitle ) ;
Args . Add ( TEXT ( " SyncGroup " ) , SyncGroupName ) ;
if ( TitleType = = ENodeTitleType : : FullTitle )
2014-09-16 15:01:38 -04:00
{
2015-03-04 08:31:40 -05:00
return FText : : Format ( LOCTEXT ( " SequenceNodeGroupWithSubtitleFull " , " {Title} \n Sync group {SyncGroup} " ) , Args ) ;
}
else
{
return FText : : Format ( LOCTEXT ( " SequenceNodeGroupWithSubtitleList " , " {Title} (Sync group {SyncGroup}) " ) , Args ) ;
2014-09-16 15:01:38 -04:00
}
}
2014-09-04 11:25:05 -04:00
}
2014-03-14 14:13:41 -04:00
}
2014-04-23 18:30:37 -04:00
FText UAnimGraphNode_SequencePlayer : : GetTitleGivenAssetInfo ( const FText & AssetName , bool bKnownToBeAdditive )
{
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " AssetName " ) , AssetName ) ;
2014-03-14 14:13:41 -04:00
if ( bKnownToBeAdditive )
{
2014-04-23 18:30:37 -04:00
return FText : : Format ( LOCTEXT ( " SequenceNodeTitleAdditive " , " Play {AssetName} (additive) " ) , Args ) ;
2014-03-14 14:13:41 -04:00
}
else
{
2014-04-23 18:30:37 -04:00
return FText : : Format ( LOCTEXT ( " SequenceNodeTitle " , " Play {AssetName} " ) , Args ) ;
2014-03-14 14:13:41 -04:00
}
}
2014-09-26 11:31:34 -04:00
FText UAnimGraphNode_SequencePlayer : : GetMenuCategory ( ) const
{
return FEditorCategoryUtils : : GetCommonCategory ( FCommonEditorCategory : : Animation ) ;
}
void UAnimGraphNode_SequencePlayer : : GetMenuActions ( FBlueprintActionDatabaseRegistrar & ActionRegistrar ) const
{
2014-09-29 14:31:25 -04:00
auto LoadedAssetSetup = [ ] ( UEdGraphNode * NewNode , bool /*bIsTemplateNode*/ , TWeakObjectPtr < UAnimSequence > SequencePtr )
2014-09-26 11:31:34 -04:00
{
UAnimGraphNode_SequencePlayer * SequencePlayerNode = CastChecked < UAnimGraphNode_SequencePlayer > ( NewNode ) ;
2014-09-29 14:31:25 -04:00
SequencePlayerNode - > Node . Sequence = SequencePtr . Get ( ) ;
} ;
2014-09-26 11:31:34 -04:00
2014-09-29 14:31:25 -04:00
auto UnloadedAssetSetup = [ ] ( UEdGraphNode * NewNode , bool bIsTemplateNode , const FAssetData AssetData )
{
UAnimGraphNode_SequencePlayer * SequencePlayerNode = CastChecked < UAnimGraphNode_SequencePlayer > ( NewNode ) ;
if ( bIsTemplateNode )
2014-09-26 11:31:34 -04:00
{
2014-09-29 14:31:25 -04:00
if ( const FString * SkeletonTag = AssetData . TagsAndValues . Find ( TEXT ( " Skeleton " ) ) )
2014-09-26 11:31:34 -04:00
{
SequencePlayerNode - > UnloadedSkeletonName = * SkeletonTag ;
}
}
else
{
2014-09-29 14:31:25 -04:00
UAnimSequence * Sequence = Cast < UAnimSequence > ( AssetData . GetAsset ( ) ) ;
check ( Sequence ! = nullptr ) ;
SequencePlayerNode - > Node . Sequence = Sequence ;
}
} ;
const UObject * QueryObject = ActionRegistrar . GetActionKeyFilter ( ) ;
if ( QueryObject = = nullptr )
{
FAssetRegistryModule & AssetRegistryModule = FModuleManager : : LoadModuleChecked < FAssetRegistryModule > ( TEXT ( " AssetRegistry " ) ) ;
// define a filter to help in pulling UAnimSequence asset data from the registry
FARFilter Filter ;
Filter . ClassNames . Add ( UAnimSequence : : StaticClass ( ) - > GetFName ( ) ) ;
Filter . bRecursiveClasses = true ;
// Find matching assets and add an entry for each one
TArray < FAssetData > SequenceList ;
AssetRegistryModule . Get ( ) . GetAssets ( Filter , /*out*/ SequenceList ) ;
for ( auto AssetIt = SequenceList . CreateConstIterator ( ) ; AssetIt ; + + AssetIt )
{
const FAssetData & Asset = * AssetIt ;
UBlueprintNodeSpawner * NodeSpawner = UBlueprintNodeSpawner : : Create ( GetClass ( ) ) ;
if ( Asset . IsAssetLoaded ( ) )
{
TWeakObjectPtr < UAnimSequence > AnimSequence = Cast < UAnimSequence > ( Asset . GetAsset ( ) ) ;
NodeSpawner - > CustomizeNodeDelegate = UBlueprintNodeSpawner : : FCustomizeNodeDelegate : : CreateStatic ( LoadedAssetSetup , AnimSequence ) ;
NodeSpawner - > DefaultMenuSignature . MenuName = GetTitleGivenAssetInfo ( FText : : FromName ( AnimSequence - > GetFName ( ) ) , AnimSequence - > IsValidAdditive ( ) ) ;
}
else
{
NodeSpawner - > CustomizeNodeDelegate = UBlueprintNodeSpawner : : FCustomizeNodeDelegate : : CreateStatic ( UnloadedAssetSetup , Asset ) ;
NodeSpawner - > DefaultMenuSignature . MenuName = GetTitleGivenAssetInfo ( FText : : FromName ( Asset . AssetName ) , /*bKnownToBeAdditive =*/ false ) ;
}
ActionRegistrar . AddBlueprintAction ( Asset , NodeSpawner ) ;
}
}
else if ( const UAnimSequence * AnimSequence = Cast < UAnimSequence > ( QueryObject ) )
{
UBlueprintNodeSpawner * NodeSpawner = UBlueprintNodeSpawner : : Create ( GetClass ( ) ) ;
TWeakObjectPtr < UAnimSequence > SequencePtr = AnimSequence ;
NodeSpawner - > CustomizeNodeDelegate = UBlueprintNodeSpawner : : FCustomizeNodeDelegate : : CreateStatic ( LoadedAssetSetup , SequencePtr ) ;
NodeSpawner - > DefaultMenuSignature . MenuName = GetTitleGivenAssetInfo ( FText : : FromName ( AnimSequence - > GetFName ( ) ) , AnimSequence - > IsValidAdditive ( ) ) ;
ActionRegistrar . AddBlueprintAction ( QueryObject , NodeSpawner ) ;
}
else if ( QueryObject = = GetClass ( ) )
{
FAssetRegistryModule & AssetRegistryModule = FModuleManager : : LoadModuleChecked < FAssetRegistryModule > ( TEXT ( " AssetRegistry " ) ) ;
// define a filter to help in pulling UAnimSequence asset data from the registry
FARFilter Filter ;
Filter . ClassNames . Add ( UAnimSequence : : StaticClass ( ) - > GetFName ( ) ) ;
Filter . bRecursiveClasses = true ;
// Find matching assets and add an entry for each one
TArray < FAssetData > SequenceList ;
AssetRegistryModule . Get ( ) . GetAssets ( Filter , /*out*/ SequenceList ) ;
for ( auto AssetIt = SequenceList . CreateConstIterator ( ) ; AssetIt ; + + AssetIt )
{
const FAssetData & Asset = * AssetIt ;
if ( Asset . IsAssetLoaded ( ) )
2014-09-26 11:31:34 -04:00
{
continue ;
}
2014-09-29 14:31:25 -04:00
UBlueprintNodeSpawner * NodeSpawner = UBlueprintNodeSpawner : : Create ( GetClass ( ) ) ;
NodeSpawner - > CustomizeNodeDelegate = UBlueprintNodeSpawner : : FCustomizeNodeDelegate : : CreateStatic ( UnloadedAssetSetup , Asset ) ;
NodeSpawner - > DefaultMenuSignature . MenuName = GetTitleGivenAssetInfo ( FText : : FromName ( Asset . AssetName ) , /*bKnownToBeAdditive =*/ false ) ;
ActionRegistrar . AddBlueprintAction ( Asset , NodeSpawner ) ;
2014-09-26 11:31:34 -04:00
}
2014-09-29 14:31:25 -04:00
}
2014-09-26 11:31:34 -04:00
}
bool UAnimGraphNode_SequencePlayer : : IsActionFilteredOut ( class FBlueprintActionFilter const & Filter )
{
bool bIsFilteredOut = false ;
FBlueprintActionContext const & FilterContext = Filter . Context ;
for ( UBlueprint * Blueprint : FilterContext . Blueprints )
{
if ( UAnimBlueprint * AnimBlueprint = Cast < UAnimBlueprint > ( Blueprint ) )
{
if ( Node . Sequence )
{
if ( Node . Sequence - > GetSkeleton ( ) ! = AnimBlueprint - > TargetSkeleton )
{
// Sequence does not use the same skeleton as the Blueprint, cannot use
bIsFilteredOut = true ;
break ;
}
}
else
{
FAssetData SkeletonData ( AnimBlueprint - > TargetSkeleton ) ;
if ( UnloadedSkeletonName ! = SkeletonData . GetExportTextName ( ) )
{
bIsFilteredOut = true ;
break ;
}
}
}
else
{
// Not an animation Blueprint, cannot use
bIsFilteredOut = true ;
break ;
}
}
return bIsFilteredOut ;
}
2014-03-14 14:13:41 -04:00
void UAnimGraphNode_SequencePlayer : : ValidateAnimNodeDuringCompilation ( class USkeleton * ForSkeleton , class FCompilerResultsLog & MessageLog )
{
if ( Node . Sequence = = NULL )
{
MessageLog . Error ( TEXT ( " @@ references an unknown sequence " ) , this ) ;
}
else
{
2014-10-01 14:45:23 -04:00
USkeleton * SeqSkeleton = Node . Sequence - > GetSkeleton ( ) ;
2014-03-14 14:13:41 -04:00
if ( SeqSkeleton & & // if anim sequence doesn't have skeleton, it might be due to anim sequence not loaded yet, @todo: wait with anim blueprint compilation until all assets are loaded?
! SeqSkeleton - > IsCompatible ( ForSkeleton ) )
{
MessageLog . Error ( TEXT ( " @@ references sequence that uses different skeleton @@ " ) , this , SeqSkeleton ) ;
}
}
}
void UAnimGraphNode_SequencePlayer : : GetContextMenuActions ( const FGraphNodeContextMenuBuilder & Context ) const
{
if ( ! Context . bIsDebugging )
{
// add an option to convert to single frame
Context . MenuBuilder - > BeginSection ( " AnimGraphNodeSequencePlayer " , NSLOCTEXT ( " A3Nodes " , " SequencePlayerHeading " , " Sequence Player " ) ) ;
{
Context . MenuBuilder - > AddMenuEntry ( FGraphEditorCommands : : Get ( ) . OpenRelatedAsset ) ;
Context . MenuBuilder - > AddMenuEntry ( FGraphEditorCommands : : Get ( ) . ConvertToSeqEvaluator ) ;
}
Context . MenuBuilder - > EndSection ( ) ;
}
}
void UAnimGraphNode_SequencePlayer : : BakeDataDuringCompilation ( class FCompilerResultsLog & MessageLog )
{
UAnimBlueprint * AnimBlueprint = GetAnimBlueprint ( ) ;
Node . GroupIndex = AnimBlueprint - > FindOrAddGroup ( SyncGroup . GroupName ) ;
Node . GroupRole = SyncGroup . GroupRole ;
}
void UAnimGraphNode_SequencePlayer : : GetAllAnimationSequencesReferred ( TArray < UAnimationAsset * > & ComplexAnims , TArray < UAnimSequence * > & AnimationSequences ) const
{
if ( Node . Sequence )
{
HandleAnimReferenceCollection ( Node . Sequence , ComplexAnims , AnimationSequences ) ;
}
}
void UAnimGraphNode_SequencePlayer : : ReplaceReferredAnimations ( const TMap < UAnimationAsset * , UAnimationAsset * > & ComplexAnimsMap , const TMap < UAnimSequence * , UAnimSequence * > & AnimSequenceMap )
{
HandleAnimReferenceReplacement ( Node . Sequence , ComplexAnimsMap , AnimSequenceMap ) ;
}
bool UAnimGraphNode_SequencePlayer : : DoesSupportTimeForTransitionGetter ( ) const
{
return true ;
}
UAnimationAsset * UAnimGraphNode_SequencePlayer : : GetAnimationAsset ( ) const
{
return Node . Sequence ;
}
const TCHAR * UAnimGraphNode_SequencePlayer : : GetTimePropertyName ( ) const
{
return TEXT ( " InternalTimeAccumulator " ) ;
}
UScriptStruct * UAnimGraphNode_SequencePlayer : : GetTimePropertyStruct ( ) const
{
return FAnimNode_SequencePlayer : : StaticStruct ( ) ;
}
# undef LOCTEXT_NAMESPACE