Files
UnrealEngineUWP/Engine/Source/Editor/AnimationModifiers/Private/SAnimationModifierContentBrowserWindow.cpp
Chris Gagnon 1dd3e0189f Merging //UE4/Dev-Main to Dev-Editor (//UE4/Dev-Editor)
#rb none

[CL 4730305 by Chris Gagnon in Dev-Editor branch]
2019-01-15 18:47:22 -05:00

267 lines
8.4 KiB
C++

// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "SAnimationModifierContentBrowserWindow.h"
#include "AnimationModifierHelpers.h"
#include "Widgets/SOverlay.h"
#include "Widgets/SBoxPanel.h"
#include "Widgets/Layout/SBorder.h"
#include "Widgets/Layout/SUniformGridPanel.h"
#include "Widgets/Input/SComboButton.h"
#include "Widgets/Text/STextBlock.h"
#include "EditorStyleSet.h"
#include "SModifierListview.h"
#include "PropertyEditorModule.h"
#include "Animation/AnimSequence.h"
#include "AnimationModifiersAssetUserData.h"
#include "Dialogs/Dialogs.h"
#include "ScopedTransaction.h"
#define LOCTEXT_NAMESPACE "AnimationModifierContentBrowserWindow"
void SAnimationModifierContentBrowserWindow::Construct(const FArguments& InArgs)
{
CreateInstanceDetailsView();
WidgetWindow = InArgs._WidgetWindow;
AnimSequences = InArgs._AnimSequences;
FOnGetContent GetContent = FOnGetContent::CreateLambda(
[this]()
{
return FAnimationModifierHelpers::GetModifierPicker(FOnClassPicked::CreateRaw(this, &SAnimationModifierContentBrowserWindow::OnModifierPicked));
});
this->ChildSlot
[
SNew(SOverlay)
+SOverlay::Slot()
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SBorder)
.Padding(2.0f)
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.Padding(3.0f, 3.0f)
.AutoWidth()
[
SAssignNew(AddModifierCombobox, SComboButton)
.OnGetMenuContent(GetContent)
.ButtonContent()
[
SNew(STextBlock)
.Text(LOCTEXT("AnimationModifierWindow_AddModifier", "Add Modifier"))
]
]
]
]
+ SVerticalBox::Slot()
[
SNew(SBorder)
.Padding(2.0f)
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
[
SNew(SSplitter)
.Orientation(EOrientation::Orient_Vertical)
+ SSplitter::Slot()
.Value(.5f)
[
SNew(SBox)
.Padding(2.0f)
[
SAssignNew(ModifierListView, SModifierListView)
.Items(&ModifierItems)
.InstanceDetailsView(ModifierInstanceDetailsView)
.OnRemoveModifier(FOnModifierArray::CreateSP(this, &SAnimationModifierContentBrowserWindow::RemoveModifiersCallback))
]
]
+ SSplitter::Slot()
.Value(.5f)
[
SNew(SBox)
.Padding(2.0f)
[
ModifierInstanceDetailsView->AsShared()
]
]
]
]
+ SVerticalBox::Slot()
.AutoHeight()
.HAlign(HAlign_Right)
.Padding(2)
[
SNew(SUniformGridPanel)
.SlotPadding(2)
+ SUniformGridPanel::Slot(0, 0)
[
SNew(SButton)
.HAlign(HAlign_Center)
.Text(LOCTEXT("AnimationModifierWindow_Import", "Apply"))
.ToolTipText(LOCTEXT("AnimationModifierWindow_Import_ToolTip", "Apply adding modifiers(s)."))
.IsEnabled(this, &SAnimationModifierContentBrowserWindow::CanApply)
.OnClicked(this, &SAnimationModifierContentBrowserWindow::OnApply)
]
+ SUniformGridPanel::Slot(1, 0)
[
SNew(SButton)
.HAlign(HAlign_Center)
.Text(LOCTEXT("AnimationModifierWindow_Cancel", "Cancel"))
.ToolTipText(LOCTEXT("AnimationModifierWindow_Cancel_ToolTip", "Cancels adding modifiers(s)."))
.OnClicked(this, &SAnimationModifierContentBrowserWindow::OnCancel)
]
]
]
];
}
FReply SAnimationModifierContentBrowserWindow::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent)
{
if (InKeyEvent.GetKey() == EKeys::Escape)
{
return OnCancel();
}
return FReply::Unhandled();
}
void SAnimationModifierContentBrowserWindow::RemoveModifiersCallback(const TArray<TWeakObjectPtr<UAnimationModifier>>& ModifiersToRemove)
{
Modifiers.RemoveAll([&ModifiersToRemove](UAnimationModifier* Modifier) { return ModifiersToRemove.Contains(Modifier); });
ModifierItems.RemoveAll([&ModifiersToRemove](TSharedPtr<FModifierListviewItem> ModifierItem) { return ModifiersToRemove.Contains(ModifierItem->Instance); });
ModifierListView->Refresh();
}
void SAnimationModifierContentBrowserWindow::OnModifierPicked(UClass* PickedClass)
{
UAnimationModifier* Processor = FAnimationModifierHelpers::CreateModifierInstance(GetTransientPackage(), PickedClass);
Modifiers.Add(Processor);
FModifierListviewItem* Item = new FModifierListviewItem();
Item->Instance = Processor;
Item->Class = Processor->GetClass();
Item->Index = Modifiers.Num() - 1;
Item->OuterClass = nullptr;
ModifierItems.Add(ModifierListviewItem(Item));
// Close the combo box
AddModifierCombobox->SetIsOpen(false);
ModifierListView->Refresh();
}
void SAnimationModifierContentBrowserWindow::CreateInstanceDetailsView()
{
// Create a property view
FPropertyEditorModule& EditModule = FModuleManager::Get().GetModuleChecked<FPropertyEditorModule>("PropertyEditor");
FDetailsViewArgs DetailsViewArgs(
/*bUpdateFromSelection=*/ false,
/*bLockable=*/ false,
/*bAllowSearch=*/ false,
FDetailsViewArgs::HideNameArea,
/*bHideSelectionTip=*/ true,
/*InNotifyHook=*/ nullptr,
/*InSearchInitialKeyFocus=*/ false,
/*InViewIdentifier=*/ NAME_None);
DetailsViewArgs.DefaultsOnlyVisibility = EEditDefaultsOnlyNodeVisibility::Automatic;
DetailsViewArgs.bShowOptions = false;
ModifierInstanceDetailsView = EditModule.CreateDetailView(DetailsViewArgs);
ModifierInstanceDetailsView->SetDisableCustomDetailLayouts(true);
}
FReply SAnimationModifierContentBrowserWindow::OnApply()
{
const FScopedTransaction Transaction(LOCTEXT("UndoAction_ApplyModifiers", "Applying Animation Modifier(s) to Animation Sequence(s)"));
TArray<UAnimationModifiersAssetUserData*> AssetUserData;
bool bCloseWindow = true;
// Retrieve or create asset user data
for (UAnimSequence* AnimationSequence : AnimSequences)
{
UAnimationModifiersAssetUserData* UserData = AnimationSequence->GetAssetUserData<UAnimationModifiersAssetUserData>();
if (!UserData)
{
UserData = NewObject<UAnimationModifiersAssetUserData>(AnimationSequence, UAnimationModifiersAssetUserData::StaticClass());
checkf(UserData, TEXT("Unable to instantiate AssetUserData class"));
UserData->SetFlags(RF_Transactional);
AnimationSequence->AddAssetUserData(UserData);
}
AssetUserData.Add(UserData);
}
// For each added modifier create add a new instance to each of the user data entries, using the one(s) set up in the window as template(s)
for (UAnimationModifier* Modifier : Modifiers)
{
for (UAnimationModifiersAssetUserData* UserData : AssetUserData)
{
const bool bAlreadyContainsModifier = UserData->GetAnimationModifierInstances().ContainsByPredicate([Modifier](UAnimationModifier* TestModifier) { return Modifier->GetClass() == TestModifier->GetClass(); });
static const FText MessageFormat = LOCTEXT("AnimationModifierWindow_AlreadyContainsModifierDialogText", "{0} already contains Animation Modifier {1}, are you sure you want to add another instance?");
const bool bUserInputResult = bAlreadyContainsModifier ? OpenMsgDlgInt(EAppMsgType::YesNo, FText::FormatOrdered(MessageFormat, FText::FromString(UserData->GetOuter()->GetName()), FText::FromString(Modifier->GetClass()->GetName())), LOCTEXT("AnimationModifierWindow_AlreadyContainsModifierTitle", "Already contains Animation Modifier!")) == EAppReturnType::Yes : true;
bCloseWindow = bUserInputResult;
if (!bAlreadyContainsModifier || bUserInputResult)
{
UObject* Outer = UserData;
UAnimationModifier* Processor = FAnimationModifierHelpers::CreateModifierInstance(Outer, Modifier->GetClass(), Modifier);
UserData->Modify();
UserData->AddAnimationModifier(Processor);
}
}
}
/** For each user data retrieve all modifiers and apply them */
for (int32 Index = 0; Index < AssetUserData.Num(); ++Index)
{
UAnimationModifiersAssetUserData* UserData = AssetUserData[Index];
if (UserData)
{
UAnimSequence* AnimSequence = AnimSequences[Index];
AnimSequence->Modify();
const TArray<UAnimationModifier*>& ModifierInstances = UserData->GetAnimationModifierInstances();
for (UAnimationModifier* Modifier : ModifierInstances)
{
Modifier->ApplyToAnimationSequence(AnimSequence);
}
}
}
if (bCloseWindow && WidgetWindow.IsValid())
{
WidgetWindow.Pin()->RequestDestroyWindow();
}
return FReply::Handled();
}
FReply SAnimationModifierContentBrowserWindow::OnCancel()
{
if (WidgetWindow.IsValid())
{
WidgetWindow.Pin()->RequestDestroyWindow();
}
return FReply::Handled();
}
bool SAnimationModifierContentBrowserWindow::CanApply() const
{
return Modifiers.Num() > 0;
}
#undef LOCTEXT_NAMESPACE // "AnimationModifierContentBrowserWindow"