178 lines
5.3 KiB
C++
178 lines
5.3 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "AnimGraphNode_PoseBlendNode.h"
|
|
#include "EdGraphSchema_K2_Actions.h"
|
|
#include "Modules/ModuleManager.h"
|
|
#include "ToolMenus.h"
|
|
|
|
#include "AnimGraphCommands.h"
|
|
#include "AssetRegistry/ARFilter.h"
|
|
#include "AssetRegistry/AssetRegistryModule.h"
|
|
#include "BlueprintActionFilter.h"
|
|
#include "BlueprintActionDatabaseRegistrar.h"
|
|
#include "BlueprintNodeSpawner.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "PoseBlendNode"
|
|
|
|
// Action to add a pose asset blend node to the graph
|
|
struct FNewPoseBlendNodeAction : public FEdGraphSchemaAction_K2NewNode
|
|
{
|
|
protected:
|
|
FAssetData AssetInfo;
|
|
public:
|
|
FNewPoseBlendNodeAction(const FAssetData& InAssetInfo, FText Title)
|
|
: FEdGraphSchemaAction_K2NewNode(LOCTEXT("PoseAsset", "PoseAssets"), Title, LOCTEXT("EvalCurvesToMakePose", "Evaluates curves to produce a pose from pose asset"), 0, FText::FromString(InAssetInfo.GetObjectPathString()))
|
|
{
|
|
AssetInfo = InAssetInfo;
|
|
|
|
UAnimGraphNode_PoseBlendNode* Template = NewObject<UAnimGraphNode_PoseBlendNode>();
|
|
NodeTemplate = Template;
|
|
}
|
|
|
|
virtual UEdGraphNode* PerformAction(class UEdGraph* ParentGraph, UEdGraphPin* FromPin, const FVector2f& Location, bool bSelectNewNode = true) override
|
|
{
|
|
UAnimGraphNode_PoseBlendNode* SpawnedNode = CastChecked<UAnimGraphNode_PoseBlendNode>(FEdGraphSchemaAction_K2NewNode::PerformAction(ParentGraph, FromPin, Location, bSelectNewNode));
|
|
SpawnedNode->Node.PoseAsset = Cast<UPoseAsset>(AssetInfo.GetAsset());
|
|
|
|
return SpawnedNode;
|
|
}
|
|
};
|
|
/////////////////////////////////////////////////////
|
|
// UAnimGraphNode_PoseBlendNode
|
|
|
|
UAnimGraphNode_PoseBlendNode::UAnimGraphNode_PoseBlendNode(const FObjectInitializer& ObjectInitializer)
|
|
: Super(ObjectInitializer)
|
|
{
|
|
}
|
|
|
|
void UAnimGraphNode_PoseBlendNode::GetAllAnimationSequencesReferred(TArray<UAnimationAsset*>& AnimationAssets) const
|
|
{
|
|
if(Node.PoseAsset)
|
|
{
|
|
HandleAnimReferenceCollection(Node.PoseAsset, AnimationAssets);
|
|
}
|
|
}
|
|
|
|
void UAnimGraphNode_PoseBlendNode::ReplaceReferredAnimations(const TMap<UAnimationAsset*, UAnimationAsset*>& AnimAssetReplacementMap)
|
|
{
|
|
HandleAnimReferenceReplacement(Node.PoseAsset, AnimAssetReplacementMap);
|
|
}
|
|
|
|
FText UAnimGraphNode_PoseBlendNode::GetTooltipText() const
|
|
{
|
|
// FText::Format() is slow, so we utilize the cached list title
|
|
return GetNodeTitle(ENodeTitleType::ListView);
|
|
}
|
|
|
|
FText UAnimGraphNode_PoseBlendNode::GetNodeTitleForPoseAsset(ENodeTitleType::Type TitleType, UPoseAsset* InPoseAsset) const
|
|
{
|
|
FFormatNamedArguments Args;
|
|
Args.Add(TEXT("PoseAssetName"), FText::FromString(InPoseAsset->GetName()));
|
|
|
|
return FText::Format(LOCTEXT("PoseByName_Title", "{PoseAssetName}"), Args);
|
|
}
|
|
|
|
FText UAnimGraphNode_PoseBlendNode::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
|
{
|
|
if (Node.PoseAsset == nullptr)
|
|
{
|
|
// we may have a valid variable connected or default pin value
|
|
UEdGraphPin* PosePin = FindPin(GET_MEMBER_NAME_STRING_CHECKED(FAnimNode_PoseBlendNode, PoseAsset));
|
|
if (PosePin && PosePin->LinkedTo.Num() > 0)
|
|
{
|
|
return LOCTEXT("PoseByName_TitleVariable", "Pose");
|
|
}
|
|
else if (PosePin && PosePin->DefaultObject != nullptr)
|
|
{
|
|
return GetNodeTitleForPoseAsset(TitleType, CastChecked<UPoseAsset>(PosePin->DefaultObject));
|
|
}
|
|
else
|
|
{
|
|
return LOCTEXT("PoseByName_TitleNONE", "Pose (None)");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return GetNodeTitleForPoseAsset(TitleType, Node.PoseAsset);
|
|
}
|
|
}
|
|
|
|
void UAnimGraphNode_PoseBlendNode::GetMenuActions(FBlueprintActionDatabaseRegistrar& InActionRegistrar) const
|
|
{
|
|
GetMenuActionsHelper(
|
|
InActionRegistrar,
|
|
GetClass(),
|
|
{ UPoseAsset::StaticClass() },
|
|
{ },
|
|
[](const FAssetData& InAssetData, UClass* InClass)
|
|
{
|
|
if(InAssetData.IsValid())
|
|
{
|
|
return GetTitleGivenAssetInfo(FText::FromName(InAssetData.AssetName));
|
|
}
|
|
else
|
|
{
|
|
return LOCTEXT("PlayerDesc", "Evaluate Pose");
|
|
}
|
|
},
|
|
[](const FAssetData& InAssetData, UClass* InClass)
|
|
{
|
|
if(InAssetData.IsValid())
|
|
{
|
|
return GetTitleGivenAssetInfo(FText::FromName(InAssetData.AssetName));
|
|
}
|
|
else
|
|
{
|
|
return LOCTEXT("PlayerDescTooltip", "Evaluate Pose Asset");
|
|
}
|
|
},
|
|
[](UEdGraphNode* InNewNode, bool bInIsTemplateNode, const FAssetData InAssetData)
|
|
{
|
|
UAnimGraphNode_AssetPlayerBase::SetupNewNode(InNewNode, bInIsTemplateNode, InAssetData);
|
|
});
|
|
}
|
|
|
|
FText UAnimGraphNode_PoseBlendNode::GetTitleGivenAssetInfo(const FText& AssetName)
|
|
{
|
|
FFormatNamedArguments Args;
|
|
Args.Add(TEXT("AssetName"), AssetName);
|
|
|
|
return FText::Format(LOCTEXT("PoseAssetNodeTitle", "Evaluate Pose {AssetName}"), Args);
|
|
}
|
|
|
|
FText UAnimGraphNode_PoseBlendNode::GetMenuCategory() const
|
|
{
|
|
return LOCTEXT("PoseAssetCategory_Label", "Animation|Poses");
|
|
}
|
|
|
|
bool UAnimGraphNode_PoseBlendNode::DoesSupportTimeForTransitionGetter() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void UAnimGraphNode_PoseBlendNode::GetNodeContextMenuActions(UToolMenu* Menu, UGraphNodeContextMenuContext* Context) const
|
|
{
|
|
if (!Context->bIsDebugging)
|
|
{
|
|
// add an option to convert to single frame
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("AnimGraphNodePoseBlender", LOCTEXT("PoseBlenderHeading", "Pose Blender"));
|
|
Section.AddMenuEntry(FAnimGraphCommands::Get().ConvertToPoseByName);
|
|
}
|
|
}
|
|
}
|
|
|
|
EAnimAssetHandlerType UAnimGraphNode_PoseBlendNode::SupportsAssetClass(const UClass* AssetClass) const
|
|
{
|
|
if (AssetClass->IsChildOf(UPoseAsset::StaticClass()))
|
|
{
|
|
return EAnimAssetHandlerType::PrimaryHandler;
|
|
}
|
|
else
|
|
{
|
|
return EAnimAssetHandlerType::NotSupported;
|
|
}
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|