You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
* Removed deprecated or dead code paths * Simplified build system setup for physics support * Deprecated build system flags and unsupported macros #jira none #rb Chris.Caulfield, Kriss.Gossart #preflight 62963ec0fe779f23c8ea0c5e [CL 20450744 by Benn Gallagher in ue5-main branch]
2566 lines
88 KiB
C++
2566 lines
88 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
#include "SAnimationEditorViewport.h"
|
|
#include "Widgets/Layout/SBorder.h"
|
|
#include "Widgets/Text/STextBlock.h"
|
|
#include "Styling/AppStyle.h"
|
|
#include "Styling/CoreStyle.h"
|
|
#include "Framework/Application/SlateApplication.h"
|
|
#include "Widgets/Input/SEditableTextBox.h"
|
|
#include "Widgets/Input/SButton.h"
|
|
#include "Animation/AnimMontage.h"
|
|
#include "Preferences/PersonaOptions.h"
|
|
#include "Rendering/SkeletalMeshRenderData.h"
|
|
|
|
#include "SAnimationScrubPanel.h"
|
|
#include "SAnimMontageScrubPanel.h"
|
|
#include "SAnimViewportToolBar.h"
|
|
#include "AnimViewportMenuCommands.h"
|
|
#include "AnimViewportShowCommands.h"
|
|
#include "AnimViewportLODCommands.h"
|
|
#include "AnimViewportPlaybackCommands.h"
|
|
#include "AnimPreviewInstance.h"
|
|
#include "Widgets/Input/STextComboBox.h"
|
|
#include "IEditableSkeleton.h"
|
|
#include "EditorViewportCommands.h"
|
|
#include "TabSpawners.h"
|
|
#include "ShowFlagMenuCommands.h"
|
|
#include "BufferVisualizationMenuCommands.h"
|
|
#include "UICommandList_Pinnable.h"
|
|
#include "IPersonaEditorModeManager.h"
|
|
#include "AssetViewerSettings.h"
|
|
#include "Editor/EditorPerProjectUserSettings.h"
|
|
#include "Materials/Material.h"
|
|
#include "EditorFontGlyphs.h"
|
|
#include "EdModeInteractiveToolsContext.h"
|
|
#include "ContextObjectStore.h"
|
|
#include "IPersonaEditMode.h"
|
|
|
|
#include "SkeletalMeshTypes.h"
|
|
#include "IPersonaToolkit.h"
|
|
#include "Subsystems/AssetEditorSubsystem.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "PersonaViewportToolbar"
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SAnimationEditorViewport
|
|
|
|
void SAnimationEditorViewport::Construct(const FArguments& InArgs, const FAnimationEditorViewportRequiredArgs& InRequiredArgs)
|
|
{
|
|
PreviewScenePtr = InRequiredArgs.PreviewScene;
|
|
TabBodyPtr = InRequiredArgs.TabBody;
|
|
AssetEditorToolkitPtr = InRequiredArgs.AssetEditorToolkit;
|
|
Extenders = InArgs._Extenders;
|
|
ContextName = InArgs._ContextName;
|
|
bShowShowMenu = InArgs._ShowShowMenu;
|
|
bShowLODMenu = InArgs._ShowLODMenu;
|
|
bShowPlaySpeedMenu = InArgs._ShowPlaySpeedMenu;
|
|
bShowStats = InArgs._ShowStats;
|
|
bShowFloorOptions = InArgs._ShowFloorOptions;
|
|
bShowTurnTable = InArgs._ShowTurnTable;
|
|
bShowPhysicsMenu = InArgs._ShowPhysicsMenu;
|
|
ViewportIndex = InRequiredArgs.ViewportIndex;
|
|
|
|
SEditorViewport::Construct(
|
|
SEditorViewport::FArguments()
|
|
.IsEnabled(FSlateApplication::Get().GetNormalExecutionAttribute())
|
|
.AddMetaData<FTagMetaData>(TEXT("Persona.Viewport"))
|
|
);
|
|
|
|
Client->VisibilityDelegate.BindSP(this, &SAnimationEditorViewport::IsVisible);
|
|
|
|
// restore last used feature level
|
|
auto ScenePtr = PreviewScenePtr.Pin();
|
|
if (ScenePtr.IsValid())
|
|
{
|
|
UWorld* World = ScenePtr->GetWorld();
|
|
if (World != nullptr)
|
|
{
|
|
World->ChangeFeatureLevel(GWorld->FeatureLevel);
|
|
}
|
|
}
|
|
|
|
UEditorEngine* Editor = (UEditorEngine*)GEngine;
|
|
PreviewFeatureLevelChangedHandle = Editor->OnPreviewFeatureLevelChanged().AddLambda([this](ERHIFeatureLevel::Type NewFeatureLevel)
|
|
{
|
|
auto ScenePtr = PreviewScenePtr.Pin();
|
|
if (ScenePtr.IsValid())
|
|
{
|
|
UWorld* World = ScenePtr->GetWorld();
|
|
if (World != nullptr)
|
|
{
|
|
World->ChangeFeatureLevel(NewFeatureLevel);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
SAnimationEditorViewport::~SAnimationEditorViewport()
|
|
{
|
|
UEditorEngine* Editor = (UEditorEngine*)GEngine;
|
|
Editor->OnPreviewFeatureLevelChanged().Remove(PreviewFeatureLevelChangedHandle);
|
|
}
|
|
|
|
void SAnimationEditorViewport::PopulateViewportOverlays(TSharedRef<SOverlay> Overlay)
|
|
{
|
|
SEditorViewport::PopulateViewportOverlays(Overlay);
|
|
|
|
// add the feature level display widget
|
|
Overlay->AddSlot()
|
|
.VAlign(VAlign_Bottom)
|
|
.HAlign(HAlign_Right)
|
|
.Padding(5.0f)
|
|
[
|
|
BuildFeatureLevelWidget()
|
|
];
|
|
}
|
|
|
|
TSharedRef<FEditorViewportClient> SAnimationEditorViewport::MakeEditorViewportClient()
|
|
{
|
|
// Create an animation viewport client
|
|
LevelViewportClient = MakeShareable(new FAnimationViewportClient(PreviewScenePtr.Pin().ToSharedRef(), SharedThis(this), AssetEditorToolkitPtr.Pin().ToSharedRef(), ViewportIndex, bShowStats));
|
|
|
|
LevelViewportClient->ViewportType = LVT_Perspective;
|
|
LevelViewportClient->bSetListenerPosition = false;
|
|
LevelViewportClient->SetViewLocation(EditorViewportDefs::DefaultPerspectiveViewLocation);
|
|
LevelViewportClient->SetViewRotation(EditorViewportDefs::DefaultPerspectiveViewRotation);
|
|
|
|
return LevelViewportClient.ToSharedRef();
|
|
}
|
|
|
|
TSharedPtr<SWidget> SAnimationEditorViewport::MakeViewportToolbar()
|
|
{
|
|
return SAssignNew(ViewportToolbar, SAnimViewportToolBar, TabBodyPtr.Pin(), SharedThis(this))
|
|
.Cursor(EMouseCursor::Default)
|
|
.Extenders(Extenders)
|
|
.ContextName(ContextName)
|
|
.ShowShowMenu(bShowShowMenu)
|
|
.ShowLODMenu(bShowLODMenu)
|
|
.ShowPlaySpeedMenu(bShowPlaySpeedMenu)
|
|
.ShowFloorOptions(bShowFloorOptions)
|
|
.ShowTurnTable(bShowTurnTable)
|
|
.ShowPhysicsMenu(bShowPhysicsMenu);
|
|
}
|
|
|
|
void SAnimationEditorViewport::PostUndo( bool bSuccess )
|
|
{
|
|
LevelViewportClient->Invalidate();
|
|
}
|
|
|
|
void SAnimationEditorViewport::PostRedo( bool bSuccess )
|
|
{
|
|
LevelViewportClient->Invalidate();
|
|
}
|
|
|
|
void SAnimationEditorViewport::OnFocusViewportToSelection()
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
AnimViewportClient->SetCameraFollowMode(EAnimationViewportCameraFollowMode::None);
|
|
AnimViewportClient->FocusViewportOnPreviewMesh(false);
|
|
}
|
|
|
|
void SAnimationEditorViewport::BindCommands()
|
|
{
|
|
SEditorViewport::BindCommands();
|
|
|
|
FShowFlagMenuCommands::Get().BindCommands(*CommandList, Client);
|
|
FBufferVisualizationMenuCommands::Get().BindCommands(*CommandList, Client);
|
|
|
|
if (TSharedPtr<SAnimationEditorViewportTabBody> TabBody = TabBodyPtr.Pin())
|
|
{
|
|
if (TSharedPtr<FAssetEditorToolkit> ParentAssetEditor = TabBody->GetAssetEditorToolkit())
|
|
{
|
|
CommandList->Append(ParentAssetEditor->GetToolkitCommands());
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SAnimationEditorViewportTabBody
|
|
|
|
SAnimationEditorViewportTabBody::SAnimationEditorViewportTabBody()
|
|
: SelectedTurnTableSpeed(EAnimationPlaybackSpeeds::Normal)
|
|
, SelectedTurnTableMode(EPersonaTurnTableMode::Stopped)
|
|
, SectionsDisplayMode(ESectionDisplayMode::None)
|
|
{
|
|
}
|
|
|
|
SAnimationEditorViewportTabBody::~SAnimationEditorViewportTabBody()
|
|
{
|
|
// Close viewport
|
|
if (LevelViewportClient.IsValid())
|
|
{
|
|
LevelViewportClient->Viewport = NULL;
|
|
}
|
|
|
|
// Release our reference to the viewport client
|
|
LevelViewportClient.Reset();
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::CanUseGizmos() const
|
|
{
|
|
if (bAlwaysShowTransformToolbar)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
class UDebugSkelMeshComponent* Component = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if (Component != NULL)
|
|
{
|
|
if (Component->bForceRefpose)
|
|
{
|
|
return false;
|
|
}
|
|
else if (Component->IsPreviewOn())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (LevelViewportClient.IsValid())
|
|
{
|
|
if(const FEditorModeTools* ModeTools = LevelViewportClient->GetModeTools())
|
|
{
|
|
if(ModeTools->UsesTransformWidget())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
FText ConcatenateLine(const FText& InText, const FText& InNewLine)
|
|
{
|
|
if(InText.IsEmpty())
|
|
{
|
|
return InNewLine;
|
|
}
|
|
|
|
return FText::Format(LOCTEXT("ViewportTextNewlineFormatter", "{0}\n{1}"), InText, InNewLine);
|
|
}
|
|
|
|
FText SAnimationEditorViewportTabBody::GetDisplayString() const
|
|
{
|
|
class UDebugSkelMeshComponent* Component = GetPreviewScene()->GetPreviewMeshComponent();
|
|
TSharedPtr<IEditableSkeleton> EditableSkeleton = GetPreviewScene()->GetPersonaToolkit()->GetEditableSkeleton();
|
|
FName TargetSkeletonName = (EditableSkeleton.IsValid() && EditableSkeleton->IsSkeletonValid()) ? EditableSkeleton->GetSkeleton().GetFName() : NAME_None;
|
|
|
|
FText DefaultText;
|
|
|
|
if (Component != NULL)
|
|
{
|
|
if (Component->bForceRefpose)
|
|
{
|
|
DefaultText = LOCTEXT("ReferencePose", "Reference pose");
|
|
}
|
|
else if (Component->IsPreviewOn())
|
|
{
|
|
DefaultText = FText::Format(LOCTEXT("Previewing", "Previewing {0}"), FText::FromString(Component->GetPreviewText()));
|
|
}
|
|
else if (Component->AnimClass != NULL)
|
|
{
|
|
TSharedPtr<FBlueprintEditor> BPEditor = BlueprintEditorPtr.Pin();
|
|
const bool bWarnAboutBoneManip = BPEditor.IsValid() && BPEditor->IsModeCurrent(FPersonaModes::AnimBlueprintEditMode);
|
|
if (bWarnAboutBoneManip)
|
|
{
|
|
DefaultText = FText::Format(LOCTEXT("PreviewingAnimBP_WarnDisabled", "Previewing {0}. \nBone manipulation is disabled in this mode. "), FText::FromString(Component->AnimClass->GetName()));
|
|
}
|
|
else
|
|
{
|
|
DefaultText = FText::Format(LOCTEXT("PreviewingAnimBP", "Previewing {0}"), FText::FromString(Component->AnimClass->GetName()));
|
|
}
|
|
}
|
|
else if (Component->SkeletalMesh == NULL && TargetSkeletonName != NAME_None)
|
|
{
|
|
DefaultText = FText::Format(LOCTEXT("NoMeshFound", "No skeletal mesh found for skeleton '{0}'"), FText::FromName(TargetSkeletonName));
|
|
}
|
|
}
|
|
|
|
if(OnGetViewportText.IsBound())
|
|
{
|
|
DefaultText = ConcatenateLine(DefaultText, OnGetViewportText.Execute(EViewportCorner::TopLeft));
|
|
}
|
|
|
|
TSharedPtr<FAnimationViewportClient> AnimViewportClient = StaticCastSharedPtr<FAnimationViewportClient>(LevelViewportClient);
|
|
|
|
if(AnimViewportClient->IsShowingMeshStats())
|
|
{
|
|
DefaultText = ConcatenateLine(DefaultText, AnimViewportClient->GetDisplayInfo(AnimViewportClient->IsDetailedMeshStats()));
|
|
}
|
|
else if(AnimViewportClient->IsShowingSelectedNodeStats())
|
|
{
|
|
// Allow edit modes (inc. skeletal control modes) to draw with the canvas, and collect on screen strings to draw later
|
|
if (IAnimationEditContext* PersonaContext = AnimViewportClient->GetModeTools()->GetInteractiveToolsContext()->ContextObjectStore->FindContext<UAnimationEditModeContext>())
|
|
{
|
|
TArray<FText> EditModeDebugText;
|
|
PersonaContext->GetOnScreenDebugInfo(EditModeDebugText);
|
|
for(FText& Text : EditModeDebugText)
|
|
{
|
|
DefaultText = ConcatenateLine(DefaultText, Text);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(Component)
|
|
{
|
|
for(const FGetExtendedViewportText& TextDelegate : Component->GetExtendedViewportTextDelegates())
|
|
{
|
|
DefaultText = ConcatenateLine(DefaultText, TextDelegate.Execute());
|
|
}
|
|
}
|
|
|
|
return DefaultText;
|
|
}
|
|
|
|
TSharedRef<IPersonaViewportState> SAnimationEditorViewportTabBody::SaveState() const
|
|
{
|
|
TSharedRef<FPersonaModeSharedData> State = MakeShareable(new(FPersonaModeSharedData));
|
|
State->Save(StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef()));
|
|
return State;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::RestoreState(TSharedRef<IPersonaViewportState> InState)
|
|
{
|
|
TSharedRef<FPersonaModeSharedData> State = StaticCastSharedRef<FPersonaModeSharedData>(InState);
|
|
State->Restore(StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef()));
|
|
}
|
|
|
|
FEditorViewportClient& SAnimationEditorViewportTabBody::GetViewportClient() const
|
|
{
|
|
return *LevelViewportClient;
|
|
}
|
|
|
|
TSharedRef<IPinnedCommandList> SAnimationEditorViewportTabBody::GetPinnedCommandList() const
|
|
{
|
|
return ViewportWidget->GetViewportToolbar()->GetPinnedCommandList().ToSharedRef();
|
|
}
|
|
|
|
TWeakPtr<SWidget> SAnimationEditorViewportTabBody::AddNotification(TAttribute<EMessageSeverity::Type> InSeverity, TAttribute<bool> InCanBeDismissed, const TSharedRef<SWidget>& InNotificationWidget, FPersonaViewportNotificationOptions InOptions)
|
|
{
|
|
TSharedPtr<SBorder> ContainingWidget = nullptr;
|
|
TWeakPtr<SWidget> WeakNotificationWidget = InNotificationWidget;
|
|
|
|
auto GetPadding = [WeakNotificationWidget]()
|
|
{
|
|
if(WeakNotificationWidget.IsValid())
|
|
{
|
|
return WeakNotificationWidget.Pin()->GetVisibility() == EVisibility::Visible ? FMargin(2.0f) : FMargin(0.0f);
|
|
}
|
|
|
|
return FMargin(0.0f);
|
|
};
|
|
|
|
TAttribute<EVisibility> GetVisibility(EVisibility::Visible);
|
|
|
|
if (InOptions.OnGetVisibility.IsSet())
|
|
{
|
|
GetVisibility = InOptions.OnGetVisibility;
|
|
}
|
|
|
|
TAttribute<const FSlateBrush*> GetBrushForSeverity = TAttribute<const FSlateBrush*>::Create([InSeverity]()
|
|
{
|
|
switch(InSeverity.Get())
|
|
{
|
|
case EMessageSeverity::CriticalError:
|
|
case EMessageSeverity::Error:
|
|
return FAppStyle::GetBrush("AnimViewport.Notification.Error");
|
|
case EMessageSeverity::PerformanceWarning:
|
|
case EMessageSeverity::Warning:
|
|
return FAppStyle::GetBrush("AnimViewport.Notification.Warning");
|
|
default:
|
|
case EMessageSeverity::Info:
|
|
return FAppStyle::GetBrush("AnimViewport.Notification.Message");
|
|
}
|
|
});
|
|
|
|
if (InOptions.OnGetBrushOverride.IsSet())
|
|
{
|
|
GetBrushForSeverity = InOptions.OnGetBrushOverride;
|
|
}
|
|
|
|
TSharedPtr<SHorizontalBox> BodyBox = nullptr;
|
|
|
|
ViewportNotificationsContainer->AddSlot()
|
|
.HAlign(HAlign_Right)
|
|
.AutoHeight()
|
|
.Padding(MakeAttributeLambda(GetPadding))
|
|
[
|
|
SAssignNew(ContainingWidget, SBorder)
|
|
.Visibility(GetVisibility)
|
|
.BorderImage(GetBrushForSeverity)
|
|
[
|
|
SAssignNew(BodyBox, SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.FillWidth(1.0f)
|
|
[
|
|
InNotificationWidget
|
|
]
|
|
]
|
|
];
|
|
|
|
TWeakPtr<SWidget> WeakContainingWidget = ContainingWidget;
|
|
auto DismissNotification = [this, WeakContainingWidget]()
|
|
{
|
|
if(WeakContainingWidget.IsValid())
|
|
{
|
|
RemoveNotification(WeakContainingWidget.Pin().ToSharedRef());
|
|
}
|
|
|
|
return FReply::Handled();
|
|
};
|
|
|
|
auto GetDismissButtonVisibility = [InCanBeDismissed]()
|
|
{
|
|
return InCanBeDismissed.Get() ? EVisibility::Visible : EVisibility::Collapsed;
|
|
};
|
|
|
|
// add dismiss button
|
|
BodyBox->InsertSlot(0)
|
|
.AutoWidth()
|
|
.HAlign(HAlign_Center)
|
|
.VAlign(VAlign_Top)
|
|
[
|
|
SNew(SButton)
|
|
.Visibility_Lambda(GetDismissButtonVisibility)
|
|
.ButtonStyle(FAppStyle::Get(), "AnimViewport.Notification.CloseButton")
|
|
.ToolTipText(LOCTEXT("DismissNotificationToolTip", "Dismiss this notification."))
|
|
.OnClicked_Lambda(DismissNotification)
|
|
];
|
|
|
|
return ContainingWidget;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::RemoveNotification(const TWeakPtr<SWidget>& InContainingWidget)
|
|
{
|
|
if(InContainingWidget.IsValid())
|
|
{
|
|
ViewportNotificationsContainer->RemoveSlot(InContainingWidget.Pin().ToSharedRef());
|
|
}
|
|
}
|
|
|
|
|
|
void SAnimationEditorViewportTabBody::AddToolbarExtender(FName MenuToExtend, FMenuExtensionDelegate MenuBuilderDelegate)
|
|
{
|
|
return ViewportWidget->ViewportToolbar->AddMenuExtender(MenuToExtend, MenuBuilderDelegate);
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::AddOverlayWidget(TSharedRef<SWidget> InOverlaidWidget)
|
|
{
|
|
ViewportWidget->ViewportOverlay->AddSlot()
|
|
[
|
|
InOverlaidWidget
|
|
];
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::RemoveOverlayWidget(TSharedRef<SWidget> InOverlaidWidget)
|
|
{
|
|
ViewportWidget->ViewportOverlay->RemoveSlot(InOverlaidWidget);
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::RefreshViewport()
|
|
{
|
|
LevelViewportClient->Invalidate();
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsVisible() const
|
|
{
|
|
return ViewportWidget.IsValid();
|
|
}
|
|
|
|
FReply SAnimationEditorViewportTabBody::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent)
|
|
{
|
|
if (UICommandList.IsValid() && UICommandList->ProcessCommandBindings(InKeyEvent))
|
|
{
|
|
return FReply::Handled();
|
|
}
|
|
|
|
if (OnKeyDownDelegate.IsBound())
|
|
{
|
|
return OnKeyDownDelegate.Execute(MyGeometry, InKeyEvent);
|
|
}
|
|
|
|
return FReply::Unhandled();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::Construct(const FArguments& InArgs, const TSharedRef<class IPersonaPreviewScene>& InPreviewScene, const TSharedRef<class FAssetEditorToolkit>& InAssetEditorToolkit, int32 InViewportIndex)
|
|
{
|
|
UICommandList = MakeShareable(new FUICommandList_Pinnable);
|
|
|
|
PreviewScenePtr = StaticCastSharedRef<FAnimationEditorPreviewScene>(InPreviewScene);
|
|
AssetEditorToolkitPtr = InAssetEditorToolkit;
|
|
BlueprintEditorPtr = InArgs._BlueprintEditor;
|
|
bShowTimeline = InArgs._ShowTimeline;
|
|
bAlwaysShowTransformToolbar = InArgs._AlwaysShowTransformToolbar;
|
|
OnInvokeTab = InArgs._OnInvokeTab;
|
|
OnGetViewportText = InArgs._OnGetViewportText;
|
|
|
|
// register delegates for change notifications
|
|
InPreviewScene->RegisterOnAnimChanged(FOnAnimChanged::CreateSP(this, &SAnimationEditorViewportTabBody::AnimChanged));
|
|
InPreviewScene->RegisterOnPreviewMeshChanged(FOnPreviewMeshChanged::CreateSP(this, &SAnimationEditorViewportTabBody::HandlePreviewMeshChanged));
|
|
|
|
const FSlateFontInfo SmallLayoutFont = FCoreStyle::GetDefaultFontStyle("Regular", 9);
|
|
|
|
FAnimViewportMenuCommands::Register();
|
|
FAnimViewportShowCommands::Register();
|
|
FAnimViewportLODCommands::Register();
|
|
FAnimViewportPlaybackCommands::Register();
|
|
|
|
// Build toolbar widgets
|
|
UVChannelCombo = SNew(STextComboBox)
|
|
.OptionsSource(&UVChannels)
|
|
.Font(SmallLayoutFont)
|
|
.OnSelectionChanged(this, &SAnimationEditorViewportTabBody::ComboBoxSelectionChanged);
|
|
|
|
PopulateSkinWeightProfileNames();
|
|
|
|
SkinWeightCombo = SNew(SNameComboBox)
|
|
.OptionsSource(&SkinWeightProfileNames)
|
|
.InitiallySelectedItem(SkinWeightProfileNames.Num() > 0 ? SkinWeightProfileNames[0] : nullptr)
|
|
.OnComboBoxOpening(FOnComboBoxOpening::CreateLambda([this]()
|
|
{
|
|
// Retrieve currently selected value, and check whether or not it is still valid, it could be that a profile has been renamed or removed without updating the entries
|
|
FName Name = SkinWeightCombo->GetSelectedItem().IsValid() ? *SkinWeightCombo->GetSelectedItem().Get() : NAME_None;
|
|
PopulateSkinWeightProfileNames();
|
|
const int32 Index = SkinWeightProfileNames.IndexOfByPredicate([Name](TSharedPtr<FName> SearchName) { return Name == *SearchName; });
|
|
if (Index != INDEX_NONE)
|
|
{
|
|
SkinWeightCombo->SetSelectedItem(SkinWeightProfileNames[Index]);
|
|
}
|
|
|
|
}))
|
|
.OnSelectionChanged(SNameComboBox::FOnNameSelectionChanged::CreateLambda([WeakScenePtr = PreviewScenePtr](TSharedPtr<FName> SelectedProfile, ESelectInfo::Type SelectInfo)
|
|
{
|
|
// Apply the skin weight profile to the component, according to the selected the name,
|
|
if (WeakScenePtr.IsValid() && SelectedProfile.IsValid())
|
|
{
|
|
UDebugSkelMeshComponent* MeshComponent = WeakScenePtr.Pin()->GetPreviewMeshComponent();
|
|
if (MeshComponent)
|
|
{
|
|
MeshComponent->ClearSkinWeightProfile();
|
|
|
|
if (*SelectedProfile != NAME_None)
|
|
{
|
|
MeshComponent->SetSkinWeightProfile(*SelectedProfile);
|
|
}
|
|
}
|
|
}
|
|
}));
|
|
|
|
FAnimationEditorViewportRequiredArgs ViewportArgs(InPreviewScene, SharedThis(this), InAssetEditorToolkit, InViewportIndex);
|
|
|
|
ViewportWidget = SNew(SAnimationEditorViewport, ViewportArgs)
|
|
.Extenders(InArgs._Extenders)
|
|
.ContextName(InArgs._ContextName)
|
|
.ShowShowMenu(InArgs._ShowShowMenu)
|
|
.ShowLODMenu(InArgs._ShowLODMenu)
|
|
.ShowPlaySpeedMenu(InArgs._ShowPlaySpeedMenu)
|
|
.ShowStats(InArgs._ShowStats)
|
|
.ShowFloorOptions(InArgs._ShowFloorOptions)
|
|
.ShowTurnTable(InArgs._ShowTurnTable)
|
|
.ShowPhysicsMenu(InArgs._ShowPhysicsMenu);
|
|
|
|
TSharedPtr<SVerticalBox> ViewportContainer = nullptr;
|
|
this->ChildSlot
|
|
[
|
|
SAssignNew(ViewportContainer, SVerticalBox)
|
|
|
|
// Build our toolbar level toolbar
|
|
+SVerticalBox::Slot()
|
|
.FillHeight(1)
|
|
[
|
|
SNew(SOverlay)
|
|
|
|
// The viewport
|
|
+SOverlay::Slot()
|
|
[
|
|
ViewportWidget.ToSharedRef()
|
|
]
|
|
|
|
// The 'dirty/in-error' indicator text in the bottom-right corner
|
|
+SOverlay::Slot()
|
|
.Padding(8)
|
|
.VAlign(VAlign_Bottom)
|
|
.HAlign(HAlign_Right)
|
|
[
|
|
SAssignNew(ViewportNotificationsContainer, SVerticalBox)
|
|
]
|
|
]
|
|
];
|
|
|
|
if(bShowTimeline && ViewportContainer.IsValid())
|
|
{
|
|
ViewportContainer->AddSlot()
|
|
.AutoHeight()
|
|
[
|
|
SAssignNew(ScrubPanelContainer, SVerticalBox)
|
|
+SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
[
|
|
SNew(SAnimationScrubPanel, GetPreviewScene())
|
|
.ViewInputMin(this, &SAnimationEditorViewportTabBody::GetViewMinInput)
|
|
.ViewInputMax(this, &SAnimationEditorViewportTabBody::GetViewMaxInput)
|
|
.bAllowZoom(true)
|
|
]
|
|
];
|
|
|
|
UpdateScrubPanel(InPreviewScene->GetPreviewAnimationAsset());
|
|
}
|
|
|
|
LevelViewportClient = ViewportWidget->GetViewportClient();
|
|
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
|
|
// Load the view mode from config
|
|
AnimViewportClient->SetViewMode(AnimViewportClient->ConfigOption->GetAssetEditorOptions(AssetEditorToolkitPtr.Pin()->GetEditorName()).ViewportConfigs[InViewportIndex].ViewModeIndex);
|
|
UpdateShowFlagForMeshEdges();
|
|
|
|
|
|
OnSetTurnTableMode(SelectedTurnTableMode);
|
|
OnSetTurnTableSpeed(SelectedTurnTableSpeed);
|
|
|
|
BindCommands();
|
|
|
|
PopulateNumUVChannels();
|
|
PopulateSkinWeightProfileNames();
|
|
|
|
GetPreviewScene()->OnRecordingStateChanged().AddSP(this, &SAnimationEditorViewportTabBody::AddRecordingNotification);
|
|
if (GetPreviewScene()->GetPreviewMesh())
|
|
{
|
|
GetPreviewScene()->GetPreviewMesh()->OnPostMeshCached().AddSP(this, &SAnimationEditorViewportTabBody::UpdateSkinWeightSelection);
|
|
}
|
|
|
|
AddPostProcessNotification();
|
|
|
|
AddMinLODNotification();
|
|
|
|
AddSkinWeightProfileNotification();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::BindCommands()
|
|
{
|
|
FUICommandList_Pinnable& CommandList = *UICommandList;
|
|
|
|
//Bind menu commands
|
|
const FAnimViewportMenuCommands& MenuActions = FAnimViewportMenuCommands::Get();
|
|
|
|
CommandList.MapAction(
|
|
MenuActions.CameraFollowNone,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::SetCameraFollowMode, EAnimationViewportCameraFollowMode::None, FName()),
|
|
FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::CanChangeCameraMode),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsCameraFollowEnabled, EAnimationViewportCameraFollowMode::None));
|
|
|
|
CommandList.MapAction(
|
|
MenuActions.CameraFollowBounds,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::SetCameraFollowMode, EAnimationViewportCameraFollowMode::Bounds, FName()),
|
|
FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::CanChangeCameraMode),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsCameraFollowEnabled, EAnimationViewportCameraFollowMode::Bounds));
|
|
|
|
CommandList.MapAction(
|
|
MenuActions.JumpToDefaultCamera,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::JumpToDefaultCamera),
|
|
FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::HasDefaultCameraSet));
|
|
|
|
CommandList.MapAction(
|
|
MenuActions.SaveCameraAsDefault,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::SaveCameraAsDefault),
|
|
FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::CanSaveCameraAsDefault));
|
|
|
|
CommandList.MapAction(
|
|
MenuActions.ClearDefaultCamera,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::ClearDefaultCamera),
|
|
FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::HasDefaultCameraSet));
|
|
|
|
CommandList.MapAction(
|
|
MenuActions.PreviewSceneSettings,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OpenPreviewSceneSettings));
|
|
|
|
TSharedRef<FAnimationViewportClient> EditorViewportClientRef = GetAnimationViewportClient();
|
|
|
|
CommandList.MapAction(
|
|
MenuActions.SetCPUSkinning,
|
|
FExecuteAction::CreateSP(EditorViewportClientRef, &FAnimationViewportClient::ToggleCPUSkinning),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(EditorViewportClientRef, &FAnimationViewportClient::IsSetCPUSkinningChecked));
|
|
|
|
CommandList.MapAction(
|
|
MenuActions.SetShowNormals,
|
|
FExecuteAction::CreateSP( EditorViewportClientRef, &FAnimationViewportClient::ToggleShowNormals ),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP( EditorViewportClientRef, &FAnimationViewportClient::IsSetShowNormalsChecked ) );
|
|
|
|
CommandList.MapAction(
|
|
MenuActions.SetShowTangents,
|
|
FExecuteAction::CreateSP( EditorViewportClientRef, &FAnimationViewportClient::ToggleShowTangents ),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP( EditorViewportClientRef, &FAnimationViewportClient::IsSetShowTangentsChecked ) );
|
|
|
|
CommandList.MapAction(
|
|
MenuActions.SetShowBinormals,
|
|
FExecuteAction::CreateSP( EditorViewportClientRef, &FAnimationViewportClient::ToggleShowBinormals ),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP( EditorViewportClientRef, &FAnimationViewportClient::IsSetShowBinormalsChecked ) );
|
|
|
|
//Bind Show commands
|
|
const FAnimViewportShowCommands& ViewportShowMenuCommands = FAnimViewportShowCommands::Get();
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowRetargetBasePose,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::ShowRetargetBasePose),
|
|
FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::CanShowRetargetBasePose),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowRetargetBasePoseEnabled));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowBound,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::ShowBound),
|
|
FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::CanShowBound),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowBoundEnabled));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.UseInGameBound,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::UseInGameBound),
|
|
FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::CanUseInGameBound),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsUsingInGameBound));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.UseFixedBounds,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::UseFixedBounds),
|
|
FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::CanUseFixedBounds),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsUsingFixedBounds));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.UsePreSkinnedBounds,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::UsePreSkinnedBounds),
|
|
FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::CanUsePreSkinnedBounds),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsUsingPreSkinnedBounds));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowPreviewMesh,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::ToggleShowPreviewMesh),
|
|
FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::CanShowPreviewMesh),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowPreviewMeshEnabled));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowMorphTargets,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowMorphTargets),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingMorphTargets));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowBoneNames,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowBoneNames),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingBoneNames));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowRawAnimation,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowRawAnimation),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingRawAnimation));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowNonRetargetedAnimation,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowNonRetargetedAnimation),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingNonRetargetedPose));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowAdditiveBaseBones,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowAdditiveBase),
|
|
FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::IsPreviewingAnimation),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingAdditiveBase));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowSourceRawAnimation,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowSourceRawAnimation),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingSourceRawAnimation));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowBakedAnimation,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowBakedAnimation),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingBakedAnimation));
|
|
|
|
//Display info
|
|
CommandList.BeginGroup(TEXT("MeshDisplayInfo"));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowDisplayInfoBasic,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowDisplayInfo, (int32)EDisplayInfoMode::Basic),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingMeshInfo, (int32)EDisplayInfoMode::Basic));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowDisplayInfoDetailed,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowDisplayInfo, (int32)EDisplayInfoMode::Detailed),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingMeshInfo, (int32)EDisplayInfoMode::Detailed));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowDisplayInfoSkelControls,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowDisplayInfo, (int32)EDisplayInfoMode::SkeletalControls),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingMeshInfo, (int32)EDisplayInfoMode::SkeletalControls));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.HideDisplayInfo,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowDisplayInfo, (int32)EDisplayInfoMode::None),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingMeshInfo, (int32)EDisplayInfoMode::None));
|
|
|
|
CommandList.EndGroup();
|
|
|
|
//Material overlay option
|
|
CommandList.BeginGroup(TEXT("MaterialOverlay"));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowOverlayNone,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowOverlayNone),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingOverlayNone));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowBoneWeight,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowOverlayBoneWeight),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingOverlayBoneWeight));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowMorphTargetVerts,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowOverlayMorphTargetVert),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingOverlayMorphTargetVerts));
|
|
|
|
CommandList.EndGroup();
|
|
|
|
// Show sockets
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowSockets,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowSockets),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingSockets));
|
|
|
|
// Show transform attributes
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowAttributes,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowAttributes),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingAttributes));
|
|
|
|
// Set bone drawing mode
|
|
CommandList.BeginGroup(TEXT("BoneDrawingMode"));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowBoneDrawNone,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetBoneDrawMode, (int32)EBoneDrawMode::None),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsBoneDrawModeSet, (int32)EBoneDrawMode::None));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowBoneDrawSelected,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetBoneDrawMode, (int32)EBoneDrawMode::Selected),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsBoneDrawModeSet, (int32)EBoneDrawMode::Selected));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowBoneDrawSelectedAndParents,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetBoneDrawMode, (int32)EBoneDrawMode::SelectedAndParents),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsBoneDrawModeSet, (int32)EBoneDrawMode::SelectedAndParents));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowBoneDrawSelectedAndChildren,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetBoneDrawMode, (int32)EBoneDrawMode::SelectedAndChildren),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsBoneDrawModeSet, (int32)EBoneDrawMode::SelectedAndChildren));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowBoneDrawSelectedAndParentsAndChildren,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetBoneDrawMode, (int32)EBoneDrawMode::SelectedAndParentsAndChildren),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsBoneDrawModeSet, (int32)EBoneDrawMode::SelectedAndParentsAndChildren));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowBoneDrawAll,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetBoneDrawMode, (int32)EBoneDrawMode::All),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsBoneDrawModeSet, (int32)EBoneDrawMode::All));
|
|
|
|
CommandList.EndGroup();
|
|
|
|
// Set bone local axes mode
|
|
CommandList.BeginGroup(TEXT("BoneLocalAxesMode"));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowLocalAxesNone,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetLocalAxesMode, (int32)ELocalAxesMode::None),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsLocalAxesModeSet, (int32)ELocalAxesMode::None));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowLocalAxesSelected,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetLocalAxesMode, (int32)ELocalAxesMode::Selected),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsLocalAxesModeSet, (int32)ELocalAxesMode::Selected));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowLocalAxesAll,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetLocalAxesMode, (int32)ELocalAxesMode::All),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsLocalAxesModeSet, (int32)ELocalAxesMode::All));
|
|
|
|
CommandList.EndGroup();
|
|
|
|
//Clothing show options
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.EnableClothSimulation,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnEnableClothSimulation),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsClothSimulationEnabled));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ResetClothSimulation,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnResetClothSimulation),
|
|
FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::IsClothSimulationEnabled));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.EnableCollisionWithAttachedClothChildren,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnEnableCollisionWithAttachedClothChildren),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsEnablingCollisionWithAttachedClothChildren));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.PauseClothWithAnim,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnPauseClothingSimWithAnim),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsPausingClothingSimWithAnim));
|
|
|
|
CommandList.BeginGroup(TEXT("ClothSectionDisplayMode"));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowAllSections,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetSectionsDisplayMode, ESectionDisplayMode::ShowAll),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsSectionsDisplayMode, ESectionDisplayMode::ShowAll));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ShowOnlyClothSections,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetSectionsDisplayMode, ESectionDisplayMode::ShowOnlyClothSections),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsSectionsDisplayMode, ESectionDisplayMode::ShowOnlyClothSections));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.HideOnlyClothSections,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetSectionsDisplayMode, ESectionDisplayMode::HideOnlyClothSections),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsSectionsDisplayMode, ESectionDisplayMode::HideOnlyClothSections));
|
|
|
|
CommandList.EndGroup();
|
|
|
|
|
|
GetPreviewScene()->RegisterOnSelectedLODChanged(FOnSelectedLODChanged::CreateSP(this, &SAnimationEditorViewportTabBody::OnLODModelChanged));
|
|
//Bind LOD preview menu commands
|
|
const FAnimViewportLODCommands& ViewportLODMenuCommands = FAnimViewportLODCommands::Get();
|
|
|
|
CommandList.BeginGroup(TEXT("LOD"));
|
|
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if (PreviewComponent)
|
|
{
|
|
//LOD Debug
|
|
CommandList.MapAction(
|
|
ViewportLODMenuCommands.LODDebug,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetLODTrackDebuggedInstance),
|
|
FCanExecuteAction::CreateLambda([PreviewComponent]() { return (bool)PreviewComponent->PreviewInstance->GetDebugSkeletalMeshComponent(); }),
|
|
FIsActionChecked::CreateLambda([PreviewComponent]() { return PreviewComponent->IsTrackingAttachedLOD(); }),
|
|
FIsActionButtonVisible::CreateLambda([PreviewComponent]() { return (bool)PreviewComponent->PreviewInstance->GetDebugSkeletalMeshComponent() ; }));
|
|
|
|
PreviewComponent->RegisterOnDebugForceLODChangedDelegate(FOnDebugForceLODChanged::CreateSP(this, &SAnimationEditorViewportTabBody::OnDebugForcedLODChanged));
|
|
}
|
|
|
|
//LOD Auto
|
|
CommandList.MapAction(
|
|
ViewportLODMenuCommands.LODAuto,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetLODModel, 0),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsLODModelSelected, 0));
|
|
|
|
// LOD 0
|
|
CommandList.MapAction(
|
|
ViewportLODMenuCommands.LOD0,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetLODModel, 1),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsLODModelSelected, 1));
|
|
|
|
// all other LODs will be added dynamically
|
|
|
|
CommandList.EndGroup();
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.AutoAlignFloorToMesh,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnToggleAutoAlignFloor),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsAutoAlignFloor));
|
|
|
|
//Bind LOD preview menu commands
|
|
const FAnimViewportPlaybackCommands& ViewportPlaybackCommands = FAnimViewportPlaybackCommands::Get();
|
|
|
|
CommandList.BeginGroup(TEXT("PlaybackSpeeds"));
|
|
|
|
//Create a menu item for each playback speed in EAnimationPlaybackSpeeds
|
|
for(int32 i = 0; i < int(EAnimationPlaybackSpeeds::NumPlaybackSpeeds); ++i)
|
|
{
|
|
CommandList.MapAction(
|
|
ViewportPlaybackCommands.PlaybackSpeedCommands[i],
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetPlaybackSpeed, i),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsPlaybackSpeedSelected, i));
|
|
}
|
|
|
|
CommandList.EndGroup();
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.MuteAudio,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnToggleMuteAudio),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsAudioMuted));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.UseAudioAttenuation,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnToggleUseAudioAttenuation),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsAudioAttenuationEnabled));
|
|
|
|
CommandList.BeginGroup(TEXT("RootMotion"));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.DoNotProcessRootMotion,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::SetProcessRootMotionMode, EProcessRootMotionMode::Ignore),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::CanUseProcessRootMotionMode, EProcessRootMotionMode::Ignore),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsProcessRootMotionModeSet, EProcessRootMotionMode::Ignore));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ProcessRootMotionLoopAndReset,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::SetProcessRootMotionMode, EProcessRootMotionMode::LoopAndReset),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::CanUseProcessRootMotionMode, EProcessRootMotionMode::LoopAndReset),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsProcessRootMotionModeSet, EProcessRootMotionMode::LoopAndReset));
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.ProcessRootMotionLoop,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::SetProcessRootMotionMode, EProcessRootMotionMode::Loop),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::CanUseProcessRootMotionMode, EProcessRootMotionMode::Loop),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsProcessRootMotionModeSet, EProcessRootMotionMode::Loop));
|
|
|
|
CommandList.EndGroup();
|
|
|
|
CommandList.MapAction(
|
|
ViewportShowMenuCommands.DisablePostProcessBlueprint,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnToggleDisablePostProcess),
|
|
FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::CanDisablePostProcess),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsDisablePostProcessChecked));
|
|
|
|
CommandList.BeginGroup(TEXT("TurnTableSpeeds"));
|
|
|
|
// Turn Table Controls
|
|
for (int32 i = 0; i < int(EAnimationPlaybackSpeeds::NumPlaybackSpeeds); ++i)
|
|
{
|
|
CommandList.MapAction(
|
|
ViewportPlaybackCommands.TurnTableSpeeds[i],
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetTurnTableSpeed, i),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsTurnTableSpeedSelected, i));
|
|
}
|
|
|
|
CommandList.EndGroup();
|
|
|
|
CommandList.BeginGroup(TEXT("TurnTableMode"));
|
|
|
|
CommandList.MapAction(
|
|
ViewportPlaybackCommands.PersonaTurnTablePlay,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetTurnTableMode, int32(EPersonaTurnTableMode::Playing)),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsTurnTableModeSelected, int32(EPersonaTurnTableMode::Playing)));
|
|
|
|
CommandList.MapAction(
|
|
ViewportPlaybackCommands.PersonaTurnTablePause,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetTurnTableMode, int32(EPersonaTurnTableMode::Paused)),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsTurnTableModeSelected, int32(EPersonaTurnTableMode::Paused)));
|
|
|
|
CommandList.MapAction(
|
|
ViewportPlaybackCommands.PersonaTurnTableStop,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetTurnTableMode, int32(EPersonaTurnTableMode::Stopped)),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsTurnTableModeSelected, int32(EPersonaTurnTableMode::Stopped)));
|
|
|
|
CommandList.EndGroup();
|
|
|
|
CommandList.MapAction(
|
|
FEditorViewportCommands::Get().FocusViewportToSelection,
|
|
FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::HandleFocusCamera));
|
|
|
|
TSharedPtr<FUICommandList> ToolkitCommandList = ConstCastSharedRef<FUICommandList>(GetAssetEditorToolkit()->GetToolkitCommands());
|
|
ToolkitCommandList->Append(UICommandList->AsShared());
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnSetTurnTableSpeed(int32 SpeedIndex)
|
|
{
|
|
SelectedTurnTableSpeed = (EAnimationPlaybackSpeeds::Type)SpeedIndex;
|
|
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if (PreviewComponent)
|
|
{
|
|
PreviewComponent->TurnTableSpeedScaling = EAnimationPlaybackSpeeds::Values[SelectedTurnTableSpeed];
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsTurnTableSpeedSelected(int32 SpeedIndex) const
|
|
{
|
|
return (SelectedTurnTableSpeed == SpeedIndex);
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnSetTurnTableMode(int32 ModeIndex)
|
|
{
|
|
SelectedTurnTableMode = (EPersonaTurnTableMode::Type)ModeIndex;
|
|
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if (PreviewComponent)
|
|
{
|
|
PreviewComponent->TurnTableMode = SelectedTurnTableMode;
|
|
|
|
if (SelectedTurnTableMode == EPersonaTurnTableMode::Stopped)
|
|
{
|
|
PreviewComponent->SetRelativeRotation(FRotator::ZeroRotator);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsTurnTableModeSelected(int32 ModeIndex) const
|
|
{
|
|
return (SelectedTurnTableMode == ModeIndex);
|
|
}
|
|
|
|
int32 SAnimationEditorViewportTabBody::GetLODModelCount() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if( PreviewComponent && PreviewComponent->SkeletalMesh )
|
|
{
|
|
return PreviewComponent->SkeletalMesh->GetResourceForRendering()->LODRenderData.Num();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnShowMorphTargets()
|
|
{
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
PreviewComponent->bDisableMorphTarget = !PreviewComponent->bDisableMorphTarget;
|
|
PreviewComponent->MarkRenderStateDirty();
|
|
RefreshViewport();
|
|
}
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnShowBoneNames()
|
|
{
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
PreviewComponent->bShowBoneNames = !PreviewComponent->bShowBoneNames;
|
|
PreviewComponent->MarkRenderStateDirty();
|
|
RefreshViewport();
|
|
}
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnShowRawAnimation()
|
|
{
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
PreviewComponent->bDisplayRawAnimation = !PreviewComponent->bDisplayRawAnimation;
|
|
PreviewComponent->MarkRenderStateDirty();
|
|
}
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnShowNonRetargetedAnimation()
|
|
{
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
PreviewComponent->bDisplayNonRetargetedPose = !PreviewComponent->bDisplayNonRetargetedPose;
|
|
PreviewComponent->MarkRenderStateDirty();
|
|
}
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnShowSourceRawAnimation()
|
|
{
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
PreviewComponent->bDisplaySourceAnimation = !PreviewComponent->bDisplaySourceAnimation;
|
|
PreviewComponent->MarkRenderStateDirty();
|
|
}
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnShowBakedAnimation()
|
|
{
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
PreviewComponent->bDisplayBakedAnimation = !PreviewComponent->bDisplayBakedAnimation;
|
|
PreviewComponent->MarkRenderStateDirty();
|
|
}
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnShowAdditiveBase()
|
|
{
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
PreviewComponent->bDisplayAdditiveBasePose = !PreviewComponent->bDisplayAdditiveBasePose;
|
|
PreviewComponent->MarkRenderStateDirty();
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsPreviewingAnimation() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return (PreviewComponent && PreviewComponent->PreviewInstance && (PreviewComponent->PreviewInstance == PreviewComponent->GetAnimInstance()));
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowingMorphTargets() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->bDisableMorphTarget == false;
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowingBoneNames() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->bShowBoneNames;
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowingRawAnimation() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->bDisplayRawAnimation;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnToggleDisablePostProcess()
|
|
{
|
|
if(UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
PreviewComponent->ToggleDisablePostProcessBlueprint();
|
|
|
|
AddPostProcessNotification();
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::CanDisablePostProcess()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent && PreviewComponent->PostProcessAnimInstance;
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsDisablePostProcessChecked()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent && PreviewComponent->GetDisablePostProcessBlueprint();
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowingNonRetargetedPose() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->bDisplayNonRetargetedPose;
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowingAdditiveBase() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->bDisplayAdditiveBasePose;
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowingSourceRawAnimation() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->bDisplaySourceAnimation;
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowingBakedAnimation() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->bDisplayBakedAnimation;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnShowDisplayInfo(int32 DisplayInfoMode)
|
|
{
|
|
GetAnimationViewportClient()->OnSetShowMeshStats(DisplayInfoMode);
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowingMeshInfo(int32 DisplayInfoMode) const
|
|
{
|
|
return GetAnimationViewportClient()->GetShowMeshStats() == DisplayInfoMode;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnShowOverlayNone()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if (PreviewComponent)
|
|
{
|
|
PreviewComponent->SetShowBoneWeight(false);
|
|
PreviewComponent->SetShowMorphTargetVerts(false);
|
|
UpdateShowFlagForMeshEdges();
|
|
PreviewComponent->MarkRenderStateDirty();
|
|
RefreshViewport();
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowingOverlayNone() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && !PreviewComponent->bDrawBoneInfluences && !PreviewComponent->bDrawMorphTargetVerts;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnShowOverlayBoneWeight()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if( PreviewComponent )
|
|
{
|
|
PreviewComponent->SetShowBoneWeight( !PreviewComponent->bDrawBoneInfluences );
|
|
UpdateShowFlagForMeshEdges();
|
|
PreviewComponent->MarkRenderStateDirty();
|
|
RefreshViewport();
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowingOverlayBoneWeight() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->bDrawBoneInfluences;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnShowOverlayMorphTargetVert()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if (PreviewComponent)
|
|
{
|
|
PreviewComponent->SetShowMorphTargetVerts(!PreviewComponent->bDrawMorphTargetVerts);
|
|
UpdateShowFlagForMeshEdges();
|
|
PreviewComponent->MarkRenderStateDirty();
|
|
RefreshViewport();
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowingOverlayMorphTargetVerts() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->bDrawMorphTargetVerts;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnSetBoneDrawMode(int32 BoneDrawMode)
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
AnimViewportClient->SetBoneDrawMode((EBoneDrawMode::Type)BoneDrawMode);
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsBoneDrawModeSet(int32 BoneDrawMode) const
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
return AnimViewportClient->IsBoneDrawModeSet((EBoneDrawMode::Type)BoneDrawMode);
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnSetLocalAxesMode(int32 LocalAxesMode)
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
AnimViewportClient->SetLocalAxesMode((ELocalAxesMode::Type)LocalAxesMode);
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsLocalAxesModeSet(int32 LocalAxesMode) const
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
return AnimViewportClient->IsLocalAxesModeSet((ELocalAxesMode::Type)LocalAxesMode);
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnShowSockets()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if( PreviewComponent )
|
|
{
|
|
PreviewComponent->bDrawSockets = !PreviewComponent->bDrawSockets;
|
|
PreviewComponent->MarkRenderStateDirty();
|
|
RefreshViewport();
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowingSockets() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->bDrawSockets;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnShowAttributes()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if (PreviewComponent)
|
|
{
|
|
PreviewComponent->bDrawAttributes = !PreviewComponent->bDrawAttributes;
|
|
PreviewComponent->MarkRenderStateDirty();
|
|
RefreshViewport();
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowingAttributes() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->bDrawAttributes;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnToggleAutoAlignFloor()
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
AnimViewportClient->OnToggleAutoAlignFloor();
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsAutoAlignFloor() const
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
return AnimViewportClient->IsAutoAlignFloor();
|
|
}
|
|
|
|
/** Function to set the current playback speed*/
|
|
void SAnimationEditorViewportTabBody::OnSetPlaybackSpeed(int32 PlaybackSpeedMode)
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
AnimViewportClient->SetPlaybackSpeedMode((EAnimationPlaybackSpeeds::Type)PlaybackSpeedMode);
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsPlaybackSpeedSelected(int32 PlaybackSpeedMode)
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
return PlaybackSpeedMode == AnimViewportClient->GetPlaybackSpeedMode();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::ShowRetargetBasePose()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if(PreviewComponent && PreviewComponent->PreviewInstance)
|
|
{
|
|
PreviewComponent->PreviewInstance->SetForceRetargetBasePose(!PreviewComponent->PreviewInstance->GetForceRetargetBasePose());
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::CanShowRetargetBasePose() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->PreviewInstance;
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowRetargetBasePoseEnabled() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if(PreviewComponent && PreviewComponent->PreviewInstance)
|
|
{
|
|
return PreviewComponent->PreviewInstance->GetForceRetargetBasePose();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::ShowBound()
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
AnimViewportClient->ToggleShowBounds();
|
|
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if(PreviewComponent)
|
|
{
|
|
PreviewComponent->bDisplayBound = AnimViewportClient->EngineShowFlags.Bounds;
|
|
PreviewComponent->RecreateRenderState_Concurrent();
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::CanShowBound() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL;
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowBoundEnabled() const
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
return AnimViewportClient->IsSetShowBoundsChecked();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::ToggleShowPreviewMesh()
|
|
{
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
bool bCurrentlyVisible = IsShowPreviewMeshEnabled();
|
|
PreviewComponent->SetVisibility(!bCurrentlyVisible);
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::CanShowPreviewMesh() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL;
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsShowPreviewMeshEnabled() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return (PreviewComponent != NULL) && PreviewComponent->IsVisible();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::UseInGameBound()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if (PreviewComponent != NULL)
|
|
{
|
|
PreviewComponent->UseInGameBounds(! PreviewComponent->IsUsingInGameBounds());
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::CanUseInGameBound() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && IsShowBoundEnabled();
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsUsingInGameBound() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->IsUsingInGameBounds();
|
|
}
|
|
|
|
|
|
void SAnimationEditorViewportTabBody::UseFixedBounds()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if (PreviewComponent != NULL)
|
|
{
|
|
PreviewComponent->bComponentUseFixedSkelBounds = !PreviewComponent->bComponentUseFixedSkelBounds;
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::CanUseFixedBounds() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && IsShowBoundEnabled();
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsUsingFixedBounds() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->bComponentUseFixedSkelBounds;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::UsePreSkinnedBounds()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if (PreviewComponent != NULL)
|
|
{
|
|
PreviewComponent->UsePreSkinnedBounds(!PreviewComponent->IsUsingPreSkinnedBounds());
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::CanUsePreSkinnedBounds() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && IsShowBoundEnabled();
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsUsingPreSkinnedBounds() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent != NULL && PreviewComponent->IsUsingPreSkinnedBounds();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::HandlePreviewMeshChanged(class USkeletalMesh* OldSkeletalMesh, class USkeletalMesh* NewSkeletalMesh)
|
|
{
|
|
PopulateNumUVChannels();
|
|
PopulateSkinWeightProfileNames();
|
|
|
|
if (OldSkeletalMesh)
|
|
{
|
|
OldSkeletalMesh->OnPostMeshCached().RemoveAll(this);
|
|
}
|
|
|
|
if (NewSkeletalMesh)
|
|
{
|
|
NewSkeletalMesh->OnPostMeshCached().AddSP(this, &SAnimationEditorViewportTabBody::UpdateSkinWeightSelection);
|
|
}
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::AnimChanged(UAnimationAsset* AnimAsset)
|
|
{
|
|
UpdateScrubPanel(AnimAsset);
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::ComboBoxSelectionChanged(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo)
|
|
{
|
|
int32 NewUVSelection = UVChannels.Find(NewSelection) - 1;
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
|
|
// "None" is index -1 here.
|
|
if ( NewUVSelection < 0 )
|
|
{
|
|
AnimViewportClient->SetDrawUVOverlay(false);
|
|
return;
|
|
}
|
|
|
|
AnimViewportClient->SetDrawUVOverlay(true);
|
|
AnimViewportClient->SetUVChannelToDraw(NewUVSelection);
|
|
|
|
RefreshViewport();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::PopulateNumUVChannels()
|
|
{
|
|
NumUVChannels.Empty();
|
|
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
if (FSkeletalMeshRenderData* MeshResource = PreviewComponent->GetSkeletalMeshRenderData())
|
|
{
|
|
int32 NumLods = MeshResource->LODRenderData.Num();
|
|
NumUVChannels.AddZeroed(NumLods);
|
|
for(int32 LOD = 0; LOD < NumLods; ++LOD)
|
|
{
|
|
NumUVChannels[LOD] = MeshResource->LODRenderData[LOD].StaticVertexBuffers.StaticMeshVertexBuffer.GetNumTexCoords();
|
|
}
|
|
}
|
|
}
|
|
|
|
PopulateUVChoices();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::PopulateUVChoices()
|
|
{
|
|
// Fill out the UV channels combo.
|
|
UVChannels.Empty();
|
|
|
|
UVChannels.Add(MakeShareable(new FString(NSLOCTEXT("AnimationEditorViewport", "NoUVChannel", "None").ToString())));
|
|
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
int32 CurrentLOD = FMath::Clamp(PreviewComponent->GetForcedLOD() - 1, 0, NumUVChannels.Num() - 1);
|
|
|
|
if (NumUVChannels.IsValidIndex(CurrentLOD))
|
|
{
|
|
for (int32 UVChannelID = 0; UVChannelID < NumUVChannels[CurrentLOD]; ++UVChannelID)
|
|
{
|
|
UVChannels.Add( MakeShareable( new FString( FText::Format( NSLOCTEXT("AnimationEditorViewport", "UVChannel_ID", "UV Channel {0}"), FText::AsNumber( UVChannelID ) ).ToString() ) ) );
|
|
}
|
|
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
int32 CurrentUVChannel = AnimViewportClient->GetUVChannelToDraw();
|
|
if (!UVChannels.IsValidIndex(CurrentUVChannel))
|
|
{
|
|
CurrentUVChannel = 0;
|
|
}
|
|
|
|
AnimViewportClient->SetUVChannelToDraw(CurrentUVChannel);
|
|
|
|
if (UVChannelCombo.IsValid() && UVChannels.IsValidIndex(CurrentUVChannel))
|
|
{
|
|
UVChannelCombo->SetSelectedItem(UVChannels[CurrentUVChannel]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::PopulateSkinWeightProfileNames()
|
|
{
|
|
SkinWeightProfileNames.Empty();
|
|
|
|
// Always make sure we have a default 'none' option
|
|
const FName DefaultProfileName = NAME_None;
|
|
SkinWeightProfileNames.Add(MakeShared<FName>(DefaultProfileName));
|
|
|
|
// Retrieve all possible skin weight profiles from the component
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
if (USkeletalMesh* Mesh = PreviewComponent->SkeletalMesh)
|
|
{
|
|
for (const FSkinWeightProfileInfo& Profile : Mesh->GetSkinWeightProfiles())
|
|
{
|
|
SkinWeightProfileNames.AddUnique(MakeShared<FName>(Profile.Name));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::UpdateSkinWeightSelection(USkeletalMesh* InSkeletalMesh)
|
|
{
|
|
// Check (post a mesh build) whether or not our currently selected profile name is still valid, and if not reset to 'none'
|
|
if (SkinWeightCombo->GetSelectedItem().IsValid())
|
|
{
|
|
const FName OldSelection = *SkinWeightCombo->GetSelectedItem();
|
|
PopulateSkinWeightProfileNames();
|
|
|
|
const int32 SelectionIndex = SkinWeightProfileNames.IndexOfByPredicate([OldSelection](TSharedPtr<FName> InName) { return *InName == OldSelection; });
|
|
|
|
// Select new entry or otherwise select none
|
|
SkinWeightCombo->SetSelectedItem(SelectionIndex != INDEX_NONE ? SkinWeightProfileNames[SelectionIndex] : SkinWeightProfileNames[0]);
|
|
}
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::UpdateScrubPanel(UAnimationAsset* AnimAsset)
|
|
{
|
|
// We might not have a scrub panel if we're in animation mode.
|
|
if (ScrubPanelContainer.IsValid())
|
|
{
|
|
ScrubPanelContainer->ClearChildren();
|
|
bool bUseDefaultScrubPanel = true;
|
|
if (UAnimMontage* Montage = Cast<UAnimMontage>(AnimAsset))
|
|
{
|
|
ScrubPanelContainer->AddSlot()
|
|
.AutoHeight()
|
|
[
|
|
SNew(SAnimMontageScrubPanel, GetPreviewScene())
|
|
.ViewInputMin(this, &SAnimationEditorViewportTabBody::GetViewMinInput)
|
|
.ViewInputMax(this, &SAnimationEditorViewportTabBody::GetViewMaxInput)
|
|
.bAllowZoom(true)
|
|
];
|
|
bUseDefaultScrubPanel = false;
|
|
}
|
|
if(bUseDefaultScrubPanel)
|
|
{
|
|
ScrubPanelContainer->AddSlot()
|
|
.AutoHeight()
|
|
[
|
|
SNew(SAnimationScrubPanel, GetPreviewScene())
|
|
.ViewInputMin(this, &SAnimationEditorViewportTabBody::GetViewMinInput)
|
|
.ViewInputMax(this, &SAnimationEditorViewportTabBody::GetViewMaxInput)
|
|
.bAllowZoom(true)
|
|
.bDisplayAnimScrubBarEditing(false)
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
float SAnimationEditorViewportTabBody::GetViewMinInput() const
|
|
{
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
UObject* PreviewAsset = GetPreviewScene()->GetPreviewAnimationAsset();
|
|
if (PreviewAsset != NULL)
|
|
{
|
|
return 0.0f;
|
|
}
|
|
else if (PreviewComponent->GetAnimInstance() != NULL)
|
|
{
|
|
return FMath::Max<float>((float)(PreviewComponent->GetAnimInstance()->LifeTimer - 30.0), 0.0f);
|
|
}
|
|
}
|
|
|
|
return 0.f;
|
|
}
|
|
|
|
float SAnimationEditorViewportTabBody::GetViewMaxInput() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if (PreviewComponent != NULL)
|
|
{
|
|
UObject* PreviewAsset = GetPreviewScene()->GetPreviewAnimationAsset();
|
|
if ((PreviewAsset != NULL) && (PreviewComponent->PreviewInstance != NULL))
|
|
{
|
|
return PreviewComponent->PreviewInstance->GetLength();
|
|
}
|
|
else if (PreviewComponent->GetAnimInstance() != NULL)
|
|
{
|
|
return PreviewComponent->GetAnimInstance()->LifeTimer;
|
|
}
|
|
}
|
|
|
|
return 0.f;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::UpdateShowFlagForMeshEdges()
|
|
{
|
|
bool bUseOverlayMaterial = false;
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
bUseOverlayMaterial = PreviewComponent->bDrawBoneInfluences || PreviewComponent->bDrawMorphTargetVerts;
|
|
}
|
|
|
|
//@TODO: SNOWPOCALYPSE: broke UnlitWithMeshEdges
|
|
bool bShowMeshEdgesViewMode = false;
|
|
#if 0
|
|
bShowMeshEdgesViewMode = (CurrentViewMode == EAnimationEditorViewportMode::UnlitWithMeshEdges);
|
|
#endif
|
|
|
|
LevelViewportClient->EngineShowFlags.SetMeshEdges(bUseOverlayMaterial || bShowMeshEdgesViewMode);
|
|
}
|
|
|
|
int32 SAnimationEditorViewportTabBody::GetLODSelection() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if (PreviewComponent)
|
|
{
|
|
// If we are forcing a LOD level, report the actual LOD level we are displaying
|
|
// as the mesh can potentially change LOD count under the viewport.
|
|
if(PreviewComponent->GetForcedLOD() > 0)
|
|
{
|
|
return PreviewComponent->GetPredictedLODLevel() + 1;
|
|
}
|
|
else
|
|
{
|
|
return PreviewComponent->GetForcedLOD();
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsLODModelSelected(int32 LODSelectionType) const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if (PreviewComponent && PreviewComponent->IsTrackingAttachedLOD())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return GetLODSelection() == LODSelectionType;
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsTrackingAttachedMeshLOD() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
if (PreviewComponent)
|
|
{
|
|
return PreviewComponent->IsTrackingAttachedLOD();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnSetLODModel(int32 LODSelectionType)
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if( PreviewComponent )
|
|
{
|
|
LODSelection = LODSelectionType;
|
|
PreviewComponent->SetDebugForcedLOD(LODSelectionType);
|
|
PreviewComponent->bTrackAttachedInstanceLOD = false;
|
|
}
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnSetLODTrackDebuggedInstance()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if (PreviewComponent)
|
|
{
|
|
PreviewComponent->bTrackAttachedInstanceLOD = true;
|
|
}
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnLODModelChanged()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if (PreviewComponent && LODSelection != PreviewComponent->GetForcedLOD())
|
|
{
|
|
LODSelection = PreviewComponent->GetForcedLOD();
|
|
PopulateUVChoices();
|
|
}
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnDebugForcedLODChanged()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if (PreviewComponent)
|
|
{
|
|
PopulateUVChoices();
|
|
GetPreviewScene()->BroadcastOnSelectedLODChanged();
|
|
}
|
|
}
|
|
|
|
TSharedRef<FAnimationViewportClient> SAnimationEditorViewportTabBody::GetAnimationViewportClient() const
|
|
{
|
|
return StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OpenPreviewSceneSettings()
|
|
{
|
|
OnInvokeTab.ExecuteIfBound(FPersonaTabs::AdvancedPreviewSceneSettingsID);
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::SetCameraFollowMode(EAnimationViewportCameraFollowMode InCameraFollowMode, FName InBoneName)
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
AnimViewportClient->SetCameraFollowMode(InCameraFollowMode, InBoneName);
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsCameraFollowEnabled(EAnimationViewportCameraFollowMode InCameraFollowMode) const
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
return (AnimViewportClient->GetCameraFollowMode() == InCameraFollowMode);
|
|
}
|
|
|
|
FName SAnimationEditorViewportTabBody::GetCameraFollowBoneName() const
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
return AnimViewportClient->GetCameraFollowBoneName();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::SaveCameraAsDefault()
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
AnimViewportClient->SaveCameraAsDefault();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::ClearDefaultCamera()
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
AnimViewportClient->ClearDefaultCamera();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::JumpToDefaultCamera()
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
AnimViewportClient->JumpToDefaultCamera();
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::CanSaveCameraAsDefault() const
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
return AnimViewportClient->CanSaveCameraAsDefault();
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::HasDefaultCameraSet() const
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
return (AnimViewportClient->HasDefaultCameraSet());
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::CanChangeCameraMode() const
|
|
{
|
|
//Not allowed to change camera type when we are in an ortho camera
|
|
return !LevelViewportClient->IsOrtho();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnToggleMuteAudio()
|
|
{
|
|
GetAnimationViewportClient()->OnToggleMuteAudio();
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsAudioMuted() const
|
|
{
|
|
return GetAnimationViewportClient()->IsAudioMuted();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnToggleUseAudioAttenuation()
|
|
{
|
|
GetAnimationViewportClient()->OnToggleUseAudioAttenuation();
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsAudioAttenuationEnabled() const
|
|
{
|
|
return GetAnimationViewportClient()->IsUsingAudioAttenuation();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::SetProcessRootMotionMode(EProcessRootMotionMode Mode)
|
|
{
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
PreviewComponent->SetProcessRootMotionMode(Mode);
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsProcessRootMotionModeSet(EProcessRootMotionMode Mode) const
|
|
{
|
|
const UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
return PreviewComponent ? (PreviewComponent->GetProcessRootMotionMode() == Mode) : false;
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::CanUseProcessRootMotionMode(EProcessRootMotionMode Mode) const
|
|
{
|
|
if(const UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
return PreviewComponent->CanUseProcessRootMotionMode(Mode);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsClothSimulationEnabled() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if( PreviewComponent )
|
|
{
|
|
return !PreviewComponent->bDisableClothSimulation;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnEnableClothSimulation()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if( PreviewComponent )
|
|
{
|
|
PreviewComponent->bDisableClothSimulation = !PreviewComponent->bDisableClothSimulation;
|
|
|
|
RefreshViewport();
|
|
}
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnResetClothSimulation()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if( PreviewComponent )
|
|
{
|
|
PreviewComponent->RecreateClothingActors();
|
|
|
|
RefreshViewport();
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsApplyingClothWind() const
|
|
{
|
|
return GetPreviewScene()->IsWindEnabled();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnPauseClothingSimWithAnim()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if(PreviewComponent)
|
|
{
|
|
PreviewComponent->bPauseClothingSimulationWithAnim = !PreviewComponent->bPauseClothingSimulationWithAnim;
|
|
|
|
bool bShouldPause = PreviewComponent->bPauseClothingSimulationWithAnim;
|
|
|
|
if(PreviewComponent->IsPreviewOn() && PreviewComponent->PreviewInstance)
|
|
{
|
|
UAnimSingleNodeInstance* PreviewInstance = PreviewComponent->PreviewInstance;
|
|
const bool bPlaying = PreviewInstance->IsPlaying();
|
|
|
|
if(!bPlaying && bShouldPause)
|
|
{
|
|
PreviewComponent->SuspendClothingSimulation();
|
|
}
|
|
else if(!bShouldPause && PreviewComponent->IsClothingSimulationSuspended())
|
|
{
|
|
PreviewComponent->ResumeClothingSimulation();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsPausingClothingSimWithAnim()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if(PreviewComponent)
|
|
{
|
|
return PreviewComponent->bPauseClothingSimulationWithAnim;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::SetWindStrength(float SliderPos)
|
|
{
|
|
TSharedRef<FAnimationEditorPreviewScene> PreviewScene = GetPreviewScene();
|
|
|
|
if ( SliderPos <= 0.0f )
|
|
{
|
|
if ( PreviewScene->IsWindEnabled() )
|
|
{
|
|
PreviewScene->EnableWind(false);
|
|
PreviewScene->SetWindStrength(0.0f);
|
|
RefreshViewport();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ( !PreviewScene->IsWindEnabled() )
|
|
{
|
|
PreviewScene->EnableWind(true);
|
|
}
|
|
|
|
GetPreviewScene()->SetWindStrength(SliderPos);
|
|
|
|
RefreshViewport();
|
|
}
|
|
|
|
TOptional<float> SAnimationEditorViewportTabBody::GetWindStrengthSliderValue() const
|
|
{
|
|
return GetPreviewScene()->GetWindStrength();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::SetGravityScale(float SliderPos)
|
|
{
|
|
GetPreviewScene()->SetGravityScale(SliderPos);
|
|
RefreshViewport();
|
|
}
|
|
|
|
float SAnimationEditorViewportTabBody::GetGravityScaleSliderValue() const
|
|
{
|
|
return GetPreviewScene()->GetGravityScale();
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnEnableCollisionWithAttachedClothChildren()
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if( PreviewComponent )
|
|
{
|
|
PreviewComponent->bCollideWithAttachedChildren = !PreviewComponent->bCollideWithAttachedChildren;
|
|
RefreshViewport();
|
|
}
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsEnablingCollisionWithAttachedClothChildren() const
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if( PreviewComponent )
|
|
{
|
|
return PreviewComponent->bCollideWithAttachedChildren;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::OnSetSectionsDisplayMode(ESectionDisplayMode DisplayMode)
|
|
{
|
|
UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent();
|
|
|
|
if (!PreviewComponent)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SectionsDisplayMode = DisplayMode;
|
|
|
|
switch (SectionsDisplayMode)
|
|
{
|
|
case ESectionDisplayMode::ShowAll:
|
|
// restore to the original states
|
|
PreviewComponent->RestoreClothSectionsVisibility();
|
|
break;
|
|
case ESectionDisplayMode::ShowOnlyClothSections:
|
|
// disable all except clothing sections and shows only cloth sections
|
|
PreviewComponent->ToggleClothSectionsVisibility(true);
|
|
break;
|
|
case ESectionDisplayMode::HideOnlyClothSections:
|
|
// disables only clothing sections
|
|
PreviewComponent->ToggleClothSectionsVisibility(false);
|
|
break;
|
|
}
|
|
|
|
RefreshViewport();
|
|
}
|
|
|
|
bool SAnimationEditorViewportTabBody::IsSectionsDisplayMode(ESectionDisplayMode DisplayMode) const
|
|
{
|
|
return SectionsDisplayMode == DisplayMode;
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::AddRecordingNotification()
|
|
{
|
|
if(WeakRecordingNotification.IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
auto GetRecordingStateText = [this]()
|
|
{
|
|
if(GetPreviewScene()->IsRecording())
|
|
{
|
|
UAnimSequence* Recording = GetPreviewScene()->GetCurrentRecording();
|
|
const FString& Name = Recording ? Recording->GetName() : TEXT("None");
|
|
float TimeRecorded = GetPreviewScene()->GetCurrentRecordingTime();
|
|
FNumberFormattingOptions NumberOption;
|
|
NumberOption.MaximumFractionalDigits = 2;
|
|
NumberOption.MinimumFractionalDigits = 2;
|
|
return FText::Format(LOCTEXT("AnimRecorder", "Recording '{0}' {1} secs"),
|
|
FText::FromString(Name), FText::AsNumber(TimeRecorded, &NumberOption));
|
|
}
|
|
|
|
return FText::GetEmpty();
|
|
};
|
|
|
|
auto GetRecordingStateStateVisibility = [this]()
|
|
{
|
|
if (GetPreviewScene()->IsRecording())
|
|
{
|
|
return EVisibility::Visible;
|
|
}
|
|
|
|
return EVisibility::Collapsed;
|
|
};
|
|
|
|
auto StopRecording = [this]()
|
|
{
|
|
if (GetPreviewScene()->IsRecording())
|
|
{
|
|
GetPreviewScene()->StopRecording();
|
|
}
|
|
|
|
return FReply::Handled();
|
|
};
|
|
|
|
WeakRecordingNotification = AddNotification(EMessageSeverity::Info,
|
|
true,
|
|
SNew(SHorizontalBox)
|
|
.Visibility_Lambda(GetRecordingStateStateVisibility)
|
|
.ToolTipText(LOCTEXT("RecordingStatusTooltip", "Shows the status of animation recording."))
|
|
+SHorizontalBox::Slot()
|
|
.FillWidth(1.0f)
|
|
.Padding(2.0f, 4.0f)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
.Padding(0.0f, 0.0f, 4.0f, 0.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.TextStyle(FAppStyle::Get(), "AnimViewport.MessageText")
|
|
.Font(FAppStyle::Get().GetFontStyle("FontAwesome.9"))
|
|
.Text(FEditorFontGlyphs::Video_Camera)
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.VAlign(VAlign_Center)
|
|
.FillWidth(1.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text_Lambda(GetRecordingStateText)
|
|
.TextStyle(FAppStyle::Get(), "AnimViewport.MessageText")
|
|
]
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding(2.0f, 0.0f)
|
|
[
|
|
SNew(SButton)
|
|
.ForegroundColor(FSlateColor::UseForeground())
|
|
.ButtonStyle(FAppStyle::Get(), "FlatButton.Success")
|
|
.ToolTipText(LOCTEXT("RecordingInViewportStop", "Stop recording animation."))
|
|
.OnClicked_Lambda(StopRecording)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
.Padding(0.0f, 0.0f, 4.0f, 0.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.TextStyle(FAppStyle::Get(), "AnimViewport.MessageText")
|
|
.Font(FAppStyle::Get().GetFontStyle("FontAwesome.9"))
|
|
.Text(FEditorFontGlyphs::Stop)
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.VAlign(VAlign_Center)
|
|
.AutoWidth()
|
|
[
|
|
SNew(STextBlock)
|
|
.TextStyle(FAppStyle::Get(), "AnimViewport.MessageText")
|
|
.Text(LOCTEXT("AnimViewportStopRecordingButtonLabel", "Stop"))
|
|
]
|
|
]
|
|
],
|
|
FPersonaViewportNotificationOptions(TAttribute<EVisibility>::Create(GetRecordingStateStateVisibility))
|
|
);
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::AddPostProcessNotification()
|
|
{
|
|
if(WeakPostProcessNotification.IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
auto GetVisibility = [this]()
|
|
{
|
|
return CanDisablePostProcess() ? EVisibility::Visible : EVisibility::Collapsed;
|
|
};
|
|
|
|
auto GetPostProcessGraphName = [this]()
|
|
{
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
if(PreviewComponent->SkeletalMesh && PreviewComponent->SkeletalMesh->GetPostProcessAnimBlueprint() && PreviewComponent->SkeletalMesh->GetPostProcessAnimBlueprint()->ClassGeneratedBy)
|
|
{
|
|
return FText::FromString(PreviewComponent->SkeletalMesh->GetPostProcessAnimBlueprint()->ClassGeneratedBy->GetName());
|
|
}
|
|
}
|
|
|
|
return FText::GetEmpty();
|
|
};
|
|
|
|
auto DoesPostProcessModifyCurves = [this]()
|
|
{
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
return (PreviewComponent->PostProcessAnimInstance && PreviewComponent->PostProcessAnimInstance->HasActiveCurves());
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
auto GetText = [this, GetPostProcessGraphName, DoesPostProcessModifyCurves]()
|
|
{
|
|
return IsDisablePostProcessChecked() ?
|
|
FText::Format(LOCTEXT("PostProcessDisabledText", "Post process Animation Blueprint '{0}' is disabled."), GetPostProcessGraphName()) :
|
|
FText::Format(LOCTEXT("PostProcessRunningText", "Post process Animation Blueprint '{0}' is running. {1}"), GetPostProcessGraphName(), DoesPostProcessModifyCurves() ? LOCTEXT("PostProcessModifiesCurves", "Post process modifes curves.") : FText::GetEmpty()) ;
|
|
};
|
|
|
|
auto GetButtonText = [this]()
|
|
{
|
|
return IsDisablePostProcessChecked() ? LOCTEXT("PostProcessEnableText", "Enable") : LOCTEXT("PostProcessDisableText", "Disable");
|
|
};
|
|
|
|
auto GetButtonTooltipText = [this]()
|
|
{
|
|
return IsDisablePostProcessChecked() ? LOCTEXT("PostProcessEnableTooltip", "Enable post process animation blueprint.") : LOCTEXT("PostProcessDisableTooltip", "Disable post process animation blueprint.");
|
|
};
|
|
|
|
auto GetButtonIcon = [this]()
|
|
{
|
|
return IsDisablePostProcessChecked() ? FEditorFontGlyphs::Check : FEditorFontGlyphs::Times;
|
|
};
|
|
|
|
auto EnablePostProcess = [this]()
|
|
{
|
|
OnToggleDisablePostProcess();
|
|
return FReply::Handled();
|
|
};
|
|
|
|
auto EditPostProcess = [this]()
|
|
{
|
|
if (UDebugSkelMeshComponent* PreviewComponent = GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
if(PreviewComponent->SkeletalMesh && PreviewComponent->SkeletalMesh->GetPostProcessAnimBlueprint())
|
|
{
|
|
GEditor->GetEditorSubsystem<UAssetEditorSubsystem>()->OpenEditorForAssets(TArray<UObject*>({ PreviewComponent->SkeletalMesh->GetPostProcessAnimBlueprint()->ClassGeneratedBy }));
|
|
}
|
|
}
|
|
|
|
return FReply::Handled();
|
|
};
|
|
|
|
WeakPostProcessNotification = AddNotification(EMessageSeverity::Warning,
|
|
true,
|
|
SNew(SHorizontalBox)
|
|
.Visibility_Lambda(GetVisibility)
|
|
+SHorizontalBox::Slot()
|
|
.FillWidth(1.0f)
|
|
.Padding(4.0f, 4.0f)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
.ToolTipText_Lambda(GetText)
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
.Padding(0.0f, 0.0f, 4.0f, 0.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.TextStyle(FAppStyle::Get(), "AnimViewport.MessageText")
|
|
.Font(FAppStyle::Get().GetFontStyle("FontAwesome.9"))
|
|
.Text(FEditorFontGlyphs::Exclamation_Triangle)
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.VAlign(VAlign_Center)
|
|
.FillWidth(1.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text_Lambda(GetText)
|
|
.TextStyle(FAppStyle::Get(), "AnimViewport.MessageText")
|
|
]
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding(2.0f, 0.0f)
|
|
[
|
|
SNew(SButton)
|
|
.ForegroundColor(FSlateColor::UseForeground())
|
|
.ButtonStyle(FAppStyle::Get(), "FlatButton.Success")
|
|
.ToolTipText_Lambda(GetButtonTooltipText)
|
|
.OnClicked_Lambda(EnablePostProcess)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
.Padding(0.0f, 0.0f, 4.0f, 0.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.TextStyle(FAppStyle::Get(), "AnimViewport.MessageText")
|
|
.Font(FAppStyle::Get().GetFontStyle("FontAwesome.9"))
|
|
.Text_Lambda(GetButtonIcon)
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.VAlign(VAlign_Center)
|
|
.AutoWidth()
|
|
[
|
|
SNew(STextBlock)
|
|
.TextStyle(FAppStyle::Get(), "AnimViewport.MessageText")
|
|
.Text_Lambda(GetButtonText)
|
|
]
|
|
]
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding(2.0f, 0.0f)
|
|
[
|
|
SNew(SButton)
|
|
.ForegroundColor(FSlateColor::UseForeground())
|
|
.ButtonStyle(FAppStyle::Get(), "FlatButton")
|
|
.ToolTipText(LOCTEXT("EditPostProcessAnimBPButtonToolTip", "Edit the post process Animation Blueprint."))
|
|
.OnClicked_Lambda(EditPostProcess)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
.Padding(0.0f, 0.0f, 4.0f, 0.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.TextStyle(FAppStyle::Get(), "AnimViewport.MessageText")
|
|
.Font(FAppStyle::Get().GetFontStyle("FontAwesome.9"))
|
|
.Text(FEditorFontGlyphs::Pencil)
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.VAlign(VAlign_Center)
|
|
.AutoWidth()
|
|
[
|
|
SNew(STextBlock)
|
|
.TextStyle(FAppStyle::Get(), "AnimViewport.MessageText")
|
|
.Text(LOCTEXT("EditPostProcessAnimBPButtonText", "Edit"))
|
|
]
|
|
]
|
|
],
|
|
FPersonaViewportNotificationOptions(TAttribute<EVisibility>::Create(GetVisibility))
|
|
);
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::AddMinLODNotification()
|
|
{
|
|
if(WeakMinLODNotification.IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
auto GetMinLODNotificationVisibility = [this]()
|
|
{
|
|
if (GetPreviewScene()->GetPreviewMesh() && GetPreviewScene()->GetPreviewMesh()->GetDefaultMinLod() != 0)
|
|
{
|
|
return EVisibility::Visible;
|
|
}
|
|
|
|
return EVisibility::Collapsed;
|
|
};
|
|
|
|
WeakMinLODNotification = AddNotification(EMessageSeverity::Info,
|
|
true,
|
|
SNew(SHorizontalBox)
|
|
.Visibility_Lambda(GetMinLODNotificationVisibility)
|
|
.ToolTipText(LOCTEXT("MinLODNotificationTooltip", "This asset has a minimum LOD applied."))
|
|
+SHorizontalBox::Slot()
|
|
.FillWidth(1.0f)
|
|
.Padding(2.0f, 4.0f)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
.Padding(0.0f, 0.0f, 4.0f, 0.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.TextStyle(FAppStyle::Get(), "AnimViewport.MessageText")
|
|
.Font(FAppStyle::Get().GetFontStyle("FontAwesome.9"))
|
|
.Text(FEditorFontGlyphs::Level_Down)
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.VAlign(VAlign_Center)
|
|
.FillWidth(1.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("MinLODNotification", "Min LOD applied"))
|
|
.TextStyle(FAppStyle::Get(), "AnimViewport.MessageText")
|
|
]
|
|
],
|
|
FPersonaViewportNotificationOptions(TAttribute<EVisibility>::Create(GetMinLODNotificationVisibility))
|
|
);
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::AddSkinWeightProfileNotification()
|
|
{
|
|
if(WeakSkinWeightPreviewNotification.IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
auto GetSkinWeightProfileNotificationVisibility = [this]()
|
|
{
|
|
if (GetPreviewScene()->GetPreviewMeshComponent() && GetPreviewScene()->GetPreviewMeshComponent()->IsUsingSkinWeightProfile())
|
|
{
|
|
return EVisibility::Visible;
|
|
}
|
|
|
|
return EVisibility::Collapsed;
|
|
};
|
|
|
|
auto GetSkinWeightProfileNotificationText = [this]() -> FText
|
|
{
|
|
FName ProfileName = NAME_None;
|
|
if (GetPreviewScene()->GetPreviewMeshComponent())
|
|
{
|
|
ProfileName = GetPreviewScene()->GetPreviewMeshComponent()->GetCurrentSkinWeightProfileName();
|
|
}
|
|
|
|
return FText::FormatOrdered(LOCTEXT("ProfileSkinWeightPreviewNotification", "Previewing Skin Weight Profile: {0}"), FText::FromName(ProfileName));
|
|
};
|
|
|
|
WeakSkinWeightPreviewNotification = AddNotification(EMessageSeverity::Info,
|
|
false,
|
|
SNew(SHorizontalBox)
|
|
.Visibility_Lambda(GetSkinWeightProfileNotificationVisibility)
|
|
.ToolTipText(LOCTEXT("ProfileSkinWeightPreviewTooltip", "Previewing a Skin Weight Profile."))
|
|
+SHorizontalBox::Slot()
|
|
.FillWidth(1.0f)
|
|
.Padding(2.0f, 4.0f)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
.Padding(0.0f, 0.0f, 4.0f, 0.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.TextStyle(FAppStyle::Get(), "AnimViewport.MessageText")
|
|
.Font(FAppStyle::Get().GetFontStyle("FontAwesome.9"))
|
|
.Text(FEditorFontGlyphs::Eye)
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.VAlign(VAlign_Center)
|
|
.FillWidth(1.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text_Lambda(GetSkinWeightProfileNotificationText)
|
|
.TextStyle(FAppStyle::Get(), "AnimViewport.MessageText")
|
|
]
|
|
],
|
|
FPersonaViewportNotificationOptions(TAttribute<EVisibility>::Create(GetSkinWeightProfileNotificationVisibility))
|
|
);
|
|
}
|
|
|
|
void SAnimationEditorViewportTabBody::HandleFocusCamera()
|
|
{
|
|
TSharedRef<FAnimationViewportClient> AnimViewportClient = StaticCastSharedRef<FAnimationViewportClient>(LevelViewportClient.ToSharedRef());
|
|
AnimViewportClient->SetCameraFollowMode(EAnimationViewportCameraFollowMode::None);
|
|
AnimViewportClient->FocusViewportOnPreviewMesh(false);
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|