Files
UnrealEngineUWP/Engine/Source/Editor/AnimationModifiers/Private/AnimationModifiersModule.cpp
Jurre deBaare 635f35f41e Option to apply Animation Modifiers to only new or changed animations
#feature add ability to only apply out-of-date animation modifiers from asset context menu, and through details view on AnimationModifier classes
#fix ensure that we do not apply pending kill modifiers or instances that are used for reverting
#jira UE-84819
#rb Thomas.Sarkanen
#preflight 60cb38fd6092ba000140842e

[CL 16704034 by Jurre deBaare in ue5-main branch]
2021-06-17 09:49:44 -04:00

130 lines
4.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "AnimationModifiersModule.h"
#include "IAssetTools.h"
#include "Animation/AnimSequence.h"
#include "AnimationModifier.h"
#include "SAnimationModifiersTab.h"
#include "AnimationModifierDetailCustomization.h"
#include "AnimationModifiersTabSummoner.h"
#include "Modules/ModuleManager.h"
#include "PropertyEditorModule.h"
#include "SAnimationModifierContentBrowserWindow.h"
#include "ScopedTransaction.h"
#include "Framework/Application/SlateApplication.h"
#include "Interfaces/IMainFrameModule.h"
#include "AnimationModifiersAssetUserData.h"
#define LOCTEXT_NAMESPACE "AnimationModifiersModule"
IMPLEMENT_MODULE(FAnimationModifiersModule, AnimationModifiers);
void FAnimationModifiersModule::StartupModule()
{
// Register class/struct customizations
FPropertyEditorModule& PropertyEditorModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
PropertyEditorModule.RegisterCustomClassLayout("AnimationModifier", FOnGetDetailCustomizationInstance::CreateStatic(&FAnimationModifierDetailCustomization::MakeInstance));
// Add application mode extender
Extender = FWorkflowApplicationModeExtender::CreateRaw(this, &FAnimationModifiersModule::ExtendApplicationMode);
FWorkflowCentricApplication::GetModeExtenderList().Add(Extender);
}
TSharedRef<FApplicationMode> FAnimationModifiersModule::ExtendApplicationMode(const FName ModeName, TSharedRef<FApplicationMode> InMode)
{
// For skeleton and animation editor modes add our custom tab factory to it
if (ModeName == TEXT("SkeletonEditorMode") || ModeName == TEXT("AnimationEditorMode"))
{
InMode->AddTabFactory(FCreateWorkflowTabFactory::CreateStatic(&FAnimationModifiersTabSummoner::CreateFactory));
RegisteredApplicationModes.Add(InMode);
}
return InMode;
}
void FAnimationModifiersModule::ShutdownModule()
{
// Make sure we unregister the class layout
FPropertyEditorModule* PropertyEditorModule = FModuleManager::GetModulePtr<FPropertyEditorModule>("PropertyEditor");
if (PropertyEditorModule)
{
PropertyEditorModule->UnregisterCustomClassLayout("AnimationModifier");
}
// Remove extender delegate
FWorkflowCentricApplication::GetModeExtenderList().RemoveAll([this](FWorkflowApplicationModeExtender& StoredExtender) { return StoredExtender.GetHandle() == Extender.GetHandle(); });
// During shutdown clean up all factories from any modes which are still active/alive
for (TWeakPtr<FApplicationMode> WeakMode : RegisteredApplicationModes)
{
if (WeakMode.IsValid())
{
TSharedPtr<FApplicationMode> Mode = WeakMode.Pin();
Mode->RemoveTabFactory(FAnimationModifiersTabSummoner::AnimationModifiersName);
}
}
RegisteredApplicationModes.Empty();
}
void FAnimationModifiersModule::ShowAddAnimationModifierWindow(const TArray<UAnimSequence*>& InSequences)
{
TSharedPtr<SAnimationModifierContentBrowserWindow> WindowContent;
TSharedRef<SWindow> Window = SNew(SWindow)
.Title(LOCTEXT("WindowTitle", "Add Animation Modifier(s)"))
.SizingRule(ESizingRule::UserSized)
.ClientSize(FVector2D(500, 500));
Window->SetContent
(
SAssignNew(WindowContent, SAnimationModifierContentBrowserWindow)
.WidgetWindow(Window)
.AnimSequences(InSequences)
);
TSharedPtr<SWindow> ParentWindow;
if (FModuleManager::Get().IsModuleLoaded("MainFrame"))
{
IMainFrameModule& MainFrame = FModuleManager::LoadModuleChecked<IMainFrameModule>("MainFrame");
ParentWindow = MainFrame.GetParentWindow();
}
FSlateApplication::Get().AddModalWindow(Window, ParentWindow, false);
}
void FAnimationModifiersModule::ApplyAnimationModifiers(const TArray<UAnimSequence*>& InSequences, bool bForceApply /*= true*/)
{
const FScopedTransaction Transaction(LOCTEXT("UndoAction_ApplyModifiers", "Applying Animation Modifier(s) to Animation Sequence(s)"));
// Iterate over each Animation Sequence and all of its contained modifiers, applying each one
UE::Anim::FApplyModifiersScope Scope;
TArray<UAnimationModifiersAssetUserData*> AssetUserData;
for (UAnimSequence* AnimationSequence : InSequences)
{
if (AnimationSequence)
{
UAnimationModifiersAssetUserData* UserData = AnimationSequence->GetAssetUserData<UAnimationModifiersAssetUserData>();
if (UserData)
{
AnimationSequence->Modify();
const TArray<UAnimationModifier*>& ModifierInstances = UserData->GetAnimationModifierInstances();
for (UAnimationModifier* Modifier : ModifierInstances)
{
if (bForceApply || !Modifier->IsLatestRevisionApplied())
{
Modifier->ApplyToAnimationSequence(AnimationSequence);
}
}
}
}
}
}
#undef LOCTEXT_NAMESPACE // "AnimationModifiersModule"