Files
Thomas Sarkanen 502797ca50 Animation Curve Runtime & Editor Improvements
Runtime notes:
- Removes 'smart name' usage across the animation systems.
- Changed curve blending from a uniform array (sized per skeleton) to a sparse array of sorted named values. Blends and other combiners are performed using a dual iteration 'tape merge'.
- Skeleton curves are no longer guaranteed to cover all curve names that can be found at runtime.

Editor notes:
- Curve metadata (flags, bone links etc.) is still present on the skeleton, but can also now exist on a skeletal mesh
- Curve metadata (for morph targets) is still populated on import
- Curves can now be used arbitrarily at runtime

New features:
- New Find/Replace dialog that allows for batch-replacing curves and notifies across all of a project's assets
- New curve debugger tab in various Persona editors that allows for viewing curve values live. This also now allows viewing curves for specific pose watches.
- Pose watches now output curve tracks to the Rewind Debugger

#rb Jurre.deBaare,Nicholas.Frechette,Sara.Schvartzman,Helge.Mathee,Kiaran.Ritchie,Jaime.Cifuentes,Martin.Wilson,Keith.Yerex,Andrean.Franc (and more!)
#jira UE-167776
#jira UE-173716
#jira UE-110407
#preflight 63fc98c81206d91a2bc3ab90
#preflight 63f3ad4f81646f1f24c240c2

[CL 24421496 by Thomas Sarkanen in ue5-main branch]
2023-02-27 07:20:58 -05:00

