Files
UnrealEngine/Engine/Source/Editor/Persona/Private/TabSpawners.cpp
2025-05-18 13:04:45 +08:00

861 lines
33 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "TabSpawners.h"
#include "Widgets/Input/SCheckBox.h"
#include "Widgets/Layout/SBorder.h"
#include "Widgets/Text/STextBlock.h"
#include "Styling/AppStyle.h"
#include "Styling/CoreStyle.h"
#include "SSkeletonAnimNotifies.h"
#include "SAnimBlueprintParentPlayerList.h"
#include "SSkeletonSlotNames.h"
#include "AdvancedPreviewSceneModule.h"
#include "ISkeletonTree.h"
#include "ISkeletonEditorModule.h"
#include "SPersonaDetails.h"
#include "PersonaUtils.h"
#include "SMorphTargetViewer.h"
#include "SAnimCurveViewer.h"
#include "SAnimAttributeView.h"
#include "SAnimationSequenceBrowser.h"
#include "SAnimationEditorViewport.h"
#include "SPoseWatchManager.h"
#include "SRetargetSources.h"
#include "SKismetInspector.h"
#include "Widgets/Input/SButton.h"
#include "PersonaPreviewSceneDescription.h"
#include "IPersonaPreviewScene.h"
#include "PreviewSceneCustomizations.h"
#include "Engine/PreviewMeshCollection.h"
#include "PoseWatchManagerPublicTypes.h"
#include "PoseWatchManagerDefaultMode.h"
#include "SAnimCurveMetadataEditor.h"
#define LOCTEXT_NAMESPACE "PersonaModes"
/////////////////////////////////////////////////////
// FPersonaTabs
// Tab constants
const FName FPersonaTabs::MorphTargetsID("MorphTargetsTab");
const FName FPersonaTabs::AnimCurveViewID("AnimCurveViewerTab");
const FName FPersonaTabs::AnimCurveMetadataEditorID("AnimCurveMetadataEditorTab");
const FName FPersonaTabs::SkeletonTreeViewID("SkeletonTreeView"); //@TODO: Name
// Skeleton Pose manager
const FName FPersonaTabs::RetargetManagerID("RetargetManager");
// Anim Blueprint params
// Explorer
// Class Defaults
const FName FPersonaTabs::AnimBlueprintPreviewEditorID("AnimBlueprintPreviewEditor");
const FName FPersonaTabs::AnimBlueprintParentPlayerEditorID("AnimBlueprintParentPlayerEditor");
// Anim Document
const FName FPersonaTabs::ScrubberID("ScrubberTab");
// Toolbar
const FName FPersonaTabs::PreviewViewportID("Viewport");
const FName FPersonaTabs::PreviewViewport1ID("Viewport1");
const FName FPersonaTabs::PreviewViewport2ID("Viewport2");
const FName FPersonaTabs::PreviewViewport3ID("Viewport3");
const FName FPersonaTabs::AssetBrowserID("SequenceBrowser"); //@TODO: Name
const FName FPersonaTabs::MirrorSetupID("MirrorSetupTab");
const FName FPersonaTabs::AnimBlueprintDebugHistoryID("AnimBlueprintDebugHistoryTab");
const FName FPersonaTabs::AnimAssetPropertiesID("AnimAssetPropertiesTab");
const FName FPersonaTabs::MeshAssetPropertiesID("MeshAssetPropertiesTab");
const FName FPersonaTabs::PreviewManagerID("AnimPreviewSetup"); //@TODO: Name
const FName FPersonaTabs::SkeletonAnimNotifiesID("SkeletonAnimNotifies");
const FName FPersonaTabs::SkeletonSlotNamesID("SkeletonSlotNames");
const FName FPersonaTabs::SkeletonSlotGroupNamesID("SkeletonSlotGroupNames");
const FName FPersonaTabs::BlendProfileManagerID("BlendProfileManager");
const FName FPersonaTabs::AnimMontageSectionsID("AnimMontageSections");
const FName FPersonaTabs::PoseWatchManagerID("PoseWatchManager");
const FName FPersonaTabs::AdvancedPreviewSceneSettingsID("AdvancedPreviewTab");
const FName FPersonaTabs::DetailsID("DetailsTab");
const FName FPersonaTabs::FindReplaceID("FindReplaceTab");
const FName FPersonaTabs::ToolboxID("ToolBox");
const FName FPersonaTabs::AnimAttributeViewID("AnimAttributeViewerTab");
/////////////////////////////////////////////////////
// FPersonaMode
// Mode constants
const FName FPersonaModes::SkeletonDisplayMode( "SkeletonName" );
const FName FPersonaModes::MeshEditMode( "MeshName" );
const FName FPersonaModes::PhysicsEditMode( "PhysicsName" );
const FName FPersonaModes::AnimationEditMode( "AnimationName" );
const FName FPersonaModes::AnimBlueprintEditMode( "GraphName" );
/////////////////////////////////////////////////////
// FPersonaModeSharedData
FPersonaModeSharedData::FPersonaModeSharedData()
: OrthoZoom(1.0f)
, bCameraLock(true)
, CameraFollowMode(EAnimationViewportCameraFollowMode::None)
, CameraFollowBoneName(NAME_None)
, bShowReferencePose(false)
, bShowBones(false)
, bShowBoneNames(false)
, bShowSockets(false)
, bShowBound(false)
, ViewportType(0)
, PlaybackSpeedMode(EAnimationPlaybackSpeeds::Normal)
, LocalAxesMode(0)
{}
void FPersonaModeSharedData::Save(const TSharedRef<FAnimationViewportClient>& InFromViewport)
{
ViewLocation = InFromViewport->GetViewLocation();
ViewRotation = InFromViewport->GetViewRotation();
LookAtLocation = InFromViewport->GetLookAtLocation();
OrthoZoom = InFromViewport->GetOrthoZoom();
bCameraLock = InFromViewport->IsCameraLocked();
CameraFollowMode = InFromViewport->GetCameraFollowMode();
CameraFollowBoneName = InFromViewport->GetCameraFollowBoneName();
bShowBound = InFromViewport->IsSetShowBoundsChecked();
LocalAxesMode = InFromViewport->GetLocalAxesMode();
ViewportType = InFromViewport->ViewportType;
const TSharedRef<FAnimationEditorPreviewScene> AnimationEditorPreviewScene =
StaticCastSharedRef<FAnimationEditorPreviewScene>(InFromViewport->GetPreviewScene());
PlaybackSpeedMode = AnimationEditorPreviewScene->GetAnimationPlaybackSpeedMode();
}
void FPersonaModeSharedData::Restore(const TSharedRef<FAnimationViewportClient>& InToViewport)
{
InToViewport->SetViewportType((ELevelViewportType)ViewportType);
InToViewport->SetViewLocation(ViewLocation);
InToViewport->SetViewRotation(ViewRotation);
InToViewport->SetShowBounds(bShowBound);
InToViewport->SetLocalAxesMode((ELocalAxesMode::Type)LocalAxesMode);
InToViewport->SetOrthoZoom(OrthoZoom);
const TSharedRef<FAnimationEditorPreviewScene> AnimationEditorPreviewScene =
StaticCastSharedRef<FAnimationEditorPreviewScene>(InToViewport->GetPreviewScene());
AnimationEditorPreviewScene->SetAnimationPlaybackSpeedMode(PlaybackSpeedMode);
if (bCameraLock)
{
InToViewport->SetLookAtLocation(LookAtLocation);
}
else if(CameraFollowMode != EAnimationViewportCameraFollowMode::None)
{
InToViewport->SetCameraFollowMode(CameraFollowMode, CameraFollowBoneName);
}
}
/////////////////////////////////////////////////////
// FMorphTargetTabSummoner
FMorphTargetTabSummoner::FMorphTargetTabSummoner(TSharedPtr<class FAssetEditorToolkit> InHostingApp, TSharedRef<IMorphTargetViewer> InViewerWidget)
: FWorkflowTabFactory(FPersonaTabs::MorphTargetsID, InHostingApp)
, ViewerWidget(InViewerWidget)
{
TabLabel = LOCTEXT("MorphTargetTabTitle", "Morph Target Previewer");
TabIcon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "Persona.Tabs.MorphTargetPreviewer");
EnableTabPadding();
bIsSingleton = true;
ViewMenuDescription = LOCTEXT("MorphTargetTabView", "Morph Target Previewer");
ViewMenuTooltip = LOCTEXT("MorphTargetTabView_ToolTip", "Shows the morph target viewer");
}
TSharedRef<SWidget> FMorphTargetTabSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const
{
return ViewerWidget->AsWidget();
}
/////////////////////////////////////////////////////
// FAnimCurveViewerTabSummoner
FAnimCurveViewerTabSummoner::FAnimCurveViewerTabSummoner(TSharedPtr<class FAssetEditorToolkit> InHostingApp, const TSharedPtr<IEditableSkeleton>& InEditableSkeleton, const TSharedRef<IPersonaPreviewScene>& InPreviewScene, FOnObjectsSelected InOnObjectsSelected)
: FWorkflowTabFactory(FPersonaTabs::AnimCurveViewID, InHostingApp)
, EditableSkeleton(InEditableSkeleton)
, PreviewScene(InPreviewScene)
, OnObjectsSelected(InOnObjectsSelected)
{
TabLabel = LOCTEXT("AnimCurveViewerTabTitle", "Curve Debugger");
TabIcon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "Persona.Tabs.AnimCurveDebugger");
EnableTabPadding();
bIsSingleton = true;
ViewMenuDescription = LOCTEXT("AnimCurveTabView", "Curve Debugger");
ViewMenuTooltip = LOCTEXT("AnimCurveTabView_ToolTip", "Shows the animation curve debugger. This shows the state of animation curves.");
}
TSharedRef<SWidget> FAnimCurveViewerTabSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const
{
return SNew(SAnimCurveViewer, PreviewScene.Pin().ToSharedRef(), OnObjectsSelected)
.EditableSkeleton(EditableSkeleton.Pin());
}
/////////////////////////////////////////////////////
// FAnimCurveViewerTabSummoner
FAnimCurveMetadataEditorTabSummoner::FAnimCurveMetadataEditorTabSummoner(TSharedPtr<class FAssetEditorToolkit> InHostingApp, UObject* InMetadataHost, const TSharedRef<IPersonaPreviewScene>& InPreviewScene, FOnObjectsSelected InOnObjectsSelected)
: FWorkflowTabFactory(FPersonaTabs::AnimCurveMetadataEditorID, InHostingApp)
, MetadataHost(InMetadataHost)
, PreviewScene(InPreviewScene)
, OnObjectsSelected(InOnObjectsSelected)
{
TabLabel = LOCTEXT("AnimCurveMetadataEditorTabTitle", "Curves");
TabIcon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "Persona.Tabs.AnimCurveMetadataEditor");
EnableTabPadding();
bIsSingleton = true;
ViewMenuDescription = LOCTEXT("AnimCurveMetadataEditorTab", "Animation Curves");
ViewMenuTooltip = LOCTEXT("AnimCurveMetadataEditorTab_ToolTip", "Shows the animation curve editor. This lets you add, remove, rename and edit curve metadata.");
}
TSharedRef<SWidget> FAnimCurveMetadataEditorTabSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const
{
return SNew(SAnimCurveMetadataEditor, MetadataHost.Get(), PreviewScene.Pin().ToSharedRef(), OnObjectsSelected);
}
/////////////////////////////////////////////////////
// FAnimationAssetBrowserSummoner
FAnimationAssetBrowserSummoner::FAnimationAssetBrowserSummoner(TSharedPtr<class FAssetEditorToolkit> InHostingApp, const TSharedRef<IPersonaToolkit>& InPersonaToolkit, FOnOpenNewAsset InOnOpenNewAsset, FOnAnimationSequenceBrowserCreated InOnAnimationSequenceBrowserCreated, bool bInShowHistory)
: FWorkflowTabFactory(FPersonaTabs::AssetBrowserID, InHostingApp)
, PersonaToolkit(InPersonaToolkit)
, OnOpenNewAsset(InOnOpenNewAsset)
, OnAnimationSequenceBrowserCreated(InOnAnimationSequenceBrowserCreated)
, bShowHistory(bInShowHistory)
{
TabLabel = LOCTEXT("AssetBrowserTabTitle", "Asset Browser");
TabIcon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "ContentBrowser.TabIcon");
bIsSingleton = true;
ViewMenuDescription = LOCTEXT("AssetBrowser", "Asset Browser");
ViewMenuTooltip = LOCTEXT("AssetBrowser_ToolTip", "Shows the animation asset browser");
}
TSharedRef<SWidget> FAnimationAssetBrowserSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const
{
TSharedRef<SAnimationSequenceBrowser> Widget = SNew(SAnimationSequenceBrowser, PersonaToolkit.Pin().ToSharedRef())
.OnOpenNewAsset(OnOpenNewAsset)
.ShowHistory(bShowHistory);
OnAnimationSequenceBrowserCreated.ExecuteIfBound(Widget);
return Widget;
}
/////////////////////////////////////////////////////
// FPreviewViewportSummoner
static FName ViewportInstanceToTabName(int32 InViewportIndex)
{
switch(InViewportIndex)
{
default:
case 0:
return FPersonaTabs::PreviewViewportID;
case 1:
return FPersonaTabs::PreviewViewport1ID;
case 2:
return FPersonaTabs::PreviewViewport2ID;
case 3:
return FPersonaTabs::PreviewViewport3ID;
}
}
static FName MakeViewportContextName(FName InContext, int32 InViewportIndex)
{
return *FString::Printf(TEXT("%s%d"), *InContext.ToString(), InViewportIndex);
}
FPreviewViewportSummoner::FPreviewViewportSummoner(TSharedPtr<class FAssetEditorToolkit> InHostingApp, const FPersonaViewportArgs& InArgs, int32 InViewportIndex)
: FWorkflowTabFactory(ViewportInstanceToTabName(InViewportIndex), InHostingApp)
, PreviewScene(InArgs.PreviewScene)
, BlueprintEditor(InArgs.BlueprintEditor)
, OnViewportCreated(InArgs.OnViewportCreated)
, OnGetViewportText(InArgs.OnGetViewportText)
, Extenders(InArgs.Extenders)
, ContextName(MakeViewportContextName(InArgs.ContextName, InViewportIndex))
, ViewportIndex(InViewportIndex)
, bShowShowMenu(InArgs.bShowShowMenu)
, bShowLODMenu(InArgs.bShowLODMenu)
, bShowPlaySpeedMenu(InArgs.bShowPlaySpeedMenu)
, bShowTimeline(InArgs.bShowTimeline)
, bShowStats(InArgs.bShowStats)
, bAlwaysShowTransformToolbar(InArgs.bAlwaysShowTransformToolbar)
, bShowFloorOptions(InArgs.bShowFloorOptions)
, bShowTurnTable(InArgs.bShowTurnTable)
, bShowPhysicsMenu(InArgs.bShowPhysicsMenu)
, TimelineDelegates(InArgs.TimelineDelegates)
{
TabLabel = FText::Format(LOCTEXT("ViewportTabTitle", "Viewport {0}"), FText::AsNumber(InViewportIndex + 1));
TabIcon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Viewports");
bIsSingleton = true;
ViewMenuDescription = FText::Format(LOCTEXT("ViewportViewFormat", "Viewport {0}"), FText::AsNumber(InViewportIndex + 1));
ViewMenuTooltip = LOCTEXT("ViewportView_ToolTip", "Shows the viewport");
}
TSharedRef<SWidget> FPreviewViewportSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const
{
TSharedRef<SAnimationEditorViewportTabBody> NewViewport = SNew(SAnimationEditorViewportTabBody, PreviewScene.Pin().ToSharedRef(), HostingApp.Pin().ToSharedRef(), ViewportIndex)
.BlueprintEditor(BlueprintEditor.Pin())
.OnInvokeTab(FOnInvokeTab::CreateSP(HostingApp.Pin().Get(), &FAssetEditorToolkit::InvokeTab))
.AddMetaData<FTagMetaData>(TEXT("Persona.Viewport"))
.Extenders(Extenders)
.ContextName(ContextName)
.OnGetViewportText(OnGetViewportText)
.ShowShowMenu(bShowShowMenu)
.ShowLODMenu(bShowLODMenu)
.ShowPlaySpeedMenu(bShowPlaySpeedMenu)
.ShowTimeline(bShowTimeline)
.ShowStats(bShowStats)
.AlwaysShowTransformToolbar(bAlwaysShowTransformToolbar)
.ShowFloorOptions(bShowFloorOptions)
.ShowTurnTable(bShowTurnTable)
.ShowPhysicsMenu(bShowPhysicsMenu)
.TimelineDelegates(TimelineDelegates);
OnViewportCreated.ExecuteIfBound(NewViewport);
return NewViewport;
}
FTabSpawnerEntry& FPreviewViewportSummoner::RegisterTabSpawner(TSharedRef<FTabManager> TabManager, const FApplicationMode* CurrentApplicationMode) const
{
FTabSpawnerEntry& SpawnerEntry = FWorkflowTabFactory::RegisterTabSpawner(TabManager, nullptr);
if(CurrentApplicationMode)
{
// find an existing workspace item or create new
TSharedPtr<FWorkspaceItem> GroupItem = nullptr;
for(const TSharedRef<FWorkspaceItem>& Item : CurrentApplicationMode->GetWorkspaceMenuCategory()->GetChildItems())
{
if(Item->GetDisplayName().ToString() == LOCTEXT("ViewportsSubMenu", "Viewports").ToString())
{
GroupItem = Item;
break;
}
}
if(!GroupItem.IsValid())
{
GroupItem = CurrentApplicationMode->GetWorkspaceMenuCategory()->AddGroup(LOCTEXT("ViewportsSubMenu", "Viewports"), LOCTEXT("ViewportsSubMenu_Tooltip", "Open a new viewport on the scene"), FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Viewports"));
}
SpawnerEntry.SetGroup(GroupItem.ToSharedRef());
}
return SpawnerEntry;
}
/////////////////////////////////////////////////////
// FRetargetManagerTabSummoner
FRetargetSourcesTabSummoner::FRetargetSourcesTabSummoner(
TSharedPtr<class FAssetEditorToolkit> InHostingApp,
const TSharedRef<IEditableSkeleton>& InEditableSkeleton,
FSimpleMulticastDelegate& InOnPostUndo)
: FWorkflowTabFactory(FPersonaTabs::RetargetManagerID, InHostingApp)
, EditableSkeleton(InEditableSkeleton)
, OnPostUndo(InOnPostUndo)
{
TabLabel = LOCTEXT("RetargetingTabTitle", "Retargeting");
TabIcon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "Persona.Tabs.RetargetManager");
EnableTabPadding();
bIsSingleton = true;
ViewMenuDescription = LOCTEXT("RetargetingTabView", "Retargeting");
ViewMenuTooltip = LOCTEXT("RetargetSourcesTabView_ToolTip", "Specify Retarget Sources and Compatible Skeletons.");
}
TSharedRef<SWidget> FRetargetSourcesTabSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const
{
return SNew(SRetargetSources, EditableSkeleton.Pin().ToSharedRef(), OnPostUndo);
}
/////////////////////////////////////////////////////
// SPersonaPreviewPropertyEditor
void SPersonaPreviewPropertyEditor::Construct(const FArguments& InArgs, TSharedRef<IPersonaPreviewScene> InPreviewScene, TSharedRef<FBlueprintEditor> InBPEditor)
{
PreviewScene = InPreviewScene;
BPEditor = InBPEditor;
bPropertyEdited = false;
SSingleObjectDetailsPanel::Construct(SSingleObjectDetailsPanel::FArguments(), /*bAutomaticallyObserveViaGetObjectToObserve*/ true, /*bAllowSearch*/ true);
PropertyView->SetIsPropertyEditingEnabledDelegate(FIsPropertyEditingEnabled::CreateStatic([] { return !GIntraFrameDebuggingGameThread; }));
PropertyView->OnFinishedChangingProperties().Add(FOnFinishedChangingProperties::FDelegate::CreateSP(this, &SPersonaPreviewPropertyEditor::HandlePropertyChanged));
}
UObject* SPersonaPreviewPropertyEditor::GetObjectToObserve() const
{
// Use the selected debug instance, if we have one.
if (UBlueprint* Blueprint = BPEditor.Pin()->GetBlueprintObj())
{
if (UObject* DebugObject = Blueprint->GetObjectBeingDebugged())
{
return DebugObject;
}
}
// If there's no selection, fall-back to preview instance.
if (UDebugSkelMeshComponent* PreviewMeshComponent = PreviewScene.Pin()->GetPreviewMeshComponent())
{
if (PreviewMeshComponent->GetAnimInstance() != nullptr)
{
return PreviewMeshComponent->GetAnimInstance();
}
}
return nullptr;
}
TSharedRef<SWidget> SPersonaPreviewPropertyEditor::PopulateSlot(TSharedRef<SWidget> PropertyEditorWidget)
{
return SNew(SVerticalBox)
+SVerticalBox::Slot()
.FillHeight(1.0f)
[
PropertyEditorWidget
]
+SVerticalBox::Slot()
.AutoHeight()
[
SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("Docking.Tab.ContentAreaBrush"))
.Visibility_Lambda([this]() { return bPropertyEdited ? EVisibility::Visible : EVisibility::Collapsed; })
[
SNew(SHorizontalBox)
+SHorizontalBox::Slot()
.FillWidth(1.0f)
.VAlign(VAlign_Center)
.Padding(2.0f)
[
SNew(STextBlock)
.Text(LOCTEXT("AnimBlueprintEditPreviewText", "Changes made to the selected instance only. Changes will not be saved!"))
.ColorAndOpacity(FLinearColor::Yellow)
.ShadowOffset(FVector2D::UnitVector)
.AutoWrapText(true)
]
+SHorizontalBox::Slot()
.AutoWidth()
.HAlign(HAlign_Right)
.VAlign(VAlign_Center)
.Padding(2.0f)
[
SNew(SButton)
.OnClicked(this, &SPersonaPreviewPropertyEditor::HandleApplyChanges)
.ToolTipText(LOCTEXT("AnimBlueprintEditApplyChanges_Tooltip", "Apply the selected instance's current property values to the defaults."))
[
SNew(STextBlock)
.Text(LOCTEXT("AnimBlueprintEditApplyChanges", "Apply"))
]
]
]
];
}
void SPersonaPreviewPropertyEditor::HandlePropertyChanged(const FPropertyChangedEvent& InPropertyChangedEvent)
{
UAnimInstance* AnimInstance = nullptr;
if (UBlueprint* Blueprint = BPEditor.Pin()->GetBlueprintObj())
{
if (UAnimInstance* DebugInstance = Cast<UAnimInstance>(Blueprint->GetObjectBeingDebugged()))
{
// Compare the selected debug instance (if we have one) against the CDO.
AnimInstance = DebugInstance;
}
else if (UDebugSkelMeshComponent* PreviewMeshComponent = PreviewScene.Pin()->GetPreviewMeshComponent())
{
// If there's no selection, fall-back to preview instance.
AnimInstance = PreviewMeshComponent->GetAnimInstance();
}
}
if (AnimInstance != nullptr)
{
// check to see how many properties have changed
const int32 NumChangedProperties = PersonaUtils::CopyPropertiesToCDO(AnimInstance, PersonaUtils::FCopyOptions(PersonaUtils::ECopyOptions::PreviewOnly));
bPropertyEdited = (NumChangedProperties > 0);
}
}
FReply SPersonaPreviewPropertyEditor::HandleApplyChanges()
{
// copy preview properties into CDO
if (UDebugSkelMeshComponent* PreviewMeshComponent = PreviewScene.Pin()->GetPreviewMeshComponent())
{
if (UAnimInstance* AnimInstance = PreviewMeshComponent->GetAnimInstance())
{
PersonaUtils::CopyPropertiesToCDO(AnimInstance);
bPropertyEdited = false;
}
}
return FReply::Handled();
}
/////////////////////////////////////////////////////
// FAnimBlueprintPreviewEditorSummoner
FAnimBlueprintPreviewEditorSummoner::FAnimBlueprintPreviewEditorSummoner(TSharedPtr<class FBlueprintEditor> InBlueprintEditor, const TSharedRef<class IPersonaPreviewScene>& InPreviewScene)
: FWorkflowTabFactory(FPersonaTabs::AnimBlueprintPreviewEditorID, InBlueprintEditor)
, BlueprintEditor(InBlueprintEditor)
, PreviewScene(InPreviewScene)
{
TabLabel = LOCTEXT("AnimBlueprintPreviewTabTitle", "Anim Preview Editor");
bIsSingleton = true;
CurrentMode = EAnimBlueprintEditorMode::PreviewMode;
ViewMenuDescription = LOCTEXT("AnimBlueprintPreviewView", "Preview");
ViewMenuTooltip = LOCTEXT("AnimBlueprintPreviewView_ToolTip", "Shows the animation preview editor view (as well as class defaults)");
}
TSharedRef<SWidget> FAnimBlueprintPreviewEditorSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const
{
return SNew(SVerticalBox)
+SVerticalBox::Slot()
.AutoHeight()
[
SNew(SHorizontalBox)
+SHorizontalBox::Slot()
.AutoWidth()
.Padding(FMargin( 5.f, 0.f, 2.f, 0.f ))
[
SNew(SCheckBox)
.Style(FAppStyle::Get(), "RadioButton")
.IsChecked(this, &FAnimBlueprintPreviewEditorSummoner::IsChecked, EAnimBlueprintEditorMode::PreviewMode)
.OnCheckStateChanged(const_cast<FAnimBlueprintPreviewEditorSummoner*>(this), &FAnimBlueprintPreviewEditorSummoner::OnCheckedChanged, EAnimBlueprintEditorMode::PreviewMode)
.ToolTip(IDocumentation::Get()->CreateToolTip( LOCTEXT("AnimBlueprintPropertyEditorPreviewMode", "Switch to editing the preview instance properties"),
NULL,
TEXT("Shared/Editors/Persona"),
TEXT("AnimBlueprintPropertyEditorPreviewMode")))
[
SNew( STextBlock )
.Text( LOCTEXT("AnimBlueprintDefaultsPreviewMode", "Edit Selected Instance") )
]
]
+SHorizontalBox::Slot()
.AutoWidth()
.Padding(FMargin( 2.f, 0.f, 0.f, 0.f ))
[
SNew(SCheckBox)
.Style(FAppStyle::Get(), "RadioButton")
.IsChecked(this, &FAnimBlueprintPreviewEditorSummoner::IsChecked, EAnimBlueprintEditorMode::DefaultsMode)
.OnCheckStateChanged(const_cast<FAnimBlueprintPreviewEditorSummoner*>(this), &FAnimBlueprintPreviewEditorSummoner::OnCheckedChanged, EAnimBlueprintEditorMode::DefaultsMode)
.ToolTip(IDocumentation::Get()->CreateToolTip( LOCTEXT("AnimBlueprintPropertyEditorDefaultMode", "Switch to editing the class defaults"),
NULL,
TEXT("Shared/Editors/Persona"),
TEXT("AnimBlueprintPropertyEditorDefaultMode")))
[
SNew( STextBlock )
.Text( LOCTEXT("AnimBlueprintDefaultsDefaultsMode", "Edit Defaults") )
]
]
]
+SVerticalBox::Slot()
[
SNew(SOverlay)
+SOverlay::Slot()
[
SNew(SBorder)
.Padding(0)
.BorderImage( FAppStyle::GetBrush("NoBorder") )
.Visibility(this, &FAnimBlueprintPreviewEditorSummoner::IsEditorVisible, EAnimBlueprintEditorMode::PreviewMode)
[
SNew(SPersonaPreviewPropertyEditor, PreviewScene.Pin().ToSharedRef(), BlueprintEditor.Pin().ToSharedRef())
]
]
+SOverlay::Slot()
[
SNew(SBorder)
.Padding(FMargin(3.0f, 2.0f))
.BorderImage( FAppStyle::GetBrush("NoBorder") )
.Visibility(this, &FAnimBlueprintPreviewEditorSummoner::IsEditorVisible, EAnimBlueprintEditorMode::DefaultsMode)
[
BlueprintEditor.Pin()->GetDefaultEditor()
]
]
];
}
FText FAnimBlueprintPreviewEditorSummoner::GetTabToolTipText(const FWorkflowTabSpawnInfo& Info) const
{
return LOCTEXT("AnimBlueprintPreviewEditorTooltip", "The editor lets you change the values of the selected instance");
}
EVisibility FAnimBlueprintPreviewEditorSummoner::IsEditorVisible(EAnimBlueprintEditorMode::Type Mode) const
{
return CurrentMode == Mode ? EVisibility::Visible: EVisibility::Hidden;
}
ECheckBoxState FAnimBlueprintPreviewEditorSummoner::IsChecked(EAnimBlueprintEditorMode::Type Mode) const
{
return CurrentMode == Mode ? ECheckBoxState::Checked: ECheckBoxState::Unchecked;
}
void FAnimBlueprintPreviewEditorSummoner::OnCheckedChanged(ECheckBoxState NewType, EAnimBlueprintEditorMode::Type Mode)
{
if(NewType == ECheckBoxState::Checked)
{
CurrentMode = Mode;
}
}
//////////////////////////////////////////////////////////////////////////
// FAnimBlueprintParentPlayerEditorSummoner
FAnimBlueprintParentPlayerEditorSummoner::FAnimBlueprintParentPlayerEditorSummoner(TSharedPtr<class FBlueprintEditor> InBlueprintEditor, FSimpleMulticastDelegate& InOnPostUndo)
: FWorkflowTabFactory(FPersonaTabs::AnimBlueprintParentPlayerEditorID, InBlueprintEditor)
, BlueprintEditor(InBlueprintEditor)
, OnPostUndo(InOnPostUndo)
{
TabLabel = LOCTEXT("ParentPlayerOverrideEditor", "Asset Override Editor");
bIsSingleton = true;
}
TSharedRef<SWidget> FAnimBlueprintParentPlayerEditorSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const
{
return SNew(SAnimBlueprintParentPlayerList, BlueprintEditor.Pin().ToSharedRef(), OnPostUndo);
}
FText FAnimBlueprintParentPlayerEditorSummoner::GetTabToolTipText(const FWorkflowTabSpawnInfo& Info) const
{
return LOCTEXT("AnimSubClassTabToolTip", "Editor for overriding the animation assets referenced by the parent animation graph.");
}
//////////////////////////////////////////////////////////////////////////
// FPoseWatchManagerSummoner
FPoseWatchManagerSummoner::FPoseWatchManagerSummoner(TSharedPtr<class FBlueprintEditor> InBlueprintEditor)
: FWorkflowTabFactory(FPersonaTabs::PoseWatchManagerID, InBlueprintEditor)
, BlueprintEditor(InBlueprintEditor)
{
TabLabel = LOCTEXT("PoseWatchManager", "Pose Watch Manager");
TabIcon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "AnimGraph.PoseWatch.Icon");
bIsSingleton = true;
}
TSharedRef<SWidget> FPoseWatchManagerSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const
{
FPoseWatchManagerInitializationOptions Options;
Options.BlueprintEditor = BlueprintEditor;
return SNew(SPoseWatchManager, Options)
.IsEnabled(FSlateApplication::Get().GetNormalExecutionAttribute());
}
FText FPoseWatchManagerSummoner::GetTabToolTipText(const FWorkflowTabSpawnInfo& Info) const
{
return LOCTEXT("PoseWatchTabToolTip", "Shows all active pose watches.");
}
/////////////////////////////////////////////////////
// FAdvancedPreviewSceneTabSummoner
FAdvancedPreviewSceneTabSummoner::FAdvancedPreviewSceneTabSummoner(TSharedPtr<class FAssetEditorToolkit> InHostingApp, const TSharedRef<IPersonaPreviewScene>& InPreviewScene)
: FWorkflowTabFactory(FPersonaTabs::AdvancedPreviewSceneSettingsID, InHostingApp)
, PreviewScene(InPreviewScene)
{
TabLabel = LOCTEXT("PreviewSceneSettingsTab", "Preview Scene Settings");
TabIcon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Details");
bIsSingleton = true;
ViewMenuDescription = LOCTEXT("AdvancedPreviewScene", "Preview Scene Settings");
ViewMenuTooltip = LOCTEXT("AdvancedPreviewScene_ToolTip", "Shows the advanced preview scene settings");
}
TSharedRef<class IDetailCustomization> FAdvancedPreviewSceneTabSummoner::CustomizePreviewSceneDescription()
{
TSharedRef<IPersonaPreviewScene> PreviewSceneRef = PreviewScene.Pin().ToSharedRef();
FString SkeletonName;
TSharedPtr<IEditableSkeleton> EditableSkeleton = PreviewSceneRef->GetPersonaToolkit()->GetEditableSkeleton();
if(EditableSkeleton.IsValid())
{
SkeletonName = FAssetData(&EditableSkeleton->GetSkeleton()).GetExportTextName();
}
return MakeShareable(new FPreviewSceneDescriptionCustomization(SkeletonName, PreviewSceneRef->GetPersonaToolkit()));
}
TSharedRef<class IPropertyTypeCustomization> FAdvancedPreviewSceneTabSummoner::CustomizePreviewMeshCollectionEntry()
{
return MakeShareable(new FPreviewMeshCollectionEntryCustomization(PreviewScene.Pin().ToSharedRef()));
}
TSharedRef<SWidget> FAdvancedPreviewSceneTabSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const
{
TSharedRef<FAnimationEditorPreviewScene> PreviewSceneRef = StaticCastSharedRef<FAnimationEditorPreviewScene>(PreviewScene.Pin().ToSharedRef());
TArray<FAdvancedPreviewSceneModule::FDetailCustomizationInfo> DetailsCustomizations;
TArray<FAdvancedPreviewSceneModule::FPropertyTypeCustomizationInfo> PropertyTypeCustomizations;
DetailsCustomizations.Add({ UPersonaPreviewSceneDescription::StaticClass(), FOnGetDetailCustomizationInstance::CreateSP(const_cast<FAdvancedPreviewSceneTabSummoner*>(this), &FAdvancedPreviewSceneTabSummoner::CustomizePreviewSceneDescription) });
PropertyTypeCustomizations.Add({ FPreviewMeshCollectionEntry::StaticStruct()->GetFName(), FOnGetPropertyTypeCustomizationInstance::CreateSP(const_cast<FAdvancedPreviewSceneTabSummoner*>(this), &FAdvancedPreviewSceneTabSummoner::CustomizePreviewMeshCollectionEntry) });
FAdvancedPreviewSceneModule& AdvancedPreviewSceneModule = FModuleManager::LoadModuleChecked<FAdvancedPreviewSceneModule>("AdvancedPreviewScene");
return AdvancedPreviewSceneModule.CreateAdvancedPreviewSceneSettingsWidget(PreviewSceneRef, PreviewSceneRef->GetPreviewSceneDescription(), DetailsCustomizations, PropertyTypeCustomizations);
}
FText FAdvancedPreviewSceneTabSummoner::GetTabToolTipText(const FWorkflowTabSpawnInfo& Info) const
{
return LOCTEXT("AdvancedPreviewSettingsToolTip", "The Advanced Preview Settings tab will let you alter the preview scene's settings.");
}
/////////////////////////////////////////////////////
// FPersonaDetailsTabSummoner
FPersonaDetailsTabSummoner::FPersonaDetailsTabSummoner(TSharedPtr<class FAssetEditorToolkit> InHostingApp, FOnDetailsCreated InOnDetailsCreated)
: FWorkflowTabFactory(FPersonaTabs::DetailsID, InHostingApp)
, OnDetailsCreated(InOnDetailsCreated)
{
TabLabel = LOCTEXT("PersonaDetailsTab", "Details");
TabIcon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Details");
bIsSingleton = true;
ViewMenuDescription = LOCTEXT("DetailsDescription", "Details");
ViewMenuTooltip = LOCTEXT("DetailsToolTip", "Shows the details tab for selected objects.");
PersonaDetails = SNew(SPersonaDetails);
OnDetailsCreated.ExecuteIfBound(PersonaDetails->DetailsView.ToSharedRef());
}
TSharedRef<SWidget> FPersonaDetailsTabSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const
{
return PersonaDetails.ToSharedRef();
}
FText FPersonaDetailsTabSummoner::GetTabToolTipText(const FWorkflowTabSpawnInfo& Info) const
{
return LOCTEXT("PersonaDetailsToolTip", "Edit the details of selected objects.");
}
/////////////////////////////////////////////////////
// SAnimAssetPropertiesTabBody
class SAssetPropertiesTabBody : public SSingleObjectDetailsPanel
{
public:
SLATE_BEGIN_ARGS(SAssetPropertiesTabBody) {}
SLATE_ARGUMENT(FOnGetAsset, OnGetAsset)
SLATE_ARGUMENT(FOnDetailsCreated, OnDetailsCreated)
SLATE_END_ARGS()
private:
FOnGetAsset OnGetAsset;
public:
void Construct(const FArguments& InArgs)
{
OnGetAsset = InArgs._OnGetAsset;
SSingleObjectDetailsPanel::Construct(SSingleObjectDetailsPanel::FArguments(), true, true);
InArgs._OnDetailsCreated.ExecuteIfBound(PropertyView.ToSharedRef());
}
virtual EVisibility GetAssetDisplayNameVisibility() const
{
return (GetObjectToObserve() != NULL) ? EVisibility::Visible : EVisibility::Collapsed;
}
virtual FText GetAssetDisplayName() const
{
if (UObject* Object = GetObjectToObserve())
{
return FText::FromString(Object->GetName());
}
else
{
return FText::GetEmpty();
}
}
// SSingleObjectDetailsPanel interface
virtual UObject* GetObjectToObserve() const override
{
if (OnGetAsset.IsBound())
{
return OnGetAsset.Execute();
}
return nullptr;
}
// End of SSingleObjectDetailsPanel interface
};
FAssetPropertiesSummoner::FAssetPropertiesSummoner(TSharedPtr<class FAssetEditorToolkit> InHostingApp, FOnGetAsset InOnGetAsset, FOnDetailsCreated InOnDetailsCreated)
: FWorkflowTabFactory(FPersonaTabs::AnimAssetPropertiesID, InHostingApp)
, OnGetAsset(InOnGetAsset)
, OnDetailsCreated(InOnDetailsCreated)
{
TabLabel = LOCTEXT("AssetProperties_TabTitle", "Asset Details");
TabIcon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "Persona.Tabs.AnimAssetDetails");
bIsSingleton = true;
ViewMenuDescription = LOCTEXT("AssetProperties_MenuTitle", "Asset Details");
ViewMenuTooltip = LOCTEXT("AssetProperties_MenuToolTip", "Shows the asset properties");
}
TSharedPtr<SToolTip> FAssetPropertiesSummoner::CreateTabToolTipWidget(const FWorkflowTabSpawnInfo& Info) const
{
return IDocumentation::Get()->CreateToolTip(LOCTEXT("AssetPropertiesTooltip", "The Asset Details tab lets you edit properties of the current asset (animation, blend space etc)."), NULL, TEXT("Shared/Editors/Persona"), TEXT("AnimationAssetDetail_Window"));
}
TSharedRef<SWidget> FAssetPropertiesSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const
{
return SNew(SAssetPropertiesTabBody)
.OnGetAsset(OnGetAsset)
.OnDetailsCreated(OnDetailsCreated);
}
/////////////////////////////////////////////////////
// FAnimAttributeViewerTabSummoner
FAnimAttributeViewerTabSummoner::FAnimAttributeViewerTabSummoner(TSharedPtr<class FAssetEditorToolkit> InHostingApp, const TSharedRef<IPersonaPreviewScene>& InPreviewScene)
: FWorkflowTabFactory(FPersonaTabs::AnimAttributeViewID, InHostingApp)
, PreviewScene(InPreviewScene)
{
TabLabel = LOCTEXT("AnimAttributeViewTabTitle", "Animation Attributes");
TabIcon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "AnimGraph.Attribute.Attributes.Icon");
EnableTabPadding();
bIsSingleton = true;
ViewMenuDescription = LOCTEXT("AnimAttributeTabView", "Animation Attributes");
ViewMenuTooltip = LOCTEXT("AnimAttributeTabView_ToolTip", "Shows the animation attribute viewer");
}
TSharedRef<SWidget> FAnimAttributeViewerTabSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const
{
return SNew(SAnimAttributeViewer, PreviewScene.Pin().ToSharedRef());
}
#undef LOCTEXT_NAMESPACE