Files
UnrealEngineUWP/Engine/Source/Editor/AnimGraph/Private/AnimGraphNode_RotationOffsetBlendSpace.cpp
Michael Schoell 63b7360ae0 Removed the Blueprint Editor's legacy node menu system.
#jira UE-13391 - Delete old BP menu system (is causing confusion)

#codereview Mike.Beach

[CL 2514361 by Michael Schoell in Main branch]
2015-04-16 11:47:54 -04:00

150 lines
5.6 KiB
C++

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#include "AnimGraphPrivatePCH.h"
#include "AnimGraphNode_RotationOffsetBlendSpace.h"
#include "GraphEditorActions.h"
#include "CompilerResultsLog.h"
#include "BlueprintNodeSpawner.h"
#include "BlueprintActionDatabaseRegistrar.h"
/////////////////////////////////////////////////////
// UAnimGraphNode_RotationOffsetBlendSpace
#define LOCTEXT_NAMESPACE "A3Nodes"
UAnimGraphNode_RotationOffsetBlendSpace::UAnimGraphNode_RotationOffsetBlendSpace(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
FText UAnimGraphNode_RotationOffsetBlendSpace::GetTooltipText() const
{
// FText::Format() is slow, so we utilize the cached list title
return GetNodeTitle(ENodeTitleType::ListView);
}
FText UAnimGraphNode_RotationOffsetBlendSpace::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
if (Node.BlendSpace == nullptr)
{
if (TitleType == ENodeTitleType::ListView || TitleType == ENodeTitleType::MenuTitle)
{
return LOCTEXT("RotationOffsetBlend_NONE_ListTitle", "AimOffset '(None)'");
}
else
{
return LOCTEXT("RotationOffsetBlend_NONE_Title", "(None)\nAimOffset");
}
}
// @TODO: the bone can be altered in the property editor, so we have to
// choose to mark this dirty when that happens for this to properly work
else //if (!CachedNodeTitles.IsTitleCached(TitleType, this))
{
const FText BlendSpaceName = FText::FromString(Node.BlendSpace->GetName());
FFormatNamedArguments Args;
Args.Add(TEXT("BlendSpaceName"), BlendSpaceName);
// FText::Format() is slow, so we cache this to save on performance
if (TitleType == ENodeTitleType::ListView || TitleType == ENodeTitleType::MenuTitle)
{
CachedNodeTitles.SetCachedTitle(TitleType, FText::Format(LOCTEXT("AimOffsetListTitle", "AimOffset '{BlendSpaceName}'"), Args), this);
}
else
{
CachedNodeTitles.SetCachedTitle(TitleType, FText::Format(LOCTEXT("AimOffsetFullTitle", "{BlendSpaceName}\nAimOffset"), Args), this);
}
}
return CachedNodeTitles[TitleType];
}
void UAnimGraphNode_RotationOffsetBlendSpace::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
{
auto PostSpawnSetupLambda = [](UEdGraphNode* NewNode, bool /*bIsTemplateNode*/, TWeakObjectPtr<UBlendSpaceBase> BlendSpace)
{
UAnimGraphNode_RotationOffsetBlendSpace* BlendSpaceNode = CastChecked<UAnimGraphNode_RotationOffsetBlendSpace>(NewNode);
BlendSpaceNode->Node.BlendSpace = BlendSpace.Get();
};
for (TObjectIterator<UBlendSpaceBase> BlendSpaceIt; BlendSpaceIt; ++BlendSpaceIt)
{
UBlendSpaceBase* BlendSpace = *BlendSpaceIt;
// to keep from needlessly instantiating a UBlueprintNodeSpawner, first
// check to make sure that the registrar is looking for actions of this type
// (could be regenerating actions for a specific asset, and therefore the
// registrar would only accept actions corresponding to that asset)
if (!ActionRegistrar.IsOpenForRegistration(BlendSpace))
{
continue;
}
bool const bIsAimOffset = BlendSpace->IsA(UAimOffsetBlendSpace::StaticClass()) ||
BlendSpace->IsA(UAimOffsetBlendSpace1D::StaticClass());
if (bIsAimOffset)
{
UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create(GetClass());
check(NodeSpawner != nullptr);
ActionRegistrar.AddBlueprintAction(BlendSpace, NodeSpawner);
TWeakObjectPtr<UBlendSpaceBase> BlendSpacePtr = BlendSpace;
NodeSpawner->CustomizeNodeDelegate = UBlueprintNodeSpawner::FCustomizeNodeDelegate::CreateStatic(PostSpawnSetupLambda, BlendSpacePtr);
}
}
}
FBlueprintNodeSignature UAnimGraphNode_RotationOffsetBlendSpace::GetSignature() const
{
FBlueprintNodeSignature NodeSignature = Super::GetSignature();
NodeSignature.AddSubObject(Node.BlendSpace);
return NodeSignature;
}
void UAnimGraphNode_RotationOffsetBlendSpace::ValidateAnimNodeDuringCompilation(class USkeleton* ForSkeleton, class FCompilerResultsLog& MessageLog)
{
if (Node.BlendSpace == NULL)
{
MessageLog.Error(TEXT("@@ references an unknown blend space"), this);
}
else if (Cast<UAimOffsetBlendSpace>(Node.BlendSpace) == NULL &&
Cast<UAimOffsetBlendSpace1D>(Node.BlendSpace) == NULL)
{
MessageLog.Error(TEXT("@@ references an invalid blend space (one that is not an aim offset)"), this);
}
else
{
USkeleton* BlendSpaceSkeleton = Node.BlendSpace->GetSkeleton();
if (BlendSpaceSkeleton && // if blend space doesn't have skeleton, it might be due to blend space not loaded yet, @todo: wait with anim blueprint compilation until all assets are loaded?
!BlendSpaceSkeleton->IsCompatible(ForSkeleton))
{
MessageLog.Error(TEXT("@@ references blendspace that uses different skeleton @@"), this, BlendSpaceSkeleton);
}
}
}
void UAnimGraphNode_RotationOffsetBlendSpace::GetContextMenuActions(const FGraphNodeContextMenuBuilder& Context) const
{
if (!Context.bIsDebugging)
{
// add an option to convert to single frame
Context.MenuBuilder->BeginSection("AnimGraphNodeBlendSpacePlayer", NSLOCTEXT("A3Nodes", "BlendSpaceHeading", "Blend Space"));
{
Context.MenuBuilder->AddMenuEntry(FGraphEditorCommands::Get().OpenRelatedAsset);
}
Context.MenuBuilder->EndSection();
}
}
void UAnimGraphNode_RotationOffsetBlendSpace::GetAllAnimationSequencesReferred(TArray<UAnimationAsset*>& ComplexAnims, TArray<UAnimSequence*>& AnimationSequences) const
{
if(Node.BlendSpace)
{
HandleAnimReferenceCollection(Node.BlendSpace, ComplexAnims, AnimationSequences);
}
}
void UAnimGraphNode_RotationOffsetBlendSpace::ReplaceReferredAnimations(const TMap<UAnimationAsset*, UAnimationAsset*>& ComplexAnimsMap, const TMap<UAnimSequence*, UAnimSequence*>& AnimSequenceMap)
{
HandleAnimReferenceReplacement(Node.BlendSpace, ComplexAnimsMap, AnimSequenceMap);
}
#undef LOCTEXT_NAMESPACE