151 lines
6.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "AnimationEditorMode.h"
#include "AnimationEditor.h"
#include "Delegates/Delegate.h"
#include "Framework/Docking/LayoutExtender.h"
#include "Framework/Docking/TabManager.h"
#include "HAL/Platform.h"
#include "IPersonaToolkit.h"
#include "ISkeletonEditorModule.h"
#include "ISkeletonTree.h"
#include "Modules/ModuleManager.h"
#include "PersonaDelegates.h"
#include "PersonaModule.h"
#include "Types/SlateEnums.h"
#include "WorkflowOrientedApp/WorkflowCentricApplication.h"
#include "AnimAssetFindReplace.h"
FAnimationEditorMode::FAnimationEditorMode(TSharedRef<FWorkflowCentricApplication> InHostingApp, TSharedRef<ISkeletonTree> InSkeletonTree)
: FApplicationMode(AnimationEditorModes::AnimationEditorMode)
{
HostingAppPtr = InHostingApp;
TSharedRef<FAnimationEditor> AnimationEditor = StaticCastSharedRef<FAnimationEditor>(InHostingApp);
ISkeletonEditorModule& SkeletonEditorModule = FModuleManager::LoadModuleChecked<ISkeletonEditorModule>("SkeletonEditor");
TabFactories.RegisterFactory(SkeletonEditorModule.CreateSkeletonTreeTabFactory(InHostingApp, InSkeletonTree));
FOnObjectsSelected OnObjectsSelected = FOnObjectsSelected::CreateSP(&AnimationEditor.Get(), &FAnimationEditor::HandleObjectsSelected);
FPersonaModule& PersonaModule = FModuleManager::LoadModuleChecked<FPersonaModule>("Persona");
TabFactories.RegisterFactory(PersonaModule.CreateDetailsTabFactory(InHostingApp, FOnDetailsCreated::CreateSP(&AnimationEditor.Get(), &FAnimationEditor::HandleDetailsCreated)));
FPersonaViewportArgs ViewportArgs(AnimationEditor->GetPersonaToolkit()->GetPreviewScene());
ViewportArgs.bShowTimeline = false;
ViewportArgs.ContextName = TEXT("AnimationEditor.Viewport");
PersonaModule.RegisterPersonaViewportTabFactories(TabFactories, InHostingApp, ViewportArgs);
TabFactories.RegisterFactory(PersonaModule.CreateAdvancedPreviewSceneTabFactory(InHostingApp, AnimationEditor->GetPersonaToolkit()->GetPreviewScene()));
TabFactories.RegisterFactory(PersonaModule.CreateAnimationAssetBrowserTabFactory(InHostingApp, AnimationEditor->GetPersonaToolkit(), FOnOpenNewAsset::CreateSP(&AnimationEditor.Get(), &FAnimationEditor::HandleOpenNewAsset), FOnAnimationSequenceBrowserCreated::CreateSP(&AnimationEditor.Get(), &FAnimationEditor::HandleAnimationSequenceBrowserCreated), true));
TabFactories.RegisterFactory(PersonaModule.CreateAssetDetailsTabFactory(InHostingApp, FOnGetAsset::CreateSP(&AnimationEditor.Get(), &FAnimationEditor::HandleGetAsset), FOnDetailsCreated()));
TabFactories.RegisterFactory(PersonaModule.CreateCurveViewerTabFactory(InHostingApp, InSkeletonTree->GetEditableSkeleton(), AnimationEditor->GetPersonaToolkit()->GetPreviewScene(), OnObjectsSelected));
TabFactories.RegisterFactory(PersonaModule.CreateSkeletonSlotNamesTabFactory(InHostingApp, InSkeletonTree->GetEditableSkeleton(), FOnObjectSelected::CreateSP(&AnimationEditor.Get(), &FAnimationEditor::HandleObjectSelected)));
TabFactories.RegisterFactory(PersonaModule.CreateAnimNotifiesTabFactory(InHostingApp, InSkeletonTree->GetEditableSkeleton(), OnObjectsSelected));
TabFactories.RegisterFactory(PersonaModule.CreateAnimMontageSectionsTabFactory(InHostingApp, AnimationEditor->GetPersonaToolkit(), AnimationEditor->OnSectionsChanged));
TabFactories.RegisterFactory(PersonaModule.CreateAnimAssetFindReplaceTabFactory(InHostingApp, FAnimAssetFindReplaceConfig()));
TabLayout = FTabManager::NewLayout("Standalone_AnimationEditor_Layout_v1.5")
->AddArea
(
FTabManager::NewPrimaryArea()
->SetOrientation(Orient_Vertical)
->Split
(
FTabManager::NewSplitter()
->SetSizeCoefficient(0.9f)
->SetOrientation(Orient_Horizontal)
->Split
(
FTabManager::NewSplitter()
->SetSizeCoefficient(0.2f)
->SetOrientation(Orient_Vertical)
->Split
(
FTabManager::NewStack()
->SetHideTabWell(false)
->AddTab(AnimationEditorTabs::SkeletonTreeTab, ETabState::OpenedTab)
->AddTab(AnimationEditorTabs::AssetDetailsTab, ETabState::OpenedTab)
)
)
->Split
(
FTabManager::NewSplitter()
->SetSizeCoefficient(0.6f)
->SetOrientation(Orient_Vertical)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.6f)
->SetHideTabWell(true)
->AddTab(AnimationEditorTabs::ViewportTab, ETabState::OpenedTab)
)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.4f)
->SetHideTabWell(true)
->AddTab(AnimationEditorTabs::DocumentTab, ETabState::ClosedTab)
->AddTab(AnimationEditorTabs::CurveEditorTab, ETabState::ClosedTab)
->AddTab(AnimationEditorTabs::FindReplaceTab, ETabState::ClosedTab)
->SetForegroundTab(AnimationEditorTabs::DocumentTab)
)
)
->Split
(
FTabManager::NewSplitter()
->SetSizeCoefficient(0.2f)
->SetOrientation(Orient_Vertical)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.6f)
->SetHideTabWell(false)
->AddTab(AnimationEditorTabs::DetailsTab, ETabState::OpenedTab)
->AddTab(AnimationEditorTabs::AdvancedPreviewTab, ETabState::OpenedTab)
->SetForegroundTab(AnimationEditorTabs::DetailsTab)
)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.4f)
->SetHideTabWell(false)
->AddTab(AnimationEditorTabs::AssetBrowserTab, ETabState::OpenedTab)
->AddTab(AnimationEditorTabs::AnimMontageSectionsTab, ETabState::ClosedTab)
->AddTab(AnimationEditorTabs::CurveNamesTab, ETabState::ClosedTab)
->AddTab(AnimationEditorTabs::SlotNamesTab, ETabState::ClosedTab)
)
)
)
);
PersonaModule.OnRegisterTabs().Broadcast(TabFactories, InHostingApp);
LayoutExtender = MakeShared<FLayoutExtender>();
PersonaModule.OnRegisterLayoutExtensions().Broadcast(*LayoutExtender.Get());
TabLayout->ProcessExtensions(*LayoutExtender.Get());
}
void FAnimationEditorMode::RegisterTabFactories(TSharedPtr<FTabManager> InTabManager)
{
TSharedPtr<FWorkflowCentricApplication> HostingApp = HostingAppPtr.Pin();
HostingApp->RegisterTabSpawners(InTabManager.ToSharedRef());
HostingApp->PushTabFactories(TabFactories);
FApplicationMode::RegisterTabFactories(InTabManager);
}
void FAnimationEditorMode::AddTabFactory(FCreateWorkflowTabFactory FactoryCreator)
{
if (FactoryCreator.IsBound())
{
TabFactories.RegisterFactory(FactoryCreator.Execute(HostingAppPtr.Pin()));
}
}
void FAnimationEditorMode::RemoveTabFactory(FName TabFactoryID)
{
TabFactories.UnregisterFactory(TabFactoryID);
}