Files
UnrealEngineUWP/Engine/Source/Editor/AnimGraph/Private/AnimGraphNode_MultiWayBlend.cpp
Thomas Sarkanen 8ba3c4c087 Merging //UE4/Dev-Main to Dev-Anim (//UE4/Dev-Anim) @ CL 4643671
#rb none
#jira none

[CL 4665410 by Thomas Sarkanen in Dev-Anim branch]
2018-12-17 06:31:16 -05:00

176 lines
5.2 KiB
C++

// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "AnimGraphNode_MultiWayBlend.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "GraphEditorActions.h"
#include "ScopedTransaction.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
/////////////////////////////////////////////////////
// UAnimGraphNode_MultiWayBlend
#define LOCTEXT_NAMESPACE "AnimGraphNode_MultiWayBlend"
UAnimGraphNode_MultiWayBlend::UAnimGraphNode_MultiWayBlend(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
FString UAnimGraphNode_MultiWayBlend::GetNodeCategory() const
{
return TEXT("Blends");
}
FLinearColor UAnimGraphNode_MultiWayBlend::GetNodeTitleColor() const
{
return FLinearColor(0.75f, 0.75f, 0.75f);
}
FText UAnimGraphNode_MultiWayBlend::GetTooltipText() const
{
return LOCTEXT("MultiWayBlendTooltip", "Blend multiple poses together by Alpha");
}
FText UAnimGraphNode_MultiWayBlend::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
return LOCTEXT("Blend", "Blend Multi");
}
void UAnimGraphNode_MultiWayBlend::GetContextMenuActions(const FGraphNodeContextMenuBuilder& Context) const
{
if (!Context.bIsDebugging)
{
Context.MenuBuilder->BeginSection("AnimGraphBlendMulti", LOCTEXT("BlendMultiHeader", "BlendMulti"));
{
if (Context.Pin != NULL)
{
// we only do this for normal BlendMulti/BlendMulti by enum, BlendMulti by Bool doesn't support add/remove pins
if (Context.Pin->Direction == EGPD_Input)
{
Context.MenuBuilder->AddMenuEntry(FGraphEditorCommands::Get().RemoveBlendListPin);
}
}
else
{
Context.MenuBuilder->AddMenuEntry(FGraphEditorCommands::Get().AddBlendListPin);
}
}
Context.MenuBuilder->EndSection();
}
}
void UAnimGraphNode_MultiWayBlend::AddPinToBlendNode()
{
FScopedTransaction Transaction(LOCTEXT("AddBlendMultiPin", "AddBlendMultiPin"));
Modify();
Node.AddPose();
ReconstructNode();
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetBlueprint());
}
void UAnimGraphNode_MultiWayBlend::RemovePinFromBlendNode(UEdGraphPin* Pin)
{
FScopedTransaction Transaction(LOCTEXT("RemoveBlendMultiPin", "RemoveBlendMultiPin"));
Modify();
UProperty* AssociatedProperty;
int32 ArrayIndex;
GetPinAssociatedProperty(GetFNodeType(), Pin, /*out*/ AssociatedProperty, /*out*/ ArrayIndex);
if (ArrayIndex != INDEX_NONE)
{
//@TODO: ANIMREFACTOR: Need to handle moving pins below up correctly
// setting up removed pins info
RemovedPinArrayIndex = ArrayIndex;
Node.RemovePose(ArrayIndex);
// removes the selected pin and related properties in reconstructNode()
// @TODO: Considering passing "RemovedPinArrayIndex" to ReconstructNode as the argument
ReconstructNode();
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetBlueprint());
}
}
void UAnimGraphNode_MultiWayBlend::PostPlacedNewNode()
{
// Make sure we start out with two inputs
Node.AddPose();
Node.AddPose();
ReconstructNode();
}
void UAnimGraphNode_MultiWayBlend::ReallocatePinsDuringReconstruction(TArray<UEdGraphPin*>& OldPins)
{
Super::ReallocatePinsDuringReconstruction(OldPins);
// Delete Pins by removed pin info
if (RemovedPinArrayIndex != INDEX_NONE)
{
RemovePinsFromOldPins(OldPins, RemovedPinArrayIndex);
// Clears removed pin info to avoid to remove multiple times
// @TODO : Considering receiving RemovedPinArrayIndex as an argument of ReconstructNode()
RemovedPinArrayIndex = INDEX_NONE;
}
}
void UAnimGraphNode_MultiWayBlend::RemovePinsFromOldPins(TArray<UEdGraphPin*>& OldPins, int32 RemovedArrayIndex)
{
TArray<FString> RemovedPropertyNames;
TArray<FName> NewPinNames;
// Store new pin names to compare with old pin names
for (int32 NewPinIndx = 0; NewPinIndx < Pins.Num(); NewPinIndx++)
{
NewPinNames.Add(Pins[NewPinIndx]->PinName);
}
// don't know which pins are removed yet so find removed pins comparing NewPins and OldPins
for (int32 OldPinIdx = 0; OldPinIdx < OldPins.Num(); OldPinIdx++)
{
const FName OldPinName = OldPins[OldPinIdx]->PinName;
if (!NewPinNames.Contains(OldPinName))
{
const FString OldPinNameStr = OldPinName.ToString();
const int32 UnderscoreIndex = OldPinNameStr.Find(TEXT("_"), ESearchCase::CaseSensitive);
if (UnderscoreIndex != INDEX_NONE)
{
FString PropertyName = OldPinNameStr.Left(UnderscoreIndex);
RemovedPropertyNames.Add(MoveTemp(PropertyName));
}
}
}
for (int32 PinIdx = 0; PinIdx < OldPins.Num(); PinIdx++)
{
// Separate the pin name into property name and index
const FString OldPinNameStr = OldPins[PinIdx]->PinName.ToString();
const int32 UnderscoreIndex = OldPinNameStr.Find(TEXT("_"), ESearchCase::CaseSensitive);
if (UnderscoreIndex != INDEX_NONE)
{
const FString PropertyName = OldPinNameStr.Left(UnderscoreIndex);
if (RemovedPropertyNames.Contains(PropertyName))
{
const int32 ArrayIndex = FCString::Atoi(*(OldPinNameStr.Mid(UnderscoreIndex + 1)));
// if array index is matched, removes pins
// and if array index is greater than removed index, decrease index
if (ArrayIndex == RemovedArrayIndex)
{
OldPins[PinIdx]->MarkPendingKill();
OldPins.RemoveAt(PinIdx);
--PinIdx;
}
else if (ArrayIndex > RemovedArrayIndex)
{
OldPins[PinIdx]->PinName = *FString::Printf(TEXT("%s_%d"), *PropertyName, ArrayIndex - 1);
}
}
}
}
}
#undef LOCTEXT_NAMESPACE