// 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 BlendSpace) { UAnimGraphNode_RotationOffsetBlendSpace* BlendSpaceNode = CastChecked(NewNode); BlendSpaceNode->Node.BlendSpace = BlendSpace.Get(); }; for (TObjectIterator 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 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(Node.BlendSpace) == NULL && Cast(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& ComplexAnims, TArray& AnimationSequences) const { if(Node.BlendSpace) { HandleAnimReferenceCollection(Node.BlendSpace, ComplexAnims, AnimationSequences); } } void UAnimGraphNode_RotationOffsetBlendSpace::ReplaceReferredAnimations(const TMap& ComplexAnimsMap, const TMap& AnimSequenceMap) { HandleAnimReferenceReplacement(Node.BlendSpace, ComplexAnimsMap, AnimSequenceMap); } #undef LOCTEXT_NAMESPACE