1098 lines
40 KiB
C++
1098 lines
40 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "SLevelViewportToolBar.h"
|
|
#include "Framework/Commands/UIAction.h"
|
|
#include "Framework/MultiBox/MultiBoxDefs.h"
|
|
#include "Framework/MultiBox/MultiBoxExtender.h"
|
|
#include "Framework/MultiBox/MultiBoxBuilder.h"
|
|
#include "SceneView.h"
|
|
#include "Subsystems/PanelExtensionSubsystem.h"
|
|
#include "ToolMenus.h"
|
|
#include "LevelEditorMenuContext.h"
|
|
#include "ViewportToolBarContext.h"
|
|
#include "Modules/ModuleManager.h"
|
|
#include "Widgets/Layout/SBorder.h"
|
|
#include "Widgets/Layout/SBox.h"
|
|
#include "Widgets/Input/SSpinBox.h"
|
|
#include "Styling/AppStyle.h"
|
|
#include "Camera/CameraActor.h"
|
|
#include "Misc/ConfigCacheIni.h"
|
|
#include "GameFramework/ActorPrimitiveColorHandler.h"
|
|
#include "GameFramework/WorldSettings.h"
|
|
#include "EngineUtils.h"
|
|
#include "LevelEditor.h"
|
|
#include "STransformViewportToolbar.h"
|
|
#include "EditorShowFlags.h"
|
|
#include "LevelViewportActions.h"
|
|
#include "LevelEditorViewport.h"
|
|
#include "Layers/LayersSubsystem.h"
|
|
#include "DeviceProfiles/DeviceProfile.h"
|
|
#include "IDeviceProfileServicesModule.h"
|
|
#include "EditorViewportCommands.h"
|
|
#include "SEditorViewportToolBarMenu.h"
|
|
#include "SEditorViewportToolBarButton.h"
|
|
#include "SEditorViewportViewMenu.h"
|
|
#include "Stats/StatsData.h"
|
|
#include "BufferVisualizationData.h"
|
|
#include "NaniteVisualizationData.h"
|
|
#include "LumenVisualizationData.h"
|
|
#include "SubstrateVisualizationData.h"
|
|
#include "GroomVisualizationData.h"
|
|
#include "VirtualShadowMapVisualizationData.h"
|
|
#include "FoliageType.h"
|
|
#include "ShowFlagMenuCommands.h"
|
|
#include "Bookmarks/BookmarkUI.h"
|
|
#include "Scalability.h"
|
|
#include "SScalabilitySettings.h"
|
|
#include "Editor/EditorPerformanceSettings.h"
|
|
#include "SEditorViewportViewMenuContext.h"
|
|
#include "Bookmarks/IBookmarkTypeTools.h"
|
|
#include "ToolMenu.h"
|
|
#include "WorldPartition/IWorldPartitionEditorModule.h"
|
|
#include "WorldPartition/WorldPartitionSubsystem.h"
|
|
#include "WorldPartition/WorldPartition.h"
|
|
#include "SLevelViewport.h"
|
|
#include "SortHelper.h"
|
|
#include "Interfaces/IMainFrameModule.h"
|
|
#include "SCommonEditorViewportToolbarBase.h"
|
|
#include "Engine/SceneCapture.h"
|
|
#include "ViewportToolbar/LevelEditorSubmenus.h"
|
|
#include "ViewportToolbar/LevelViewportContext.h"
|
|
#include "ViewportToolbar/UnrealEdViewportToolbar.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "LevelViewportToolBar"
|
|
|
|
/** Override the view menu, just so we can specify the level viewport as active when the button is clicked */
|
|
class SLevelEditorViewportViewMenu : public SEditorViewportViewMenu
|
|
{
|
|
public:
|
|
|
|
void Construct(const FArguments& InArgs, TSharedRef<SEditorViewport> InViewport, TSharedRef<class SViewportToolBar> InParentToolBar)
|
|
{
|
|
SEditorViewportViewMenu::Construct(InArgs, InViewport, InParentToolBar);
|
|
MenuName = FName("LevelEditor.LevelViewportToolBar.View");
|
|
}
|
|
|
|
virtual void RegisterMenus() const override
|
|
{
|
|
SEditorViewportViewMenu::RegisterMenus();
|
|
|
|
// Use a static bool to track whether or not this menu is registered. Bool instead of checking the registered
|
|
// state with ToolMenus because we want the new viewport toolbar to be able to create this menu without breaking
|
|
// this code. Static because this code can be called multiple times using different instances of this class.
|
|
static bool bDidRegisterMenu = false;
|
|
if (!bDidRegisterMenu)
|
|
{
|
|
bDidRegisterMenu = true;
|
|
|
|
// Don't warn here to avoid warnings if the new viewport toolbar already has created an empty version
|
|
// of this menu.
|
|
UToolMenu* Menu = UToolMenus::Get()->RegisterMenu(
|
|
"LevelEditor.LevelViewportToolBar.View", "UnrealEd.ViewportToolbar.View", EMultiBoxType::Menu, false
|
|
);
|
|
Menu->AddDynamicSection("LevelSection", FNewToolMenuDelegate::CreateLambda([](UToolMenu* InMenu) {
|
|
if (UEditorViewportViewMenuContext* Context = InMenu->FindContext<UEditorViewportViewMenuContext>())
|
|
{
|
|
if (TSharedPtr<const SEditorViewportToolbarMenu> Menu = Context->EditorViewportViewMenu.Pin())
|
|
{
|
|
if (TSharedPtr<SLevelViewportToolBar> LevelViewportToolBar = StaticCastSharedPtr<SLevelViewportToolBar>(Menu->GetParentToolBar().Pin()))
|
|
{
|
|
LevelViewportToolBar->FillViewMenu(InMenu);
|
|
}
|
|
}
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
|
|
virtual TSharedRef<SWidget> GenerateViewMenuContent() const override
|
|
{
|
|
SLevelViewport* LevelViewport = static_cast<SLevelViewport*>(Viewport.Pin().Get());
|
|
LevelViewport->OnFloatingButtonClicked();
|
|
|
|
return SEditorViewportViewMenu::GenerateViewMenuContent();
|
|
}
|
|
};
|
|
|
|
void SLevelViewportToolBar::Construct( const FArguments& InArgs )
|
|
{
|
|
Viewport = InArgs._Viewport;
|
|
TSharedRef<SLevelViewport> ViewportRef = Viewport.Pin().ToSharedRef();
|
|
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>(TEXT("LevelEditor"));
|
|
|
|
UViewportToolBarContext* ExtensionContextObject = NewObject<UViewportToolBarContext>();
|
|
ExtensionContextObject->ViewportToolBar = SharedThis(this);
|
|
ExtensionContextObject->Viewport = Viewport;
|
|
|
|
const FMargin ToolbarSlotPadding(4.0f, 1.0f);
|
|
|
|
// clang-format off
|
|
ChildSlot
|
|
[
|
|
SNew(SBorder)
|
|
.BorderImage(FAppStyle::Get().GetBrush("EditorViewportToolBar.Background"))
|
|
.Visibility(EVisibility::SelfHitTestInvisible)
|
|
[
|
|
SNew( SVerticalBox )
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(ToolbarSlotPadding)
|
|
[
|
|
SNew( SHorizontalBox )
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding(ToolbarSlotPadding)
|
|
[
|
|
SNew( SEditorViewportToolbarMenu )
|
|
.ParentToolBar( SharedThis( this ) )
|
|
.Visibility(Viewport.Pin().Get(), &SLevelViewport::GetOptionsMenuVisibility)
|
|
.Image("EditorViewportToolBar.OptionsDropdown")
|
|
.AddMetaData<FTagMetaData>(FTagMetaData(TEXT("EditorViewportToolBar.MenuDropdown")))
|
|
.OnGetMenuContent( this, &SLevelViewportToolBar::GenerateOptionsMenu )
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
[
|
|
SNew( SHorizontalBox )
|
|
.Visibility(Viewport.Pin().Get(), &SLevelViewport::GetFullToolbarVisibility)
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding( ToolbarSlotPadding )
|
|
[
|
|
SNew( SEditorViewportToolbarMenu )
|
|
.ParentToolBar( SharedThis( this ) )
|
|
.Label( this, &SLevelViewportToolBar::GetCameraMenuLabel )
|
|
.LabelIcon( this, &SLevelViewportToolBar::GetCameraMenuLabelIcon )
|
|
.AddMetaData<FTagMetaData>(FTagMetaData(TEXT("EditorViewportToolBar.CameraMenu")))
|
|
.OnGetMenuContent( this, &SLevelViewportToolBar::GenerateCameraMenu )
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding( ToolbarSlotPadding )
|
|
[
|
|
SNew( SLevelEditorViewportViewMenu, ViewportRef, SharedThis(this) )
|
|
.MenuExtenders(UE::LevelEditor::GetViewModesLegacyExtenders())
|
|
.AddMetaData<FTagMetaData>(FTagMetaData(TEXT("ViewMenuButton")))
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding( ToolbarSlotPadding )
|
|
[
|
|
SNew( SEditorViewportToolbarMenu )
|
|
.Label( LOCTEXT("ShowMenuTitle", "Show") )
|
|
.ParentToolBar( SharedThis( this ) )
|
|
.AddMetaData<FTagMetaData>(FTagMetaData(TEXT("EditorViewportToolBar.ShowMenu")))
|
|
.OnGetMenuContent( this, &SLevelViewportToolBar::GenerateShowMenu )
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding( ToolbarSlotPadding )
|
|
[
|
|
SNew( SEditorViewportToolbarMenu )
|
|
.Label( this, &SLevelViewportToolBar::GetViewModeOptionsMenuLabel )
|
|
.ParentToolBar( SharedThis( this ) )
|
|
.Visibility( this, &SLevelViewportToolBar::GetViewModeOptionsVisibility )
|
|
.AddMetaData<FTagMetaData>(FTagMetaData(TEXT("EditorViewportToolBar.ViewModeOptions")))
|
|
.OnGetMenuContent( this, &SLevelViewportToolBar::GenerateViewModeOptionsMenu )
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding( ToolbarSlotPadding )
|
|
[
|
|
SNew( SEditorViewportToolbarMenu )
|
|
.ParentToolBar( SharedThis( this ) )
|
|
.Label( this, &SLevelViewportToolBar::GetDevicePreviewMenuLabel )
|
|
.LabelIcon( this, &SLevelViewportToolBar::GetDevicePreviewMenuLabelIcon )
|
|
.OnGetMenuContent( this, &SLevelViewportToolBar::GenerateDevicePreviewMenu )
|
|
//@todo rendering: mobile preview in view port is not functional yet - remove this once it is.
|
|
.Visibility(EVisibility::Collapsed)
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.Padding(ToolbarSlotPadding)
|
|
.AutoWidth()
|
|
.HAlign(HAlign_Left)
|
|
.VAlign(VAlign_Fill)
|
|
[
|
|
SNew(SExtensionPanel)
|
|
.ExtensionPanelID("LevelViewportToolBar.LeftExtension")
|
|
.ExtensionContext(ExtensionContextObject)
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding(ToolbarSlotPadding)
|
|
[
|
|
// Button to show that realtime is off
|
|
SNew(SEditorViewportToolBarButton)
|
|
.ButtonType(EUserInterfaceActionType::Button)
|
|
.ButtonStyle(&FAppStyle::Get().GetWidgetStyle<FButtonStyle>("EditorViewportToolBar.WarningButton"))
|
|
.OnClicked(this, &SLevelViewportToolBar::OnRealtimeWarningClicked)
|
|
.Visibility(this, &SLevelViewportToolBar::GetRealtimeWarningVisibility)
|
|
.ToolTipText(LOCTEXT("RealtimeOff_ToolTip", "This viewport is not updating in realtime. Click to turn on realtime mode."))
|
|
.Content()
|
|
[
|
|
SNew(STextBlock)
|
|
.TextStyle(&FAppStyle::Get().GetWidgetStyle<FTextBlockStyle>("SmallText"))
|
|
.Text(LOCTEXT("RealtimeOff", "Realtime Off"))
|
|
]
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding(ToolbarSlotPadding)
|
|
[
|
|
// Button to show scalability warnings
|
|
SNew(SEditorViewportToolbarMenu)
|
|
.ParentToolBar(SharedThis(this))
|
|
.Label_Static(&UE::UnrealEd::GetScalabilityWarningLabel)
|
|
.MenuStyle(&FAppStyle::Get().GetWidgetStyle<FButtonStyle>("EditorViewportToolBar.WarningButton"))
|
|
.OnGetMenuContent(this, &SLevelViewportToolBar::GetScalabilityWarningMenuContent)
|
|
.Visibility(this, &SLevelViewportToolBar::GetScalabilityWarningVisibility)
|
|
.ToolTipText_Static(&UE::UnrealEd::GetScalabilityWarningTooltip)
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.Padding(ToolbarSlotPadding)
|
|
.HAlign(HAlign_Center)
|
|
.VAlign(VAlign_Fill)
|
|
[
|
|
SNew(SExtensionPanel)
|
|
.ExtensionPanelID("LevelViewportToolBar.MiddleExtension")
|
|
.ExtensionContext(ExtensionContextObject)
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.Padding(ToolbarSlotPadding)
|
|
.AutoWidth()
|
|
.HAlign(HAlign_Right)
|
|
.VAlign(VAlign_Fill)
|
|
[
|
|
SNew(SExtensionPanel)
|
|
.ExtensionPanelID("LevelViewportToolBar.RightExtension")
|
|
.ExtensionContext(ExtensionContextObject)
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.MaxWidth(TAttribute<float>::CreateSP(this, &SLevelViewportToolBar::GetTransformToolbarWidth))
|
|
.Padding(ToolbarSlotPadding)
|
|
.HAlign(HAlign_Right)
|
|
[
|
|
SAssignNew(TransformToolbar, STransformViewportToolBar)
|
|
.Viewport(ViewportRef)
|
|
.CommandList(ViewportRef->GetCommandList())
|
|
.Extenders(LevelEditorModule.GetToolBarExtensibilityManager()->GetAllExtenders())
|
|
.Visibility(ViewportRef, &SLevelViewport::GetTransformToolbarVisibility)
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.Padding(ToolbarSlotPadding)
|
|
.AutoWidth()
|
|
.HAlign(HAlign_Right)
|
|
.VAlign(VAlign_Fill)
|
|
[
|
|
SNew(SExtensionPanel)
|
|
.ExtensionPanelID("LevelViewportToolBar.RightmostExtension")
|
|
.ExtensionContext(ExtensionContextObject)
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Right)
|
|
.AutoWidth()
|
|
.Padding(ToolbarSlotPadding)
|
|
[
|
|
//The Maximize/Minimize button is only displayed when not in Immersive mode.
|
|
SNew(SEditorViewportToolBarButton)
|
|
.ButtonType(EUserInterfaceActionType::ToggleButton)
|
|
.CheckBoxStyle(&FAppStyle::Get().GetWidgetStyle<FCheckBoxStyle>("EditorViewportToolBar.MaximizeRestoreButton"))
|
|
.IsChecked(ViewportRef, &SLevelViewport::IsMaximized)
|
|
.OnClicked(ViewportRef, &SLevelViewport::OnToggleMaximize)
|
|
.Visibility(ViewportRef, &SLevelViewport::GetMaximizeToggleVisibility)
|
|
.Image("EditorViewportToolBar.Maximize")
|
|
.ToolTipText(LOCTEXT("Maximize_ToolTip", "Maximizes or restores this viewport"))
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Right)
|
|
.AutoWidth()
|
|
.Padding(ToolbarSlotPadding)
|
|
[
|
|
//The Restore from Immersive' button is only displayed when the editor is in Immersive mode.
|
|
SNew(SEditorViewportToolBarButton)
|
|
.ButtonType(EUserInterfaceActionType::Button)
|
|
.OnClicked(ViewportRef, &SLevelViewport::OnToggleMaximize)
|
|
.Visibility(ViewportRef, &SLevelViewport::GetCloseImmersiveButtonVisibility)
|
|
.Image("EditorViewportToolBar.RestoreFromImmersive.Normal")
|
|
.ToolTipText(LOCTEXT("RestoreFromImmersive_ToolTip", "Restore from Immersive"))
|
|
]
|
|
]
|
|
]
|
|
]
|
|
];
|
|
// clang-format on
|
|
|
|
SViewportToolBar::Construct(SViewportToolBar::FArguments());
|
|
}
|
|
|
|
bool SLevelViewportToolBar::IsViewModeSupported(EViewModeIndex ViewModeIndex) const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
FLevelEditorViewportClient* SLevelViewportToolBar::GetLevelViewportClient() const
|
|
{
|
|
if (TSharedPtr<SLevelViewport> PinnedViewport = Viewport.Pin())
|
|
{
|
|
return &PinnedViewport->GetLevelViewportClient();
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
FText SLevelViewportToolBar::GetCameraMenuLabel() const
|
|
{
|
|
TSharedPtr< SLevelViewport > PinnedViewport( Viewport.Pin() );
|
|
if( PinnedViewport.IsValid() )
|
|
{
|
|
return UE::UnrealEd::GetCameraSubmenuLabelFromViewportType(PinnedViewport->GetLevelViewportClient().ViewportType);
|
|
}
|
|
|
|
return LOCTEXT("CameraMenuTitle_Default", "Camera");
|
|
}
|
|
|
|
const FSlateBrush* SLevelViewportToolBar::GetCameraMenuLabelIcon() const
|
|
{
|
|
TSharedPtr< SLevelViewport > PinnedViewport( Viewport.Pin() );
|
|
if( PinnedViewport.IsValid() )
|
|
{
|
|
return GetCameraMenuLabelIconFromViewportType(PinnedViewport->GetLevelViewportClient().ViewportType );
|
|
}
|
|
|
|
return FStyleDefaults::GetNoBrush();
|
|
}
|
|
|
|
FText SLevelViewportToolBar::GetDevicePreviewMenuLabel() const
|
|
{
|
|
FText Label = LOCTEXT("DevicePreviewMenuTitle_Default", "Preview");
|
|
|
|
TSharedPtr< SLevelViewport > PinnedViewport( Viewport.Pin() );
|
|
if( PinnedViewport.IsValid() )
|
|
{
|
|
if ( PinnedViewport->GetDeviceProfileString() != "Default" )
|
|
{
|
|
Label = FText::FromString( PinnedViewport->GetDeviceProfileString() );
|
|
}
|
|
}
|
|
|
|
return Label;
|
|
}
|
|
|
|
const FSlateBrush* SLevelViewportToolBar::GetDevicePreviewMenuLabelIcon() const
|
|
{
|
|
TSharedRef<SLevelViewport> ViewportRef = Viewport.Pin().ToSharedRef();
|
|
FString DeviceProfileName = ViewportRef->GetDeviceProfileString();
|
|
|
|
FName PlatformIcon = NAME_None;
|
|
if( !DeviceProfileName.IsEmpty() && DeviceProfileName != "Default" )
|
|
{
|
|
static FName DeviceProfileServices( "DeviceProfileServices" );
|
|
|
|
IDeviceProfileServicesModule& ScreenDeviceProfileUIServices = FModuleManager::LoadModuleChecked<IDeviceProfileServicesModule>(TEXT( "DeviceProfileServices"));
|
|
IDeviceProfileServicesUIManagerPtr UIManager = ScreenDeviceProfileUIServices.GetProfileServicesManager();
|
|
|
|
PlatformIcon = UIManager->GetDeviceIconName( DeviceProfileName );
|
|
|
|
return FAppStyle::GetOptionalBrush( PlatformIcon );
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
bool SLevelViewportToolBar::IsCurrentLevelViewport() const
|
|
{
|
|
TSharedPtr< SLevelViewport > PinnedViewport( Viewport.Pin() );
|
|
if( PinnedViewport.IsValid() )
|
|
{
|
|
if( &( PinnedViewport->GetLevelViewportClient() ) == GCurrentLevelEditingViewportClient )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool SLevelViewportToolBar::IsPerspectiveViewport() const
|
|
{
|
|
TSharedPtr< SLevelViewport > PinnedViewport( Viewport.Pin() );
|
|
if( PinnedViewport.IsValid() )
|
|
{
|
|
if( PinnedViewport->GetLevelViewportClient().IsPerspective() )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
TSharedRef<SWidget> SLevelViewportToolBar::GenerateOptionsMenu()
|
|
{
|
|
static const FName MenuName("LevelEditor.LevelViewportToolBar.Options");
|
|
if (!UToolMenus::Get()->IsMenuRegistered(MenuName))
|
|
{
|
|
UToolMenu* Menu = UToolMenus::Get()->RegisterMenu(MenuName);
|
|
Menu->AddDynamicSection("DynamicSection", FNewToolMenuDelegate::CreateLambda([](UToolMenu* InMenu)
|
|
{
|
|
if (ULevelViewportToolBarContext* Context = InMenu->FindContext<ULevelViewportToolBarContext>())
|
|
{
|
|
if (TSharedPtr<SLevelViewportToolBar> ToolBar = Context->LevelViewportToolBarWidget.Pin())
|
|
{
|
|
ToolBar->FillOptionsMenu(InMenu);
|
|
}
|
|
}
|
|
|
|
}));
|
|
}
|
|
|
|
Viewport.Pin()->OnFloatingButtonClicked();
|
|
|
|
const FLevelViewportCommands& LevelViewportActions = FLevelViewportCommands::Get();
|
|
TSharedRef<FUICommandList> CommandList = Viewport.Pin()->GetCommandList().ToSharedRef();
|
|
|
|
// Get all menu extenders for this context menu from the level editor module
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>( TEXT("LevelEditor") );
|
|
TSharedPtr<FExtender> MenuExtender = LevelEditorModule.AssembleExtenders(CommandList, LevelEditorModule.GetAllLevelViewportOptionsMenuExtenders());
|
|
|
|
FToolMenuContext MenuContext(CommandList, MenuExtender);
|
|
{
|
|
{
|
|
ULevelViewportToolBarContext* ToolbarContextObject = NewObject<ULevelViewportToolBarContext>();
|
|
ToolbarContextObject->LevelViewportToolBarWidget = SharedThis(this);
|
|
MenuContext.AddObject(ToolbarContextObject);
|
|
}
|
|
|
|
{
|
|
ULevelViewportContext* const LevelContextObject = NewObject<ULevelViewportContext>();
|
|
LevelContextObject->LevelViewport = Viewport;
|
|
MenuContext.AddObject(LevelContextObject);
|
|
}
|
|
|
|
{
|
|
UUnrealEdViewportToolbarContext* EdViewportToolbarContext = NewObject<UUnrealEdViewportToolbarContext>();
|
|
EdViewportToolbarContext->Viewport = Viewport;
|
|
MenuContext.AddObject(EdViewportToolbarContext);
|
|
}
|
|
}
|
|
|
|
return UToolMenus::Get()->GenerateWidget(MenuName, MenuContext);
|
|
}
|
|
|
|
void SLevelViewportToolBar::FillOptionsMenu(UToolMenu* Menu)
|
|
{
|
|
const FLevelViewportCommands& LevelViewportActions = FLevelViewportCommands::Get();
|
|
const bool bIsPerspective = Viewport.Pin()->GetLevelViewportClient().IsPerspective();
|
|
|
|
{
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("LevelViewportViewportOptions", LOCTEXT("OptionsMenuHeader", "Viewport Options"));
|
|
Section.AddMenuEntry(FEditorViewportCommands::Get().ToggleRealTime);
|
|
|
|
// Add an option to disable the temporary override if there is one
|
|
{
|
|
Section.AddEntry(UE::UnrealEd::CreateRemoveRealtimeOverrideEntry(Viewport));
|
|
|
|
Section.AddSeparator("DisableRealtimeOverrideSeparator");
|
|
}
|
|
|
|
Section.AddMenuEntry(FEditorViewportCommands::Get().ToggleFPS);
|
|
|
|
#if STATS
|
|
{
|
|
Section.AddMenuEntry(FEditorViewportCommands::Get().ToggleStats);
|
|
|
|
Section.AddEntry(UE::LevelEditor::CreateShowStatsSubmenu());
|
|
}
|
|
#endif
|
|
Section.AddMenuEntry(LevelViewportActions.ToggleAllowConstrainedAspectRatioInPreview);
|
|
Section.AddMenuEntry(LevelViewportActions.ToggleViewportToolbar);
|
|
|
|
if( bIsPerspective )
|
|
{
|
|
Section.AddEntry(UE::LevelEditor::CreateFOVMenu(Viewport));
|
|
Section.AddEntry(UE::LevelEditor::CreateFarViewPlaneMenu(Viewport));
|
|
}
|
|
|
|
Section.AddEntry(UE::UnrealEd::CreateScreenPercentageSubmenu());
|
|
}
|
|
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("LevelViewportViewportOptions2");
|
|
|
|
if( bIsPerspective )
|
|
{
|
|
// Cinematic preview only applies to perspective
|
|
Section.AddMenuEntry( LevelViewportActions.ToggleCinematicPreview );
|
|
}
|
|
|
|
Section.AddMenuEntry( LevelViewportActions.ToggleGameView );
|
|
Section.AddMenuEntry( LevelViewportActions.ToggleImmersive );
|
|
}
|
|
|
|
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("LevelViewportBookmarks");
|
|
if( bIsPerspective )
|
|
{
|
|
// Bookmarks only work in perspective viewports so only show the menu option if this toolbar is in one
|
|
|
|
Section.AddSubMenu(
|
|
"Bookmark",
|
|
LOCTEXT("BookmarkSubMenu", "Bookmarks"),
|
|
LOCTEXT("BookmarkSubMenu_ToolTip", "Viewport location bookmarking"),
|
|
FNewToolMenuDelegate::CreateStatic(&UE::LevelEditor::CreateBookmarksMenu),
|
|
false,
|
|
FSlateIcon(FAppStyle::Get().GetStyleSetName(), "EditorViewport.SubMenu.Bookmarks")
|
|
);
|
|
|
|
Section.AddSubMenu(
|
|
"Camera",
|
|
LOCTEXT("CameraSubMeun", "Create Camera Here"),
|
|
LOCTEXT("CameraSubMenu_ToolTip", "Select a camera type to create at current viewport's location"),
|
|
FNewToolMenuDelegate::CreateStatic(&UE::LevelEditor::CreateCameraSpawnMenu),
|
|
false,
|
|
FSlateIcon(FAppStyle::Get().GetStyleSetName(), "EditorViewport.SubMenu.CreateCamera")
|
|
);
|
|
}
|
|
|
|
Section.AddMenuEntry(LevelViewportActions.HighResScreenshot);
|
|
}
|
|
|
|
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("LevelViewportLayouts");
|
|
Section.AddSubMenu("Configs", LOCTEXT("ConfigsSubMenu", "Layouts"), FText::GetEmpty(),
|
|
FNewToolMenuDelegate::CreateLambda(
|
|
[](UToolMenu* InMenu)
|
|
{
|
|
UE::LevelEditor::GenerateViewportLayoutsMenu(InMenu);
|
|
}),
|
|
false, FSlateIcon(FAppStyle::Get().GetStyleSetName(), "Icons.Layout"));
|
|
}
|
|
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("LevelViewportSettings");
|
|
Section.AddMenuEntry(LevelViewportActions.AdvancedSettings);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
TSharedRef<SWidget> SLevelViewportToolBar::GenerateDevicePreviewMenu() const
|
|
{
|
|
static const FName MenuName("LevelEditor.LevelViewportToolBar.DevicePreview");
|
|
if (!UToolMenus::Get()->IsMenuRegistered(MenuName))
|
|
{
|
|
UToolMenu* Menu = UToolMenus::Get()->RegisterMenu(MenuName);
|
|
Menu->AddDynamicSection("DynamicSection", FNewToolMenuDelegate::CreateLambda([](UToolMenu* InMenu)
|
|
{
|
|
if (ULevelViewportToolBarContext* Context = InMenu->FindContext<ULevelViewportToolBarContext>())
|
|
{
|
|
if (TSharedPtr<SLevelViewportToolBar> ToolBar = Context->LevelViewportToolBarWidget.Pin())
|
|
{
|
|
ToolBar->FillDevicePreviewMenu(InMenu);
|
|
}
|
|
}
|
|
}));
|
|
}
|
|
|
|
ULevelViewportToolBarContext* ContextObject = NewObject<ULevelViewportToolBarContext>();
|
|
ContextObject->LevelViewportToolBarWidget = ConstCastSharedRef<SLevelViewportToolBar>(SharedThis(this));
|
|
|
|
FToolMenuContext MenuContext(Viewport.Pin()->GetCommandList(), TSharedPtr<FExtender>(), ContextObject);
|
|
return UToolMenus::Get()->GenerateWidget(MenuName, MenuContext);
|
|
}
|
|
|
|
void SLevelViewportToolBar::FillDevicePreviewMenu(UToolMenu* Menu) const
|
|
{
|
|
IDeviceProfileServicesModule& ScreenDeviceProfileUIServices = FModuleManager::LoadModuleChecked<IDeviceProfileServicesModule>(TEXT( "DeviceProfileServices"));
|
|
IDeviceProfileServicesUIManagerPtr UIManager = ScreenDeviceProfileUIServices.GetProfileServicesManager();
|
|
|
|
TSharedRef<SLevelViewport> ViewportRef = Viewport.Pin().ToSharedRef();
|
|
|
|
// Default menu - clear all settings
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("DevicePreview", LOCTEXT("DevicePreviewMenuTitle", "Device Preview"));
|
|
FUIAction Action( FExecuteAction::CreateSP( const_cast<SLevelViewportToolBar*>(this), &SLevelViewportToolBar::SetLevelProfile, FString( "Default" ) ),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP( ViewportRef, &SLevelViewport::IsDeviceProfileStringSet, FString( "Default" ) ) );
|
|
Section.AddMenuEntry("DevicePreviewMenuClear", LOCTEXT("DevicePreviewMenuClear", "Off"), FText::GetEmpty(), FSlateIcon(), Action, EUserInterfaceActionType::Button);
|
|
}
|
|
|
|
// Recent Device Profiles
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("Recent", LOCTEXT("RecentMenuHeading", "Recent"));
|
|
|
|
const FString INISection = "SelectedProfile";
|
|
const FString INIKeyBase = "ProfileItem";
|
|
const int32 MaxItems = 4; // Move this into a config file
|
|
FString CurItem;
|
|
for( int32 ItemIdx = 0 ; ItemIdx < MaxItems; ++ItemIdx )
|
|
{
|
|
// Build the menu from the contents of the game ini
|
|
//@todo This should probably be using GConfig->GetText [10/21/2013 justin.sargent]
|
|
if ( GConfig->GetString( *INISection, *FString::Printf( TEXT("%s%d"), *INIKeyBase, ItemIdx ), CurItem, GEditorPerProjectIni ) )
|
|
{
|
|
const FName PlatformIcon = UIManager->GetDeviceIconName( CurItem );
|
|
|
|
FUIAction Action( FExecuteAction::CreateSP( const_cast<SLevelViewportToolBar*>(this), &SLevelViewportToolBar::SetLevelProfile, CurItem ),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP( ViewportRef, &SLevelViewport::IsDeviceProfileStringSet, CurItem ) );
|
|
Section.AddMenuEntry(NAME_None, FText::FromString(CurItem), FText(), FSlateIcon(FAppStyle::GetAppStyleSetName(), PlatformIcon), Action, EUserInterfaceActionType::Button );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Device List
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("Devices", LOCTEXT("DevicesMenuHeading", "Devices"));
|
|
|
|
const TArray<TSharedPtr<FString> > PlatformList = UIManager->GetPlatformList();
|
|
for ( int32 Index = 0; Index < PlatformList.Num(); Index++ )
|
|
{
|
|
TArray< UDeviceProfile* > DeviceProfiles;
|
|
UIManager->GetProfilesByType( DeviceProfiles, *PlatformList[Index] );
|
|
if ( DeviceProfiles.Num() > 0 )
|
|
{
|
|
const FString PlatformNameStr = DeviceProfiles[0]->DeviceType;
|
|
const FName PlatformIcon = UIManager->GetPlatformIconName( PlatformNameStr );
|
|
Section.AddSubMenu(
|
|
NAME_None,
|
|
FText::FromString( PlatformNameStr ),
|
|
FText::GetEmpty(),
|
|
FNewToolMenuDelegate::CreateRaw( const_cast<SLevelViewportToolBar*>(this), &SLevelViewportToolBar::MakeDevicePreviewSubMenu, DeviceProfiles ),
|
|
false,
|
|
FSlateIcon(FAppStyle::GetAppStyleSetName(), PlatformIcon)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SLevelViewportToolBar::MakeDevicePreviewSubMenu(UToolMenu* Menu, TArray< class UDeviceProfile* > InProfiles)
|
|
{
|
|
TSharedRef<SLevelViewport> ViewportRef = Viewport.Pin().ToSharedRef();
|
|
FToolMenuSection& Section = Menu->AddSection("Section");
|
|
|
|
for ( int32 Index = 0; Index < InProfiles.Num(); Index++ )
|
|
{
|
|
FUIAction Action( FExecuteAction::CreateSP( this, &SLevelViewportToolBar::SetLevelProfile, InProfiles[ Index ]->GetName() ),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP( ViewportRef, &SLevelViewport::IsDeviceProfileStringSet, InProfiles[ Index ]->GetName() ) );
|
|
|
|
Section.AddMenuEntry(NAME_None, FText::FromString( InProfiles[ Index ]->GetName() ), FText(), FSlateIcon(), Action, EUserInterfaceActionType::RadioButton );
|
|
}
|
|
}
|
|
|
|
void SLevelViewportToolBar::SetLevelProfile( FString DeviceProfileName )
|
|
{
|
|
TSharedRef<SLevelViewport> ViewportRef = Viewport.Pin().ToSharedRef();
|
|
ViewportRef->SetDeviceProfileString( DeviceProfileName );
|
|
|
|
IDeviceProfileServicesModule& ScreenDeviceProfileUIServices = FModuleManager::LoadModuleChecked<IDeviceProfileServicesModule>(TEXT( "DeviceProfileServices"));
|
|
IDeviceProfileServicesUIManagerPtr UIManager = ScreenDeviceProfileUIServices.GetProfileServicesManager();
|
|
UIManager->SetProfile( DeviceProfileName );
|
|
}
|
|
|
|
void SLevelViewportToolBar::GeneratePlacedCameraMenuEntries(FToolMenuSection& Section, TArray<AActor*> LookThroughActors) const
|
|
{
|
|
FSlateIcon CameraIcon( FAppStyle::GetAppStyleSetName(), "ClassIcon.CameraComponent" );
|
|
|
|
// Sort the cameras to make the ordering predictable for users.
|
|
LookThroughActors.StableSort([](const AActor& Left, const AActor& Right)
|
|
{
|
|
// Do "natural sorting" via SceneOutliner::FNumericStringWrapper to make more sense to humans (also matches the Scene Outliner). This sorts "Camera2" before "Camera10" which a normal lexicographical sort wouldn't.
|
|
SceneOutliner::FNumericStringWrapper LeftWrapper(FString(Left.GetActorLabel()));
|
|
SceneOutliner::FNumericStringWrapper RightWrapper(FString(Right.GetActorLabel()));
|
|
|
|
return LeftWrapper < RightWrapper;
|
|
});
|
|
|
|
for( AActor* LookThroughActor : LookThroughActors)
|
|
{
|
|
// Needed for the delegate hookup to work below
|
|
AActor* GenericActor = LookThroughActor;
|
|
|
|
FText ActorDisplayName = FText::FromString(LookThroughActor->GetActorLabel());
|
|
FUIAction LookThroughCameraAction(
|
|
FExecuteAction::CreateSP(Viewport.Pin().ToSharedRef(), &SLevelViewport::OnActorLockToggleFromMenu, GenericActor),
|
|
FCanExecuteAction(),
|
|
FIsActionChecked::CreateSP(Viewport.Pin().ToSharedRef(), &SLevelViewport::IsActorLocked, MakeWeakObjectPtr(GenericActor))
|
|
);
|
|
|
|
Section.AddMenuEntry( NAME_None, ActorDisplayName, FText::Format(LOCTEXT("LookThroughCameraActor_ToolTip", "Look through and pilot {0}"), ActorDisplayName), CameraIcon, LookThroughCameraAction, EUserInterfaceActionType::RadioButton );
|
|
}
|
|
}
|
|
|
|
void SLevelViewportToolBar::GeneratePlacedCameraMenuEntries(UToolMenu* Menu, TArray<AActor*> LookThroughActors) const
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("Section");
|
|
GeneratePlacedCameraMenuEntries(Section, LookThroughActors);
|
|
}
|
|
|
|
void SLevelViewportToolBar::GenerateViewportTypeMenu(FToolMenuSection& Section) const
|
|
{
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>(TEXT("LevelEditor"));
|
|
LevelEditorModule.IterateViewportTypes([&](FName ViewportTypeName, const FViewportTypeDefinition& InDefinition)
|
|
{
|
|
if (InDefinition.ActivationCommand.IsValid())
|
|
{
|
|
Section.AddMenuEntry(*FString::Printf(TEXT("ViewportType_%s"), *ViewportTypeName.ToString()), InDefinition.ActivationCommand);
|
|
}
|
|
});
|
|
}
|
|
|
|
void SLevelViewportToolBar::GenerateViewportTypeMenu(UToolMenu* Menu) const
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("Section");
|
|
GenerateViewportTypeMenu(Section);
|
|
}
|
|
|
|
void SLevelViewportToolBar::GenerateCameraSpawnMenu(UToolMenu* Menu) const
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("Section");
|
|
const FLevelViewportCommands& Actions = FLevelViewportCommands::Get();
|
|
|
|
for (TSharedPtr<FUICommandInfo> Camera : Actions.CreateCameras)
|
|
{
|
|
Section.AddMenuEntry(NAME_None, Camera);
|
|
}
|
|
}
|
|
|
|
TSharedRef<SWidget> SLevelViewportToolBar::GenerateCameraMenu() const
|
|
{
|
|
static const FName MenuName("LevelEditor.LevelViewportToolBar.Camera");
|
|
|
|
// Use a static bool to track whether or not this menu is registered. Bool instead of checking the registered
|
|
// state with ToolMenus because we want the new viewport toolbar to be able to create this menu without breaking
|
|
// this code. Static because this code can be called multiple times using different instances of this class.
|
|
static bool bDidRegisterMenu = false;
|
|
if (!bDidRegisterMenu)
|
|
{
|
|
bDidRegisterMenu = true;
|
|
|
|
constexpr bool bWarnIfAlreadyRegistered = false;
|
|
UToolMenu* Menu =
|
|
UToolMenus::Get()->RegisterMenu(MenuName, NAME_None, EMultiBoxType::Menu, bWarnIfAlreadyRegistered);
|
|
Menu->AddDynamicSection(
|
|
"DynamicSection",
|
|
FNewToolMenuDelegate::CreateLambda(
|
|
[](UToolMenu* InMenu)
|
|
{
|
|
if (ULevelViewportToolBarContext* Context = InMenu->FindContext<ULevelViewportToolBarContext>())
|
|
{
|
|
if (TSharedPtr<SLevelViewportToolBar> ViewportToolbar = Context->LevelViewportToolBarWidget.Pin())
|
|
{
|
|
ViewportToolbar->FillCameraMenu(InMenu);
|
|
}
|
|
}
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
Viewport.Pin()->OnFloatingButtonClicked();
|
|
|
|
ULevelViewportToolBarContext* ContextObject = NewObject<ULevelViewportToolBarContext>();
|
|
ContextObject->LevelViewportToolBarWidget = ConstCastSharedRef<SLevelViewportToolBar>(SharedThis(this));
|
|
|
|
FToolMenuContext MenuContext(Viewport.Pin()->GetCommandList(), TSharedPtr<FExtender>(), ContextObject);
|
|
return UToolMenus::Get()->GenerateWidget(MenuName, MenuContext);
|
|
}
|
|
|
|
void SLevelViewportToolBar::FillCameraMenu(UToolMenu* Menu) const
|
|
{
|
|
// Camera types
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("CameraTypes");
|
|
Section.AddMenuEntry(FEditorViewportCommands::Get().Perspective);
|
|
}
|
|
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("LevelViewportCameraType_Ortho", LOCTEXT("CameraTypeHeader_Ortho", "Orthographic"));
|
|
Section.AddMenuEntry(FEditorViewportCommands::Get().Top);
|
|
Section.AddMenuEntry(FEditorViewportCommands::Get().Bottom);
|
|
Section.AddMenuEntry(FEditorViewportCommands::Get().Left);
|
|
Section.AddMenuEntry(FEditorViewportCommands::Get().Right);
|
|
Section.AddMenuEntry(FEditorViewportCommands::Get().Front);
|
|
Section.AddMenuEntry(FEditorViewportCommands::Get().Back);
|
|
}
|
|
|
|
TArray<AActor*> LookThroughActors;
|
|
|
|
for( TActorIterator<ACameraActor> It(GetWorld().Get()); It; ++It )
|
|
{
|
|
LookThroughActors.Add( Cast<AActor>(*It) );
|
|
}
|
|
|
|
for (TActorIterator<ASceneCapture> It(GetWorld().Get()); It; ++It)
|
|
{
|
|
LookThroughActors.Add(Cast<AActor>(*It));
|
|
}
|
|
|
|
FText CameraActorsHeading = LOCTEXT("CameraActorsHeading", "Placed Cameras and Scene Capture Actors");
|
|
|
|
// Don't add too many cameras to the top level menu or else it becomes too large
|
|
const uint32 MaxCamerasInTopLevelMenu = 10;
|
|
if(LookThroughActors.Num() > MaxCamerasInTopLevelMenu )
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("CameraActors");
|
|
Section.AddSubMenu("CameraActors", CameraActorsHeading, LOCTEXT("LookThroughPlacedCameras_ToolTip", "Look through and pilot placed cameras"), FNewToolMenuDelegate::CreateSP(this, &SLevelViewportToolBar::GeneratePlacedCameraMenuEntries, LookThroughActors ) );
|
|
}
|
|
else
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("CameraActors", CameraActorsHeading);
|
|
GeneratePlacedCameraMenuEntries(Section, LookThroughActors);
|
|
}
|
|
|
|
UE::UnrealEd::GenerateViewportTypeMenu(Menu);
|
|
}
|
|
|
|
TSharedRef<SWidget> SLevelViewportToolBar::GenerateShowMenu() const
|
|
{
|
|
static const FName MenuName("LevelEditor.LevelViewportToolbar.Show");
|
|
|
|
// Use a static bool to track whether or not this menu is registered. Bool instead of checking the registered state
|
|
// with ToolMenus because we want the new viewport toolbar to be able to create this menu without breaking this
|
|
// code. Static because this code can be called multiple times using different instances of this class.
|
|
static bool bDidRegisterMenu = false;
|
|
if (!bDidRegisterMenu)
|
|
{
|
|
bDidRegisterMenu = true;
|
|
|
|
// Don't warn here to avoid warnings if the new viewport toolbar already has created an empty version
|
|
// of this menu.
|
|
UToolMenu* Menu = UToolMenus::Get()->RegisterMenu(MenuName, NAME_None, EMultiBoxType::Menu, false);
|
|
Menu->AddDynamicSection(
|
|
"LevelDynamicSection",
|
|
FNewToolMenuDelegate::CreateLambda(
|
|
[](UToolMenu* InMenu)
|
|
{
|
|
if (ULevelViewportToolBarContext* Context = InMenu->FindContext<ULevelViewportToolBarContext>())
|
|
{
|
|
if (TSharedPtr<SLevelViewportToolBar> ToolBar = Context->LevelViewportToolBarWidget.Pin())
|
|
{
|
|
ToolBar->FillShowMenu(InMenu);
|
|
}
|
|
}
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
Viewport.Pin()->OnFloatingButtonClicked();
|
|
|
|
TSharedRef<FUICommandList> CommandList = Viewport.Pin()->GetCommandList().ToSharedRef();
|
|
|
|
// Get all menu extenders for this context menu from the level editor module
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>(TEXT("LevelEditor"));
|
|
TSharedPtr<FExtender> MenuExtender = LevelEditorModule.AssembleExtenders(CommandList, LevelEditorModule.GetAllLevelViewportShowMenuExtenders());
|
|
|
|
FToolMenuContext MenuContext;
|
|
{
|
|
MenuContext.AppendCommandList(CommandList);
|
|
MenuContext.AddExtender(MenuExtender);
|
|
|
|
{
|
|
ULevelViewportToolBarContext* ContextObject = NewObject<ULevelViewportToolBarContext>();
|
|
ContextObject->LevelViewportToolBarWidget = ConstCastSharedRef<SLevelViewportToolBar>(SharedThis(this));
|
|
MenuContext.AddObject(ContextObject);
|
|
}
|
|
|
|
{
|
|
ULevelViewportContext* const ContextObject = NewObject<ULevelViewportContext>();
|
|
ContextObject->LevelViewport = Viewport;
|
|
MenuContext.AddObject(ContextObject);
|
|
}
|
|
}
|
|
|
|
return UToolMenus::Get()->GenerateWidget(MenuName, MenuContext);
|
|
}
|
|
|
|
void SLevelViewportToolBar::FillShowMenu(UToolMenu* Menu) const
|
|
{
|
|
const FLevelViewportCommands& Actions = FLevelViewportCommands::Get();
|
|
{
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("UseDefaultShowFlags");
|
|
Section.AddMenuEntry(Actions.UseDefaultShowFlags);
|
|
}
|
|
|
|
FShowFlagMenuCommands::Get().BuildShowFlagsMenu(Menu);
|
|
|
|
FText ShowAllLabel = LOCTEXT("ShowAllLabel", "Show All");
|
|
FText HideAllLabel = LOCTEXT("HideAllLabel", "Hide All");
|
|
|
|
FLevelEditorViewportClient& ViewClient = Viewport.Pin()->GetLevelViewportClient();
|
|
const UWorld* World = ViewClient.GetWorld();
|
|
|
|
{
|
|
FToolMenuSection& Section = Menu->AddSection("LevelViewportEditorShow", LOCTEXT("EditorShowHeader", "Editor"));
|
|
|
|
Section.AddEntry(UE::LevelEditor::CreateShowVolumesSubmenu());
|
|
Section.AddEntry(UE::LevelEditor::CreateShowLayersSubmenu());
|
|
Section.AddEntry(UE::LevelEditor::CreateShowSpritesSubmenu());
|
|
Section.AddEntry(UE::LevelEditor::CreateShowFoliageSubmenu());
|
|
|
|
// Show 'HLODs' sub-menu is dynamically generated when the user enters 'show' menu
|
|
if (World->IsPartitionedWorld())
|
|
{
|
|
Section.AddEntry(UE::LevelEditor::CreateShowHLODsSubmenu());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
EVisibility SLevelViewportToolBar::GetViewModeOptionsVisibility() const
|
|
{
|
|
const FLevelEditorViewportClient& ViewClient = Viewport.Pin()->GetLevelViewportClient();
|
|
if (ViewClient.GetViewMode() == VMI_MeshUVDensityAccuracy || ViewClient.GetViewMode() == VMI_MaterialTextureScaleAccuracy || ViewClient.GetViewMode() == VMI_RequiredTextureResolution)
|
|
{
|
|
return EVisibility::SelfHitTestInvisible;
|
|
}
|
|
else
|
|
{
|
|
return EVisibility::Collapsed;
|
|
}
|
|
}
|
|
|
|
FText SLevelViewportToolBar::GetViewModeOptionsMenuLabel() const
|
|
{
|
|
Viewport.Pin()->OnFloatingButtonClicked();
|
|
const FLevelEditorViewportClient& ViewClient = Viewport.Pin()->GetLevelViewportClient();
|
|
return ::GetViewModeOptionsMenuLabel(ViewClient.GetViewMode());
|
|
}
|
|
|
|
|
|
TSharedRef<SWidget> SLevelViewportToolBar::GenerateViewModeOptionsMenu() const
|
|
{
|
|
Viewport.Pin()->OnFloatingButtonClicked();
|
|
FLevelEditorViewportClient& ViewClient = Viewport.Pin()->GetLevelViewportClient();
|
|
const UWorld* World = ViewClient.GetWorld();
|
|
return BuildViewModeOptionsMenu(Viewport.Pin()->GetCommandList(), ViewClient.GetViewMode(), World ? World->GetFeatureLevel() : GMaxRHIFeatureLevel, ViewClient.GetViewModeParamNameMap());
|
|
}
|
|
|
|
double SLevelViewportToolBar::OnGetHLODInEditorMaxDrawDistanceValue() const
|
|
{
|
|
IWorldPartitionEditorModule* WorldPartitionEditorModule = FModuleManager::GetModulePtr<IWorldPartitionEditorModule>("WorldPartitionEditor");
|
|
return WorldPartitionEditorModule ? WorldPartitionEditorModule->GetHLODInEditorMaxDrawDistance() : 0;
|
|
}
|
|
|
|
void SLevelViewportToolBar::OnHLODInEditorMaxDrawDistanceValueChanged(double NewValue) const
|
|
{
|
|
IWorldPartitionEditorModule* WorldPartitionEditorModule = FModuleManager::GetModulePtr<IWorldPartitionEditorModule>("WorldPartitionEditor");
|
|
if (WorldPartitionEditorModule)
|
|
{
|
|
WorldPartitionEditorModule->SetHLODInEditorMaxDrawDistance(NewValue);
|
|
GEditor->RedrawLevelEditingViewports(true);
|
|
}
|
|
}
|
|
|
|
TWeakObjectPtr<UWorld> SLevelViewportToolBar::GetWorld() const
|
|
{
|
|
if (Viewport.IsValid())
|
|
{
|
|
return Viewport.Pin()->GetWorld();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void SLevelViewportToolBar::FillViewMenu(UToolMenu* Menu)
|
|
{
|
|
if (!Menu)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ULevelViewportContext* const ContextObject = NewObject<ULevelViewportContext>();
|
|
ContextObject->LevelViewport = Viewport;
|
|
Menu->Context.AddObject(ContextObject);
|
|
|
|
UE::LevelEditor::PopulateViewModesMenu(Menu);
|
|
}
|
|
|
|
float SLevelViewportToolBar::GetTransformToolbarWidth() const
|
|
{
|
|
if (TransformToolbar)
|
|
{
|
|
const float TransformToolbarWidth = TransformToolbar->GetDesiredSize().X;
|
|
if (TransformToolbar_CachedMaxWidth == 0.0f)
|
|
{
|
|
TransformToolbar_CachedMaxWidth = TransformToolbarWidth;
|
|
}
|
|
|
|
const float ToolbarWidthMinusPreviousTransformToolbar = GetDesiredSize().X - TransformToolbar_CachedMaxWidth;
|
|
const float ToolbarWidthEstimate = ToolbarWidthMinusPreviousTransformToolbar + TransformToolbarWidth;
|
|
|
|
const float ViewportToolBarWidth = static_cast<float>(GetCachedGeometry().GetLocalSize().X);
|
|
const float OverflowWidth = ToolbarWidthEstimate - ViewportToolBarWidth;
|
|
if (OverflowWidth > 0.0f)
|
|
{
|
|
// There isn't enough space in the viewport to show the toolbar!
|
|
// Try and shrink the transform toolbar (which has an overflow area) to make things fit
|
|
TransformToolbar_CachedMaxWidth = FMath::Max(FMath::Min(4.0f, TransformToolbarWidth), TransformToolbarWidth - OverflowWidth);
|
|
}
|
|
else
|
|
{
|
|
TransformToolbar_CachedMaxWidth = TransformToolbarWidth;
|
|
}
|
|
|
|
return TransformToolbar_CachedMaxWidth;
|
|
}
|
|
|
|
return 0.0f;
|
|
}
|
|
|
|
FReply SLevelViewportToolBar::OnRealtimeWarningClicked()
|
|
{
|
|
FLevelEditorViewportClient& ViewportClient = Viewport.Pin()->GetLevelViewportClient();
|
|
ViewportClient.SetRealtime(true);
|
|
|
|
return FReply::Handled();
|
|
}
|
|
|
|
EVisibility SLevelViewportToolBar::GetRealtimeWarningVisibility() const
|
|
{
|
|
const FEditorViewportClient& ViewportClient = Viewport.Pin()->GetLevelViewportClient();
|
|
const bool bWarn = UE::UnrealEd::ShouldShowViewportRealtimeWarning(ViewportClient);
|
|
return bWarn ? EVisibility::Visible : EVisibility::Collapsed;
|
|
}
|
|
|
|
FText SLevelViewportToolBar::GetScalabilityWarningLabel() const
|
|
{
|
|
const int32 QualityLevel = Scalability::GetQualityLevels().GetMinQualityLevel();
|
|
if (QualityLevel >= 0)
|
|
{
|
|
return FText::Format(LOCTEXT("ScalabilityWarning", "Scalability: {0}"), Scalability::GetScalabilityNameFromQualityLevel(QualityLevel));
|
|
}
|
|
|
|
return FText::GetEmpty();
|
|
}
|
|
|
|
EVisibility SLevelViewportToolBar::GetScalabilityWarningVisibility() const
|
|
{
|
|
return UE::UnrealEd::IsScalabilityWarningVisible() ? EVisibility::Visible : EVisibility::Collapsed;
|
|
}
|
|
|
|
TSharedRef<SWidget> SLevelViewportToolBar::GetScalabilityWarningMenuContent() const
|
|
{
|
|
return
|
|
SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("Menu.Background"))
|
|
[
|
|
SNew(SScalabilitySettings)
|
|
];
|
|
}
|
|
|
|
FLevelEditorViewportClient* ULevelViewportToolBarContext::GetLevelViewportClient() const
|
|
{
|
|
if (TSharedPtr<SLevelViewportToolBar> Toolbar = LevelViewportToolBarWidget.Pin())
|
|
{
|
|
return Toolbar->GetLevelViewportClient();
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|