// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. #include "PersonaPrivatePCH.h" #include "SAnimationEditorViewport.h" #include "SAnimationScrubPanel.h" #include "SAnimMontageScrubPanel.h" #include "Runtime/Engine/Public/Slate/SceneViewport.h" #include "SAnimViewportToolBar.h" #include "AnimViewportMenuCommands.h" #include "AnimViewportShowCommands.h" #include "AnimViewportLODCommands.h" #include "AnimViewportPlaybackCommands.h" #include "AnimGraphDefinitions.h" #include "AnimPreviewInstance.h" #include "AnimationEditorViewportClient.h" #include "ScopedTransaction.h" #include "Editor/UnrealEd/Public/LODUtilities.h" #include "DetailLayoutBuilder.h" #include "STextComboBox.h" #define LOCTEXT_NAMESPACE "PersonaViewportToolbar" namespace EAnimationPlaybackSpeeds { // Speed scales for animation playback, must match EAnimationPlaybackSpeeds::Type float Values[EAnimationPlaybackSpeeds::NumPlaybackSpeeds] = {0.1f, 0.25f, 0.5f, 1.0f, 2.0f, 5.0f, 10.0f}; }; ////////////////////////////////////////////////////////////////////////// // SAnimationEditorViewport SAnimationEditorViewport::~SAnimationEditorViewport() { if(PersonaPtr.IsValid()) { PersonaPtr.Pin()->UnregisterOnPostUndo(this); } } void SAnimationEditorViewport::Construct(const FArguments& InArgs, TSharedPtr InPersona, TSharedPtr InTabBody) { PersonaPtr = InPersona; TabBodyPtr = InTabBody; PersonaPtr.Pin()->RegisterOnPostUndo(FPersona::FOnPostUndo::CreateSP(this, &SAnimationEditorViewport::OnUndoRedo)); SEditorViewport::Construct( SEditorViewport::FArguments() .IsEnabled(FSlateApplication::Get().GetNormalExecutionAttribute()) .AddMetaData(TEXT("Persona.Viewport")) ); Client->VisibilityDelegate.BindSP(this, &SAnimationEditorViewport::IsVisible); } TSharedRef SAnimationEditorViewport::MakeEditorViewportClient() { // Create an animation viewport client LevelViewportClient = MakeShareable(new FAnimationViewportClient(PersonaPtr.Pin()->GetPreviewScene(), PersonaPtr, SharedThis(this))); LevelViewportClient->ViewportType = LVT_Perspective; LevelViewportClient->bSetListenerPosition = false; LevelViewportClient->SetViewLocation(EditorViewportDefs::DefaultPerspectiveViewLocation); LevelViewportClient->SetViewRotation(EditorViewportDefs::DefaultPerspectiveViewRotation); return LevelViewportClient.ToSharedRef(); } TSharedPtr SAnimationEditorViewport::MakeViewportToolbar() { return SNew(SAnimViewportToolBar, TabBodyPtr.Pin(), SharedThis(this)) .Cursor(EMouseCursor::Default); } void SAnimationEditorViewport::OnUndoRedo() { LevelViewportClient->Invalidate(); LevelViewportClient->PostUndo(); } ////////////////////////////////////////////////////////////////////////// // /** //@TODO MODES: Simple text entry popup used it to get 3 vector position*/ class STranslationInputWindow : public SCompoundWidget { public: SLATE_BEGIN_ARGS( STranslationInputWindow ) : _X_Value(0.0f) , _Y_Value(0.0f) , _Z_Value(0.0f) {} SLATE_ARGUMENT( float, X_Value ) SLATE_ARGUMENT( float, Y_Value ) SLATE_ARGUMENT( float, Z_Value ) SLATE_EVENT( FOnTextCommitted, OnXModified ) SLATE_EVENT( FOnTextCommitted, OnYModified ) SLATE_EVENT( FOnTextCommitted, OnZModified ) SLATE_END_ARGS() void Construct( const FArguments& InArgs ) { FString XString = FString::Printf(TEXT("%0.2f"), InArgs._X_Value); FString YString = FString::Printf(TEXT("%0.2f"), InArgs._Y_Value); FString ZString = FString::Printf(TEXT("%0.2f"), InArgs._Z_Value); this->ChildSlot [ SNew(SBorder) . BorderImage(FEditorStyle::GetBrush(TEXT("Menu.Background"))) . Padding(10) [ SNew(SVerticalBox) +SVerticalBox::Slot() .AutoHeight() [ SNew(SHorizontalBox) +SHorizontalBox::Slot() .AutoWidth() [ SNew(STextBlock) .Text(NSLOCTEXT("AnimationEditorViewport", "XValueLabel", "X:")) ] +SHorizontalBox::Slot() .AutoWidth() [ SNew(SEditableTextBox) .MinDesiredWidth(10.0f) .Text( FText::FromString(XString) ) .OnTextCommitted( InArgs._OnXModified ) ] ] +SVerticalBox::Slot() .AutoHeight() [ SNew(SHorizontalBox) +SHorizontalBox::Slot() .AutoWidth() [ SNew(STextBlock) .Text(NSLOCTEXT("AnimationEditorViewport", "YValueLabel", "Y:")) ] +SHorizontalBox::Slot() .AutoWidth() [ SNew(SEditableTextBox) .MinDesiredWidth(10.0f) .Text( FText::FromString(YString) ) .OnTextCommitted( InArgs._OnYModified ) ] ] +SVerticalBox::Slot() .AutoHeight() [ SNew(SHorizontalBox) +SHorizontalBox::Slot() .AutoWidth() [ SNew(STextBlock) .Text(NSLOCTEXT("AnimationEditorViewport", "ZValueLabel", "Z: ")) ] +SHorizontalBox::Slot() .AutoWidth() [ SNew(SEditableTextBox) .MinDesiredWidth(10.0f) .Text( FText::FromString(ZString) ) .OnTextCommitted( InArgs._OnZModified ) ] ] ] ]; } }; ////////////////////////////////////////////////////////////////////////// // SAnimationEditorViewportTabBody SAnimationEditorViewportTabBody::SAnimationEditorViewportTabBody() : SelectedTurnTableSpeed(EAnimationPlaybackSpeeds::Normal) , SelectedTurnTableMode(EPersonaTurnTableMode::Stopped) , AnimationPlaybackSpeedMode(EAnimationPlaybackSpeeds::Normal) { } SAnimationEditorViewportTabBody::~SAnimationEditorViewportTabBody() { CleanupPersonaReferences(); // Close viewport if (LevelViewportClient.IsValid()) { LevelViewportClient->Viewport = NULL; } // Release our reference to the viewport client LevelViewportClient.Reset(); } void SAnimationEditorViewportTabBody::CleanupPersonaReferences() { if (PersonaPtr.IsValid()) { PersonaPtr.Pin()->UnregisterOnAnimChanged(this); PersonaPtr.Reset(); } } bool SAnimationEditorViewportTabBody::CanUseGizmos() const { class UDebugSkelMeshComponent* Component = PersonaPtr.Pin()->PreviewComponent; if (Component != NULL) { if (Component->bForceRefpose) { return false; } else if (Component->IsPreviewOn()) { return true; } } return false; } FText SAnimationEditorViewportTabBody::GetDisplayString() const { class UDebugSkelMeshComponent* Component = PersonaPtr.Pin()->PreviewComponent; FString TargetSkeletonName = TargetSkeleton ? TargetSkeleton->GetName() : FName(NAME_None).ToString(); if (Component != NULL) { if (Component->bForceRefpose) { return LOCTEXT("ReferencePose", "Reference pose"); } else if (Component->IsPreviewOn()) { return FText::Format(LOCTEXT("Previewing", "Previewing {0}"), FText::FromString(Component->GetPreviewText())); } else if (Component->AnimBlueprintGeneratedClass != NULL) { const bool bWarnAboutBoneManip = !PersonaPtr.Pin()->IsModeCurrent(FPersonaModes::AnimBlueprintEditMode); if (bWarnAboutBoneManip) { return FText::Format(LOCTEXT("PreviewingAnimBP_WarnDisabled", "Previewing {0}. \nBone manipulation is disabled in this mode. "), FText::FromString(Component->AnimBlueprintGeneratedClass->GetName())); } else { return FText::Format(LOCTEXT("PreviewingAnimBP", "Previewing {0}"), FText::FromString(Component->AnimBlueprintGeneratedClass->GetName())); } } else if (Component->SkeletalMesh == NULL) { return FText::Format(LOCTEXT("NoMeshFound", "No skeletal mesh found for skeleton '{0}'"), FText::FromString(TargetSkeletonName)); } else { return LOCTEXT("NothingToPlay", "Nothing to play"); } } else { return FText::Format(LOCTEXT("NoMeshFound", "No skeletal mesh found for skeleton '{0}'"), FText::FromString(TargetSkeletonName)); } } void SAnimationEditorViewportTabBody::RefreshViewport() { LevelViewportClient->Invalidate(); } bool SAnimationEditorViewportTabBody::IsVisible() const { return ViewportWidget.IsValid(); } void SAnimationEditorViewportTabBody::Construct(const FArguments& InArgs) { UICommandList = MakeShareable(new FUICommandList); PersonaPtr = InArgs._Persona; IsEditable = InArgs._IsEditable; TargetSkeleton = InArgs._Skeleton; bPreviewLockModeOn = 0; LODSelection = LOD_Auto; TSharedPtr SharedPersona = PersonaPtr.Pin(); check(SharedPersona.IsValid()); // register delegate for anim change notification SharedPersona->RegisterOnAnimChanged(FPersona::FOnAnimChanged::CreateSP(this, &SAnimationEditorViewportTabBody::AnimChanged)); const FSlateFontInfo SmallLayoutFont( FPaths::EngineContentDir() / TEXT("Slate/Fonts/Roboto-Regular.ttf"), 10 ); FAnimViewportMenuCommands::Register(); FAnimViewportShowCommands::Register(); FAnimViewportLODCommands::Register(); FAnimViewportPlaybackCommands::Register(); // Build toolbar widgets UVChannelCombo = SNew(STextComboBox) .OptionsSource(&UVChannels) .OnSelectionChanged(this, &SAnimationEditorViewportTabBody::ComboBoxSelectionChanged); ViewportWidget = SNew(SAnimationEditorViewport, InArgs._Persona, SharedThis(this)); TSharedPtr 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) [ SNew(SButton) .ButtonStyle(FEditorStyle::Get(), "NoBorder") .Visibility(this, &SAnimationEditorViewportTabBody::GetViewportCornerTextVisibility) .OnClicked(this, &SAnimationEditorViewportTabBody::ClickedOnViewportCornerText) .Content() [ SNew(SHorizontalBox) +SHorizontalBox::Slot() .AutoWidth() [ SNew(SImage) .Visibility(this, &SAnimationEditorViewportTabBody::GetViewportCornerImageVisibility) .Image(this, &SAnimationEditorViewportTabBody::GetViewportCornerImage) ] +SHorizontalBox::Slot() .FillWidth(1) [ SNew(STextBlock) .TextStyle(FEditorStyle::Get(), "Persona.Viewport.BlueprintDirtyText") .Text(this, &SAnimationEditorViewportTabBody::GetViewportCornerText) .ToolTipText(this, &SAnimationEditorViewportTabBody::GetViewportCornerTooltip) ] ] ] ] ]; if(!SharedPersona->IsModeCurrent(FPersonaModes::AnimationEditMode) && ViewportContainer.IsValid()) { ViewportContainer->AddSlot() .AutoHeight() [ SAssignNew(ScrubPanelContainer, SVerticalBox) +SVerticalBox::Slot() .AutoHeight() [ SNew(SAnimationScrubPanel) .Persona(PersonaPtr) .ViewInputMin(this, &SAnimationEditorViewportTabBody::GetViewMinInput) .ViewInputMax(this, &SAnimationEditorViewportTabBody::GetViewMaxInput) .bAllowZoom(true) ] ]; UpdateScrubPanel(Cast(SharedPersona->GetPreviewAnimationAsset())); } LevelViewportClient = ViewportWidget->GetViewportClient(); TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); // Load the view mode from config AnimViewportClient->SetViewMode(AnimViewportClient->ConfigOption->ViewModeIndex); UpdateShowFlagForMeshEdges(); UpdateViewportClientPlaybackScale(); OnSetTurnTableMode(SelectedTurnTableMode); OnSetTurnTableSpeed(SelectedTurnTableSpeed); BindCommands(); } void SAnimationEditorViewportTabBody::BindCommands() { FUICommandList& CommandList = *UICommandList; //Bind menu commands const FAnimViewportMenuCommands& MenuActions = FAnimViewportMenuCommands::Get(); CommandList.MapAction( MenuActions.Lock, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::SetPreviewMode, 1), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsPreviewModeOn, 1)); CommandList.MapAction( MenuActions.Auto, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::SetPreviewMode, 0), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsPreviewModeOn, 0)); CommandList.MapAction( MenuActions.CameraFollow, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::ToggleCameraFollow), FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::CanChangeCameraMode), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsCameraFollowEnabled)); CommandList.MapAction( MenuActions.UseInGameBound, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::UseInGameBound), FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::CanUseInGameBound), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsUsingInGameBound)); TSharedRef EditorViewportClientRef = GetAnimationViewportClient(); 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 ) ); CommandList.MapAction( MenuActions.AnimSetDrawUVs, FExecuteAction::CreateSP( EditorViewportClientRef, &FAnimationViewportClient::ToggleDrawUVOverlay ), FCanExecuteAction(), FIsActionChecked::CreateSP( EditorViewportClientRef, &FAnimationViewportClient::IsSetDrawUVOverlayChecked ) ); //Bind Show commands const FAnimViewportShowCommands& ViewportShowMenuCommands = FAnimViewportShowCommands::Get(); CommandList.MapAction( ViewportShowMenuCommands.ShowReferencePose, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::ShowReferencePose), FCanExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::CanShowReferencePose), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowReferencePoseEnabled)); 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.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.ShowBones, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowBones), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingBones)); 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.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.HideDisplayInfo, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowDisplayInfo, (int32)EDisplayInfoMode::None), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingMeshInfo, (int32)EDisplayInfoMode::None)); //Bone weight CommandList.MapAction( ViewportShowMenuCommands.ShowBoneWeight, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowBoneWeight), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingBoneWeight)); // Show sockets CommandList.MapAction( ViewportShowMenuCommands.ShowSockets, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowSockets), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingSockets)); // Set bone local axes mode 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)); #if WITH_APEX_CLOTHING //Clothing show options CommandList.MapAction( ViewportShowMenuCommands.DisableClothSimulation, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnDisableClothSimulation), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsDisablingClothSimulation)); //Apply wind CommandList.MapAction( ViewportShowMenuCommands.ApplyClothWind, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnApplyClothWind), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsApplyingClothWind)); //Cloth simulation normal CommandList.MapAction( ViewportShowMenuCommands.ShowClothSimulationNormals, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowClothSimulationNormals), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingClothSimulationNormals)); CommandList.MapAction( ViewportShowMenuCommands.ShowClothGraphicalTangents, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowClothGraphicalTangents), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingClothGraphicalTangents)); CommandList.MapAction( ViewportShowMenuCommands.ShowClothCollisionVolumes, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowClothCollisionVolumes), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingClothCollisionVolumes)); CommandList.MapAction( ViewportShowMenuCommands.EnableCollisionWithAttachedClothChildren, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnEnableCollisionWithAttachedClothChildren), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsEnablingCollisionWithAttachedClothChildren)); CommandList.MapAction( ViewportShowMenuCommands.ShowClothPhysicalMeshWire, FExecuteAction::CreateSP( this, &SAnimationEditorViewportTabBody::OnShowClothPhysicalMeshWire ), FCanExecuteAction(), FIsActionChecked::CreateSP( this, &SAnimationEditorViewportTabBody::IsShowingClothPhysicalMeshWire ) ); CommandList.MapAction( ViewportShowMenuCommands.ShowClothMaxDistances, FExecuteAction::CreateSP( this, &SAnimationEditorViewportTabBody::OnShowClothMaxDistances ), FCanExecuteAction(), FIsActionChecked::CreateSP( this, &SAnimationEditorViewportTabBody::IsShowingClothMaxDistances ) ); CommandList.MapAction( ViewportShowMenuCommands.ShowClothBackstop, FExecuteAction::CreateSP( this, &SAnimationEditorViewportTabBody::OnShowClothBackstops ), FCanExecuteAction(), FIsActionChecked::CreateSP( this, &SAnimationEditorViewportTabBody::IsShowingClothBackstops ) ); CommandList.MapAction( ViewportShowMenuCommands.ShowClothFixedVertices, FExecuteAction::CreateSP( this, &SAnimationEditorViewportTabBody::OnShowClothFixedVertices ), FCanExecuteAction(), FIsActionChecked::CreateSP( this, &SAnimationEditorViewportTabBody::IsShowingClothFixedVertices ) ); CommandList.MapAction( ViewportShowMenuCommands.ShowAllSections, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetSectionsDisplayMode, (int32)UDebugSkelMeshComponent::ESectionDisplayMode::ShowAll), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsSectionsDisplayMode, (int32)UDebugSkelMeshComponent::ESectionDisplayMode::ShowAll)); CommandList.MapAction( ViewportShowMenuCommands.ShowOnlyClothSections, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetSectionsDisplayMode, (int32)UDebugSkelMeshComponent::ESectionDisplayMode::ShowOnlyClothSections), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsSectionsDisplayMode, (int32)UDebugSkelMeshComponent::ESectionDisplayMode::ShowOnlyClothSections)); CommandList.MapAction( ViewportShowMenuCommands.HideOnlyClothSections, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetSectionsDisplayMode, (int32)UDebugSkelMeshComponent::ESectionDisplayMode::HideOnlyClothSections), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsSectionsDisplayMode, (int32)UDebugSkelMeshComponent::ESectionDisplayMode::HideOnlyClothSections)); #endif// #if WITH_APEX_CLOTHING //Bind LOD preview menu commands const FAnimViewportLODCommands& ViewportLODMenuCommands = FAnimViewportLODCommands::Get(); //LOD Auto CommandList.MapAction( ViewportLODMenuCommands.LODAuto, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetLODModel, LOD_Auto), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsLODModelSelected, LOD_Auto)); //LOD 0 CommandList.MapAction( ViewportLODMenuCommands.LOD0, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetLODModel, LOD_0), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsLODModelSelected, LOD_0)); //LOD 1 CommandList.MapAction( ViewportLODMenuCommands.LOD1, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetLODModel, LOD_1), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsLODModelSelected, LOD_1)); //LOD 2 CommandList.MapAction( ViewportLODMenuCommands.LOD2, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetLODModel, LOD_2), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsLODModelSelected, LOD_2)); //LOD 3 CommandList.MapAction( ViewportLODMenuCommands.LOD3, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnSetLODModel, LOD_3), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsLODModelSelected, LOD_3)); CommandList.MapAction( ViewportShowMenuCommands.ToggleGrid, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowGrid), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingGrid)); CommandList.MapAction( ViewportShowMenuCommands.ToggleFloor, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowFloor), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingFloor)); CommandList.MapAction( ViewportShowMenuCommands.AutoAlignFloorToMesh, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnToggleAutoAlignFloor), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsAutoAlignFloor)); CommandList.MapAction( ViewportShowMenuCommands.ToggleSky, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnShowSky), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsShowingSky)); //Bind LOD preview menu commands const FAnimViewportPlaybackCommands& ViewportPlaybackCommands = FAnimViewportPlaybackCommands::Get(); //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.MapAction( ViewportShowMenuCommands.MuteAudio, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnMuteAudio), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsAudioMuted)); CommandList.MapAction( ViewportShowMenuCommands.ProcessRootMotion, FExecuteAction::CreateSP(this, &SAnimationEditorViewportTabBody::OnTogglePreviewRootMotion), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &SAnimationEditorViewportTabBody::IsPreviewingRootMotion)); // 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.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))); } void SAnimationEditorViewportTabBody::OnSetTurnTableSpeed(int32 SpeedIndex) { SelectedTurnTableSpeed = (EAnimationPlaybackSpeeds::Type)SpeedIndex; UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; 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 = PersonaPtr.Pin()->PreviewComponent; if (PreviewComponent) { PreviewComponent->TurnTableMode = SelectedTurnTableMode; if (SelectedTurnTableMode == EPersonaTurnTableMode::Stopped) { PreviewComponent->SetRelativeRotation(FRotator::ZeroRotator); } } } bool SAnimationEditorViewportTabBody::IsTurnTableModeSelected(int32 ModeIndex) const { return (SelectedTurnTableMode == ModeIndex); } bool SAnimationEditorViewportTabBody::IsPreviewModeOn(int32 PreviewMode) const { if (bPreviewLockModeOn && PreviewMode) { return true; } else if (!bPreviewLockModeOn && !PreviewMode) { return true; } return false; } void SAnimationEditorViewportTabBody::SetPreviewMode(int32 PreviewMode) { if (PreviewMode) { bPreviewLockModeOn = true; } else { bPreviewLockModeOn = false; } } int32 SAnimationEditorViewportTabBody::GetLODModelCount() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent && PreviewComponent->SkeletalMesh ) { return PreviewComponent->SkeletalMesh->GetImportedResource()->LODModels.Num(); } return 0; } void SAnimationEditorViewportTabBody::OnShowBones() { if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { PreviewComponent->bDisplayBones = !PreviewComponent->bDisplayBones; PreviewComponent->MarkRenderStateDirty(); RefreshViewport(); } } void SAnimationEditorViewportTabBody::OnShowMorphTargets() { if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { PreviewComponent->bDisableMorphTarget = !PreviewComponent->bDisableMorphTarget; PreviewComponent->MarkRenderStateDirty(); RefreshViewport(); } } void SAnimationEditorViewportTabBody::OnShowBoneNames() { if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { PreviewComponent->bShowBoneNames = !PreviewComponent->bShowBoneNames; PreviewComponent->MarkRenderStateDirty(); RefreshViewport(); } } void SAnimationEditorViewportTabBody::OnShowRawAnimation() { if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { PreviewComponent->bDisplayRawAnimation = !PreviewComponent->bDisplayRawAnimation; PreviewComponent->MarkRenderStateDirty(); } } void SAnimationEditorViewportTabBody::OnShowNonRetargetedAnimation() { if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { PreviewComponent->bDisplayNonRetargetedPose = !PreviewComponent->bDisplayNonRetargetedPose; PreviewComponent->MarkRenderStateDirty(); } } void SAnimationEditorViewportTabBody::OnShowSourceRawAnimation() { if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { PreviewComponent->bDisplaySourceAnimation = !PreviewComponent->bDisplaySourceAnimation; PreviewComponent->MarkRenderStateDirty(); } } void SAnimationEditorViewportTabBody::OnShowBakedAnimation() { if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { PreviewComponent->bDisplayBakedAnimation = !PreviewComponent->bDisplayBakedAnimation; PreviewComponent->MarkRenderStateDirty(); } } void SAnimationEditorViewportTabBody::OnShowAdditiveBase() { if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { PreviewComponent->bDisplayAdditiveBasePose = !PreviewComponent->bDisplayAdditiveBasePose; PreviewComponent->MarkRenderStateDirty(); } } bool SAnimationEditorViewportTabBody::IsPreviewingAnimation() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return (PreviewComponent && PreviewComponent->PreviewInstance && (PreviewComponent->PreviewInstance == PreviewComponent->AnimScriptInstance)); } bool SAnimationEditorViewportTabBody::IsShowingBones() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return PreviewComponent != NULL && PreviewComponent->bDisplayBones; } bool SAnimationEditorViewportTabBody::IsShowingMorphTargets() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return PreviewComponent != NULL && PreviewComponent->bDisableMorphTarget == false; } bool SAnimationEditorViewportTabBody::IsShowingBoneNames() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return PreviewComponent != NULL && PreviewComponent->bShowBoneNames; } bool SAnimationEditorViewportTabBody::IsShowingRawAnimation() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return PreviewComponent != NULL && PreviewComponent->bDisplayRawAnimation; } bool SAnimationEditorViewportTabBody::IsShowingNonRetargetedPose() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return PreviewComponent != NULL && PreviewComponent->bDisplayNonRetargetedPose; } bool SAnimationEditorViewportTabBody::IsShowingAdditiveBase() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return PreviewComponent != NULL && PreviewComponent->bDisplayAdditiveBasePose; } bool SAnimationEditorViewportTabBody::IsShowingSourceRawAnimation() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return PreviewComponent != NULL && PreviewComponent->bDisplaySourceAnimation; } bool SAnimationEditorViewportTabBody::IsShowingBakedAnimation() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; 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::OnShowBoneWeight() { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { PreviewComponent->SetShowBoneWeight( !PreviewComponent->bDrawBoneInfluences ); UpdateShowFlagForMeshEdges(); PreviewComponent->MarkRenderStateDirty(); RefreshViewport(); } } bool SAnimationEditorViewportTabBody::IsShowingBoneWeight() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return PreviewComponent != NULL && PreviewComponent->bDrawBoneInfluences; } void SAnimationEditorViewportTabBody::OnSetLocalAxesMode(int32 LocalAxesMode) { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); AnimViewportClient->SetLocalAxesMode((ELocalAxesMode::Type)LocalAxesMode); } bool SAnimationEditorViewportTabBody::IsLocalAxesModeSet(int32 LocalAxesMode) const { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); return AnimViewportClient->IsLocalAxesModeSet((ELocalAxesMode::Type)LocalAxesMode); } void SAnimationEditorViewportTabBody::OnShowSockets() { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { PreviewComponent->bDrawSockets = !PreviewComponent->bDrawSockets; PreviewComponent->MarkRenderStateDirty(); RefreshViewport(); } } bool SAnimationEditorViewportTabBody::IsShowingSockets() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return PreviewComponent != NULL && PreviewComponent->bDrawSockets; } void SAnimationEditorViewportTabBody::OnShowGrid() { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); AnimViewportClient->OnToggleShowGrid(); } bool SAnimationEditorViewportTabBody::IsShowingGrid() const { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); return AnimViewportClient->IsShowingGrid(); } void SAnimationEditorViewportTabBody::OnShowFloor() { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); AnimViewportClient->OnToggleShowFloor(); } bool SAnimationEditorViewportTabBody::IsShowingFloor() const { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); return AnimViewportClient->IsShowingFloor(); } void SAnimationEditorViewportTabBody::OnToggleAutoAlignFloor() { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); AnimViewportClient->OnToggleAutoAlignFloor(); } bool SAnimationEditorViewportTabBody::IsAutoAlignFloor() const { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); return AnimViewportClient->IsAutoAlignFloor(); } void SAnimationEditorViewportTabBody::OnShowSky() { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); AnimViewportClient->OnToggleShowSky(); } bool SAnimationEditorViewportTabBody::IsShowingSky() const { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); return AnimViewportClient->IsShowingSky(); } /** Function to set the current playback speed*/ void SAnimationEditorViewportTabBody::OnSetPlaybackSpeed(int32 PlaybackSpeedMode) { AnimationPlaybackSpeedMode = (EAnimationPlaybackSpeeds::Type)PlaybackSpeedMode; UpdateViewportClientPlaybackScale(); } bool SAnimationEditorViewportTabBody::IsPlaybackSpeedSelected(int32 PlaybackSpeedMode) { return PlaybackSpeedMode == AnimationPlaybackSpeedMode; } void SAnimationEditorViewportTabBody::ShowReferencePose() { PersonaPtr.Pin()->ShowReferencePose(IsShowReferencePoseEnabled() == false); } bool SAnimationEditorViewportTabBody::CanShowReferencePose() const { return PersonaPtr.Pin()->CanShowReferencePose(); } bool SAnimationEditorViewportTabBody::IsShowReferencePoseEnabled() const { return PersonaPtr.Pin()->IsShowReferencePoseEnabled(); } void SAnimationEditorViewportTabBody::ShowRetargetBasePose() { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if(PreviewComponent && PreviewComponent->PreviewInstance) { PreviewComponent->PreviewInstance->bForceRetargetBasePose = !PreviewComponent->PreviewInstance->bForceRetargetBasePose; } } bool SAnimationEditorViewportTabBody::CanShowRetargetBasePose() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return PreviewComponent != NULL && PreviewComponent->PreviewInstance; } bool SAnimationEditorViewportTabBody::IsShowRetargetBasePoseEnabled() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if(PreviewComponent && PreviewComponent->PreviewInstance) { return PreviewComponent->PreviewInstance->bForceRetargetBasePose; } return false; } void SAnimationEditorViewportTabBody::ShowBound() { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); AnimViewportClient->ToggleShowBounds(); UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if(PreviewComponent) { PreviewComponent->bDisplayBound = AnimViewportClient->EngineShowFlags.Bounds; PreviewComponent->RecreateRenderState_Concurrent(); } } bool SAnimationEditorViewportTabBody::CanShowBound() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return PreviewComponent != NULL; } bool SAnimationEditorViewportTabBody::IsShowBoundEnabled() const { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); return AnimViewportClient->IsSetShowBoundsChecked(); } void SAnimationEditorViewportTabBody::ToggleShowPreviewMesh() { if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { bool bCurrentlyVisible = IsShowPreviewMeshEnabled(); PreviewComponent->SetVisibility(!bCurrentlyVisible); } } bool SAnimationEditorViewportTabBody::CanShowPreviewMesh() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return PreviewComponent != NULL; } bool SAnimationEditorViewportTabBody::IsShowPreviewMeshEnabled() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return (PreviewComponent != NULL) && PreviewComponent->IsVisible(); } void SAnimationEditorViewportTabBody::UseInGameBound() { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if (PreviewComponent != NULL) { PreviewComponent->UseInGameBounds(! PreviewComponent->IsUsingInGameBounds()); } } bool SAnimationEditorViewportTabBody::CanUseInGameBound() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return PreviewComponent != NULL; } bool SAnimationEditorViewportTabBody::IsUsingInGameBound() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; return PreviewComponent != NULL && PreviewComponent->IsUsingInGameBounds(); } void SAnimationEditorViewportTabBody::SetPreviewComponent(class UDebugSkelMeshComponent* PreviewComponent) { PreviewComponent->MeshComponentUpdateFlag = EMeshComponentUpdateFlag::AlwaysTickPoseAndRefreshBones; PreviewComponent->bCanHighlightSelectedSections = true; //Set preview skeleton mesh component TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); AnimViewportClient->SetPreviewMeshComponent(PreviewComponent); AnimViewportClient->FocusViewportOnPreviewMesh(); // Adding the component to the PreviewScene can change AnimScriptInstance so we must re register it // with the AnimBlueprint UAnimBlueprint* SourceBlueprint = Cast(PersonaPtr.Pin()->GetBlueprintObj()); if ( SourceBlueprint && PreviewComponent->IsAnimBlueprintInstanced() ) { SourceBlueprint->SetObjectBeingDebugged(PreviewComponent->AnimScriptInstance); } PopulateNumUVChannels(); } void SAnimationEditorViewportTabBody::AnimChanged(UAnimationAsset* AnimAsset) { UpdateScrubPanel(AnimAsset); } void SAnimationEditorViewportTabBody::ComboBoxSelectionChanged(TSharedPtr NewSelection, ESelectInfo::Type SelectInfo) { int32 NewUVSelection = UVChannels.Find(NewSelection); TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); AnimViewportClient->SetUVChannelToDraw(NewUVSelection); RefreshViewport(); } void SAnimationEditorViewportTabBody::PopulateNumUVChannels() { NumUVChannels.Empty(); if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { if (FSkeletalMeshResource* MeshResource = PreviewComponent->GetSkeletalMeshResource()) { int32 NumLods = MeshResource->LODModels.Num(); NumUVChannels.AddZeroed(NumLods); for(int32 LOD = 0; LOD < NumLods; ++LOD) { NumUVChannels[LOD] = MeshResource->LODModels[LOD].VertexBufferGPUSkin.GetNumTexCoords(); } } } PopulateUVChoices(); } void SAnimationEditorViewportTabBody::PopulateUVChoices() { // Fill out the UV channels combo. UVChannels.Empty(); if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { int32 CurrentLOD = FMath::Clamp(PreviewComponent->ForcedLodModel - 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 AnimViewportClient = StaticCastSharedRef(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::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(AnimAsset)) { ScrubPanelContainer->AddSlot() .AutoHeight() [ SNew(SAnimMontageScrubPanel) .Persona(PersonaPtr) .ViewInputMin(this, &SAnimationEditorViewportTabBody::GetViewMinInput) .ViewInputMax(this, &SAnimationEditorViewportTabBody::GetViewMaxInput) .bAllowZoom(true) ]; bUseDefaultScrubPanel = false; } if(bUseDefaultScrubPanel) { ScrubPanelContainer->AddSlot() .AutoHeight() [ SNew(SAnimationScrubPanel) .Persona(PersonaPtr) .ViewInputMin(this, &SAnimationEditorViewportTabBody::GetViewMinInput) .ViewInputMax(this, &SAnimationEditorViewportTabBody::GetViewMaxInput) .bAllowZoom(true) ]; } } } float SAnimationEditorViewportTabBody::GetViewMinInput() const { if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { UObject* PreviewAsset = PersonaPtr.Pin()->GetPreviewAnimationAsset(); if (PreviewAsset != NULL) { return 0.0f; } else if (PreviewComponent->AnimScriptInstance != NULL) { return FMath::Max((float)(PreviewComponent->AnimScriptInstance->LifeTimer - 30.0), 0.0f); } } return 0.f; } float SAnimationEditorViewportTabBody::GetViewMaxInput() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if (PreviewComponent != NULL) { UObject* PreviewAsset = PersonaPtr.Pin()->GetPreviewAnimationAsset(); if ((PreviewAsset != NULL) && (PreviewComponent->PreviewInstance != NULL)) { return PreviewComponent->PreviewInstance->GetLength(); } else if (PreviewComponent->AnimScriptInstance != NULL) { return PreviewComponent->AnimScriptInstance->LifeTimer; } } return 0.f; } void SAnimationEditorViewportTabBody::UpdateShowFlagForMeshEdges() { bool bDrawBonesInfluence = false; if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { bDrawBonesInfluence = PreviewComponent->bDrawBoneInfluences; } //@TODO: SNOWPOCALYPSE: broke UnlitWithMeshEdges bool bShowMeshEdgesViewMode = false; #if 0 bShowMeshEdgesViewMode = (CurrentViewMode == EAnimationEditorViewportMode::UnlitWithMeshEdges); #endif LevelViewportClient->EngineShowFlags.MeshEdges = (bDrawBonesInfluence || bShowMeshEdgesViewMode) ? 1 : 0; } bool SAnimationEditorViewportTabBody::IsLODModelSelected(ELODViewSelection LODSelectionType) const { return (LODSelection == LODSelectionType) ? true : false; } void SAnimationEditorViewportTabBody::OnSetLODModel(ELODViewSelection LODSelectionType) { LODSelection = LODSelectionType; UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { PreviewComponent->ForcedLodModel = LODSelection; PopulateUVChoices(); } } FLinearColor SAnimationEditorViewportTabBody::GetViewportBackgroundColor() const { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); return AnimViewportClient->GetBackgroundColor(); } void SAnimationEditorViewportTabBody::SetViewportBackgroundColor(FLinearColor InColor) { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); AnimViewportClient->SetBackgroundColor( InColor ); } float SAnimationEditorViewportTabBody::GetBackgroundBrightness() const { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); return AnimViewportClient->GetBrightnessValue(); } void SAnimationEditorViewportTabBody::SetBackgroundBrightness(float Value) { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); AnimViewportClient->SetBrightnessValue(Value); RefreshViewport(); } TSharedRef SAnimationEditorViewportTabBody::GetAnimationViewportClient() const { return StaticCastSharedRef(LevelViewportClient.ToSharedRef()); } void SAnimationEditorViewportTabBody::ToggleCameraFollow() { // Switch to rotation mode TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); AnimViewportClient->SetCameraFollow(); } bool SAnimationEditorViewportTabBody::IsCameraFollowEnabled() const { // need a single selected bone in the skeletal tree TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); return (AnimViewportClient->IsSetCameraFollowChecked()); } bool SAnimationEditorViewportTabBody::CanChangeCameraMode() const { //Not allowed to change camera type when we are in an ortho camera return !LevelViewportClient->IsOrtho(); } void SAnimationEditorViewportTabBody::SaveData(class SAnimationEditorViewportTabBody* OldViewport) { if ( PersonaPtr.IsValid() && OldViewport ) { FPersonaModeSharedData& SharedData = PersonaPtr.Pin()->ModeSharedData; TSharedRef OldAnimViewportClient = StaticCastSharedRef(OldViewport->LevelViewportClient.ToSharedRef()); // set camera set up SharedData.ViewLocation = OldAnimViewportClient.Get().GetViewLocation(); SharedData.ViewRotation = OldAnimViewportClient.Get().GetViewRotation(); SharedData.LookAtLocation = OldAnimViewportClient.Get().GetLookAtLocation(); SharedData.OrthoZoom = OldAnimViewportClient.Get().GetOrthoZoom(); SharedData.bCameraLock = OldAnimViewportClient.Get().IsCameraLocked(); SharedData.bCameraFollow = OldAnimViewportClient.Get().IsSetCameraFollowChecked(); SharedData.bShowBound = OldAnimViewportClient.Get().IsSetShowBoundsChecked(); SharedData.LocalAxesMode = OldAnimViewportClient.Get().GetLocalAxesMode(); SharedData.ViewportType = OldAnimViewportClient.Get().ViewportType; SharedData.PlaybackSpeedMode = OldViewport->AnimationPlaybackSpeedMode; } } void SAnimationEditorViewportTabBody::RestoreData() { if ( PersonaPtr.IsValid() ) { FPersonaModeSharedData& SharedData = PersonaPtr.Pin()->ModeSharedData; TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); AnimViewportClient.Get().SetViewportType((ELevelViewportType)SharedData.ViewportType); AnimViewportClient.Get().SetViewLocation( SharedData.ViewLocation ); AnimViewportClient.Get().SetViewRotation( SharedData.ViewRotation ); AnimViewportClient.Get().SetShowBounds(SharedData.bShowBound); AnimViewportClient.Get().SetLocalAxesMode((ELocalAxesMode::Type)SharedData.LocalAxesMode); AnimViewportClient.Get().SetOrthoZoom(SharedData.OrthoZoom); OnSetPlaybackSpeed(SharedData.PlaybackSpeedMode); if (SharedData.bCameraLock) { AnimViewportClient.Get().SetLookAtLocation( SharedData.LookAtLocation ); } else if(SharedData.bCameraFollow) { AnimViewportClient.Get().SetCameraFollow(); } } } void SAnimationEditorViewportTabBody::UpdateViewportClientPlaybackScale() { TSharedRef AnimViewportClient = StaticCastSharedRef(LevelViewportClient.ToSharedRef()); AnimViewportClient->SetPlaybackScale(EAnimationPlaybackSpeeds::Values[AnimationPlaybackSpeedMode]); UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if (PreviewComponent) { PreviewComponent->PlaybackSpeedScaling = EAnimationPlaybackSpeeds::Values[AnimationPlaybackSpeedMode]; } } void SAnimationEditorViewportTabBody::OnLODChanged() { int32 LodCount = 0; UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent && PreviewComponent->SkeletalMesh ) { LodCount = PreviewComponent->SkeletalMesh->GetImportedResource()->LODModels.Num(); } // If the currently selected LoD is invalid, revert to LOD_Auto if ( LodCount < LODSelection ) { OnSetLODModel( LOD_Auto ); } if (PersonaPtr.Pin()->PersonaMeshDetailLayout) { PersonaPtr.Pin()->PersonaMeshDetailLayout->ForceRefreshDetails(); } } void SAnimationEditorViewportTabBody::OnMuteAudio() { GetAnimationViewportClient()->OnToggleMuteAudio(); } bool SAnimationEditorViewportTabBody::IsAudioMuted() { return GetAnimationViewportClient()->IsAudioMuted(); } void SAnimationEditorViewportTabBody::OnTogglePreviewRootMotion() { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if (PreviewComponent) { PreviewComponent->bPreviewRootMotion = !PreviewComponent->bPreviewRootMotion; } } bool SAnimationEditorViewportTabBody::IsPreviewingRootMotion() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if (PreviewComponent) { return PreviewComponent->bPreviewRootMotion; } return false; } #if WITH_APEX_CLOTHING bool SAnimationEditorViewportTabBody::IsDisablingClothSimulation() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { return PreviewComponent->bDisableClothSimulation; } return false; } void SAnimationEditorViewportTabBody::OnDisableClothSimulation() { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { PreviewComponent->bDisableClothSimulation = !PreviewComponent->bDisableClothSimulation; // if the user turns on cloth simulation option while displaying max distances, then turns off max distance option if(!PreviewComponent->bDisableClothSimulation && PreviewComponent->bDisplayClothMaxDistances) { PreviewComponent->bDisplayClothMaxDistances = false; } // if the user turns on cloth simulation option while displaying back stops, then turns off back stops option if (!PreviewComponent->bDisableClothSimulation && PreviewComponent->bDisplayClothBackstops) { PreviewComponent->bDisplayClothBackstops = false; } RefreshViewport(); } } bool SAnimationEditorViewportTabBody::IsApplyingClothWind() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { return PreviewComponent->IsWindEnabled(); } return false; } void SAnimationEditorViewportTabBody::OnApplyClothWind() { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { PreviewComponent->bEnableWind = !PreviewComponent->IsWindEnabled(); GetAnimationViewportClient()->EnableWindActor(PreviewComponent->IsWindEnabled()); RefreshViewport(); } } void SAnimationEditorViewportTabBody::SetWindStrength(float SliderPos) { GetAnimationViewportClient()->SetWindStrength( SliderPos ); RefreshViewport(); } float SAnimationEditorViewportTabBody::GetWindStrengthSliderValue() const { return GetAnimationViewportClient()->GetWindStrengthSliderValue(); } FText SAnimationEditorViewportTabBody::GetWindStrengthLabel() const { return GetAnimationViewportClient()->GetWindStrengthLabel(); } void SAnimationEditorViewportTabBody::OnShowClothSimulationNormals() { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { PreviewComponent->bDisplayClothingNormals = !PreviewComponent->bDisplayClothingNormals; RefreshViewport(); } } bool SAnimationEditorViewportTabBody::IsShowingClothSimulationNormals() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { return PreviewComponent->bDisplayClothingNormals; } return false; } void SAnimationEditorViewportTabBody::OnShowClothGraphicalTangents() { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { PreviewComponent->bDisplayClothingTangents = !PreviewComponent->bDisplayClothingTangents; RefreshViewport(); } } bool SAnimationEditorViewportTabBody::IsShowingClothGraphicalTangents() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { return PreviewComponent->bDisplayClothingTangents; } return false; } void SAnimationEditorViewportTabBody::OnShowClothCollisionVolumes() { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { PreviewComponent->bDisplayClothingCollisionVolumes = !PreviewComponent->bDisplayClothingCollisionVolumes; RefreshViewport(); } } bool SAnimationEditorViewportTabBody::IsShowingClothCollisionVolumes() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { return PreviewComponent->bDisplayClothingCollisionVolumes; } return false; } void SAnimationEditorViewportTabBody::SetGravityScale(float SliderPos) { GetAnimationViewportClient()->SetGravityScale(SliderPos); RefreshViewport(); } float SAnimationEditorViewportTabBody::GetGravityScaleSliderValue() const { return GetAnimationViewportClient()->GetGravityScaleSliderValue(); } FText SAnimationEditorViewportTabBody::GetGravityScaleLabel() const { return GetAnimationViewportClient()->GetGravityScaleLabel(); } void SAnimationEditorViewportTabBody::OnEnableCollisionWithAttachedClothChildren() { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { PreviewComponent->bCollideWithAttachedChildren = !PreviewComponent->bCollideWithAttachedChildren; RefreshViewport(); } } bool SAnimationEditorViewportTabBody::IsEnablingCollisionWithAttachedClothChildren() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { return PreviewComponent->bCollideWithAttachedChildren; } return false; } void SAnimationEditorViewportTabBody::OnShowClothPhysicalMeshWire() { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { PreviewComponent->bDisplayClothPhysicalMeshWire = !PreviewComponent->bDisplayClothPhysicalMeshWire; RefreshViewport(); } } bool SAnimationEditorViewportTabBody::IsShowingClothPhysicalMeshWire() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { return PreviewComponent->bDisplayClothPhysicalMeshWire; } return false; } void SAnimationEditorViewportTabBody::OnShowClothMaxDistances() { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { PreviewComponent->bDisplayClothMaxDistances = !PreviewComponent->bDisplayClothMaxDistances; // disables cloth simulation and stop animation because showing max distances is only useful when the cloth is not moving if(PreviewComponent->bDisplayClothMaxDistances) { PreviewComponent->bPrevDisableClothSimulation = PreviewComponent->bDisableClothSimulation; PreviewComponent->bDisableClothSimulation = true; PreviewComponent->InitAnim(false); } else { // restore previous state PreviewComponent->bDisableClothSimulation = PreviewComponent->bPrevDisableClothSimulation; } RefreshViewport(); } } bool SAnimationEditorViewportTabBody::IsShowingClothMaxDistances() const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { return PreviewComponent->bDisplayClothMaxDistances; } return false; } void SAnimationEditorViewportTabBody::OnShowClothBackstops() { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if( PreviewComponent ) { PreviewComponent->bDisplayClothBackstops = !PreviewComponent->bDisplayClothBackstops; // disables cloth simulation and stop animation because showing back stops is only useful when the cloth is not moving if (PreviewComponent->bDisplayClothBackstops) { PreviewComponent->bPrevDisableClothSimulation = PreviewComponent->bDisableClothSimulation; PreviewComponent->bDisableClothSimulation = true; PreviewComponent->InitAnim(false); } else { // restore previous state PreviewComponent->bDisableClothSimulation = PreviewComponent->bPrevDisableClothSimulation; } RefreshViewport(); } } bool SAnimationEditorViewportTabBody::IsShowingClothBackstops() const { if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { return PreviewComponent->bDisplayClothBackstops; } return false; } void SAnimationEditorViewportTabBody::OnShowClothFixedVertices() { if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { PreviewComponent->bDisplayClothFixedVertices = !PreviewComponent->bDisplayClothFixedVertices; RefreshViewport(); } } bool SAnimationEditorViewportTabBody::IsShowingClothFixedVertices() const { if (UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent) { return PreviewComponent->bDisplayClothFixedVertices; } return false; } void SAnimationEditorViewportTabBody::OnSetSectionsDisplayMode(int32 DisplayMode) { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if (!PreviewComponent) { return; } PreviewComponent->SectionsDisplayMode = DisplayMode; switch (DisplayMode) { case UDebugSkelMeshComponent::ESectionDisplayMode::ShowAll: // restore to the original states PreviewComponent->RestoreClothSectionsVisibility(); break; case UDebugSkelMeshComponent::ESectionDisplayMode::ShowOnlyClothSections: // disable all except clothing sections and shows only cloth sections PreviewComponent->ToggleClothSectionsVisibility(true); break; case UDebugSkelMeshComponent::ESectionDisplayMode::HideOnlyClothSections: // disables only clothing sections PreviewComponent->ToggleClothSectionsVisibility(false); break; } RefreshViewport(); } bool SAnimationEditorViewportTabBody::IsSectionsDisplayMode(int32 DisplayMode) const { UDebugSkelMeshComponent* PreviewComponent = PersonaPtr.Pin()->PreviewComponent; if (ensure(PreviewComponent)) { return (PreviewComponent->SectionsDisplayMode == DisplayMode); } return false; } #endif // #if WITH_APEX_CLOTHING EVisibility SAnimationEditorViewportTabBody::GetViewportCornerImageVisibility() const { TSharedPtr Persona = PersonaPtr.Pin(); return Persona->Recorder.InRecording()? EVisibility::Visible : EVisibility::Collapsed; } const FSlateBrush* SAnimationEditorViewportTabBody::GetViewportCornerImage() const { static int32 Count=0; TSharedPtr Persona = PersonaPtr.Pin(); // if(Persona->Recorder.InRecording()) { if(Count++ < 5) { return FEditorStyle::GetBrush("Persona.StopRecordAnimation"); } else { if(Count == 10) { Count = 0; } return FEditorStyle::GetBrush("Persona.StopRecordAnimation_Alt"); } } // return NULL; } EVisibility SAnimationEditorViewportTabBody::GetViewportCornerTextVisibility() const { TSharedPtr Persona = PersonaPtr.Pin(); if (Persona->Recorder.InRecording()) { return EVisibility::Visible; } else if (Persona->IsModeCurrent(FPersonaModes::AnimBlueprintEditMode)) { if (UBlueprint* Blueprint = Persona->GetBlueprintObj()) { const bool bUpToDate = (Blueprint->Status == BS_UpToDate) || (Blueprint->Status == BS_UpToDateWithWarnings); return bUpToDate ? EVisibility::Collapsed : EVisibility::Visible; } } return EVisibility::Collapsed; } FText SAnimationEditorViewportTabBody::GetViewportCornerText() const { TSharedPtr Persona = PersonaPtr.Pin(); if(Persona->Recorder.InRecording()) { const FString& Name = Persona->Recorder.GetAnimationObject()->GetName(); float TimeRecorded = Persona->Recorder.GetTimeRecorded(); FNumberFormattingOptions NumberOption; NumberOption.MaximumFractionalDigits = 2; NumberOption.MinimumFractionalDigits = 2; return FText::Format(LOCTEXT("AnimRecorder", "Recording '{0}' - Time {1} sec(s)]\nTo stop, click here. "), FText::FromString(Name), FText::AsNumber(TimeRecorded, &NumberOption)); } if (Persona->IsModeCurrent(FPersonaModes::AnimBlueprintEditMode)) { if (UBlueprint* Blueprint = Persona->GetBlueprintObj()) { switch (Blueprint->Status) { case BS_UpToDate: case BS_UpToDateWithWarnings: // Fall thru and return empty string break; case BS_Dirty: return LOCTEXT("AnimBP_Dirty", "Preview out of date\nClick to recompile"); case BS_Error: return LOCTEXT("AnimBP_CompileError", "Compile Error"); default: return LOCTEXT("AnimBP_UnknownStatus", "Unknown Status"); } } } return FText::GetEmpty(); } FText SAnimationEditorViewportTabBody::GetViewportCornerTooltip() const { TSharedPtr Persona = PersonaPtr.Pin(); if(Persona->Recorder.InRecording()) { return LOCTEXT("RecordingStatusTooltip", "Shows the status of animation recording.\nClick to stop the recording."); } if(Persona->IsModeCurrent(FPersonaModes::AnimBlueprintEditMode)) { return LOCTEXT("BlueprintStatusTooltip", "Shows the status of the animation blueprint.\nClick to recompile a dirty blueprint"); } return FText::GetEmpty(); } FReply SAnimationEditorViewportTabBody::ClickedOnViewportCornerText() { TSharedPtr Persona = PersonaPtr.Pin(); // if it's recording, it won't be able to see the message // so disable it if (Persona->Recorder.InRecording()) { Persona->Recorder.StopRecord(true); } else { Persona->RecompileAnimBlueprintIfDirty(); } return FReply::Handled(); } #undef LOCTEXT_NAMESPACE