2019-12-26 15:33:43 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-05-22 12:00:20 -04:00
2019-09-23 07:23:26 -04:00
# include "AnimGraphNode_LinkedAnimGraphBase.h"
2019-05-22 12:00:20 -04:00
# include "Widgets/Text/STextBlock.h"
# include "Widgets/Input/SCheckBox.h"
# include "EdGraphSchema_K2.h"
# include "Kismet2/CompilerResultsLog.h"
# include "Kismet2/BlueprintEditorUtils.h"
# include "PropertyHandle.h"
# include "DetailLayoutBuilder.h"
# include "DetailCategoryBuilder.h"
2019-09-23 07:23:26 -04:00
# include "Animation/AnimNode_LinkedInputPose.h"
2019-05-22 12:00:20 -04:00
# include "PropertyCustomizationHelpers.h"
# include "ScopedTransaction.h"
# include "AnimationGraphSchema.h"
# include "Widgets/Layout/SBox.h"
# include "UObject/CoreRedirects.h"
2019-09-23 07:23:26 -04:00
# include "Animation/AnimNode_LinkedAnimGraph.h"
2021-01-06 09:11:59 -04:00
# include "AnimGraphAttributes.h"
2021-01-25 08:43:19 -04:00
# include "IAnimBlueprintCopyTermDefaultsContext.h"
2021-04-22 04:57:09 -04:00
# include "AnimBlueprintExtension_LinkedAnimGraph.h"
2021-10-12 21:21:22 -04:00
# include "AnimGraphNodeCustomizationInterface.h"
# include "BlueprintNodeTemplateCache.h"
2021-05-24 06:55:32 -04:00
# include "EdGraphSchema_K2_Actions.h"
2019-05-22 12:00:20 -04:00
2019-09-23 07:23:26 -04:00
# define LOCTEXT_NAMESPACE "LinkedAnimGraph"
2019-05-22 12:00:20 -04:00
2019-09-23 07:23:26 -04:00
namespace LinkedAnimGraphGraphNodeConstants
2019-05-22 12:00:20 -04:00
{
FLinearColor TitleColor ( 0.2f , 0.2f , 0.8f ) ;
}
2020-09-01 14:07:48 -04:00
void UAnimGraphNode_LinkedAnimGraphBase : : AllocatePoseLinks ( )
{
FAnimNode_LinkedAnimGraph & RuntimeNode = * GetLinkedAnimGraphNode ( ) ;
RuntimeNode . InputPoses . Empty ( ) ;
RuntimeNode . InputPoseNames . Empty ( ) ;
for ( UEdGraphPin * Pin : Pins )
{
if ( ! Pin - > bOrphanedPin )
{
if ( UAnimationGraphSchema : : IsPosePin ( Pin - > PinType ) )
{
if ( Pin - > Direction = = EGPD_Input )
{
RuntimeNode . InputPoses . AddDefaulted ( ) ;
RuntimeNode . InputPoseNames . Add ( Pin - > GetFName ( ) ) ;
}
}
}
}
}
2019-09-23 07:23:26 -04:00
FLinearColor UAnimGraphNode_LinkedAnimGraphBase : : GetNodeTitleColor ( ) const
2019-05-22 12:00:20 -04:00
{
2021-10-12 21:21:22 -04:00
TOptional < FLinearColor > Color ;
UClass * TargetClass = GetTargetClass ( ) ;
if ( TargetClass & & TargetClass - > ImplementsInterface ( UAnimGraphNodeCustomizationInterface : : StaticClass ( ) ) )
{
FEditorScriptExecutionGuard AllowScripts ;
Color = IAnimGraphNodeCustomizationInterface : : Execute_GetTitleColor ( TargetClass - > GetDefaultObject ( ) ) ;
}
if ( ! Color . IsSet ( ) )
{
2022-03-10 21:02:48 -05:00
return GetDefaultNodeTitleColor ( ) ;
2021-10-12 21:21:22 -04:00
}
return Color . GetValue ( ) ;
2019-05-22 12:00:20 -04:00
}
2021-05-24 06:55:32 -04:00
FSlateIcon UAnimGraphNode_LinkedAnimGraphBase : : GetIconAndTint ( FLinearColor & OutColor ) const
{
2022-05-09 13:12:28 -04:00
return FSlateIcon ( FAppStyle : : GetAppStyleSetName ( ) , " ClassIcon.AnimBlueprint " ) ;
2021-05-24 06:55:32 -04:00
}
2019-09-23 07:23:26 -04:00
FText UAnimGraphNode_LinkedAnimGraphBase : : GetTooltipText ( ) const
2019-05-22 12:00:20 -04:00
{
2021-10-12 21:21:22 -04:00
TOptional < FText > TooltipText ;
UClass * TargetClass = GetTargetClass ( ) ;
// With a null class, template nodes return an empty string to let the metadata take priority
if ( TargetClass = = nullptr & & FBlueprintNodeTemplateCache : : IsTemplateOuter ( GetGraph ( ) ) )
{
return FText : : GetEmpty ( ) ;
}
static const FName NAME_Tooltip ( TEXT ( " Tooltip " ) ) ;
if ( TargetClass & & TargetClass - > HasMetaData ( NAME_Tooltip ) )
{
TooltipText = TargetClass - > GetMetaDataText ( NAME_Tooltip ) ;
}
if ( ! TooltipText . IsSet ( ) | | TooltipText . GetValue ( ) . IsEmpty ( ) )
{
return LOCTEXT ( " ToolTip " , " Runs a linked anim graph in another instance to process animation " ) ;
}
return TooltipText . GetValue ( ) ;
2019-05-22 12:00:20 -04:00
}
2021-05-24 06:55:32 -04:00
FText UAnimGraphNode_LinkedAnimGraphBase : : GetMenuCategory ( ) const
{
2021-10-12 21:21:22 -04:00
TOptional < FText > Category ;
UClass * TargetClass = GetTargetClass ( ) ;
static const FName NAME_Category ( TEXT ( " Category " ) ) ;
if ( TargetClass & & TargetClass - > HasMetaData ( NAME_Category ) )
{
Category = TargetClass - > GetMetaDataText ( NAME_Category ) ;
}
if ( ! Category . IsSet ( ) | | Category . GetValue ( ) . IsEmpty ( ) )
{
2022-06-15 10:37:36 -04:00
return LOCTEXT ( " LinkedAnimGraphCategory " , " Animation|Linked Anim Graphs " ) ;
2021-10-12 21:21:22 -04:00
}
return Category . GetValue ( ) ;
2021-05-24 06:55:32 -04:00
}
2019-09-23 07:23:26 -04:00
FText UAnimGraphNode_LinkedAnimGraphBase : : GetNodeTitle ( ENodeTitleType : : Type TitleType ) const
2019-05-22 12:00:20 -04:00
{
2021-10-12 21:21:22 -04:00
TOptional < FText > Title ;
2019-05-22 12:00:20 -04:00
UClass * TargetClass = GetTargetClass ( ) ;
2021-10-12 21:21:22 -04:00
static const FName NAME_DisplayName ( TEXT ( " DisplayName " ) ) ;
if ( TargetClass & & TargetClass - > HasMetaData ( NAME_DisplayName ) )
2019-05-22 12:00:20 -04:00
{
2021-10-12 21:21:22 -04:00
Title = TargetClass - > GetMetaDataText ( NAME_DisplayName ) ;
2019-05-22 12:00:20 -04:00
}
2021-10-12 21:21:22 -04:00
if ( ! Title . IsSet ( ) | | Title . GetValue ( ) . IsEmpty ( ) )
2019-05-22 12:00:20 -04:00
{
2021-10-12 21:21:22 -04:00
UAnimBlueprint * TargetAnimBlueprint = TargetClass ? CastChecked < UAnimBlueprint > ( TargetClass - > ClassGeneratedBy ) : nullptr ;
const FName TargetAnimBlueprintName = TargetAnimBlueprint ? TargetAnimBlueprint - > GetFName ( ) : NAME_None ;
const FAnimNode_LinkedAnimGraph & Node = * GetLinkedAnimGraphNode ( ) ;
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " NodeType " ) , LOCTEXT ( " Title " , " Linked Anim Graph " ) ) ;
Args . Add ( TEXT ( " TargetClass " ) , FText : : FromName ( TargetAnimBlueprintName ) ) ;
if ( TitleType = = ENodeTitleType : : MenuTitle )
2021-05-24 06:55:32 -04:00
{
2021-10-12 21:21:22 -04:00
Title = LOCTEXT ( " Title " , " Linked Anim Graph " ) ;
2021-05-24 06:55:32 -04:00
}
2021-10-12 21:21:22 -04:00
else if ( TitleType = = ENodeTitleType : : ListView )
2021-05-24 06:55:32 -04:00
{
2021-10-12 21:21:22 -04:00
if ( TargetClass )
{
Title = FText : : Format ( LOCTEXT ( " TitleListFormat " , " {TargetClass} " ) , Args ) ;
}
else
{
Title = LOCTEXT ( " Title " , " Linked Anim Graph " ) ;
}
2019-05-22 12:00:20 -04:00
}
else
{
2021-10-12 21:21:22 -04:00
if ( TargetClass )
{
Title = FText : : Format ( LOCTEXT ( " TitleFormat " , " {TargetClass} \n {NodeType} " ) , Args ) ;
}
else
{
Title = LOCTEXT ( " Title " , " Linked Anim Graph " ) ;
}
2019-05-22 12:00:20 -04:00
}
}
2021-10-12 21:21:22 -04:00
return Title . GetValue ( ) ;
2019-05-22 12:00:20 -04:00
}
2019-09-23 07:23:26 -04:00
void UAnimGraphNode_LinkedAnimGraphBase : : ValidateAnimNodeDuringCompilation ( USkeleton * ForSkeleton , FCompilerResultsLog & MessageLog )
2019-05-22 12:00:20 -04:00
{
Super : : ValidateAnimNodeDuringCompilation ( ForSkeleton , MessageLog ) ;
UAnimBlueprint * AnimBP = CastChecked < UAnimBlueprint > ( GetBlueprint ( ) ) ;
UObject * OriginalNode = MessageLog . FindSourceObject ( this ) ;
if ( HasInstanceLoop ( ) )
{
2019-09-23 07:23:26 -04:00
MessageLog . Error ( TEXT ( " Detected loop in linked instance chain starting at @@ inside class @@ " ) , this , AnimBP - > GetAnimBlueprintGeneratedClass ( ) ) ;
2019-05-22 12:00:20 -04:00
}
2019-09-23 07:23:26 -04:00
// Check for cycles from other linked instance nodes
2019-05-22 12:00:20 -04:00
TArray < UEdGraph * > Graphs ;
AnimBP - > GetAllGraphs ( Graphs ) ;
2019-09-23 07:23:26 -04:00
const FAnimNode_LinkedAnimGraph & Node = * GetLinkedAnimGraphNode ( ) ;
2019-05-22 12:00:20 -04:00
// Check we don't try to spawn our own blueprint
if ( GetTargetClass ( ) = = AnimBP - > GetAnimBlueprintGeneratedClass ( ) )
{
2019-09-23 07:23:26 -04:00
MessageLog . Error ( TEXT ( " Linked instance node @@ targets instance class @@ which it is inside, this would cause a loop. " ) , this , AnimBP - > GetAnimBlueprintGeneratedClass ( ) ) ;
2019-05-22 12:00:20 -04:00
}
2021-12-08 06:43:16 -05:00
// Check for compatibility
if ( UAnimBlueprint * TargetAnimBP = Cast < UAnimBlueprint > ( UBlueprint : : GetBlueprintFromClass ( GetTargetClass ( ) ) ) )
{
if ( ! AnimBP - > IsCompatible ( TargetAnimBP ) )
{
MessageLog . Error ( TEXT ( " Linked instance node @@ targets instance class @@ which is incompatible. " ) , this , GetTargetClass ( ) ) ;
}
}
2019-05-22 12:00:20 -04:00
}
2021-11-07 23:43:01 -05:00
void UAnimGraphNode_LinkedAnimGraphBase : : CreateOutputPins ( )
2019-05-22 12:00:20 -04:00
{
2021-11-07 23:43:01 -05:00
Super : : CreateOutputPins ( ) ;
2019-05-22 12:00:20 -04:00
// Grab the SKELETON class here as when we are reconstructed during during BP compilation
// the full generated class is not yet present built.
UClass * TargetClass = GetTargetSkeletonClass ( ) ;
2021-11-07 23:43:01 -05:00
if ( TargetClass )
2019-05-22 12:00:20 -04:00
{
2021-11-07 23:43:01 -05:00
IAnimClassInterface * AnimClassInterface = IAnimClassInterface : : GetFromClass ( TargetClass ) ;
2019-05-22 12:00:20 -04:00
2021-11-07 23:43:01 -05:00
const FAnimNode_LinkedAnimGraph & Node = * GetLinkedAnimGraphNode ( ) ;
2019-05-22 12:00:20 -04:00
2021-11-07 23:43:01 -05:00
// Add any pose pins
for ( const FAnimBlueprintFunction & AnimBlueprintFunction : AnimClassInterface - > GetAnimBlueprintFunctions ( ) )
2019-05-22 12:00:20 -04:00
{
2021-11-07 23:43:01 -05:00
if ( AnimBlueprintFunction . Name = = Node . GetDynamicLinkFunctionName ( ) )
2019-05-22 12:00:20 -04:00
{
2021-11-07 23:43:01 -05:00
for ( const FName & PoseName : AnimBlueprintFunction . InputPoseNames )
{
UEdGraphPin * NewPin = CreatePin ( EEdGraphPinDirection : : EGPD_Input , UAnimationGraphSchema : : MakeLocalSpacePosePin ( ) , PoseName ) ;
NewPin - > PinFriendlyName = FText : : FromName ( PoseName ) ;
CustomizePinData ( NewPin , PoseName , INDEX_NONE ) ;
}
2019-05-22 12:00:20 -04:00
2021-11-07 23:43:01 -05:00
break ;
}
2019-05-22 12:00:20 -04:00
}
}
}
2019-09-23 07:23:26 -04:00
void UAnimGraphNode_LinkedAnimGraphBase : : PostEditChangeProperty ( FPropertyChangedEvent & PropertyChangedEvent )
2019-05-22 12:00:20 -04:00
{
Super : : PostEditChangeProperty ( PropertyChangedEvent ) ;
bool bRequiresNodeReconstruct = false ;
2019-12-13 11:07:03 -05:00
FProperty * ChangedProperty = PropertyChangedEvent . Property ;
2019-05-22 12:00:20 -04:00
if ( ChangedProperty )
{
if ( IsStructuralProperty ( ChangedProperty ) )
{
bRequiresNodeReconstruct = true ;
}
}
if ( bRequiresNodeReconstruct )
{
ReconstructNode ( ) ;
}
}
2019-09-23 07:23:26 -04:00
bool UAnimGraphNode_LinkedAnimGraphBase : : HasInstanceLoop ( )
2019-05-22 12:00:20 -04:00
{
TArray < FGuid > VisitedList ;
TArray < FGuid > CurrentStack ;
return HasInstanceLoop_Recursive ( this , VisitedList , CurrentStack ) ;
}
2019-09-23 07:23:26 -04:00
bool UAnimGraphNode_LinkedAnimGraphBase : : HasInstanceLoop_Recursive ( UAnimGraphNode_LinkedAnimGraphBase * CurrNode , TArray < FGuid > & VisitedNodes , TArray < FGuid > & NodeStack )
2019-05-22 12:00:20 -04:00
{
if ( ! VisitedNodes . Contains ( CurrNode - > NodeGuid ) )
{
VisitedNodes . Add ( CurrNode - > NodeGuid ) ;
NodeStack . Add ( CurrNode - > NodeGuid ) ;
if ( UAnimBlueprint * AnimBP = Cast < UAnimBlueprint > ( UBlueprint : : GetBlueprintFromClass ( CurrNode - > GetTargetClass ( ) ) ) )
{
2019-09-23 07:23:26 -04:00
// Check for cycles from other linked instance nodes
2019-05-22 12:00:20 -04:00
TArray < UEdGraph * > Graphs ;
AnimBP - > GetAllGraphs ( Graphs ) ;
for ( UEdGraph * Graph : Graphs )
{
2019-09-23 07:23:26 -04:00
TArray < UAnimGraphNode_LinkedAnimGraphBase * > LinkedInstanceNodes ;
Graph - > GetNodesOfClass ( LinkedInstanceNodes ) ;
2019-05-22 12:00:20 -04:00
2019-09-23 07:23:26 -04:00
for ( UAnimGraphNode_LinkedAnimGraphBase * LinkedInstanceNode : LinkedInstanceNodes )
2019-05-22 12:00:20 -04:00
{
// If we haven't visited this node, then check it for loops, otherwise if we're pointing to a previously visited node that is in the current instance stack we have a loop
2019-09-23 07:23:26 -04:00
if ( ( ! VisitedNodes . Contains ( LinkedInstanceNode - > NodeGuid ) & & HasInstanceLoop_Recursive ( LinkedInstanceNode , VisitedNodes , NodeStack ) ) | | NodeStack . Contains ( LinkedInstanceNode - > NodeGuid ) )
2019-05-22 12:00:20 -04:00
{
return true ;
}
}
}
}
}
NodeStack . Remove ( CurrNode - > NodeGuid ) ;
return false ;
}
2019-09-23 07:23:26 -04:00
void UAnimGraphNode_LinkedAnimGraphBase : : CustomizeDetails ( IDetailLayoutBuilder & DetailBuilder )
2019-05-22 12:00:20 -04:00
{
Super : : CustomizeDetails ( DetailBuilder ) ;
2019-08-08 11:18:26 -04:00
GenerateExposedPinsDetails ( DetailBuilder ) ;
IDetailCategoryBuilder & CategoryBuilder = DetailBuilder . EditCategory ( FName ( TEXT ( " Settings " ) ) ) ;
// Customize InstanceClass
{
TSharedRef < IPropertyHandle > ClassHandle = DetailBuilder . GetProperty ( TEXT ( " Node.InstanceClass " ) , GetClass ( ) ) ;
ClassHandle - > MarkHiddenByCustomization ( ) ;
FDetailWidgetRow & ClassWidgetRow = CategoryBuilder . AddCustomRow ( LOCTEXT ( " FilterStringInstanceClass " , " Instance Class " ) ) ;
ClassWidgetRow . NameContent ( )
[
ClassHandle - > CreatePropertyNameWidget ( )
]
. ValueContent ( )
. MinDesiredWidth ( 250.0f )
[
SNew ( SObjectPropertyEntryBox )
2019-09-23 07:23:26 -04:00
. ObjectPath_UObject ( this , & UAnimGraphNode_LinkedAnimGraphBase : : GetCurrentInstanceBlueprintPath )
2019-08-08 11:18:26 -04:00
. AllowedClass ( UAnimBlueprint : : StaticClass ( ) )
. NewAssetFactories ( TArray < UFactory * > ( ) )
2019-09-23 07:23:26 -04:00
. OnShouldFilterAsset ( FOnShouldFilterAsset : : CreateUObject ( this , & UAnimGraphNode_LinkedAnimGraphBase : : OnShouldFilterInstanceBlueprint ) )
. OnObjectChanged ( FOnSetObject : : CreateUObject ( this , & UAnimGraphNode_LinkedAnimGraphBase : : OnSetInstanceBlueprint , & DetailBuilder ) )
2019-08-08 11:18:26 -04:00
] ;
}
}
2019-09-23 07:23:26 -04:00
void UAnimGraphNode_LinkedAnimGraphBase : : GenerateExposedPinsDetails ( IDetailLayoutBuilder & DetailBuilder )
2019-08-08 11:18:26 -04:00
{
2019-05-22 12:00:20 -04:00
// We dont allow multi-select here
if ( DetailBuilder . GetSelectedObjects ( ) . Num ( ) > 1 )
{
DetailBuilder . HideCategory ( TEXT ( " Settings " ) ) ;
return ;
}
2021-10-12 21:21:22 -04:00
const FStructProperty * NodeProperty = GetFNodeProperty ( ) ;
if ( NodeProperty = = nullptr )
2019-07-10 17:06:13 -04:00
{
2021-10-12 21:21:22 -04:00
return ;
}
if ( CustomPinProperties . Num ( ) > 0 )
{
TSharedRef < IPropertyHandle > NodePropertyHandle = DetailBuilder . GetProperty ( NodeProperty - > GetFName ( ) , GetClass ( ) ) ;
2019-07-10 17:06:13 -04:00
IDetailCategoryBuilder & CategoryBuilder = DetailBuilder . EditCategory ( FName ( TEXT ( " Exposable Properties " ) ) ) ;
2021-10-12 21:21:22 -04:00
for ( int32 OptionalPinIndex = 0 ; OptionalPinIndex < CustomPinProperties . Num ( ) ; + + OptionalPinIndex )
2019-07-10 17:06:13 -04:00
{
2021-10-12 21:21:22 -04:00
const FOptionalPinFromProperty & OptionalProperty = CustomPinProperties [ OptionalPinIndex ] ;
// Find the property of our inner class
FProperty * Property = GetPinProperty ( OptionalProperty . PropertyName ) ;
if ( Property = = nullptr )
{
continue ;
}
2019-07-10 17:06:13 -04:00
FDetailWidgetRow & PropertyWidgetRow = CategoryBuilder . AddCustomRow ( FText : : FromString ( Property - > GetName ( ) ) ) ;
FName PropertyName = Property - > GetFName ( ) ;
FText PropertyTypeText = GetPropertyTypeText ( Property ) ;
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " PropertyName " ) , FText : : FromName ( PropertyName ) ) ;
Args . Add ( TEXT ( " PropertyType " ) , PropertyTypeText ) ;
FText TooltipText = FText : : Format ( LOCTEXT ( " PropertyTooltipText " , " {PropertyName} \n Type: {PropertyType} " ) , Args ) ;
PropertyWidgetRow . NameContent ( )
[
SNew ( STextBlock )
. Text ( FText : : FromString ( Property - > GetName ( ) ) )
. ToolTipText ( TooltipText )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
] ;
2021-10-12 21:21:22 -04:00
TSharedPtr < SWidget > BindingWidget = UAnimationGraphSchema : : MakeBindingWidgetForPin ( { this } , PropertyName , false , true ) ;
if ( BindingWidget . IsValid ( ) )
{
PropertyWidgetRow . ExtensionContent ( )
2019-07-10 17:06:13 -04:00
[
2021-10-12 21:21:22 -04:00
BindingWidget . ToSharedRef ( )
] ;
}
2019-07-10 17:06:13 -04:00
}
}
2019-05-22 12:00:20 -04:00
}
2019-12-13 11:07:03 -05:00
bool UAnimGraphNode_LinkedAnimGraphBase : : IsStructuralProperty ( FProperty * InProperty ) const
2019-05-22 12:00:20 -04:00
{
2019-09-23 07:23:26 -04:00
return InProperty - > GetFName ( ) = = GET_MEMBER_NAME_CHECKED ( FAnimNode_LinkedAnimGraph , InstanceClass ) ;
2019-05-22 12:00:20 -04:00
}
2019-09-23 07:23:26 -04:00
FString UAnimGraphNode_LinkedAnimGraphBase : : GetCurrentInstanceBlueprintPath ( ) const
2019-05-22 12:00:20 -04:00
{
UClass * InstanceClass = GetTargetClass ( ) ;
if ( InstanceClass )
{
UBlueprint * ActualBlueprint = UBlueprint : : GetBlueprintFromClass ( InstanceClass ) ;
if ( ActualBlueprint )
{
return ActualBlueprint - > GetPathName ( ) ;
}
}
return FString ( ) ;
}
2019-09-23 07:23:26 -04:00
bool UAnimGraphNode_LinkedAnimGraphBase : : OnShouldFilterInstanceBlueprint ( const FAssetData & AssetData ) const
2019-05-22 12:00:20 -04:00
{
// Check recursion
if ( AssetData . IsAssetLoaded ( ) & & Cast < UBlueprint > ( AssetData . GetAsset ( ) ) = = GetBlueprint ( ) )
{
return true ;
}
2021-12-08 06:43:16 -05:00
// Check skeleton & flags
FAssetDataTagMapSharedView : : FFindTagResult TargetSkeletonResult = AssetData . TagsAndValues . FindTag ( " TargetSkeleton " ) ;
FAssetDataTagMapSharedView : : FFindTagResult IsTemplateResult = AssetData . TagsAndValues . FindTag ( " bIsTemplate " ) ;
FAssetDataTagMapSharedView : : FFindTagResult BlueprintTypeResult = AssetData . TagsAndValues . FindTag ( " BlueprintType " ) ;
if ( TargetSkeletonResult . IsSet ( ) )
2019-05-22 12:00:20 -04:00
{
2021-12-08 06:43:16 -05:00
const bool bIsTemplate = IsTemplateResult . IsSet ( ) & & IsTemplateResult . Equals ( TEXT ( " True " ) ) ;
const bool bIsInterface = BlueprintTypeResult . IsSet ( ) & & BlueprintTypeResult . Equals ( TEXT ( " BPTYPE_Interface " ) ) ;
2019-05-22 12:00:20 -04:00
if ( UAnimBlueprint * CurrentBlueprint = Cast < UAnimBlueprint > ( GetBlueprint ( ) ) )
{
2021-12-08 06:43:16 -05:00
if ( ! CurrentBlueprint - > IsCompatibleByAssetString ( TargetSkeletonResult . GetValue ( ) , bIsTemplate , bIsInterface ) )
2019-05-22 12:00:20 -04:00
{
return true ;
}
}
}
return false ;
}
2019-09-23 07:23:26 -04:00
void UAnimGraphNode_LinkedAnimGraphBase : : OnSetInstanceBlueprint ( const FAssetData & AssetData , IDetailLayoutBuilder * InDetailBuilder )
2019-05-22 12:00:20 -04:00
{
2019-09-23 07:23:26 -04:00
FScopedTransaction Transaction ( LOCTEXT ( " SetInstanceBlueprint " , " Set Linked Blueprint " ) ) ;
2019-05-22 12:00:20 -04:00
Modify ( ) ;
TSharedRef < IPropertyHandle > ClassHandle = InDetailBuilder - > GetProperty ( TEXT ( " Node.InstanceClass " ) , GetClass ( ) ) ;
if ( UAnimBlueprint * Blueprint = Cast < UAnimBlueprint > ( AssetData . GetAsset ( ) ) )
{
ClassHandle - > SetValue ( Blueprint - > GetAnimBlueprintGeneratedClass ( ) ) ;
}
else
{
ClassHandle - > SetValue ( ( UObject * ) nullptr ) ;
}
}
2022-03-10 21:02:48 -05:00
FLinearColor UAnimGraphNode_LinkedAnimGraphBase : : GetDefaultNodeTitleColor ( ) const
{
return LinkedAnimGraphGraphNodeConstants : : TitleColor ;
}
2019-09-23 07:23:26 -04:00
FPoseLinkMappingRecord UAnimGraphNode_LinkedAnimGraphBase : : GetLinkIDLocation ( const UScriptStruct * NodeType , UEdGraphPin * SourcePin )
2019-05-22 12:00:20 -04:00
{
FPoseLinkMappingRecord Record = Super : : GetLinkIDLocation ( NodeType , SourcePin ) ;
if ( Record . IsValid ( ) )
{
return Record ;
}
else if ( SourcePin - > LinkedTo . Num ( ) > 0 & & SourcePin - > Direction = = EGPD_Input )
{
2019-09-23 07:23:26 -04:00
const FAnimNode_LinkedAnimGraph & Node = * GetLinkedAnimGraphNode ( ) ;
2019-05-22 12:00:20 -04:00
check ( Node . InputPoses . Num ( ) = = Node . InputPoseNames . Num ( ) ) ;
// perform name-based logic for input pose pins
if ( UAnimGraphNode_Base * LinkedNode = Cast < UAnimGraphNode_Base > ( FBlueprintEditorUtils : : FindFirstCompilerRelevantNode ( SourcePin - > LinkedTo [ 0 ] ) ) )
{
2019-12-13 11:07:03 -05:00
FArrayProperty * ArrayProperty = FindFieldChecked < FArrayProperty > ( NodeType , GET_MEMBER_NAME_CHECKED ( FAnimNode_LinkedAnimGraph , InputPoses ) ) ;
2019-05-22 12:00:20 -04:00
int32 ArrayIndex = INDEX_NONE ;
if ( Node . InputPoseNames . Find ( SourcePin - > GetFName ( ) , ArrayIndex ) )
{
check ( Node . InputPoses . IsValidIndex ( ArrayIndex ) ) ;
return FPoseLinkMappingRecord : : MakeFromArrayEntry ( this , LinkedNode , ArrayProperty , ArrayIndex ) ;
}
}
}
return FPoseLinkMappingRecord : : MakeInvalid ( ) ;
}
2021-01-06 09:11:59 -04:00
void UAnimGraphNode_LinkedAnimGraphBase : : GetOutputLinkAttributes ( FNodeAttributeArray & OutAttributes ) const
{
// We have the potential to output ALL registered attributes as we can contain any dynamically-linked graph
const UAnimGraphAttributes * AnimGraphAttributes = GetDefault < UAnimGraphAttributes > ( ) ;
AnimGraphAttributes - > ForEachAttribute ( [ & OutAttributes ] ( const FAnimGraphAttributeDesc & InDesc )
{
OutAttributes . Add ( InDesc . Name ) ;
} ) ;
}
2021-01-25 08:43:19 -04:00
void UAnimGraphNode_LinkedAnimGraphBase : : OnCopyTermDefaultsToDefaultObject ( IAnimBlueprintCopyTermDefaultsContext & InCompilationContext , IAnimBlueprintNodeCopyTermDefaultsContext & InPerNodeContext , IAnimBlueprintGeneratedClassCompiledData & OutCompiledData )
{
2021-06-17 08:59:23 -04:00
Super : : OnCopyTermDefaultsToDefaultObject ( InCompilationContext , InPerNodeContext , OutCompiledData ) ;
2021-01-25 08:43:19 -04:00
UAnimGraphNode_LinkedAnimGraphBase * TrueNode = InCompilationContext . GetMessageLog ( ) . FindSourceObjectTypeChecked < UAnimGraphNode_LinkedAnimGraphBase > ( this ) ;
FAnimNode_LinkedAnimGraph * DestinationNode = reinterpret_cast < FAnimNode_LinkedAnimGraph * > ( InPerNodeContext . GetDestinationPtr ( ) ) ;
DestinationNode - > NodeIndex = InPerNodeContext . GetNodePropertyIndex ( ) ;
}
2021-04-22 04:57:09 -04:00
void UAnimGraphNode_LinkedAnimGraphBase : : GetRequiredExtensions ( TArray < TSubclassOf < UAnimBlueprintExtension > > & OutExtensions ) const
{
OutExtensions . Add ( UAnimBlueprintExtension_LinkedAnimGraph : : StaticClass ( ) ) ;
}
2021-05-24 06:55:32 -04:00
TSharedPtr < FEdGraphSchemaAction > UAnimGraphNode_LinkedAnimGraphBase : : GetEventNodeAction ( const FText & ActionCategory )
{
TSharedPtr < FEdGraphSchemaAction_K2Event > NodeAction = MakeShareable ( new FEdGraphSchemaAction_K2Event ( ActionCategory , GetNodeTitle ( ENodeTitleType : : ListView ) , GetTooltipText ( ) , 0 ) ) ;
NodeAction - > NodeTemplate = this ;
return NodeAction ;
}
2019-05-22 12:00:20 -04:00
# undef LOCTEXT_NAMESPACE