2014-03-14 14:13:41 -04:00
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
# 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-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
Keywords = InAssetInfo . ObjectPath . ToString ( ) ;
}
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
UAnimGraphNode_SequencePlayer : : UAnimGraphNode_SequencePlayer ( const FPostConstructInitializeProperties & PCIP )
: Super ( PCIP )
{
}
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 ) ;
}
}
FString UAnimGraphNode_SequencePlayer : : GetTooltip ( ) const
{
const bool bAdditive = ( ( Node . Sequence ! = NULL ) & & Node . Sequence - > IsValidAdditive ( ) ) ;
2014-04-23 18:30:37 -04:00
return GetTitleGivenAssetInfo ( FText : : FromString ( Node . Sequence - > GetPathName ( ) ) , bAdditive ) . ToString ( ) ;
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
{
const bool bAdditive = ( ( Node . Sequence ! = NULL ) & & Node . Sequence - > IsValidAdditive ( ) ) ;
2014-04-23 18:30:37 -04:00
FText Title = GetTitleGivenAssetInfo ( ( Node . Sequence ! = NULL ) ? FText : : FromString ( Node . Sequence - > GetName ( ) ) : LOCTEXT ( " None " , " (None) " ) , bAdditive ) ;
2014-03-14 14:13:41 -04:00
if ( ( TitleType = = ENodeTitleType : : FullTitle ) & & ( SyncGroup . GroupName ! = NAME_None ) )
{
2014-04-23 18:30:37 -04:00
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " Title " ) , Title ) ;
2014-04-23 19:15:09 -04:00
Args . Add ( TEXT ( " SyncGroup " ) , FText : : FromName ( SyncGroup . GroupName ) ) ;
2014-04-23 18:30:37 -04:00
2014-04-23 19:15:09 -04:00
Title = FText : : Format ( LOCTEXT ( " SequenceNodeGroupWithSubtitle " , " {Title} \n Sync group {SyncGroup} " ) , Args ) ;
2014-03-14 14:13:41 -04:00
}
return Title ;
}
2014-04-23 18:30:37 -04:00
FString UAnimGraphNode_SequencePlayer : : GetNodeNativeTitle ( ENodeTitleType : : Type TitleType ) const
2014-03-14 14:13:41 -04:00
{
2014-04-23 18:30:37 -04:00
// Do not setup this function for localization, intentionally left unlocalized!
const bool bAdditive = ( ( Node . Sequence ! = NULL ) & & Node . Sequence - > IsValidAdditive ( ) ) ;
FString Title = GetTitleGivenAssetInfo ( ( Node . Sequence ! = NULL ) ? FText : : FromString ( Node . Sequence - > GetName ( ) ) : LOCTEXT ( " None " , " (None) " ) , bAdditive ) . ToString ( ) ;
if ( ( TitleType = = ENodeTitleType : : FullTitle ) & & ( SyncGroup . GroupName ! = NAME_None ) )
{
Title + = TEXT ( " \n " ) ;
Title + = FString : : Printf ( TEXT ( " Sync group %s " ) , * SyncGroup . GroupName . ToString ( ) ) ;
}
return Title ;
}
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
}
}
void UAnimGraphNode_SequencePlayer : : GetMenuEntries ( FGraphContextMenuBuilder & ContextMenuBuilder ) const
{
if ( ( ContextMenuBuilder . FromPin = = NULL ) | | ( UAnimationGraphSchema : : IsPosePin ( ContextMenuBuilder . FromPin - > PinType ) & & ( ContextMenuBuilder . FromPin - > Direction = = EGPD_Input ) ) )
{
UBlueprint * Blueprint = FBlueprintEditorUtils : : FindBlueprintForGraphChecked ( ContextMenuBuilder . CurrentGraph ) ;
if ( UAnimBlueprint * AnimBlueprint = Cast < UAnimBlueprint > ( Blueprint ) )
{
// Load the asset registry module
FAssetRegistryModule & AssetRegistryModule = FModuleManager : : LoadModuleChecked < FAssetRegistryModule > ( TEXT ( " AssetRegistry " ) ) ;
FARFilter Filter ;
Filter . ClassNames . Add ( UAnimSequence : : StaticClass ( ) - > GetFName ( ) ) ;
Filter . bRecursiveClasses = true ;
// Filter by skeleton
FAssetData SkeletonData ( AnimBlueprint - > TargetSkeleton ) ;
Filter . TagsAndValues . Add ( TEXT ( " Skeleton " ) , SkeletonData . GetExportTextName ( ) ) ;
// 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 ;
// Try to determine if the asset is additive (can't do it right now if the asset is unloaded)
bool bAdditive = false ;
if ( Asset . IsAssetLoaded ( ) )
{
if ( UAnimSequence * Sequence = Cast < UAnimSequence > ( Asset . GetAsset ( ) ) )
{
bAdditive = Sequence - > IsValidAdditive ( ) ;
}
}
// Create the menu item
2014-04-23 18:30:37 -04:00
const FText Title = UAnimGraphNode_SequencePlayer : : GetTitleGivenAssetInfo ( FText : : FromName ( Asset . AssetName ) , bAdditive ) ;
2014-03-14 14:13:41 -04:00
TSharedPtr < FNewSequencePlayerAction > NewAction ( new FNewSequencePlayerAction ( Asset , Title ) ) ;
ContextMenuBuilder . AddAction ( NewAction ) ;
}
}
}
}
void UAnimGraphNode_SequencePlayer : : ValidateAnimNodeDuringCompilation ( class USkeleton * ForSkeleton , class FCompilerResultsLog & MessageLog )
{
if ( Node . Sequence = = NULL )
{
MessageLog . Error ( TEXT ( " @@ references an unknown sequence " ) , this ) ;
}
else
{
USkeleton * SeqSkeleton = Node . Sequence - > GetSkeleton ( ) ;
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