// 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& 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 AnimationEditorPreviewScene = StaticCastSharedRef(InFromViewport->GetPreviewScene()); PlaybackSpeedMode = AnimationEditorPreviewScene->GetAnimationPlaybackSpeedMode(); } void FPersonaModeSharedData::Restore(const TSharedRef& InToViewport) { InToViewport->SetViewportType((ELevelViewportType)ViewportType); InToViewport->SetViewLocation(ViewLocation); InToViewport->SetViewRotation(ViewRotation); InToViewport->SetShowBounds(bShowBound); InToViewport->SetLocalAxesMode((ELocalAxesMode::Type)LocalAxesMode); InToViewport->SetOrthoZoom(OrthoZoom); const TSharedRef AnimationEditorPreviewScene = StaticCastSharedRef(InToViewport->GetPreviewScene()); AnimationEditorPreviewScene->SetAnimationPlaybackSpeedMode(PlaybackSpeedMode); if (bCameraLock) { InToViewport->SetLookAtLocation(LookAtLocation); } else if(CameraFollowMode != EAnimationViewportCameraFollowMode::None) { InToViewport->SetCameraFollowMode(CameraFollowMode, CameraFollowBoneName); } } ///////////////////////////////////////////////////// // FMorphTargetTabSummoner FMorphTargetTabSummoner::FMorphTargetTabSummoner(TSharedPtr InHostingApp, TSharedRef 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 FMorphTargetTabSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const { return ViewerWidget->AsWidget(); } ///////////////////////////////////////////////////// // FAnimCurveViewerTabSummoner FAnimCurveViewerTabSummoner::FAnimCurveViewerTabSummoner(TSharedPtr InHostingApp, const TSharedPtr& InEditableSkeleton, const TSharedRef& 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 FAnimCurveViewerTabSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const { return SNew(SAnimCurveViewer, PreviewScene.Pin().ToSharedRef(), OnObjectsSelected) .EditableSkeleton(EditableSkeleton.Pin()); } ///////////////////////////////////////////////////// // FAnimCurveViewerTabSummoner FAnimCurveMetadataEditorTabSummoner::FAnimCurveMetadataEditorTabSummoner(TSharedPtr InHostingApp, UObject* InMetadataHost, const TSharedRef& 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 FAnimCurveMetadataEditorTabSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const { return SNew(SAnimCurveMetadataEditor, MetadataHost.Get(), PreviewScene.Pin().ToSharedRef(), OnObjectsSelected); } ///////////////////////////////////////////////////// // FAnimationAssetBrowserSummoner FAnimationAssetBrowserSummoner::FAnimationAssetBrowserSummoner(TSharedPtr InHostingApp, const TSharedRef& 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 FAnimationAssetBrowserSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const { TSharedRef 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 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 FPreviewViewportSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const { TSharedRef NewViewport = SNew(SAnimationEditorViewportTabBody, PreviewScene.Pin().ToSharedRef(), HostingApp.Pin().ToSharedRef(), ViewportIndex) .BlueprintEditor(BlueprintEditor.Pin()) .OnInvokeTab(FOnInvokeTab::CreateSP(HostingApp.Pin().Get(), &FAssetEditorToolkit::InvokeTab)) .AddMetaData(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 TabManager, const FApplicationMode* CurrentApplicationMode) const { FTabSpawnerEntry& SpawnerEntry = FWorkflowTabFactory::RegisterTabSpawner(TabManager, nullptr); if(CurrentApplicationMode) { // find an existing workspace item or create new TSharedPtr GroupItem = nullptr; for(const TSharedRef& 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 InHostingApp, const TSharedRef& 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 FRetargetSourcesTabSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const { return SNew(SRetargetSources, EditableSkeleton.Pin().ToSharedRef(), OnPostUndo); } ///////////////////////////////////////////////////// // SPersonaPreviewPropertyEditor void SPersonaPreviewPropertyEditor::Construct(const FArguments& InArgs, TSharedRef InPreviewScene, TSharedRef 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 SPersonaPreviewPropertyEditor::PopulateSlot(TSharedRef 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(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 InBlueprintEditor, const TSharedRef& 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 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(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(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 InBlueprintEditor, FSimpleMulticastDelegate& InOnPostUndo) : FWorkflowTabFactory(FPersonaTabs::AnimBlueprintParentPlayerEditorID, InBlueprintEditor) , BlueprintEditor(InBlueprintEditor) , OnPostUndo(InOnPostUndo) { TabLabel = LOCTEXT("ParentPlayerOverrideEditor", "Asset Override Editor"); bIsSingleton = true; } TSharedRef 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 InBlueprintEditor) : FWorkflowTabFactory(FPersonaTabs::PoseWatchManagerID, InBlueprintEditor) , BlueprintEditor(InBlueprintEditor) { TabLabel = LOCTEXT("PoseWatchManager", "Pose Watch Manager"); TabIcon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "AnimGraph.PoseWatch.Icon"); bIsSingleton = true; } TSharedRef 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 InHostingApp, const TSharedRef& 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 FAdvancedPreviewSceneTabSummoner::CustomizePreviewSceneDescription() { TSharedRef PreviewSceneRef = PreviewScene.Pin().ToSharedRef(); FString SkeletonName; TSharedPtr EditableSkeleton = PreviewSceneRef->GetPersonaToolkit()->GetEditableSkeleton(); if(EditableSkeleton.IsValid()) { SkeletonName = FAssetData(&EditableSkeleton->GetSkeleton()).GetExportTextName(); } return MakeShareable(new FPreviewSceneDescriptionCustomization(SkeletonName, PreviewSceneRef->GetPersonaToolkit())); } TSharedRef FAdvancedPreviewSceneTabSummoner::CustomizePreviewMeshCollectionEntry() { return MakeShareable(new FPreviewMeshCollectionEntryCustomization(PreviewScene.Pin().ToSharedRef())); } TSharedRef FAdvancedPreviewSceneTabSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const { TSharedRef PreviewSceneRef = StaticCastSharedRef(PreviewScene.Pin().ToSharedRef()); TArray DetailsCustomizations; TArray PropertyTypeCustomizations; DetailsCustomizations.Add({ UPersonaPreviewSceneDescription::StaticClass(), FOnGetDetailCustomizationInstance::CreateSP(const_cast(this), &FAdvancedPreviewSceneTabSummoner::CustomizePreviewSceneDescription) }); PropertyTypeCustomizations.Add({ FPreviewMeshCollectionEntry::StaticStruct()->GetFName(), FOnGetPropertyTypeCustomizationInstance::CreateSP(const_cast(this), &FAdvancedPreviewSceneTabSummoner::CustomizePreviewMeshCollectionEntry) }); FAdvancedPreviewSceneModule& AdvancedPreviewSceneModule = FModuleManager::LoadModuleChecked("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 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 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 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 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 FAssetPropertiesSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const { return SNew(SAssetPropertiesTabBody) .OnGetAsset(OnGetAsset) .OnDetailsCreated(OnDetailsCreated); } ///////////////////////////////////////////////////// // FAnimAttributeViewerTabSummoner FAnimAttributeViewerTabSummoner::FAnimAttributeViewerTabSummoner(TSharedPtr InHostingApp, const TSharedRef& 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 FAnimAttributeViewerTabSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const { return SNew(SAnimAttributeViewer, PreviewScene.Pin().ToSharedRef()); } #undef LOCTEXT_NAMESPACE