You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
World Browser: LOD maps generator now correctly handles maps under SC ProxyMesh utilitiy now produces assets in a separate packages or in one single package ProxyMesh and MergeActors utilities now use more consistent names for a produced assets (demolet naming conventions) [CL 2104291 by Dmitriy Dyomin in Main branch]
2930 lines
123 KiB
C++
2930 lines
123 KiB
C++
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
#include "LevelEditor.h"
|
|
#include "Matinee/MatineeActor.h"
|
|
#include "Engine/LevelScriptBlueprint.h"
|
|
#include "LightingBuildOptions.h"
|
|
#include "EditorSupportDelegates.h"
|
|
#include "SLevelEditor.h"
|
|
#include "LevelEditorActions.h"
|
|
#include "SLevelViewport.h"
|
|
#include "EditorBuildUtils.h"
|
|
#include "Toolkits/AssetEditorManager.h"
|
|
#include "ScopedTransaction.h"
|
|
#include "Editor/Kismet/Public/BlueprintEditorModule.h"
|
|
#include "Editor/PropertyEditor/Public/PropertyEditorModule.h"
|
|
#include "Editor/ContentBrowser/Public/ContentBrowserModule.h"
|
|
#include "Editor/MainFrame/Public/MainFrame.h"
|
|
#include "Editor/SceneOutliner/Public/SceneOutlinerModule.h"
|
|
#include "Editor/UnrealEd/Private/GeomFitUtils.h"
|
|
#include "Editor/UnrealEd/Public/BSPOps.h"
|
|
#include "Editor/LevelEditor/Public/DlgDeltaTransform.h"
|
|
#include "Runtime/Engine/Classes/PhysicsEngine/BodySetup.h"
|
|
#include "Editor/NewLevelDialog/Public/NewLevelDialogModule.h"
|
|
#include "DelegateFilter.h"
|
|
#include "BlueprintUtilities.h"
|
|
#include "LightingTools.h"
|
|
#include "MRUFavoritesList.h"
|
|
#include "Editor/SceneOutliner/Private/SSocketChooser.h"
|
|
#include "Runtime/AssetRegistry/Public/AssetRegistryModule.h"
|
|
#include "SnappingUtils.h"
|
|
#include "Layers/ILayers.h"
|
|
#include "IPlacementModeModule.h"
|
|
#include "AssetSelection.h"
|
|
#include "IDocumentation.h"
|
|
#include "SourceCodeNavigation.h"
|
|
#include "Dialogs/DlgPickAssetPath.h"
|
|
#include "AssetToolsModule.h"
|
|
#include "BlueprintEditorUtils.h"
|
|
#include "KismetEditorUtilities.h"
|
|
#include "DesktopPlatformModule.h"
|
|
#include "EngineAnalytics.h"
|
|
#include "AnalyticsEventAttribute.h"
|
|
#include "IAnalyticsProvider.h"
|
|
#include "ReferenceViewer.h"
|
|
|
|
#include "EditorActorFolders.h"
|
|
#include "ActorPickerMode.h"
|
|
|
|
DEFINE_LOG_CATEGORY_STATIC(LevelEditorActions, Log, All);
|
|
|
|
#define LOCTEXT_NAMESPACE "LevelEditorActions"
|
|
|
|
namespace LevelEditorActionsHelpers
|
|
{
|
|
/**
|
|
* If the passed in class is generated by a Blueprint, it will open that Blueprint, otherwise it will help the user create a Blueprint based on that class
|
|
*
|
|
* @param InWindowTitle The window title if the Blueprint needs to be created
|
|
* @param InBlueprintClass The class to create a Blueprint based on or to open if it is a Blueprint
|
|
* @param InLevelEditor When opening the Blueprint, this level editor is the parent window
|
|
* @param InNewBPName If we have to create a new BP, this is the suggested name
|
|
*/
|
|
UBlueprint* OpenOrCreateBlueprintFromClass(FText InWindowTitle, UClass* InBlueprintClass, TWeakPtr< SLevelEditor > InLevelEditor, FString InNewBPName = TEXT(""))
|
|
{
|
|
UBlueprint* Blueprint = NULL;
|
|
|
|
// If the current set class is not a Blueprint, we need to allow the user to create one to edit
|
|
if(!InBlueprintClass->ClassGeneratedBy)
|
|
{
|
|
Blueprint = FKismetEditorUtilities::CreateBlueprintFromClass(InWindowTitle, InBlueprintClass, InNewBPName);
|
|
}
|
|
else
|
|
{
|
|
Blueprint = Cast<UBlueprint>(InBlueprintClass->ClassGeneratedBy);
|
|
}
|
|
|
|
if(Blueprint)
|
|
{
|
|
// @todo Re-enable once world centric works
|
|
const bool bOpenWorldCentric = false;
|
|
FAssetEditorManager::Get().OpenEditorForAsset(
|
|
Blueprint,
|
|
bOpenWorldCentric ? EToolkitMode::WorldCentric : EToolkitMode::Standalone,
|
|
InLevelEditor.Pin() );
|
|
}
|
|
|
|
return Blueprint;
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::DefaultCanExecuteAction()
|
|
{
|
|
return FSlateApplication::Get().IsNormalExecution();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::BrowseDocumentation()
|
|
{
|
|
IDocumentation::Get()->OpenHome();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::BrowseAPIReference()
|
|
{
|
|
IDocumentation::Get()->OpenAPIHome();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::BrowseViewportControls()
|
|
{
|
|
FString URL;
|
|
if (FUnrealEdMisc::Get().GetURL(TEXT("ViewportControlsURL"), URL))
|
|
{
|
|
FPlatformProcess::LaunchURL(*URL, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::NewLevel()
|
|
{
|
|
if (GUnrealEd->WarnIfLightingBuildIsCurrentlyRunning())
|
|
{
|
|
return;
|
|
}
|
|
|
|
IMainFrameModule& MainFrameModule = FModuleManager::GetModuleChecked<IMainFrameModule>("MainFrame");
|
|
|
|
FString TemplateMapPackageName;
|
|
FNewLevelDialogModule& NewLevelDialogModule = FModuleManager::LoadModuleChecked<FNewLevelDialogModule>("NewLevelDialog");
|
|
if (NewLevelDialogModule.CreateAndShowNewLevelDialog(MainFrameModule.GetParentWindow(), TemplateMapPackageName))
|
|
{
|
|
// The new map screen will return a blank TemplateName if the user has selected to begin a new blank map
|
|
if (TemplateMapPackageName.IsEmpty())
|
|
{
|
|
GEditor->CreateNewMapForEditing();
|
|
}
|
|
else
|
|
{
|
|
// New map screen returned a non-empty TemplateName, so the user has selected to begin from a template map
|
|
bool TemplateFound = false;
|
|
|
|
// Search all template map folders for a match with TemplateName
|
|
const bool bIncludeReadOnlyRoots = true;
|
|
if ( FPackageName::IsValidLongPackageName(TemplateMapPackageName, bIncludeReadOnlyRoots) )
|
|
{
|
|
const FString MapPackageFilename = FPackageName::LongPackageNameToFilename(TemplateMapPackageName, FPackageName::GetMapPackageExtension());
|
|
if ( FPaths::FileExists(MapPackageFilename) )
|
|
{
|
|
// File found because the size check came back non-zero
|
|
TemplateFound = true;
|
|
|
|
// If there are any unsaved changes to the current level, see if the user wants to save those first.
|
|
bool bPromptUserToSave = true;
|
|
bool bSaveMapPackages = true;
|
|
bool bSaveContentPackages = false;
|
|
if ( FEditorFileUtils::SaveDirtyPackages(bPromptUserToSave, bSaveMapPackages, bSaveContentPackages) )
|
|
{
|
|
// Load the template map file - passes LoadAsTemplate==true making the
|
|
// level load into an untitled package that won't save over the template
|
|
FEditorFileUtils::LoadMap(*MapPackageFilename, /*bLoadAsTemplate=*/true);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!TemplateFound)
|
|
{
|
|
UE_LOG( LevelEditorActions, Warning, TEXT("Couldn't find template map package %s"), *TemplateMapPackageName);
|
|
GEditor->CreateNewMapForEditing();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::NewLevel_CanExecute()
|
|
{
|
|
return FSlateApplication::Get().IsNormalExecution() && !GEditorModeTools().IsTracking();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenLevel()
|
|
{
|
|
FEditorFileUtils::LoadMap();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OpenLevel_CanExecute()
|
|
{
|
|
return FSlateApplication::Get().IsNormalExecution() && !GEditorModeTools().IsTracking();
|
|
}
|
|
|
|
FAssetPickerConfig FLevelEditorActionCallbacks::CreateLevelAssetPickerConfig()
|
|
{
|
|
FAssetPickerConfig AssetPickerConfig;
|
|
AssetPickerConfig.Filter.ClassNames.Add(UWorld::StaticClass()->GetFName());
|
|
AssetPickerConfig.bAllowDragging = false;
|
|
AssetPickerConfig.SelectionMode = ESelectionMode::Single;
|
|
AssetPickerConfig.InitialAssetViewType = EAssetViewType::List;
|
|
UWorld* CurrentWorld = GEditor->GetEditorWorldContext().World();
|
|
if (CurrentWorld)
|
|
{
|
|
AssetPickerConfig.InitialAssetSelection = FAssetData(CurrentWorld);
|
|
}
|
|
|
|
return AssetPickerConfig;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenLevelPickingDialog()
|
|
{
|
|
const FVector2D AssetPickerSize(600.0f, 586.0f);
|
|
|
|
FMenuBuilder MenuBuilder(false, NULL);
|
|
|
|
// Create the contents of the popup
|
|
FContentBrowserModule& ContentBrowserModule = FModuleManager::Get().LoadModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser"));
|
|
FAssetPickerConfig AssetPickerConfig = CreateLevelAssetPickerConfig();
|
|
AssetPickerConfig.OnAssetsActivated = FOnAssetsActivated::CreateStatic(&FLevelEditorActionCallbacks::OpenLevelFromAssetPicker);
|
|
TSharedRef<SWidget> ActualWidget =
|
|
SNew(SBox)
|
|
.HeightOverride(AssetPickerSize.X)
|
|
.WidthOverride(AssetPickerSize.Y)
|
|
[
|
|
ContentBrowserModule.Get().CreateAssetPicker(AssetPickerConfig)
|
|
];
|
|
|
|
// Wrap the picker widget in a multibox-style menu body
|
|
MenuBuilder.BeginSection("AssetPickerOpenLevel", NSLOCTEXT("OpenLevelDialog", "WindowTitle", "Open Level"));
|
|
{
|
|
const bool bNoIndent = true;
|
|
MenuBuilder.AddWidget(ActualWidget, FText::GetEmpty(), bNoIndent);
|
|
}
|
|
MenuBuilder.EndSection();
|
|
|
|
TSharedRef<SWidget> WindowContents = MenuBuilder.MakeWidget();
|
|
|
|
// Determine where the pop-up should open
|
|
TSharedPtr<SWindow> ParentWindow = FSlateApplication::Get().GetActiveTopLevelWindow();
|
|
FVector2D WindowPosition = FSlateApplication::Get().GetCursorPos();
|
|
if (ParentWindow.IsValid())
|
|
{
|
|
FSlateRect ParentMonitorRect = ParentWindow->GetFullScreenInfo();
|
|
const FVector2D MonitorCenter((ParentMonitorRect.Right + ParentMonitorRect.Left) * 0.5f, (ParentMonitorRect.Top + ParentMonitorRect.Bottom) * 0.5f);
|
|
WindowPosition = MonitorCenter - AssetPickerSize * 0.5f;
|
|
|
|
// Open the pop-up
|
|
FPopupTransitionEffect TransitionEffect(FPopupTransitionEffect::None);
|
|
TSharedRef<SWindow> PopupWindow = FSlateApplication::Get().PushMenu(ParentWindow.ToSharedRef(), WindowContents, WindowPosition, TransitionEffect);
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenLevelFromAssetPicker(const TArray<class FAssetData>& SelectedAssets, EAssetTypeActivationMethod::Type ActivationType)
|
|
{
|
|
const bool bCorrectActivationMethod = (ActivationType == EAssetTypeActivationMethod::DoubleClicked || ActivationType == EAssetTypeActivationMethod::Opened);
|
|
if (SelectedAssets.Num() > 0 && bCorrectActivationMethod)
|
|
{
|
|
const FAssetData& AssetData = SelectedAssets[0];
|
|
if (AssetData.AssetClass == UWorld::StaticClass()->GetFName())
|
|
{
|
|
// Close the menu that we were picking from
|
|
FSlateApplication::Get().DismissAllMenus();
|
|
|
|
// If there are any unsaved changes to the current level, see if the user wants to save those first.
|
|
bool bPromptUserToSave = true;
|
|
bool bSaveMapPackages = true;
|
|
bool bSaveContentPackages = true;
|
|
if (FEditorFileUtils::SaveDirtyPackages(bPromptUserToSave, bSaveMapPackages, bSaveContentPackages))
|
|
{
|
|
const FString FileToOpen = FPackageName::LongPackageNameToFilename(AssetData.PackageName.ToString(), FPackageName::GetMapPackageExtension());
|
|
const bool bLoadAsTemplate = false;
|
|
const bool bShowProgress = true;
|
|
FEditorFileUtils::LoadMap(FileToOpen, bLoadAsTemplate, bShowProgress);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::DeltaTransform()
|
|
{
|
|
if (GUnrealEd->WarnIfLightingBuildIsCurrentlyRunning())
|
|
{
|
|
return;
|
|
}
|
|
|
|
FDlgDeltaTransform DeltaDialog;
|
|
|
|
const FDlgDeltaTransform::EResult MoveDialogResult = DeltaDialog.ShowModal();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenRecentFile( int32 RecentFileIndex )
|
|
{
|
|
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>( "MainFrame" );
|
|
FMainMRUFavoritesList* RecentsAndFavorites = MainFrameModule.GetMRUFavoritesList();
|
|
|
|
// Save the name of the file we are attempting to load as VerifyFile/AskSaveChanges might rearrange the MRU list on us
|
|
const FString NewFilename = RecentsAndFavorites->GetMRUItem( RecentFileIndex );
|
|
|
|
if( RecentsAndFavorites->VerifyMRUFile( RecentFileIndex ) )
|
|
{
|
|
// Prompt the user to save any outstanding changes.
|
|
if( FEditorFileUtils::SaveDirtyPackages(true, true, false) )
|
|
{
|
|
// Load the requested level.
|
|
FEditorFileUtils::LoadMap( NewFilename );
|
|
}
|
|
else
|
|
{
|
|
// something went wrong or the user pressed cancel. Return to the editor so the user doesn't lose their changes
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::OpenFavoriteFile( int32 FavoriteFileIndex )
|
|
{
|
|
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>( "MainFrame" );
|
|
FMainMRUFavoritesList* MRUFavoritesList = MainFrameModule.GetMRUFavoritesList();
|
|
|
|
const FString FileName = MRUFavoritesList->GetFavoritesItem( FavoriteFileIndex );
|
|
|
|
if( MRUFavoritesList->VerifyFavoritesFile( FavoriteFileIndex ) )
|
|
{
|
|
// Prompt the user to save any outstanding changes
|
|
if( FEditorFileUtils::SaveDirtyPackages(true, true, false) )
|
|
{
|
|
// Load the requested level.
|
|
FEditorFileUtils::LoadMap( FileName );
|
|
}
|
|
else
|
|
{
|
|
// something went wrong or the user pressed cancel. Return to the editor so the user doesn't lose their changes
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::ToggleFavorite()
|
|
{
|
|
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>( "MainFrame" );
|
|
FMainMRUFavoritesList* MRUFavoritesList = MainFrameModule.GetMRUFavoritesList();
|
|
check( MRUFavoritesList );
|
|
|
|
FString MapFileName;
|
|
const bool bMapFileExists = FPackageName::DoesPackageExist(GetWorld()->GetOutermost()->GetName(), NULL, &MapFileName);
|
|
|
|
// If the user clicked the toggle favorites button, the map file should exist, but double check to be safe.
|
|
if ( bMapFileExists )
|
|
{
|
|
// If the map was already favorited, remove it from the favorites
|
|
if ( MRUFavoritesList->ContainsFavoritesItem( MapFileName ) )
|
|
{
|
|
MRUFavoritesList->RemoveFavoritesItem( MapFileName );
|
|
}
|
|
// If the map was not already favorited, add it to the favorites
|
|
else
|
|
{
|
|
MRUFavoritesList->AddFavoritesItem( MapFileName );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::RemoveFavorite( int32 FavoriteFileIndex )
|
|
{
|
|
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>( "MainFrame" );
|
|
FMainMRUFavoritesList* MRUFavoritesList = MainFrameModule.GetMRUFavoritesList();
|
|
|
|
const FString FileName = MRUFavoritesList->GetFavoritesItem( FavoriteFileIndex );
|
|
|
|
if( MRUFavoritesList->VerifyFavoritesFile( FavoriteFileIndex ) )
|
|
{
|
|
if ( MRUFavoritesList->ContainsFavoritesItem( FileName ) )
|
|
{
|
|
MRUFavoritesList->RemoveFavoritesItem( FileName );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::ToggleFavorite_CanExecute()
|
|
{
|
|
FString FileName;
|
|
const bool bMapFileExists = FPackageName::DoesPackageExist(GetWorld()->GetOutermost()->GetName(), NULL, &FileName);
|
|
|
|
// Disable the favorites button if the map isn't associated to a file yet (new map, never before saved, etc.)
|
|
return bMapFileExists;
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::ToggleFavorite_IsChecked()
|
|
{
|
|
bool bIsChecked = false;
|
|
|
|
FString FileName;
|
|
const bool bMapFileExists = FPackageName::DoesPackageExist(GetWorld()->GetOutermost()->GetName(), NULL, &FileName);
|
|
|
|
// If the map exists, determine its state based on whether the map is already favorited or not
|
|
if ( bMapFileExists )
|
|
{
|
|
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>( "MainFrame" );
|
|
|
|
const FString CleanedName = FPaths::ConvertRelativePathToFull(FileName);
|
|
const bool bCleanAlreadyFavorited = MainFrameModule.GetMRUFavoritesList()->ContainsFavoritesItem( CleanedName );
|
|
const bool bAlreadyFavorited = bCleanAlreadyFavorited || MainFrameModule.GetMRUFavoritesList()->ContainsFavoritesItem( FileName );
|
|
bIsChecked = bAlreadyFavorited;
|
|
}
|
|
|
|
return bIsChecked;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::Save()
|
|
{
|
|
FEditorFileUtils::SaveCurrentLevel();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SaveAs()
|
|
{
|
|
FEditorFileUtils::SaveAs( GetWorld()->PersistentLevel );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SaveAllLevels()
|
|
{
|
|
const bool bPromptUserToSave = false;
|
|
const bool bSaveMapPackages = true;
|
|
const bool bSaveContentPackages = false;
|
|
const bool bFastSave = false;
|
|
FEditorFileUtils::SaveDirtyPackages( bPromptUserToSave, bSaveMapPackages, bSaveContentPackages, bFastSave );
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::Import_Clicked()
|
|
{
|
|
FEditorFileUtils::Import();
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::ExportAll_Clicked()
|
|
{
|
|
const bool bExportSelectedActorsOnly = false;
|
|
FEditorFileUtils::Export( bExportSelectedActorsOnly );
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::ExportSelected_Clicked()
|
|
{
|
|
const bool bExportSelectedActorsOnly = true;
|
|
FEditorFileUtils::Export( bExportSelectedActorsOnly );
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::ExportSelected_CanExecute()
|
|
{
|
|
// Only enable the option if at least one thing is selected and its not a worldsettings
|
|
return GEditor->GetSelectedActors()->Num() > 0 && !GEditor->IsWorldSettingsSelected();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AttachToActor(AActor* ParentActorPtr)
|
|
{
|
|
USceneComponent* ComponentWithSockets = NULL;
|
|
|
|
//@TODO: Should create a menu for each component that contains sockets, or have some form of disambiguation within the menu (like a fully qualified path)
|
|
// Instead, we currently only display the sockets on the root component
|
|
if (ParentActorPtr != NULL)
|
|
{
|
|
if (USceneComponent* RootComponent = Cast<USceneComponent>(ParentActorPtr->GetRootComponent()))
|
|
{
|
|
if (RootComponent->HasAnySockets())
|
|
{
|
|
ComponentWithSockets = RootComponent;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Show socket chooser if we have sockets to select
|
|
if (ComponentWithSockets != NULL)
|
|
{
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>( "LevelEditor");
|
|
TSharedPtr< ILevelEditor > LevelEditor = LevelEditorModule.GetFirstLevelEditor();
|
|
|
|
// Create as context menu
|
|
FSlateApplication::Get().PushMenu(
|
|
LevelEditor.ToSharedRef(),
|
|
SNew(SSocketChooserPopup)
|
|
.SceneComponent( ComponentWithSockets )
|
|
.OnSocketChosen_Static( &FLevelEditorActionCallbacks::AttachToSocketSelection, ParentActorPtr ),
|
|
FSlateApplication::Get().GetCursorPos(),
|
|
FPopupTransitionEffect( FPopupTransitionEffect::ContextMenu )
|
|
);
|
|
}
|
|
else
|
|
{
|
|
AttachToSocketSelection( NAME_None, ParentActorPtr );
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AttachToSocketSelection(const FName SocketName, AActor* ParentActorPtr)
|
|
{
|
|
FSlateApplication::Get().DismissAllMenus();
|
|
|
|
if(ParentActorPtr != NULL)
|
|
{
|
|
// Attach each child
|
|
FScopedTransaction Transaction(LOCTEXT("AttachActors", "Attach actors"));
|
|
bool bAttached = false;
|
|
|
|
for ( FSelectionIterator It( GEditor->GetSelectedActorIterator() ) ; It ; ++It )
|
|
{
|
|
AActor* Actor = Cast<AActor>( *It );
|
|
if (GEditor->CanParentActors(ParentActorPtr, Actor))
|
|
{
|
|
bAttached = true;
|
|
GEditor->ParentActors(ParentActorPtr, Actor, SocketName);
|
|
}
|
|
}
|
|
|
|
if (!bAttached)
|
|
{
|
|
Transaction.Cancel();
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetMaterialQualityLevel( EMaterialQualityLevel::Type NewQualityLevel )
|
|
{
|
|
GUnrealEd->AccessEditorUserSettings().MaterialQualityLevel = NewQualityLevel;
|
|
GUnrealEd->AccessEditorUserSettings().PostEditChange();
|
|
|
|
//Ensure the material quality cvar is also set.
|
|
static IConsoleVariable* MaterialQualityLevelVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.MaterialQualityLevel"));
|
|
MaterialQualityLevelVar->Set(NewQualityLevel);
|
|
|
|
GUnrealEd->RedrawAllViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsMaterialQualityLevelChecked( EMaterialQualityLevel::Type TestQualityLevel )
|
|
{
|
|
static const auto MaterialQualityLevelVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MaterialQualityLevel"));
|
|
EMaterialQualityLevel::Type MaterialQualityLevel = (EMaterialQualityLevel::Type)FMath::Clamp(MaterialQualityLevelVar->GetValueOnGameThread(), 0, 1);
|
|
return TestQualityLevel == MaterialQualityLevel;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetFeatureLevelPreview(ERHIFeatureLevel::Type InPreviewFeatureLevel)
|
|
{
|
|
// try iterating over all worlds here
|
|
for (TObjectIterator<UWorld> It; It; ++It)
|
|
{
|
|
UWorld* World = *It;
|
|
World->ChangeFeatureLevel(InPreviewFeatureLevel);
|
|
}
|
|
|
|
UWorld::ForceFeatureLevelUpdate(InPreviewFeatureLevel);
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsFeatureLevelPreviewChecked(ERHIFeatureLevel::Type InPreviewFeatureLevel)
|
|
{
|
|
// For now, we just stay stuck on the system max feature level
|
|
return InPreviewFeatureLevel == GRHIFeatureLevel;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ConfigureLightingBuildOptions( const FLightingBuildOptions& Options )
|
|
{
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildSelected"), Options.bOnlyBuildSelected, GEditorUserSettingsIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildCurrentLevel"), Options.bOnlyBuildCurrentLevel, GEditorUserSettingsIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildSelectedLevels"),Options.bOnlyBuildSelectedLevels, GEditorUserSettingsIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildVisibility"), Options.bOnlyBuildVisibility, GEditorUserSettingsIni );
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::Build_Execute()
|
|
{
|
|
// Reset build options
|
|
ConfigureLightingBuildOptions( FLightingBuildOptions() );
|
|
|
|
// Build everything!
|
|
FEditorBuildUtils::EditorBuild( GetWorld(), EBuildOptions::BuildAll );
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::BuildAndSubmitToSourceControl_Execute()
|
|
{
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>( TEXT("LevelEditor") );
|
|
LevelEditorModule.SummonBuildAndSubmit();
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::BuildLightingOnly_Execute()
|
|
{
|
|
// Reset build options
|
|
ConfigureLightingBuildOptions( FLightingBuildOptions() );
|
|
|
|
// Build lighting!
|
|
const bool bAllowLightingDialog = false;
|
|
FEditorBuildUtils::EditorBuild( GetWorld(), EBuildOptions::BuildLighting, bAllowLightingDialog );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::BuildLighting_CanExecute()
|
|
{
|
|
static const auto AllowStaticLightingVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.AllowStaticLighting"));
|
|
const bool bAllowStaticLighting = (!AllowStaticLightingVar || AllowStaticLightingVar->GetValueOnGameThread() != 0);
|
|
return bAllowStaticLighting;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::BuildReflectionCapturesOnly_Execute()
|
|
{
|
|
GEditor->UpdateReflectionCaptures();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::BuildLightingOnly_VisibilityOnly_Execute()
|
|
{
|
|
// Configure build options
|
|
FLightingBuildOptions LightingBuildOptions;
|
|
LightingBuildOptions.bOnlyBuildVisibility = true;
|
|
ConfigureLightingBuildOptions( LightingBuildOptions );
|
|
|
|
// Build lighting!
|
|
const bool bAllowLightingDialog = false;
|
|
FEditorBuildUtils::EditorBuild( GetWorld(), EBuildOptions::BuildLighting, bAllowLightingDialog );
|
|
|
|
// Reset build options
|
|
ConfigureLightingBuildOptions( FLightingBuildOptions() );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::LightingBuildOptions_UseErrorColoring_IsChecked()
|
|
{
|
|
bool bUseErrorColoring = false;
|
|
GConfig->GetBool(TEXT("LightingBuildOptions"), TEXT("UseErrorColoring"), bUseErrorColoring, GEditorUserSettingsIni);
|
|
return bUseErrorColoring;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::LightingBuildOptions_UseErrorColoring_Toggled()
|
|
{
|
|
bool bUseErrorColoring = false;
|
|
GConfig->GetBool( TEXT("LightingBuildOptions"), TEXT("UseErrorColoring"), bUseErrorColoring, GEditorUserSettingsIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("UseErrorColoring"), !bUseErrorColoring, GEditorUserSettingsIni );
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::LightingBuildOptions_ShowLightingStats_IsChecked()
|
|
{
|
|
bool bShowLightingBuildInfo = false;
|
|
GConfig->GetBool(TEXT("LightingBuildOptions"), TEXT("ShowLightingBuildInfo"), bShowLightingBuildInfo, GEditorUserSettingsIni);
|
|
return bShowLightingBuildInfo;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::LightingBuildOptions_ShowLightingStats_Toggled()
|
|
{
|
|
bool bShowLightingBuildInfo = false;
|
|
GConfig->GetBool( TEXT("LightingBuildOptions"), TEXT("ShowLightingBuildInfo"), bShowLightingBuildInfo, GEditorUserSettingsIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("ShowLightingBuildInfo"), !bShowLightingBuildInfo, GEditorUserSettingsIni );
|
|
}
|
|
|
|
|
|
|
|
void FLevelEditorActionCallbacks::BuildGeometryOnly_Execute()
|
|
{
|
|
// Build geometry!
|
|
FEditorBuildUtils::EditorBuild( GetWorld(), EBuildOptions::BuildVisibleGeometry );
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::BuildGeometryOnly_OnlyCurrentLevel_Execute()
|
|
{
|
|
// Build geometry (current level)!
|
|
FEditorBuildUtils::EditorBuild( GetWorld(), EBuildOptions::BuildGeometry );
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::BuildPathsOnly_Execute()
|
|
{
|
|
// Build paths!
|
|
FEditorBuildUtils::EditorBuild( GetWorld(), EBuildOptions::BuildAIPaths );
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::IsLightingQualityChecked( ELightingBuildQuality TestQuality )
|
|
{
|
|
int32 CurrentQualityLevel;
|
|
GConfig->GetInt(TEXT("LightingBuildOptions"), TEXT("QualityLevel"), CurrentQualityLevel, GEditorUserSettingsIni);
|
|
return TestQuality == CurrentQualityLevel;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingQuality( ELightingBuildQuality NewQuality )
|
|
{
|
|
GConfig->SetInt(TEXT("LightingBuildOptions"), TEXT("QualityLevel"), (int32)NewQuality, GEditorUserSettingsIni);
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingToolShowBounds()
|
|
{
|
|
FLightingToolsSettings& Settings = FLightingToolsSettings::Get();
|
|
Settings.bShowLightingBounds = !Settings.bShowLightingBounds;
|
|
Settings.ApplyToggle();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsLightingToolShowBoundsChecked()
|
|
{
|
|
return FLightingToolsSettings::Get().bShowLightingBounds;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingToolShowTraces()
|
|
{
|
|
FLightingToolsSettings& Settings = FLightingToolsSettings::Get();
|
|
Settings.bShowShadowTraces = !Settings.bShowShadowTraces;
|
|
Settings.ApplyToggle();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsLightingToolShowTracesChecked()
|
|
{
|
|
return FLightingToolsSettings::Get().bShowShadowTraces;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingToolShowDirectOnly()
|
|
{
|
|
FLightingToolsSettings& Settings = FLightingToolsSettings::Get();
|
|
Settings.bShowDirectOnly = !Settings.bShowDirectOnly;
|
|
Settings.ApplyToggle();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsLightingToolShowDirectOnlyChecked()
|
|
{
|
|
return FLightingToolsSettings::Get().bShowDirectOnly;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingToolShowIndirectOnly()
|
|
{
|
|
FLightingToolsSettings& Settings = FLightingToolsSettings::Get();
|
|
Settings.bShowIndirectOnly = !Settings.bShowIndirectOnly;
|
|
Settings.ApplyToggle();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsLightingToolShowIndirectOnlyChecked()
|
|
{
|
|
return FLightingToolsSettings::Get().bShowIndirectOnly;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingToolShowIndirectSamples()
|
|
{
|
|
FLightingToolsSettings& Settings = FLightingToolsSettings::Get();
|
|
Settings.bShowIndirectSamples = !Settings.bShowIndirectSamples;
|
|
Settings.ApplyToggle();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsLightingToolShowIndirectSamplesChecked()
|
|
{
|
|
return FLightingToolsSettings::Get().bShowIndirectSamples;
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingDensityIdeal()
|
|
{
|
|
return ( GEngine->IdealLightMapDensity );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingDensityIdeal( float Value )
|
|
{
|
|
GEngine->IdealLightMapDensity = Value;
|
|
|
|
// We need to make sure that Maximum is always slightly larger than ideal...
|
|
if (GEngine->IdealLightMapDensity >= GEngine->MaxLightMapDensity - 0.01f)
|
|
{
|
|
SetLightingDensityMaximum( GEngine->IdealLightMapDensity + 0.01f );
|
|
}
|
|
|
|
FEditorSupportDelegates::RedrawAllViewports.Broadcast();
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingDensityMaximum()
|
|
{
|
|
return ( GEngine->MaxLightMapDensity );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingDensityMaximum( float Value )
|
|
{
|
|
GEngine->MaxLightMapDensity = Value;
|
|
|
|
// We need to make sure that Maximum is always slightly larger than ideal...
|
|
if (GEngine->MaxLightMapDensity <= GEngine->IdealLightMapDensity + 0.01f)
|
|
{
|
|
GEngine->MaxLightMapDensity = GEngine->IdealLightMapDensity + 0.01f;
|
|
}
|
|
|
|
FEditorSupportDelegates::RedrawAllViewports.Broadcast();
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingDensityColorScale()
|
|
{
|
|
return ( GEngine->RenderLightMapDensityColorScale );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingDensityColorScale( float Value )
|
|
{
|
|
GEngine->RenderLightMapDensityColorScale = Value;
|
|
|
|
FEditorSupportDelegates::RedrawAllViewports.Broadcast();
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingDensityGrayscaleScale()
|
|
{
|
|
return ( GEngine->RenderLightMapDensityGrayscaleScale );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingDensityGrayscaleScale( float Value )
|
|
{
|
|
GEngine->RenderLightMapDensityGrayscaleScale = Value;
|
|
|
|
FEditorSupportDelegates::RedrawAllViewports.Broadcast();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingDensityRenderGrayscale()
|
|
{
|
|
GEngine->bRenderLightMapDensityGrayscale = !GEngine->bRenderLightMapDensityGrayscale;
|
|
GEngine->SaveConfig();
|
|
FEditorSupportDelegates::RedrawAllViewports.Broadcast();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsLightingDensityRenderGrayscaleChecked()
|
|
{
|
|
return GEngine->bRenderLightMapDensityGrayscale;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionStaticMeshes( ESlateCheckBoxState::Type NewCheckedState )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.bStaticMeshes = ( NewCheckedState == ESlateCheckBoxState::Checked );
|
|
}
|
|
|
|
ESlateCheckBoxState::Type FLevelEditorActionCallbacks::IsLightingResolutionStaticMeshesChecked()
|
|
{
|
|
return ( FLightmapResRatioAdjustSettings::Get().bStaticMeshes ? ESlateCheckBoxState::Checked : ESlateCheckBoxState::Unchecked );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionBSPSurfaces( ESlateCheckBoxState::Type NewCheckedState )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.bBSPSurfaces = ( NewCheckedState == ESlateCheckBoxState::Checked );
|
|
}
|
|
|
|
ESlateCheckBoxState::Type FLevelEditorActionCallbacks::IsLightingResolutionBSPSurfacesChecked()
|
|
{
|
|
return ( FLightmapResRatioAdjustSettings::Get().bBSPSurfaces ? ESlateCheckBoxState::Checked : ESlateCheckBoxState::Unchecked );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionLevel( FLightmapResRatioAdjustSettings::AdjustLevels NewLevel )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.LevelOptions = NewLevel;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsLightingResolutionLevelChecked( FLightmapResRatioAdjustSettings::AdjustLevels TestLevel )
|
|
{
|
|
return ( FLightmapResRatioAdjustSettings::Get().LevelOptions == TestLevel );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionSelectedObjectsOnly()
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.bSelectedObjectsOnly = !Settings.bSelectedObjectsOnly;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsLightingResolutionSelectedObjectsOnlyChecked()
|
|
{
|
|
return FLightmapResRatioAdjustSettings::Get().bSelectedObjectsOnly;
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingResolutionMinSMs()
|
|
{
|
|
return static_cast<float>( FLightmapResRatioAdjustSettings::Get().Min_StaticMeshes );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionMinSMs( float Value )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.Min_StaticMeshes = static_cast<int32>( Value );
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingResolutionMaxSMs()
|
|
{
|
|
return static_cast<float>( FLightmapResRatioAdjustSettings::Get().Max_StaticMeshes );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionMaxSMs( float Value )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.Max_StaticMeshes = static_cast<int32>( Value );
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingResolutionMinBSPs()
|
|
{
|
|
return static_cast<float>( FLightmapResRatioAdjustSettings::Get().Min_BSPSurfaces );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionMinBSPs( float Value )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.Min_BSPSurfaces = static_cast<int32>( Value );
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingResolutionMaxBSPs()
|
|
{
|
|
return static_cast<float>( FLightmapResRatioAdjustSettings::Get().Max_BSPSurfaces );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionMaxBSPs( float Value )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.Max_BSPSurfaces = static_cast<int32>( Value );
|
|
}
|
|
|
|
int32 FLevelEditorActionCallbacks::GetLightingResolutionRatio()
|
|
{
|
|
return FMath::RoundToInt(FLightmapResRatioAdjustSettings::Get().Ratio * 100.0f);
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionRatio( int32 Value )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
const float NewValue = Value / 100.0f;
|
|
if ( Settings.Ratio != NewValue )
|
|
{
|
|
Settings.Ratio = NewValue;
|
|
Settings.ApplyRatioAdjustment();
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionRatioCommit( int32 Value, ETextCommit::Type CommitInfo)
|
|
{
|
|
if ((CommitInfo == ETextCommit::OnEnter) || (CommitInfo == ETextCommit::OnUserMovedFocus))
|
|
{
|
|
SetLightingResolutionRatio( Value );
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ShowLightingStaticMeshInfo()
|
|
{
|
|
if (GUnrealEd)
|
|
{
|
|
GUnrealEd->ShowLightingStaticMeshInfoWindow();
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ShowSceneStats()
|
|
{
|
|
if (GUnrealEd)
|
|
{
|
|
GUnrealEd->OpenSceneStatsWindow();
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ShowTextureStats()
|
|
{
|
|
if (GUnrealEd)
|
|
{
|
|
GUnrealEd->OpenTextureStatsWindow();
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::MapCheck_Execute()
|
|
{
|
|
GEditor->Exec( GetWorld(), TEXT("MAP CHECK") );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanShowSourceCodeActions()
|
|
{
|
|
// Ask the module manager for a list of currently-loaded gameplay modules
|
|
TArray< FModuleManager::FModuleStatus > ModuleStatuses;
|
|
FModuleManager::Get().QueryModules( ModuleStatuses );
|
|
|
|
for( auto ModuleStatusIt = ModuleStatuses.CreateConstIterator(); ModuleStatusIt; ++ModuleStatusIt )
|
|
{
|
|
const FModuleManager::FModuleStatus& ModuleStatus = *ModuleStatusIt;
|
|
|
|
// We only care about game modules that are currently loaded
|
|
if( ModuleStatus.bIsLoaded && ModuleStatus.bIsGameModule )
|
|
{
|
|
// There is at least one loaded game module. Source code actions should be available.
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::RecompileLevelEditor_Clicked()
|
|
{
|
|
GEngine->DeferredCommands.Add( TEXT( "Module Recompile LevelEditor" ) );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ReloadLevelEditor_Clicked()
|
|
{
|
|
GEngine->DeferredCommands.Add( TEXT( "Module Reload LevelEditor" ) );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::RecompileGameCode_Clicked()
|
|
{
|
|
// Don't allow a recompile while already compiling!
|
|
if( !FModuleManager::Get().IsCurrentlyCompiling() )
|
|
{
|
|
TArray< FString > GameModuleNames;
|
|
{
|
|
// Ask the module manager for a list of currently-loaded gameplay modules
|
|
TArray< FModuleManager::FModuleStatus > ModuleStatuses;
|
|
FModuleManager::Get().QueryModules( ModuleStatuses );
|
|
|
|
for( TArray< FModuleManager::FModuleStatus >::TConstIterator ModuleStatusIt( ModuleStatuses ); ModuleStatusIt; ++ModuleStatusIt )
|
|
{
|
|
const FModuleManager::FModuleStatus& ModuleStatus = *ModuleStatusIt;
|
|
|
|
// We only care about game modules that are currently loaded
|
|
if( ModuleStatus.bIsLoaded && ModuleStatus.bIsGameModule )
|
|
{
|
|
GameModuleNames.AddUnique( ModuleStatus.Name );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( GameModuleNames.Num() > 0 )
|
|
{
|
|
TArray< UPackage*> PackagesToRebind;
|
|
// Packages that rely on packages with UObject, but don't contain UObjects.
|
|
TArray< FName > DependentModules;
|
|
|
|
for( int32 CurModuleIndex = 0; CurModuleIndex < GameModuleNames.Num(); ++CurModuleIndex )
|
|
{
|
|
const FString& GameModuleName = *GameModuleNames[ CurModuleIndex ];
|
|
FString PackagePath( FString( TEXT( "/Script/" ) ) + GameModuleName );
|
|
|
|
UPackage* Package = FindPackage(NULL, *PackagePath);
|
|
if( Package != NULL )
|
|
{
|
|
PackagesToRebind.Add( Package );
|
|
}
|
|
else
|
|
{
|
|
DependentModules.Add( *GameModuleName );
|
|
}
|
|
}
|
|
|
|
GWarn->BeginSlowTask( LOCTEXT("CompilingGameCode", "Compiling Game Code"), true );
|
|
|
|
const bool bWaitForCompletion = false; // Don't wait -- we want compiling to happen asynchronously
|
|
RebindPackages( PackagesToRebind, DependentModules, bWaitForCompletion, *GLog );
|
|
|
|
GWarn->EndSlowTask();
|
|
|
|
GEditor->BroadcastHotReload();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Recompile_CanExecute()
|
|
{
|
|
// We're not able to recompile if a compile is already in progress!
|
|
return !FModuleManager::Get().IsCurrentlyCompiling();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Reload_CanExecute()
|
|
{
|
|
// We're not able to reload if a compile is already in progress!
|
|
return !FModuleManager::Get().IsCurrentlyCompiling();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::GoToCodeForActor_Clicked()
|
|
{
|
|
const auto& SelectedActorInfo = AssetSelectionUtils::GetSelectedActorInfo();
|
|
if( SelectedActorInfo.SelectionClass != nullptr )
|
|
{
|
|
FString ClassHeaderPath;
|
|
if( FSourceCodeNavigation::FindClassHeaderPath( SelectedActorInfo.SelectionClass, ClassHeaderPath ) && IFileManager::Get().FileSize( *ClassHeaderPath ) != INDEX_NONE )
|
|
{
|
|
FString AbsoluteHeaderPath = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*ClassHeaderPath);
|
|
FSourceCodeNavigation::OpenSourceFile( AbsoluteHeaderPath );
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::FindInContentBrowser_Clicked()
|
|
{
|
|
GEditor->SyncToContentBrowser();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ViewReferences_Execute()
|
|
{
|
|
if( GEditor->GetSelectedActorCount() > 0 )
|
|
{
|
|
TArray< UObject* > ReferencedAssets;
|
|
GEditor->GetReferencedAssetsForEditorSelection( ReferencedAssets );
|
|
|
|
if (ReferencedAssets.Num() > 0)
|
|
{
|
|
TArray< FName > ViewableObjects;
|
|
for( auto ObjectIter = ReferencedAssets.CreateConstIterator(); ObjectIter; ++ObjectIter )
|
|
{
|
|
// Don't allow user to perform certain actions on objects that aren't actually assets (e.g. Level Script blueprint objects)
|
|
const auto EditingObject = *ObjectIter;
|
|
if( EditingObject != NULL && EditingObject->IsAsset() )
|
|
{
|
|
ViewableObjects.Add( EditingObject->GetOuter()->GetFName());
|
|
}
|
|
}
|
|
|
|
IReferenceViewerModule::Get().InvokeReferenceViewerTab(ViewableObjects);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanViewReferences()
|
|
{
|
|
TArray< UObject* > ReferencedAssets;
|
|
GEditor->GetReferencedAssetsForEditorSelection(ReferencedAssets);
|
|
return ReferencedAssets.Num() > 0;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::EditAsset_Clicked( const EToolkitMode::Type ToolkitMode, TWeakPtr< SLevelEditor > LevelEditor, bool bConfirmMultiple )
|
|
{
|
|
if( GEditor->GetSelectedActorCount() > 0 )
|
|
{
|
|
TArray< UObject* > ReferencedAssets;
|
|
GEditor->GetReferencedAssetsForEditorSelection( ReferencedAssets );
|
|
|
|
bool bShouldOpenEditors = (ReferencedAssets.Num() == 1);
|
|
|
|
if (ReferencedAssets.Num() > 1)
|
|
{
|
|
if (bConfirmMultiple)
|
|
{
|
|
int32 Response = FMessageDialog::Open(
|
|
EAppMsgType::YesNo,
|
|
LOCTEXT("OpenAllAssetEditors", "There is more than one referenced asset in the selection. Do you want to open them all for editing?")
|
|
);
|
|
|
|
bShouldOpenEditors = (Response == EAppReturnType::Yes);
|
|
}
|
|
else
|
|
{
|
|
bShouldOpenEditors = true;
|
|
}
|
|
}
|
|
|
|
if (bShouldOpenEditors)
|
|
{
|
|
auto LevelEditorSharedPtr = LevelEditor.Pin();
|
|
|
|
if (LevelEditorSharedPtr.IsValid())
|
|
{
|
|
for (auto Asset : ReferencedAssets)
|
|
{
|
|
FAssetEditorManager::Get().OpenEditorForAsset(Asset, ToolkitMode, LevelEditorSharedPtr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::LockActorMovement_Clicked()
|
|
{
|
|
GEditor->ToggleSelectedActorMovementLock();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::DetachActor_Clicked()
|
|
{
|
|
GEditor->DetachSelectedActors();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AttachSelectedActors()
|
|
{
|
|
GUnrealEd->AttachSelectedActors();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AttachActorIteractive()
|
|
{
|
|
if(GUnrealEd->GetSelectedActorCount())
|
|
{
|
|
FActorPickerModeModule& ActorPickerMode = FModuleManager::Get().GetModuleChecked<FActorPickerModeModule>("ActorPickerMode");
|
|
|
|
ActorPickerMode.BeginActorPickingMode(
|
|
FOnGetAllowedClasses(),
|
|
FOnShouldFilterActor::CreateStatic(&FLevelEditorActionCallbacks::IsAttachableActor),
|
|
FOnActorSelected::CreateStatic(&FLevelEditorActionCallbacks::AttachToActor)
|
|
);
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsAttachableActor( const AActor* const ParentActor )
|
|
{
|
|
for ( FSelectionIterator It( GEditor->GetSelectedActorIterator() ) ; It ; ++It )
|
|
{
|
|
AActor* Actor = static_cast<AActor*>( *It );
|
|
if (!GEditor->CanParentActors(ParentActor, Actor))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
USceneComponent* ChildRoot = Actor->GetRootComponent();
|
|
USceneComponent* ParentRoot = ParentActor->GetRootComponent();
|
|
|
|
if (ChildRoot != nullptr && ParentRoot != nullptr && ChildRoot->IsAttachedTo(ParentRoot))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::CreateNewOutlinerFolder_Clicked()
|
|
{
|
|
const FName NewFolderName = FActorFolders::Get().GetDefaultFolderNameForSelection(*GetWorld());
|
|
FActorFolders::Get().CreateFolderContainingSelection(*GetWorld(), NewFolderName);
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::LockActorMovement_IsChecked()
|
|
{
|
|
return GEditor->HasLockedActors();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AddActor_Clicked( UActorFactory* ActorFactory, FAssetData AssetData, bool bUsePlacement )
|
|
{
|
|
UObject* Object = AssetData.GetAsset();
|
|
if(bUsePlacement && IPlacementModeModule::IsAvailable() && Object != NULL)
|
|
{
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
|
|
LevelEditorModule.FocusViewport();
|
|
|
|
TArray<UObject*> AssetsToPlace;
|
|
AssetsToPlace.Add(Object);
|
|
IPlacementModeModule::Get().GetPlacementMode()->StartPlacing(AssetsToPlace, ActorFactory);
|
|
}
|
|
else
|
|
{
|
|
FLevelEditorActionCallbacks::AddActor(ActorFactory, AssetData, NULL);
|
|
}
|
|
}
|
|
|
|
AActor* FLevelEditorActionCallbacks::AddActor( UActorFactory* ActorFactory, const FAssetData& AssetData, const FVector* ActorLocation )
|
|
{
|
|
AActor* NewActor = GEditor->UseActorFactory( ActorFactory, AssetData, ActorLocation, ActorFactory->bUseSurfaceOrientation );
|
|
|
|
if ( NewActor != NULL && IPlacementModeModule::IsAvailable() )
|
|
{
|
|
IPlacementModeModule::Get().AddToRecentlyPlaced( AssetData.GetAsset(), ActorFactory );
|
|
}
|
|
|
|
return NewActor;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AddActorFromClass_Clicked( UClass* ActorClass )
|
|
{
|
|
FLevelEditorActionCallbacks::AddActorFromClass(ActorClass, NULL);
|
|
}
|
|
|
|
AActor* FLevelEditorActionCallbacks::AddActorFromClass( UClass* ActorClass, const FVector* ActorLocation )
|
|
{
|
|
AActor* NewActor = NULL;
|
|
|
|
if ( ActorClass )
|
|
{
|
|
// Look for an actor factory capable of creating actors of that type.
|
|
UActorFactory* ActorFactory = GEditor->FindActorFactoryForActorClass( ActorClass );
|
|
if( ActorFactory )
|
|
{
|
|
NewActor = GEditor->UseActorFactoryOnCurrentSelection( ActorFactory, ActorLocation, ActorFactory->bUseSurfaceOrientation );
|
|
|
|
if ( NewActor != NULL && IPlacementModeModule::IsAvailable() )
|
|
{
|
|
IPlacementModeModule::Get().AddToRecentlyPlaced( ActorClass, ActorFactory );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No actor factory was found; use SpawnActor instead.
|
|
GUnrealEd->Exec( GetWorld(), *FString::Printf( TEXT("ACTOR ADD CLASS=%s"), *ActorClass->GetName() ) );
|
|
}
|
|
}
|
|
|
|
return NewActor;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ReplaceActors_Clicked( UActorFactory* ActorFactory, FAssetData AssetData )
|
|
{
|
|
FLevelEditorActionCallbacks::ReplaceActors(ActorFactory, AssetData);
|
|
}
|
|
|
|
AActor* FLevelEditorActionCallbacks::ReplaceActors( UActorFactory* ActorFactory, const FAssetData& AssetData )
|
|
{
|
|
AActor* NewActor = NULL;
|
|
|
|
// Have a first stab at filling in the factory properties.
|
|
FText ErrorMessage;
|
|
if( ActorFactory->CanCreateActorFrom( AssetData, ErrorMessage ) )
|
|
{
|
|
// Replace all selected actors with actors created from the specified factory
|
|
GEditor->ReplaceSelectedActors( ActorFactory, AssetData, NULL );
|
|
|
|
if ( IPlacementModeModule::IsAvailable() )
|
|
{
|
|
IPlacementModeModule::Get().AddToRecentlyPlaced( AssetData.GetAsset(), ActorFactory );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FNotificationInfo ErrorNotification( ErrorMessage );
|
|
ErrorNotification.Image = FEditorStyle::GetBrush(TEXT("MessageLog.Error"));
|
|
ErrorNotification.bFireAndForget = true;
|
|
ErrorNotification.ExpireDuration = 3.0f; // Need this message to last a little longer than normal since the user may want to "Show Log"
|
|
ErrorNotification.bUseThrobber = true;
|
|
|
|
FSlateNotificationManager::Get().AddNotification(ErrorNotification);
|
|
}
|
|
|
|
return NewActor;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::ReplaceActorsFromClass_Clicked( UClass* ActorClass )
|
|
{
|
|
if ( ActorClass )
|
|
{
|
|
// Look for an actor factory capable of creating actors of that type.
|
|
UActorFactory* ActorFactory = GEditor->FindActorFactoryForActorClass( ActorClass );
|
|
if( ActorFactory )
|
|
{
|
|
// Replace all selected actors with actors created from the specified factory
|
|
UObject* TargetAsset = GEditor->GetSelectedObjects()->GetTop<UObject>();
|
|
|
|
FText ErrorMessage;
|
|
FText UnusedErrorMessage;
|
|
const FAssetData NoAssetData;
|
|
const FAssetData TargetAssetData(TargetAsset);
|
|
if( ActorFactory->CanCreateActorFrom( TargetAssetData, ErrorMessage ) )
|
|
{
|
|
// Replace all selected actors with actors created from the specified factory
|
|
GEditor->ReplaceSelectedActors( ActorFactory, TargetAssetData, NULL );
|
|
}
|
|
else if ( ActorFactory->CanCreateActorFrom( NoAssetData, UnusedErrorMessage ) )
|
|
{
|
|
// Replace all selected actors with actors created from the specified factory
|
|
GEditor->ReplaceSelectedActors( ActorFactory, NoAssetData, NULL );
|
|
}
|
|
else
|
|
{
|
|
FNotificationInfo ErrorNotification( ErrorMessage );
|
|
ErrorNotification.Image = FEditorStyle::GetBrush(TEXT("MessageLog.Error"));
|
|
ErrorNotification.bFireAndForget = true;
|
|
ErrorNotification.ExpireDuration = 3.0f; // Need this message to last a little longer than normal since the user may want to "Show Log"
|
|
ErrorNotification.bUseThrobber = true;
|
|
|
|
FSlateNotificationManager::Get().AddNotification(ErrorNotification);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No actor factory was found; use SpawnActor instead.
|
|
GUnrealEd->Exec( GetWorld(), *FString::Printf( TEXT("ACTOR REPLACE CLASS=%s"), *ActorClass->GetName() ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Duplicate_CanExecute()
|
|
{
|
|
TArray<FEdMode*> ActiveModes;
|
|
GEditorModeTools().GetActiveModes( ActiveModes );
|
|
for( int32 ModeIndex = 0; ModeIndex < ActiveModes.Num(); ++ModeIndex )
|
|
{
|
|
const EEditAction::Type CanProcess = ActiveModes[ModeIndex]->GetActionEditDuplicate();
|
|
if (CanProcess == EEditAction::Process)
|
|
{
|
|
return true;
|
|
}
|
|
else if (CanProcess == EEditAction::Halt)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return GUnrealEd->CanCopySelectedActorsToClipboard( GetWorld() ); // If we can copy, we can duplicate
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Delete_CanExecute()
|
|
{
|
|
TArray<FEdMode*> ActiveModes;
|
|
GEditorModeTools().GetActiveModes( ActiveModes );
|
|
for( int32 ModeIndex = 0; ModeIndex < ActiveModes.Num(); ++ModeIndex )
|
|
{
|
|
const EEditAction::Type CanProcess = ActiveModes[ModeIndex]->GetActionEditDelete();
|
|
if (CanProcess == EEditAction::Process)
|
|
{
|
|
return true;
|
|
}
|
|
else if (CanProcess == EEditAction::Halt)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return GUnrealEd->CanDeleteSelectedActors( GetWorld(), true, false );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::Rename_Execute()
|
|
{
|
|
AActor* Actor = Cast<AActor>( *GEditor->GetSelectedActorIterator() );
|
|
if(Actor)
|
|
{
|
|
GEditor->BroadcastLevelActorRequestRename(Actor);
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Rename_CanExecute()
|
|
{
|
|
return GEditor->GetSelectedActorCount() == 1;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Cut_CanExecute()
|
|
{
|
|
TArray<FEdMode*> ActiveModes;
|
|
GEditorModeTools().GetActiveModes( ActiveModes );
|
|
for( int32 ModeIndex = 0; ModeIndex < ActiveModes.Num(); ++ModeIndex )
|
|
{
|
|
const EEditAction::Type CanProcess = ActiveModes[ModeIndex]->GetActionEditCut();
|
|
if (CanProcess == EEditAction::Process)
|
|
{
|
|
return true;
|
|
}
|
|
else if (CanProcess == EEditAction::Halt)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return GUnrealEd->CanCopySelectedActorsToClipboard( GetWorld() ); // If we can copy, we can cut
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Copy_CanExecute()
|
|
{
|
|
TArray<FEdMode*> ActiveModes;
|
|
GEditorModeTools().GetActiveModes( ActiveModes );
|
|
for( int32 ModeIndex = 0; ModeIndex < ActiveModes.Num(); ++ModeIndex )
|
|
{
|
|
const EEditAction::Type CanProcess = ActiveModes[ModeIndex]->GetActionEditCopy();
|
|
if (CanProcess == EEditAction::Process)
|
|
{
|
|
return true;
|
|
}
|
|
else if (CanProcess == EEditAction::Halt)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return GUnrealEd->CanCopySelectedActorsToClipboard( GetWorld() );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Paste_CanExecute()
|
|
{
|
|
TArray<FEdMode*> ActiveModes;
|
|
GEditorModeTools().GetActiveModes( ActiveModes );
|
|
for( int32 ModeIndex = 0; ModeIndex < ActiveModes.Num(); ++ModeIndex )
|
|
{
|
|
const EEditAction::Type CanProcess = ActiveModes[ModeIndex]->GetActionEditPaste();
|
|
if (CanProcess == EEditAction::Process)
|
|
{
|
|
return true;
|
|
}
|
|
else if (CanProcess == EEditAction::Halt)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return GUnrealEd->CanPasteSelectedActorsFromClipboard( GetWorld() );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::PasteHere_CanExecute()
|
|
{
|
|
return Paste_CanExecute(); // For now, just do the same check as Paste
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ExecuteExecCommand( FString Command )
|
|
{
|
|
GUnrealEd->Exec( GetWorld(), *Command );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectAllActorsOfClass( bool bArchetype )
|
|
{
|
|
GEditor->SelectAllActorsWithClass( bArchetype );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectAllActorsControlledByMatinee()
|
|
{
|
|
GEditor->SelectAllActorsControlledByMatinee();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectMatineeActor( AMatineeActor * ActorToSelect )
|
|
{
|
|
GEditor->SelectNone( false, true );
|
|
GEditor->SelectActor(ActorToSelect, true, false, true);
|
|
|
|
GEditor->NoteSelectionChange();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectMatineeGroup( AActor * Actor )
|
|
{
|
|
if( GEditorModeTools().IsModeActive( FBuiltinEditorModes::EM_InterpEdit ) )
|
|
{
|
|
FEdModeInterpEdit* InterpEditMode = (FEdModeInterpEdit*)GEditorModeTools().GetActiveMode( FBuiltinEditorModes::EM_InterpEdit );
|
|
|
|
if ( InterpEditMode && InterpEditMode->MatineeActor )
|
|
{
|
|
InterpEditMode->UpdateSelectedActor();
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnApplyMaterialToSurface()
|
|
{
|
|
FEditorDelegates::LoadSelectedAssetsIfNeeded.Broadcast();
|
|
|
|
GUnrealEd->Exec( GetWorld(), TEXT("POLY SETMATERIAL") );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectAllLights()
|
|
{
|
|
// Select all light actors.
|
|
for( FActorIterator It(GetWorld()); It; ++It )
|
|
{
|
|
ALight* Light = Cast<ALight>(*It);
|
|
if( Light )
|
|
{
|
|
GUnrealEd->SelectActor( Light, true, true, false );
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectStationaryLightsExceedingOverlap()
|
|
{
|
|
GEditor->SelectNone( true, true );
|
|
for( FActorIterator It(GetWorld()); It; ++It )
|
|
{
|
|
AActor* Actor = *It;
|
|
|
|
TArray<ULightComponent*> Components;
|
|
Actor->GetComponents(Components);
|
|
|
|
for (int32 ComponentIndex = 0; ComponentIndex < Components.Num(); ComponentIndex++)
|
|
{
|
|
ULightComponent* LightComponent = Components[ComponentIndex];
|
|
|
|
if (LightComponent->GetOwner()
|
|
// Use the component's lighting properties to determine if this is a stationary light, instead of checking the actor type
|
|
// Because blueprint lights may be operating as stationary lights
|
|
&& LightComponent->HasStaticShadowing()
|
|
&& !LightComponent->HasStaticLighting()
|
|
&& LightComponent->bAffectsWorld
|
|
&& LightComponent->CastShadows
|
|
&& LightComponent->CastStaticShadows
|
|
&& LightComponent->PreviewShadowMapChannel == INDEX_NONE)
|
|
{
|
|
GUnrealEd->SelectActor( LightComponent->GetOwner(), true, true, false );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSurfaceAlignment( ETexAlign AlignmentMode )
|
|
{
|
|
GTexAlignTools.GetAligner( AlignmentMode )->Align( AlignmentMode );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::RegroupActor_Clicked()
|
|
{
|
|
GUnrealEd->edactRegroupFromSelected();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::UngroupActor_Clicked()
|
|
{
|
|
GUnrealEd->edactUngroupFromSelected();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::LockGroup_Clicked()
|
|
{
|
|
GUnrealEd->edactLockSelectedGroups();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::UnlockGroup_Clicked()
|
|
{
|
|
GUnrealEd->edactUnlockSelectedGroups();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AddActorsToGroup_Clicked()
|
|
{
|
|
GUnrealEd->edactAddToGroup();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::RemoveActorsFromGroup_Clicked()
|
|
{
|
|
GUnrealEd->edactRemoveFromGroup();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::MergeActors_Clicked()
|
|
{
|
|
GUnrealEd->edactMergeActors();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanExecuteMergeActors()
|
|
{
|
|
FSelectedActorInfo Info = AssetSelectionUtils::GetSelectedActorInfo();
|
|
return (Info.bHaveStaticMeshComponent || Info.bHaveLandscape);
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::MergeActorsByMaterials_Clicked()
|
|
{
|
|
GUnrealEd->edactMergeActorsByMaterials();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanExecuteMergeActorsByMaterials()
|
|
{
|
|
FSelectedActorInfo Info = AssetSelectionUtils::GetSelectedActorInfo();
|
|
return Info.bHaveStaticMeshComponent;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::LocationGridSnap_Clicked()
|
|
{
|
|
GUnrealEd->Exec( GetWorld(), *FString::Printf( TEXT("MODE GRID=%d"), !GetDefault<ULevelEditorViewportSettings>()->GridEnabled ? 1 : 0 ) );
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::LocationGridSnap_IsChecked()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->GridEnabled;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::RotationGridSnap_Clicked()
|
|
{
|
|
GUnrealEd->Exec( GetWorld(), *FString::Printf( TEXT("MODE ROTGRID=%d"), !GetDefault<ULevelEditorViewportSettings>()->RotGridEnabled ? 1 : 0 ) );
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::RotationGridSnap_IsChecked()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->RotGridEnabled;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::ScaleGridSnap_Clicked()
|
|
{
|
|
GUnrealEd->Exec( GetWorld(), *FString::Printf( TEXT("MODE SCALEGRID=%d"), !GetDefault<ULevelEditorViewportSettings>()->SnapScaleEnabled ? 1 : 0 ) );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::ScaleGridSnap_IsChecked()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->SnapScaleEnabled;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::OnKeepSimulationChanges()
|
|
{
|
|
// @todo simulate: There are lots of types of changes that can't be "kept", like attachment or newly-spawned actors. This
|
|
// feature currently only supports propagating changes to regularly-editable properties on an instance of a PIE actor
|
|
// that still exists in the editor world.
|
|
|
|
// Make sure we have some actors selected, and PIE is running
|
|
if( GEditor->GetSelectedActorCount() > 0 && GEditor->PlayWorld != NULL )
|
|
{
|
|
int32 UpdatedActorCount = 0;
|
|
int32 TotalCopiedPropertyCount = 0;
|
|
FString FirstUpdatedActorLabel;
|
|
{
|
|
const FScopedTransaction Transaction( NSLOCTEXT( "LevelEditorCommands", "KeepSimulationChanges", "Keep Simulation Changes" ) );
|
|
|
|
for( auto ActorIt( GEditor->GetSelectedActorIterator() ); ActorIt; ++ActorIt )
|
|
{
|
|
auto* SimWorldActor = CastChecked<AActor>( *ActorIt );
|
|
|
|
// Find our counterpart actor
|
|
AActor* EditorWorldActor = EditorUtilities::GetEditorWorldCounterpartActor( SimWorldActor );
|
|
if( EditorWorldActor != NULL )
|
|
{
|
|
// We only want to copy CPF_Edit properties back, or properties that are set through editor manipulation
|
|
// NOTE: This needs to match what we're doing in the BuildSelectedActorInfo() function
|
|
const auto CopyOptions = ( EditorUtilities::ECopyOptions::Type )(
|
|
EditorUtilities::ECopyOptions::CallPostEditChangeProperty |
|
|
EditorUtilities::ECopyOptions::CallPostEditMove |
|
|
EditorUtilities::ECopyOptions::OnlyCopyEditOrInterpProperties );
|
|
const int32 CopiedPropertyCount = EditorUtilities::CopyActorProperties( SimWorldActor, EditorWorldActor, CopyOptions );
|
|
|
|
if( CopiedPropertyCount > 0 )
|
|
{
|
|
++UpdatedActorCount;
|
|
TotalCopiedPropertyCount += CopiedPropertyCount;
|
|
|
|
if( FirstUpdatedActorLabel.IsEmpty() )
|
|
{
|
|
FirstUpdatedActorLabel = EditorWorldActor->GetActorLabel();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Let the user know what happened
|
|
{
|
|
FNotificationInfo NotificationInfo( FText::GetEmpty() );
|
|
NotificationInfo.bFireAndForget = true;
|
|
NotificationInfo.FadeInDuration = 0.25f;
|
|
NotificationInfo.FadeOutDuration = 1.0f;
|
|
NotificationInfo.ExpireDuration = 1.0f;
|
|
NotificationInfo.bUseLargeFont = false;
|
|
NotificationInfo.bUseSuccessFailIcons = true;
|
|
NotificationInfo.bAllowThrottleWhenFrameRateIsLow = false; // Don't throttle as it causes distracting hitches in Simulate mode
|
|
SNotificationItem::ECompletionState CompletionState;
|
|
if( UpdatedActorCount > 0 )
|
|
{
|
|
if( UpdatedActorCount > 1 )
|
|
{
|
|
FFormatNamedArguments Args;
|
|
Args.Add( TEXT("UpdatedActorCount"), UpdatedActorCount );
|
|
Args.Add( TEXT("TotalCopiedPropertyCount"), TotalCopiedPropertyCount );
|
|
NotificationInfo.Text = FText::Format( NSLOCTEXT( "LevelEditorCommands", "KeepSimulationChanges_MultipleActorsUpdatedNotification", "Saved state for {UpdatedActorCount} actors ({TotalCopiedPropertyCount} properties)" ), Args );
|
|
}
|
|
else
|
|
{
|
|
FFormatNamedArguments Args;
|
|
Args.Add( TEXT("FirstUpdatedActorLabel"), FText::FromString( FirstUpdatedActorLabel ) );
|
|
Args.Add( TEXT("TotalCopiedPropertyCount"), TotalCopiedPropertyCount );
|
|
NotificationInfo.Text = FText::Format( NSLOCTEXT( "LevelEditorCommands", "KeepSimulationChanges_ActorUpdatedNotification", "Saved state for {FirstUpdatedActorLabel} ({TotalCopiedPropertyCount} properties)" ), Args );
|
|
}
|
|
CompletionState = SNotificationItem::CS_Success;
|
|
}
|
|
else
|
|
{
|
|
NotificationInfo.Text = NSLOCTEXT( "LevelEditorCommands", "KeepSimulationChanges_NoActorsUpdated", "No properties were copied" );
|
|
CompletionState = SNotificationItem::CS_Fail;
|
|
}
|
|
const auto Notification = FSlateNotificationManager::Get().AddNotification( NotificationInfo );
|
|
Notification->SetCompletionState( CompletionState );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::CanExecuteKeepSimulationChanges()
|
|
{
|
|
return AssetSelectionUtils::GetSelectedActorInfo().NumSimulationChanges > 0;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::OnMakeSelectedActorLevelCurrent()
|
|
{
|
|
GUnrealEd->MakeSelectedActorsLevelCurrent();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnMoveSelectedToCurrentLevel()
|
|
{
|
|
GEditor->MoveSelectedActorsToLevel( GetWorld()->GetCurrentLevel() );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnFindLevelsInLevelBrowser()
|
|
{
|
|
const bool bDeselectOthers = true;
|
|
GEditor->SelectLevelInLevelBrowser( bDeselectOthers );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectLevelInLevelBrowser()
|
|
{
|
|
const bool bDeselectOthers = false;
|
|
GEditor->SelectLevelInLevelBrowser( bDeselectOthers );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnDeselectLevelInLevelBrowser()
|
|
{
|
|
GEditor->DeselectLevelInLevelBrowser();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnFindActorInLevelScript()
|
|
{
|
|
GUnrealEd->FindSelectedActorsInLevelScript();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnShowWorldProperties( TWeakPtr< SLevelEditor > LevelEditor )
|
|
{
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>( TEXT("LevelEditor") );
|
|
LevelEditorModule.GetLevelEditorTabManager()->InvokeTab(FName("WorldSettingsTab"));
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenContentBrowser()
|
|
{
|
|
FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser");
|
|
ContentBrowserModule.Get().FocusPrimaryContentBrowser(true);
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenMarketplace()
|
|
{
|
|
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
|
|
|
|
if (DesktopPlatform != nullptr)
|
|
{
|
|
TArray<FAnalyticsEventAttribute> EventAttributes;
|
|
|
|
if (DesktopPlatform->OpenLauncher(false, TEXT("-OpenMarket")))
|
|
{
|
|
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("OpenSucceeded"), TEXT("TRUE")));
|
|
}
|
|
else
|
|
{
|
|
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("OpenSucceeded"), TEXT("FALSE")));
|
|
|
|
if (EAppReturnType::Yes == FMessageDialog::Open(EAppMsgType::YesNo, LOCTEXT("InstallMarketplacePrompt", "The Marketplace requires the Unreal Engine Launcher, which does not seem to be installed on your computer. Would you like to install it now?")))
|
|
{
|
|
if (!DesktopPlatform->OpenLauncher(true, TEXT("-OpenMarket")))
|
|
{
|
|
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("InstallSucceeded"), TEXT("FALSE")));
|
|
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(TEXT("Sorry, there was a problem installing the Launcher.\nPlease try to install it manually!")));
|
|
}
|
|
else
|
|
{
|
|
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("InstallSucceeded"), TEXT("TRUE")));
|
|
}
|
|
}
|
|
}
|
|
|
|
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("Source"), TEXT("EditorToolbar")));
|
|
|
|
if( FEngineAnalytics::IsAvailable() )
|
|
{
|
|
FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.Usage.OpenMarketplace"), EventAttributes);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanEditGameInfoBlueprints( TWeakPtr< SLevelEditor > LevelEditor)
|
|
{
|
|
return LevelEditor.Pin()->GetWorld()->GetWorldSettings()->DefaultGameMode && LevelEditor.Pin()->GetWorld()->GetWorldSettings()->DefaultGameMode->ClassGeneratedBy;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenLevelBlueprint( TWeakPtr< SLevelEditor > LevelEditor )
|
|
{
|
|
if( LevelEditor.Pin()->GetWorld()->GetCurrentLevel() )
|
|
{
|
|
ULevelScriptBlueprint* LevelScriptBlueprint = LevelEditor.Pin()->GetWorld()->PersistentLevel->GetLevelScriptBlueprint();
|
|
if (LevelScriptBlueprint)
|
|
{
|
|
// @todo Re-enable once world centric works
|
|
const bool bOpenWorldCentric = false;
|
|
FAssetEditorManager::Get().OpenEditorForAsset(
|
|
LevelScriptBlueprint,
|
|
bOpenWorldCentric ? EToolkitMode::WorldCentric : EToolkitMode::Standalone,
|
|
LevelEditor.Pin() );
|
|
}
|
|
else
|
|
{
|
|
FMessageDialog::Open( EAppMsgType::Ok, NSLOCTEXT("UnrealEd", "UnableToCreateLevelScript", "Unable to find or create a level blueprint for this level.") );
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::CreateClassBlueprint()
|
|
{
|
|
// Use the BlueprintFactory to allow the user to pick a parent class for the new class Blueprint
|
|
UBlueprintFactory* NewFactory = Cast<UBlueprintFactory>(ConstructObject<UFactory>( UBlueprintFactory::StaticClass() ));
|
|
FEditorDelegates::OnConfigureNewAssetProperties.Broadcast(NewFactory);
|
|
if ( NewFactory->ConfigureProperties() )
|
|
{
|
|
UClass* SelectedClass = NewFactory->ParentClass;
|
|
|
|
// Now help the user pick a path and name for the new Blueprint
|
|
UBlueprint* Blueprint = FKismetEditorUtilities::CreateBlueprintFromClass(NSLOCTEXT("LevelEditorCommands", "CreateClassBlueprint_Title", "Create Class Blueprint"), SelectedClass);
|
|
|
|
if( Blueprint )
|
|
{
|
|
// @todo Re-enable once world centric works
|
|
const bool bOpenWorldCentric = false;
|
|
FAssetEditorManager::Get().OpenEditorForAsset(
|
|
Blueprint,
|
|
bOpenWorldCentric ? EToolkitMode::WorldCentric : EToolkitMode::Standalone);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenGameModeBlueprint( TWeakPtr< SLevelEditor > LevelEditor )
|
|
{
|
|
if( LevelEditor.Pin()->GetWorld()->GetCurrentLevel() )
|
|
{
|
|
TSubclassOf<class AGameMode> ActiveGameMode = LevelEditor.Pin()->GetWorld()->GetWorldSettings()->DefaultGameMode;
|
|
UClass* ParentBlueprintClass = NULL;
|
|
|
|
if(ActiveGameMode)
|
|
{
|
|
ParentBlueprintClass = ActiveGameMode;
|
|
}
|
|
else
|
|
{
|
|
ParentBlueprintClass = AGameMode::StaticClass();
|
|
}
|
|
|
|
const FString NewBPName(TEXT("NewGameMode"));
|
|
UBlueprint* Blueprint = LevelEditorActionsHelpers::OpenOrCreateBlueprintFromClass(NSLOCTEXT("LevelEditorCommands", "CreateGameModeBlueprint_Title", "Create GameMode Blueprint"), ParentBlueprintClass, LevelEditor, NewBPName);
|
|
if(Blueprint)
|
|
{
|
|
LevelEditor.Pin()->GetWorld()->GetWorldSettings()->DefaultGameMode = Cast<UClass>(Blueprint->GeneratedClass);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenGameStateBlueprint( TWeakPtr< SLevelEditor > LevelEditor )
|
|
{
|
|
if( LevelEditor.Pin()->GetWorld()->GetCurrentLevel() )
|
|
{
|
|
TSubclassOf<class AGameMode> ActiveGameMode = LevelEditor.Pin()->GetWorld()->GetWorldSettings()->DefaultGameMode;
|
|
AGameMode* GameMode = Cast<AGameMode>(ActiveGameMode->GetDefaultObject());
|
|
|
|
UClass* ParentBlueprintClass = NULL;
|
|
if(GameMode->GameStateClass)
|
|
{
|
|
ParentBlueprintClass = GameMode->GameStateClass;
|
|
}
|
|
else
|
|
{
|
|
ParentBlueprintClass = AGameState::StaticClass();
|
|
}
|
|
|
|
const FString NewBPName(TEXT("NewGameState"));
|
|
UBlueprint* Blueprint = LevelEditorActionsHelpers::OpenOrCreateBlueprintFromClass(NSLOCTEXT("LevelEditorCommands", "CreateGameStateBlueprint_Title", "Create GameState Blueprint"), ParentBlueprintClass, LevelEditor, NewBPName);
|
|
if(Blueprint)
|
|
{
|
|
GameMode->GameStateClass = Cast<UClass>(Blueprint->GeneratedClass);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenDefaultPawnBlueprint( TWeakPtr< SLevelEditor > LevelEditor )
|
|
{
|
|
if( LevelEditor.Pin()->GetWorld()->GetCurrentLevel() )
|
|
{
|
|
TSubclassOf<class AGameMode> ActiveGameMode = LevelEditor.Pin()->GetWorld()->GetWorldSettings()->DefaultGameMode;
|
|
AGameMode* GameMode = Cast<AGameMode>(ActiveGameMode->GetDefaultObject());
|
|
|
|
UClass* ParentBlueprintClass = NULL;
|
|
if(GameMode->DefaultPawnClass)
|
|
{
|
|
ParentBlueprintClass = GameMode->DefaultPawnClass;
|
|
}
|
|
else
|
|
{
|
|
ParentBlueprintClass = APawn::StaticClass();
|
|
}
|
|
|
|
const FString NewBPName(TEXT("NewPawn"));
|
|
UBlueprint* Blueprint = LevelEditorActionsHelpers::OpenOrCreateBlueprintFromClass(NSLOCTEXT("LevelEditorCommands", "CreateDefaultPawnBlueprint_Title", "Create DefaultPawn Blueprint"), ParentBlueprintClass, LevelEditor, NewBPName);
|
|
if(Blueprint)
|
|
{
|
|
GameMode->DefaultPawnClass = Cast<UClass>(Blueprint->GeneratedClass);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenHUDBlueprint( TWeakPtr< SLevelEditor > LevelEditor )
|
|
{
|
|
if( LevelEditor.Pin()->GetWorld()->GetCurrentLevel() )
|
|
{
|
|
TSubclassOf<class AGameMode> ActiveGameMode = LevelEditor.Pin()->GetWorld()->GetWorldSettings()->DefaultGameMode;
|
|
AGameMode* GameMode = Cast<AGameMode>(ActiveGameMode->GetDefaultObject());
|
|
|
|
UClass* ParentBlueprintClass = NULL;
|
|
if(GameMode->HUDClass)
|
|
{
|
|
ParentBlueprintClass = GameMode->HUDClass;
|
|
}
|
|
else
|
|
{
|
|
ParentBlueprintClass = AHUD::StaticClass();
|
|
}
|
|
|
|
const FString NewBPName(TEXT("NewHUD"));
|
|
UBlueprint* Blueprint = LevelEditorActionsHelpers::OpenOrCreateBlueprintFromClass(NSLOCTEXT("LevelEditorCommands", "CreateHUDBlueprint_Title", "Create HUD Blueprint"), ParentBlueprintClass, LevelEditor, NewBPName);
|
|
if(Blueprint)
|
|
{
|
|
GameMode->HUDClass = Cast<UClass>(Blueprint->GeneratedClass);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenPlayerControllerBlueprint( TWeakPtr< SLevelEditor > LevelEditor )
|
|
{
|
|
if( LevelEditor.Pin()->GetWorld()->GetCurrentLevel() )
|
|
{
|
|
TSubclassOf<class AGameMode> ActiveGameMode = LevelEditor.Pin()->GetWorld()->GetWorldSettings()->DefaultGameMode;
|
|
AGameMode* GameMode = Cast<AGameMode>(ActiveGameMode->GetDefaultObject());
|
|
|
|
UClass* ParentBlueprintClass = NULL;
|
|
if(GameMode->PlayerControllerClass)
|
|
{
|
|
ParentBlueprintClass = GameMode->PlayerControllerClass;
|
|
}
|
|
else
|
|
{
|
|
ParentBlueprintClass = APlayerController::StaticClass();
|
|
}
|
|
|
|
const FString NewBPName(TEXT("NewPC"));
|
|
UBlueprint* Blueprint = LevelEditorActionsHelpers::OpenOrCreateBlueprintFromClass(NSLOCTEXT("LevelEditorCommands", "CreatePlayerControllerBlueprint_Title", "Create PlayerController Blueprint"), ParentBlueprintClass, LevelEditor, NewBPName);
|
|
if(Blueprint)
|
|
{
|
|
GameMode->PlayerControllerClass = Cast<UClass>(Blueprint->GeneratedClass);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnShowOnlySelectedActors()
|
|
{
|
|
const FScopedTransaction Transaction( NSLOCTEXT( "LevelEditorCommands", "ShowOnlySelectedActors", "Show Only Selected Actors" ) );
|
|
GUnrealEd->edactUnhideSelected( GetWorld() );
|
|
GUnrealEd->edactHideUnselected( GetWorld() );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleTransformWidgetVisibility()
|
|
{
|
|
GEditorModeTools().SetShowWidget( !GEditorModeTools().GetShowWidget() );
|
|
GUnrealEd->RedrawAllViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnGetTransformWidgetVisibility()
|
|
{
|
|
return GEditorModeTools().GetShowWidget();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnAllowTranslucentSelection()
|
|
{
|
|
// Toggle 'allow select translucent'
|
|
GEditor->AccessEditorUserSettings().bAllowSelectTranslucent = !GEditor->AccessEditorUserSettings().bAllowSelectTranslucent;
|
|
GEditor->AccessEditorUserSettings().PostEditChange();
|
|
|
|
// Need to refresh hit proxies as we changed what should be rendered into them
|
|
GUnrealEd->RedrawAllViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsAllowTranslucentSelectionEnabled()
|
|
{
|
|
return GEditor->GetEditorUserSettings().bAllowSelectTranslucent == true;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnAllowGroupSelection()
|
|
{
|
|
AGroupActor::ToggleGroupMode();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsAllowGroupSelectionEnabled()
|
|
{
|
|
return GUnrealEd->bGroupingActive;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleStrictBoxSelect()
|
|
{
|
|
ULevelEditorViewportSettings* ViewportSettings = GetMutableDefault<ULevelEditorViewportSettings>();
|
|
ViewportSettings->bStrictBoxSelection = !ViewportSettings->bStrictBoxSelection;
|
|
ViewportSettings->PostEditChange();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsStrictBoxSelectEnabled()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->bStrictBoxSelection;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnDrawBrushMarkerPolys()
|
|
{
|
|
GEditor->Exec( GetWorld(), *FString::Printf( TEXT("MODE SHOWBRUSHMARKERPOLYS=%d"), !GEditor->bShowBrushMarkerPolys ? 1 : 0 ) );
|
|
GEditor->SaveConfig();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsDrawBrushMarkerPolysEnabled()
|
|
{
|
|
return GEditor->bShowBrushMarkerPolys;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleOnlyLoadVisibleInPIE()
|
|
{
|
|
ULevelEditorPlaySettings* PlaySettings = GetMutableDefault<ULevelEditorPlaySettings>();
|
|
PlaySettings->bOnlyLoadVisibleLevelsInPIE = !PlaySettings->bOnlyLoadVisibleLevelsInPIE;
|
|
PlaySettings->PostEditChange();
|
|
PlaySettings->SaveConfig();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsOnlyLoadVisibleInPIEEnabled()
|
|
{
|
|
return GetDefault<ULevelEditorPlaySettings>()->bOnlyLoadVisibleLevelsInPIE;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleSocketSnapping()
|
|
{
|
|
GEditor->bEnableSocketSnapping = !GEditor->bEnableSocketSnapping;
|
|
GEditor->RedrawLevelEditingViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsSocketSnappingEnabled()
|
|
{
|
|
return GEditor->bEnableSocketSnapping;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleParticleSystemLOD()
|
|
{
|
|
GEngine->bEnableEditorPSysRealtimeLOD = !GEngine->bEnableEditorPSysRealtimeLOD;
|
|
GEditor->RedrawLevelEditingViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsParticleSystemLODEnabled()
|
|
{
|
|
return GEditor->bEnableEditorPSysRealtimeLOD;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleFreezeParticleSimulation()
|
|
{
|
|
IConsoleManager& ConsoleManager = IConsoleManager::Get();
|
|
IConsoleVariable* CVar = ConsoleManager.FindConsoleVariable(TEXT("FX.FreezeParticleSimulation"));
|
|
if (CVar)
|
|
{
|
|
CVar->Set(CVar->GetInt() == 0 ? 1 : 0);
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsParticleSimulationFrozen()
|
|
{
|
|
IConsoleManager& ConsoleManager = IConsoleManager::Get();
|
|
static const auto* CVar = ConsoleManager.FindTConsoleVariableDataInt(TEXT("FX.FreezeParticleSimulation"));
|
|
if (CVar)
|
|
{
|
|
return CVar->GetValueOnGameThread() == 0 ? false : true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleParticleSystemHelpers()
|
|
{
|
|
GEditor->bDrawParticleHelpers = !GEditor->bDrawParticleHelpers;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsParticleSystemHelpersEnabled()
|
|
{
|
|
return GEditor->bDrawParticleHelpers;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleLODViewLocking()
|
|
{
|
|
GEditor->bEnableLODLocking = !GEditor->bEnableLODLocking;
|
|
GEditor->RedrawLevelEditingViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsLODViewLockingEnabled()
|
|
{
|
|
return GEditor->bEnableLODLocking;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleLevelStreamingVolumePrevis()
|
|
{
|
|
ULevelEditorViewportSettings* ViewportSettings = GetMutableDefault<ULevelEditorViewportSettings>();
|
|
|
|
ViewportSettings->bLevelStreamingVolumePrevis = !ViewportSettings->bLevelStreamingVolumePrevis;
|
|
ViewportSettings->PostEditChange();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsLevelStreamingVolumePrevisEnabled()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->bLevelStreamingVolumePrevis;
|
|
}
|
|
|
|
FString FLevelEditorActionCallbacks::GetAudioVolumeToolTip()
|
|
{
|
|
if ( !GEditor->IsRealTimeAudioMuted() )
|
|
{
|
|
const float Volume = GEditor->GetRealTimeAudioVolume() * 100.0f;
|
|
return FString::Printf( TEXT( "%.0f" ), Volume );
|
|
}
|
|
return NSLOCTEXT("UnrealEd", "Muted", "Muted" ).ToString();
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetAudioVolume()
|
|
{
|
|
return GEditor->GetRealTimeAudioVolume();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnAudioVolumeChanged(float Volume)
|
|
{
|
|
GEditor->SetRealTimeAudioVolume(Volume);
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::GetAudioMuted()
|
|
{
|
|
return GEditor->IsRealTimeAudioMuted();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnAudioMutedChanged(bool bMuted)
|
|
{
|
|
GEditor->MuteRealTimeAudio(bMuted);
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnEnableActorSnap()
|
|
{
|
|
FSnappingUtils::EnableActorSnap( !FSnappingUtils::IsSnapToActorEnabled() );
|
|
|
|
// If the setting is enabled and there's no distance, revert to default
|
|
if ( FSnappingUtils::IsSnapToActorEnabled() && FSnappingUtils::GetActorSnapDistance() == 0.0f )
|
|
{
|
|
FSnappingUtils::SetActorSnapDistance( 1.0f );
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsActorSnapEnabled()
|
|
{
|
|
return FSnappingUtils::IsSnapToActorEnabled();
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::OnEnableVertexSnap()
|
|
{
|
|
ULevelEditorViewportSettings* ViewportSettings = GetMutableDefault<ULevelEditorViewportSettings>();
|
|
ViewportSettings->bSnapVertices = !ViewportSettings->bSnapVertices;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsVertexSnapEnabled()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->bSnapVertices;
|
|
}
|
|
|
|
FString FLevelEditorActionCallbacks::GetActorSnapTooltip()
|
|
{
|
|
// If the setting is enabled, return the distance, otherwise say disabled
|
|
if ( FSnappingUtils::IsSnapToActorEnabled() )
|
|
{
|
|
return FString::Printf( TEXT( "%.2f" ), FSnappingUtils::GetActorSnapDistance() );
|
|
}
|
|
return NSLOCTEXT("UnrealEd", "Disabled", "Disabled" ).ToString();
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetActorSnapSetting()
|
|
{
|
|
// If the setting is enabled, return the distance, otherwise say 0
|
|
if (FSnappingUtils::IsSnapToActorEnabled() )
|
|
{
|
|
return FSnappingUtils::GetActorSnapDistance(true) ;
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetActorSnapSetting(float Distance)
|
|
{
|
|
FSnappingUtils::SetActorSnapDistance( Distance );
|
|
|
|
// If the distance is 0, disable the setting until it's > 0
|
|
FSnappingUtils::EnableActorSnap( ( Distance > 0.0f ? true : false ) );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleHideViewportUI()
|
|
{
|
|
GEditorModeTools().SetHideViewportUI( !GEditorModeTools().IsViewportUIHidden() );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsViewportUIHidden()
|
|
{
|
|
return GEditorModeTools().IsViewportUIHidden();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsEditorModeActive( FEditorModeID EditorMode )
|
|
{
|
|
return GEditorModeTools().IsModeActive( EditorMode );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnAddVolume( UClass* VolumeClass )
|
|
{
|
|
GUnrealEd->Exec( GetWorld(), *FString::Printf( TEXT("BRUSH ADDVOLUME CLASS=%s"), *VolumeClass->GetName() ) );
|
|
|
|
// A new volume actor was added, update the volumes visibility.
|
|
// This volume should be hidden if the user doesn't have this type of volume visible.
|
|
GUnrealEd->UpdateVolumeActorVisibility( VolumeClass );
|
|
|
|
GEditor->RedrawAllViewports();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnAddMatinee()
|
|
{
|
|
// Warn the user prior to creating our actor
|
|
if ( GEditor->ShouldOpenMatinee( NULL ) )
|
|
{
|
|
// Spawn a matinee actor at the origin, and either move infront of the camera or focus camera on it (depending on the viewport) and open for edit
|
|
UActorFactory* ActorFactory = GEditor->FindActorFactoryForActorClass( AMatineeActor::StaticClass() );
|
|
check( ActorFactory );
|
|
AMatineeActor* MatineeActor = CastChecked<AMatineeActor>( FLevelEditorActionCallbacks::AddActor( ActorFactory, FAssetData(), &FVector::ZeroVector ) );
|
|
if( GCurrentLevelEditingViewportClient->IsPerspective() )
|
|
{
|
|
GEditor->MoveActorInFrontOfCamera( *MatineeActor, GCurrentLevelEditingViewportClient->GetViewLocation(), GCurrentLevelEditingViewportClient->GetViewRotation().Vector() );
|
|
}
|
|
else
|
|
{
|
|
GEditor->MoveViewportCamerasToActor( *MatineeActor, false );
|
|
}
|
|
GEditor->OpenMatinee( MatineeActor, false );
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SelectActorsInLayers()
|
|
{
|
|
// Iterate over selected actors and make a list of all layers the selected actors belong to.
|
|
TArray< FName > SelectedLayers;
|
|
for ( FSelectionIterator It( GEditor->GetSelectedActorIterator() ) ; It ; ++It )
|
|
{
|
|
AActor* Actor = Cast<AActor>( *It );
|
|
|
|
// Add them to the list of selected layers.
|
|
for( int32 LayerIndex = 0 ; LayerIndex < Actor->Layers.Num() ; ++LayerIndex )
|
|
{
|
|
SelectedLayers.AddUnique( Actor->Layers[ LayerIndex ] );
|
|
}
|
|
}
|
|
|
|
bool bSelect = true;
|
|
bool bNotify = true;
|
|
GEditor->Layers->SelectActorsInLayers( SelectedLayers, bSelect, bNotify );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetWidgetMode( FWidget::EWidgetMode WidgetMode )
|
|
{
|
|
if( !GEditorModeTools().IsTracking() )
|
|
{
|
|
GEditorModeTools().SetWidgetMode( WidgetMode );
|
|
GEditor->RedrawAllViewports();
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsWidgetModeActive( FWidget::EWidgetMode WidgetMode )
|
|
{
|
|
return GEditorModeTools().GetWidgetMode() == WidgetMode;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanSetWidgetMode( FWidget::EWidgetMode WidgetMode )
|
|
{
|
|
return GEditorModeTools().GetShowWidget() == true;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsTranslateRotateModeVisible()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->bAllowTranslateRotateZWidget;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetCoordinateSystem( ECoordSystem CoordinateSystem )
|
|
{
|
|
GEditorModeTools().SetCoordSystem( CoordinateSystem );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsCoordinateSystemActive( ECoordSystem CoordinateSystem )
|
|
{
|
|
return GEditorModeTools().GetCoordSystem() == CoordinateSystem;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::MoveActorToGrid_Clicked( bool InAlign, bool bInPerActor )
|
|
{
|
|
const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "MoveActorToGrid", "Snap Origin to Grid") );
|
|
MoveActorTo_Clicked( InAlign, NULL, bInPerActor );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::MoveActorToActor_Clicked( bool InAlign )
|
|
{
|
|
AActor* Actor = GEditor->GetSelectedActors()->GetBottom<AActor>();
|
|
if( Actor )
|
|
{
|
|
const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "MoveActorToActor", "Snap Origin to Actor") );
|
|
MoveActorTo_Clicked( InAlign, Actor );
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::MoveActorTo_Clicked( const bool InAlign, const AActor* InDestination/* = NULL*/, bool bInPerActor/* = false*/ )
|
|
{
|
|
// Fires ULevel::LevelDirtiedEvent when falling out of scope.
|
|
FScopedLevelDirtied LevelDirtyCallback;
|
|
|
|
// Update the pivot location.
|
|
FVector Delta = FVector::ZeroVector;
|
|
FVector NewLocation = FVector::ZeroVector;
|
|
FRotator NewRotation = FRotator::ZeroRotator;
|
|
|
|
if(!bInPerActor)
|
|
{
|
|
if ( InDestination )
|
|
{
|
|
NewLocation = InDestination->GetActorLocation();
|
|
NewRotation = InDestination->GetActorRotation();
|
|
GEditor->SetPivot( NewLocation, false, true );
|
|
}
|
|
else
|
|
{
|
|
const FVector OldPivot = GEditor->GetPivotLocation();
|
|
const FVector NewPivot = OldPivot.GridSnap(GEditor->GetGridSize());
|
|
Delta = NewPivot - OldPivot;
|
|
GEditor->SetPivot( NewPivot, false, true );
|
|
}
|
|
}
|
|
|
|
for ( FSelectionIterator It( GEditor->GetSelectedActorIterator() ) ; It ; ++It )
|
|
{
|
|
AActor* Actor = Cast<AActor>( *It );
|
|
checkSlow( Actor->IsA(AActor::StaticClass()) );
|
|
if ( Actor == InDestination ) // Early out
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Actor->Modify();
|
|
|
|
if(!InDestination)
|
|
{
|
|
if ( bInPerActor )
|
|
{
|
|
const FVector OldPivot = Actor->GetActorLocation();
|
|
const FVector NewPivot = OldPivot.GridSnap(GEditor->GetGridSize());
|
|
Delta = NewPivot - OldPivot;
|
|
GEditor->SetPivot( NewPivot, false, true );
|
|
}
|
|
|
|
NewLocation = Actor->GetActorLocation() + Delta;
|
|
}
|
|
|
|
Actor->TeleportTo( NewLocation, ( !InAlign ? Actor->GetActorRotation() : NewRotation ), false, true );
|
|
Actor->InvalidateLightingCache();
|
|
Actor->UpdateComponentTransforms();
|
|
|
|
Actor->MarkPackageDirty();
|
|
LevelDirtyCallback.Request();
|
|
}
|
|
|
|
GEditor->RedrawLevelEditingViewports();
|
|
GEditor->RebuildAlteredBSP(); // Update the Bsp of any levels containing a modified brush
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SnapActorToFloor_Clicked( bool InAlign, bool InUseLineTrace, bool InUseBounds, bool InUsePivot )
|
|
{
|
|
const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "SnapActorsToFloor", "Snap Actors To Floor") );
|
|
SnapActorTo_Clicked( InAlign, InUseLineTrace, InUseBounds, InUsePivot );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SnapActorToActor_Clicked( bool InAlign, bool InUseLineTrace, bool InUseBounds, bool InUsePivot )
|
|
{
|
|
AActor* Actor = GEditor->GetSelectedActors()->GetBottom<AActor>();
|
|
if( Actor )
|
|
{
|
|
const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "SnapActorsToActor", "Snap Actors To Actor") );
|
|
SnapActorTo_Clicked( InAlign, InUseLineTrace, InUseBounds, InUsePivot, Actor );
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SnapActorTo_Clicked( const bool InAlign, const bool InUseLineTrace, const bool InUseBounds, const bool InUsePivot, const AActor* InDestination/* = NULL*/ )
|
|
{
|
|
// Fires ULevel::LevelDirtiedEvent when falling out of scope.
|
|
FScopedLevelDirtied LevelDirtyCallback;
|
|
|
|
for ( FSelectionIterator It( GEditor->GetSelectedActorIterator() ) ; It ; ++It )
|
|
{
|
|
AActor* Actor = Cast<AActor>( *It );
|
|
checkSlow( Actor->IsA(AActor::StaticClass()) );
|
|
|
|
Actor->Modify();
|
|
GEditor->SnapActorTo(Actor,InAlign,InUseLineTrace,InUseBounds,InUsePivot,InDestination);
|
|
Actor->InvalidateLightingCache();
|
|
Actor->UpdateComponentTransforms();
|
|
|
|
Actor->MarkPackageDirty();
|
|
LevelDirtyCallback.Request();
|
|
}
|
|
|
|
AActor* Actor = GEditor->GetSelectedActors()->GetBottom<AActor>();
|
|
if( Actor )
|
|
{
|
|
GEditor->SetPivot( Actor->GetActorLocation(), false, true );
|
|
|
|
if( GEditor->bGroupingActive )
|
|
{
|
|
// set group pivot for the root-most group
|
|
AGroupActor* ActorGroupRoot = AGroupActor::GetRootForActor(Actor, true, true);
|
|
if(ActorGroupRoot)
|
|
{
|
|
ActorGroupRoot->CenterGroupLocation();
|
|
}
|
|
}
|
|
}
|
|
|
|
GEditor->RedrawLevelEditingViewports();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSaveBrushAsCollision()
|
|
{
|
|
// First, find the currently selected actor with a static mesh.
|
|
// Fail if more than one actor with staticmesh is selected.
|
|
UStaticMesh* StaticMesh = NULL;
|
|
FMatrix MeshToWorld;
|
|
|
|
// Pointer to the world
|
|
UWorld* World = NULL;
|
|
for ( FSelectionIterator It( GEditor->GetSelectedActorIterator() ) ; It ; ++It )
|
|
{
|
|
AActor* Actor = Cast<AActor>( *It );
|
|
checkSlow( Actor->IsA(AActor::StaticClass()) );
|
|
|
|
UStaticMeshComponent* FoundStaticMeshComponent = NULL;
|
|
if( Actor->IsA(AStaticMeshActor::StaticClass()) )
|
|
{
|
|
FoundStaticMeshComponent = CastChecked<AStaticMeshActor>(Actor)->StaticMeshComponent;
|
|
}
|
|
|
|
UStaticMesh* FoundMesh = FoundStaticMeshComponent ? FoundStaticMeshComponent->StaticMesh : NULL;
|
|
if( FoundMesh )
|
|
{
|
|
// If we find multiple actors with static meshes, warn and do nothing.
|
|
if( StaticMesh )
|
|
{
|
|
FMessageDialog::Open( EAppMsgType::Ok, NSLOCTEXT("UnrealEd", "Error_SelectOneActor", "Please select just one Actor with a StaticMesh.") );
|
|
return;
|
|
}
|
|
StaticMesh = FoundMesh;
|
|
MeshToWorld = FoundStaticMeshComponent->ComponentToWorld.ToMatrixWithScale();
|
|
// Store the pointer to the world
|
|
World = Actor->GetWorld();
|
|
}
|
|
}
|
|
|
|
// If no static-mesh-toting actor found, warn and do nothing.
|
|
if(!StaticMesh)
|
|
{
|
|
FMessageDialog::Open( EAppMsgType::Ok, NSLOCTEXT("UnrealEd", "Error_NoActorWithStaticMesh", "No Actor found with a StaticMesh.") );
|
|
return;
|
|
}
|
|
|
|
// If we already have a collision model for this staticmesh, ask if we want to replace it.
|
|
if( StaticMesh->BodySetup )
|
|
{
|
|
const bool bDoReplace = EAppReturnType::Yes == FMessageDialog::Open( EAppMsgType::YesNo, NSLOCTEXT("UnrealEd", "Prompt_24", "Static Mesh already has a collision model. \nDo you want to replace it with Builder Brush?") );
|
|
if( !bDoReplace )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
check(World)
|
|
ABrush* BuildBrush = World->GetDefaultBrush();
|
|
if(BuildBrush != nullptr)
|
|
{
|
|
// Now get the builder brush.
|
|
UModel* BuilderModel = BuildBrush->Brush;
|
|
|
|
// Need the transform between builder brush space and static mesh actor space.
|
|
const FMatrix BrushL2W = BuildBrush->ActorToWorld().ToMatrixWithScale();
|
|
const FMatrix MeshW2L = MeshToWorld.Inverse();
|
|
const FMatrix SMToBB = BrushL2W * MeshW2L;
|
|
const FMatrix SMToBB_AT = SMToBB.TransposeAdjoint();
|
|
|
|
// Copy the current builder brush into a temp model.
|
|
// We keep no reference to this, so it will be GC'd at some point.
|
|
UModel* TempModel = new UModel(FPostConstructInitializeProperties(), NULL, 1);
|
|
TempModel->Polys->Element.AssignButKeepOwner(BuilderModel->Polys->Element);
|
|
|
|
// Now transform each poly into local space for the selected static mesh.
|
|
for (int32 i = 0; i < TempModel->Polys->Element.Num(); i++)
|
|
{
|
|
FPoly* Poly = &TempModel->Polys->Element[i];
|
|
|
|
for (int32 j = 0; j < Poly->Vertices.Num(); j++)
|
|
{
|
|
Poly->Vertices[j] = SMToBB.TransformPosition(Poly->Vertices[j]);
|
|
}
|
|
|
|
Poly->Normal = SMToBB_AT.TransformVector(Poly->Normal);
|
|
Poly->Normal.Normalize(); // SmToBB might have scaling in it.
|
|
}
|
|
|
|
// Build bounding box.
|
|
TempModel->BuildBound();
|
|
|
|
// Build BSP for the brush.
|
|
FBSPOps::bspBuild(TempModel, FBSPOps::BSP_Good, 15, 70, 1, 0);
|
|
FBSPOps::bspRefresh(TempModel, 1);
|
|
FBSPOps::bspBuildBounds(TempModel);
|
|
|
|
|
|
// Now - use this as the Rigid Body collision for this static mesh as well.
|
|
|
|
// Make sure rendering is done - so we are not changing data being used by collision drawing.
|
|
FlushRenderingCommands();
|
|
|
|
// If we already have a BodySetup - clear it.
|
|
if (StaticMesh->BodySetup)
|
|
{
|
|
StaticMesh->BodySetup->RemoveSimpleCollision();
|
|
}
|
|
// If we don't already have physics props, construct them here.
|
|
else
|
|
{
|
|
StaticMesh->CreateBodySetup();
|
|
}
|
|
|
|
// Convert collision model into a collection of convex hulls.
|
|
// NB: This removes any convex hulls that were already part of the collision data.
|
|
StaticMesh->BodySetup->CreateFromModel(TempModel, true);
|
|
}
|
|
// refresh collision change back to staticmesh components
|
|
RefreshCollisionChange(StaticMesh);
|
|
|
|
// Finally mark the parent package as 'dirty', so user will be prompted if they want to save it etc.
|
|
StaticMesh->MarkPackageDirty();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::ActorSelected_CanExecute()
|
|
{
|
|
// Had to have something selected
|
|
return ( ( GEditor->GetSelectedActorCount() > 0 ) ? true : false );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::ActorsSelected_CanExecute()
|
|
{
|
|
// Has to have more than one selected
|
|
return ( ( GEditor->GetSelectedActorCount() > 1 ) ? true : false );
|
|
}
|
|
|
|
class UWorld* FLevelEditorActionCallbacks::GetWorld()
|
|
{
|
|
return GEditor->GetEditorWorldContext().World();
|
|
}
|
|
|
|
/** UI_COMMAND takes long for the compile to optimize */
|
|
PRAGMA_DISABLE_OPTIMIZATION
|
|
void FLevelEditorCommands::RegisterCommands()
|
|
{
|
|
UI_COMMAND( BrowseDocumentation, "Documentation...", "Opens the main documentation page", EUserInterfaceActionType::Button, FInputGesture( EKeys::F1 ) );
|
|
UI_COMMAND( BrowseAPIReference, "API Reference...", "Opens the API reference documentation", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( BrowseViewportControls, "Viewport Controls...", "Opens the viewport controls cheat sheet", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( NewLevel, "New Level...", "Create a new level, or choose a level template to start from.", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Control, EKeys::N ) );
|
|
if (FParse::Param(FCommandLine::Get(), TEXT("WorldAssets")))
|
|
{
|
|
UI_COMMAND( OpenLevel, "Open Level...", "Loads an existing level", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Control, EKeys::O ) );
|
|
UI_COMMAND( LegacyOpenLevel, "Open Other Level...", "Loads an existing level using the file explorer", EUserInterfaceActionType::Button, FInputGesture() );
|
|
}
|
|
else
|
|
{
|
|
UI_COMMAND( OpenLevel, "Open Level...", "Loads an existing level", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Control, EKeys::O ) );
|
|
}
|
|
UI_COMMAND( Save, "Save", "Saves the current level to disk", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SaveAs, "Save As...", "Save the current level as...", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Shift|EModifierKey::Control, EKeys::S ) );
|
|
UI_COMMAND( SaveAllLevels, "Save All Levels", "Saves all unsaved levels to disk", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( ToggleFavorite, "Toggle Favorite", "Sets whether the currently loaded level will appear in the list of favorite levels", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
for( int32 CurRecentIndex = 0; CurRecentIndex < FLevelEditorCommands::MaxRecentFiles; ++CurRecentIndex )
|
|
{
|
|
// NOTE: The actual label and tool-tip will be overridden at runtime when the command is bound to a menu item, however
|
|
// we still need to set one here so that the key bindings UI can function properly
|
|
TSharedRef< FUICommandInfo > OpenRecentFile =
|
|
FUICommandInfoDecl(
|
|
this->AsShared(),
|
|
FName( *FString::Printf( TEXT( "OpenRecentFile%i" ), CurRecentIndex ) ),
|
|
FText::Format( NSLOCTEXT( "LevelEditorCommands", "OpenRecentFile", "Open Recent File {0}" ), FText::AsNumber( CurRecentIndex ) ),
|
|
NSLOCTEXT( "LevelEditorCommands", "OpenRecentFileToolTip", "Opens a recently opened file" ) )
|
|
.UserInterfaceType( EUserInterfaceActionType::Button )
|
|
.DefaultGesture( FInputGesture() );
|
|
OpenRecentFileCommands.Add( OpenRecentFile );
|
|
}
|
|
|
|
for( int32 CurFavoriteIndex = 0; CurFavoriteIndex < FLevelEditorCommands::MaxFavoriteFiles; ++CurFavoriteIndex )
|
|
{
|
|
// NOTE: The actual label and tool-tip will be overridden at runtime when the command is bound to a menu item, however
|
|
// we still need to set one here so that the key bindings UI can function properly
|
|
TSharedRef< FUICommandInfo > OpenFavoriteFile =
|
|
FUICommandInfoDecl(
|
|
this->AsShared(),
|
|
FName( *FString::Printf( TEXT( "OpenFavoriteFile%i" ), CurFavoriteIndex ) ),
|
|
FText::Format( NSLOCTEXT( "LevelEditorCommands", "OpenFavoriteFile", "Open Favorite File {0}" ), FText::AsNumber( CurFavoriteIndex ) ),
|
|
NSLOCTEXT( "LevelEditorCommands", "OpenFavoriteFileTaggedToolTip", "Opens a file that was tagged as a favorite" ) )
|
|
.UserInterfaceType( EUserInterfaceActionType::Button )
|
|
.DefaultGesture( FInputGesture() );
|
|
OpenFavoriteFileCommands.Add( OpenFavoriteFile );
|
|
}
|
|
|
|
for( int32 CurFavoriteIndex = 0; CurFavoriteIndex < FLevelEditorCommands::MaxFavoriteFiles; ++CurFavoriteIndex )
|
|
{
|
|
// NOTE: The actual label and tool-tip will be overridden at runtime when the command is bound to a menu item, however
|
|
// we still need to set one here so that the key bindings UI can function properly
|
|
TSharedRef< FUICommandInfo > RemoveFavorite =
|
|
FUICommandInfoDecl(
|
|
this->AsShared(),
|
|
FName( *FString::Printf( TEXT( "RemoveFavorite%i" ), CurFavoriteIndex ) ),
|
|
FText::Format( NSLOCTEXT( "LevelEditorCommands", "RemoveFavorite", "Remove Favorite {0}" ), FText::AsNumber( CurFavoriteIndex ) ),
|
|
NSLOCTEXT( "LevelEditorCommands", "RemoveFavoriteToolTip", "Removes an entry from the favorites list" ) )
|
|
.UserInterfaceType( EUserInterfaceActionType::Button )
|
|
.DefaultGesture( FInputGesture() );
|
|
RemoveFavoriteCommands.Add( RemoveFavorite );
|
|
}
|
|
|
|
UI_COMMAND( Import, "Import...", "Imports objects and actors from a T3D format into the current level", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( ExportAll, "Export All...", "Exports the entire level to a file on disk (multiple formats are supported.)", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( ExportSelected, "Export Selected...", "Exports currently-selected objects to a file on disk (multiple formats are supported.)", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( Build, "Build All Levels", "Builds all levels (precomputes lighting data and visibility data, generates navigation networks and updates brush models.)", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( BuildAndSubmitToSourceControl, "Build and Submit...", "Displays a window that allows you to build all levels and submit them to source control", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( BuildLightingOnly, "Build Lighting", "Only precomputes lighting (all levels.)", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Control|EModifierKey::Shift, EKeys::Semicolon) );
|
|
UI_COMMAND( BuildReflectionCapturesOnly, "Update Reflection Captures", "Only updates Reflection Captures (all levels.)", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( BuildLightingOnly_VisibilityOnly, "Precompute Static Visibility", "Only precomputes static visibility data (all levels.)", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( LightingBuildOptions_UseErrorColoring, "Use Error Coloring", "When enabled, errors during lighting precomputation will be baked as colors into light map data", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( LightingBuildOptions_ShowLightingStats, "Show Lighting Stats", "When enabled, a window containing metrics about lighting performance and memory will be displayed after a successful build.", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( BuildGeometryOnly, "Build Geometry", "Only builds geometry (all levels.)", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( BuildGeometryOnly_OnlyCurrentLevel, "Build Geometry (Current Level)", "Builds geometry, only for the current level", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( BuildPathsOnly, "Build Paths", "Only builds paths (all levels.)", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( LightingQuality_Production, "Production", "Sets precomputed lighting quality to highest possible quality (slowest computation time.)", EUserInterfaceActionType::RadioButton, FInputGesture() );
|
|
UI_COMMAND( LightingQuality_High, "High", "Sets precomputed lighting quality to high quality", EUserInterfaceActionType::RadioButton, FInputGesture() );
|
|
UI_COMMAND( LightingQuality_Medium, "Medium", "Sets precomputed lighting quality to medium quality", EUserInterfaceActionType::RadioButton, FInputGesture() );
|
|
UI_COMMAND( LightingQuality_Preview, "Preview", "Sets precomputed lighting quality to preview quality (fastest computation time.)", EUserInterfaceActionType::RadioButton, FInputGesture() );
|
|
UI_COMMAND( LightingTools_ShowBounds, "Show Lighting Bounds", "Draws a wireframe sphere for the lighting bounds of the Light Environment, and a point for the center, or multiple points if NumVolumeVisibilitySamples is greater than zero.", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( LightingTools_ShowTraces, "Show Shadow Traces", "Draws lines for any shadow rays that the Light Environment traced. The lines will be white if the light is not shadowed, and red otherwise.", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( LightingTools_ShowDirectOnly, "Show Direct Lighting", "Renders only the influence of direct lighting on the Light Environments.", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( LightingTools_ShowIndirectOnly, "Show Indirect Lighting", "Renders only the influence of indirect lighting on the Light Environments.", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( LightingTools_ShowIndirectSamples, "Show Indirect Lighting Samples", "Draws the indirect lighting samples that contributed to the indirect lighting for the Light Environments.", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( LightingDensity_RenderGrayscale, "Render Grayscale", "Renders the lightmap density.", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( LightingResolution_CurrentLevel, "Current Level", "Adjust only primitives in the current level.", EUserInterfaceActionType::RadioButton, FInputGesture() );
|
|
UI_COMMAND( LightingResolution_SelectedLevels, "Selected Levels", "Adjust only primitives in the selected levels.", EUserInterfaceActionType::RadioButton, FInputGesture() );
|
|
UI_COMMAND( LightingResolution_AllLoadedLevels, "All Loaded Levels", "Adjust primitives in all loaded levels.", EUserInterfaceActionType::RadioButton, FInputGesture() );
|
|
UI_COMMAND( LightingResolution_SelectedObjectsOnly, "Selected Objects Only", "Adjust only selected objects in the levels.", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( LightingStaticMeshInfo, "Lighting StaticMesh Info...", "Shows the lighting information for the StaticMeshes.", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SceneStats, "Open Scene Stats", "Opens the Scene Stats viewer", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( TextureStats, "Open Texture Stats", "Opens the Texture Stats viewer", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( MapCheck, "Open Map Check", "Checks map for errors", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>("LevelEditor");
|
|
if (LevelEditorModule.CanBeRecompiled())
|
|
{
|
|
UI_COMMAND( RecompileLevelEditor, "Recompile Level Editor", "Recompiles and reloads C++ code for the Level Editor on the fly", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( ReloadLevelEditor, "Reload Level Editor", "Reloads C++ code for the Level Editor on the fly", EUserInterfaceActionType::Button, FInputGesture() );
|
|
}
|
|
|
|
UI_COMMAND( RecompileGameCode, "Recompile Game Code", "Recompiles and reloads C++ code for game systems on the fly", EUserInterfaceActionType::Button, FInputGesture( EKeys::P, EModifierKey::Alt | EModifierKey::Control | EModifierKey::Shift ) );
|
|
|
|
UI_COMMAND( EditAsset, "Edit Asset", "Edits the asset associated with the selected actor", EUserInterfaceActionType::Button, FInputGesture( EKeys::E, EModifierKey::Control ) );
|
|
UI_COMMAND( EditAssetNoConfirmMultiple, "Edit Asset", "Edits the asset associated with the selected actor", EUserInterfaceActionType::Button, FInputGesture( EKeys::E, EModifierKey::Control | EModifierKey::Shift ) );
|
|
|
|
UI_COMMAND( SnapCameraToActor, "Snap View to Actor", "Snaps the view to the selected actors", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( GoToCodeForActor, "Go to C++ Code for Actor", "Opens a code editing IDE and navigates to the source file associated with the seleced actor", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( PasteHere, "Paste Here", "Pastes the actor at the click location", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( SnapOriginToGrid, "Snap Origin to Grid", "Snaps the actor to the nearest grid location at its origin", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Control, EKeys::End ) );
|
|
UI_COMMAND( SnapOriginToGridPerActor, "Snap Origin to Grid Per Actor", "Snaps each selected actor separately to the nearest grid location at its origin", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( AlignOriginToGrid, "Align Origin to Grid", "Aligns the actor to the nearest grid location at its origin", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SnapToFloor, "Snap to Floor", "Snaps the actor to the floor below it", EUserInterfaceActionType::Button, FInputGesture( EKeys::End ) );
|
|
UI_COMMAND( AlignToFloor, "Align to Floor", "Aligns the actor with the floor", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SnapPivotToFloor, "Snap Pivot to Floor", "Snaps the actor to the floor at its pivot point", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Alt, EKeys::End ) );
|
|
UI_COMMAND( AlignPivotToFloor, "Align Pivot to Floor", "Aligns the actor with the floor at its pivot point", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SnapBottomCenterBoundsToFloor, "Snap Bottom Center Bounds to Floor", "Snaps the actor to the floor at its bottom center bounds", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Shift, EKeys::End ) );
|
|
UI_COMMAND( AlignBottomCenterBoundsToFloor, "Align Bottom Center Bounds to Floor", "Aligns the actor with the floor at its bottom center bounds", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SnapOriginToActor, "Snap Origin to Actor", "SNaps the actor to another actor at its origin", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( AlignOriginToActor, "Align Origin to Actor", "Aligns the actor to another actor at its origin", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SnapToActor, "Snap to Actor", "Snaps the actor to another actor", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( AlignToActor, "Align to Actor", "Aligns the actor with another actor", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SnapPivotToActor, "Snap Pivot to Actor", "Snaps the actor to another actor at its pivot point", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( AlignPivotToActor, "Align Pivot to Actor", "Aligns the actor with another actor at its pivot point", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SnapBottomCenterBoundsToActor, "Snap Bottom Center Bounds to Actor", "Snaps the actor to another actor at its bottom center bounds", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( AlignBottomCenterBoundsToActor, "Align Bottom Center Bounds to Actor", "Aligns the actor with another actor at its bottom center bounds", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( DeltaTransformToActors, "Delta Transform", "Apply Delta Transform to selected actors", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( MirrorActorX, "Mirror X", "Mirrors the actor along the X axis", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( MirrorActorY, "Mirror Y", "Mirrors the actor along the Y axis", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( MirrorActorZ, "Mirror Z", "Mirrors the actor along the Z axis", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( LockActorMovement, "Lock Actor Movement", "Locks the actor so it cannot be moved", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( DetachFromParent, "Detach", "Detach the actor from its parent", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( AttachSelectedActors, "Attach Selected Actors", "Attach the selected actors to the last selected actor", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Alt, EKeys::B) );
|
|
UI_COMMAND( AttachActorIteractive, "Attach Actor Interactive", "Start an interactive actor picker to let you choose a parent for the currently selected actor", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Alt, EKeys::A) );
|
|
UI_COMMAND( CreateNewOutlinerFolder, "Create Folder", "Place the selected actors in a new folder", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( HoldToEnableVertexSnapping, "Hold to Enable Vertex Snapping", "When the key binding is pressed and held vertex snapping will be enabled", EUserInterfaceActionType::ToggleButton, FInputGesture(EKeys::V) );
|
|
|
|
//@ todo Slate better tooltips for pivot options
|
|
UI_COMMAND( SavePivotToPrePivot, "Save Pivot to Pre-Pivot", "Saves the pivot to the pre-pivot", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( ResetPivot, "Reset Pivot", "Resets the pivot", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( ResetPrePivot, "Reset Pre-Pivot", "Resets the pre-pivot", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( MovePivotHere, "Move Here", "Moves the pivot to the clicked location", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( MovePivotHereSnapped, "Move Here (Snapped)", "Moves the pivot to the nearest grid point to the clicked location", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( MovePivotToCenter, "Center on Selection", "Centers the pivot to the middle of the selection", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( ConvertToAdditive, "Additive", "Converts the selected brushes to additive brushes", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( ConvertToSubtractive, "Subtractive", "Converts the selected brushes to subtractive brushes", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( OrderFirst, "To First", "Changes the drawing order of the selected brushes so they are the first to draw", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( OrderLast, "To Last", "Changes the drawing order of the selected brushes so they are the last to draw", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( MakeSolid, "Solid", "Makes the selected brushes solid", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( MakeSemiSolid, "Semi-Solid", "Makes the selected brushes semi-solid", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( MakeNonSolid, "Non-Solid", "Makes the selected brushes non-solid", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( MergePolys, "Merge", "Merges multiple polygons on a brush face into as few as possible", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SeparatePolys, "Separate", "Reverses the effect of a previous merge", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
// RegroupActors uses GroupActors for it's label and tooltip when simply grouping a selection of actors using overrides. This is to provide display of the gesture which is the same for both.
|
|
UI_COMMAND( GroupActors, "Group", "Groups the selected actors", EUserInterfaceActionType::Button, FInputGesture( /*EKeys::G, EModifierKey::Control*/ ) );
|
|
UI_COMMAND( RegroupActors, "Regroup", "Regroups the selected actors into a new group, removing any current groups in the selection", EUserInterfaceActionType::Button, FInputGesture( EKeys::G, EModifierKey::Control ) );
|
|
UI_COMMAND( UngroupActors, "Ungroup", "Ungroups the selected actors", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Shift, EKeys::G ) );
|
|
UI_COMMAND( AddActorsToGroup, "Add to Group", "Adds the selected actors to the selected group", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( RemoveActorsFromGroup, "Remove from Group", "Removes the selected actors from the selected groups", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( LockGroup, "Lock", "Locks the selected groups", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( UnlockGroup, "Unlock", "Unlocks the selected groups", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( MergeActors, "Create Mesh Proxy...", "Harvest geometry from selected actors and merge them into single mesh", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( MergeActorsByMaterials, "Merge Actors...", "Harvest geometry from selected actors and merge grouping them by materials", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( ShowAll, "Show All Actors", "Shows all actors", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Control, EKeys::H ) );
|
|
UI_COMMAND( ShowSelectedOnly, "Show Only Selected", "Shows only the selected actors", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( ShowSelected, "Show Selected", "Shows the selected actors", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Shift, EKeys::H ) );
|
|
UI_COMMAND( HideSelected, "Hide Selected", "Hides the selected actors", EUserInterfaceActionType::Button, FInputGesture( EKeys::H ) );
|
|
UI_COMMAND( ShowAllStartup, "Show All At Startup", "Shows all actors at startup", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( ShowSelectedStartup, "Show Selected At Startup", "Shows selected actors at startup", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( HideSelectedStartup, "Hide Selected At Startup", "Hide selected actors at startup", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( CycleNavigationDataDrawn, "Cycle Navigation Data Drawn", "Cycles through navigation data (navmeshes for example) to draw one at a time", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Alt, EKeys::N ) );
|
|
|
|
UI_COMMAND( SelectNone, "Unselect All", "Unselects all actors", EUserInterfaceActionType::Button, FInputGesture( EKeys::Escape ) ) ;
|
|
UI_COMMAND( InvertSelection, "Invert Selection", "Inverts the current selection", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( SelectAllActorsOfSameClass, "Select All Actors of Same Class", "Selects all the actors that have the same class", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift|EModifierKey::Control, EKeys::A) );
|
|
UI_COMMAND( SelectAllActorsOfSameClassWithArchetype, "Select All Actors with Same Archetype", "Selects all the actors of the same class that have the same archetype", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SelectRelevantLights, "Select Relevant Lights", "Select all lights relevant to the current selection", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SelectStaticMeshesOfSameClass, "Select All Using Selected Static Meshes (Selected Actor Types)", "Selects all actors with the same static mesh and actor class as the selection", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SelectStaticMeshesAllClasses, "Select All Using Selected Static Meshes (All Actor Types)", "Selects all actors with the same static mesh as the selection", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Shift, EKeys::E ) );
|
|
UI_COMMAND( SelectSkeletalMeshesOfSameClass, "Select All Using Selected Skeletal Meshes (Selected Actor Types)", "Selects all actors with the same skeletal mesh and actor class as the selection", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SelectSkeletalMeshesAllClasses, "Select All Using Selected Skeletal Meshes (All Actor Types)", "Selects all actors with the same skeletal mesh as the selection", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SelectAllWithSameMaterial, "Select All With Same Material", "Selects all actors with the same material as the selection", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SelectMatchingEmitter, "Select All Matching Emitters", "Selects all emitters with the same particle system as the selection", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SelectAllLights, "Select All Lights", "Selects all lights", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SelectStationaryLightsExceedingOverlap, "Select Stationary Lights exceeding overlap", "Selects all stationary lights exceeding the overlap limit", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SelectAllAddditiveBrushes, "Select All Additive Brushes", "Selects all additive brushes", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SelectAllSubtractiveBrushes, "Select All Subtractive Brushes", "Selects all subtractive brushes", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SelectAllSemiSolidBrushes, "Select All Semi-Solid Brushes", "Selects all semi-solid brushes", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SelectAllNonSolidBrushes, "Select All Non-Solid Brushes", "Selects all non-solid brushes", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SelectAllActorsControlledByMatinee, "Select Actors Used by This Matinee", "Selects all actors controlled by this Matinee", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( SelectAllSurfaces, "Select All Surfaces", "Selects all bsp surfaces", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift, EKeys::S) );
|
|
|
|
UI_COMMAND( SurfSelectAllMatchingBrush, "Select Matching Brush", "Selects the surfaces belonging to the same brush as the selected surfaces", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift, EKeys::B) );
|
|
UI_COMMAND( SurfSelectAllMatchingTexture, "Select Matching Material", "Selects all surfaces with the same material as the selected surfaces", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift, EKeys::T) );
|
|
UI_COMMAND( SurfSelectAllAdjacents, "Select All Adjacent Surfaces", "Selects all surfaces adjacent to the currently selected surfaces", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift, EKeys::J) );
|
|
UI_COMMAND( SurfSelectAllAdjacentCoplanars, "Select All Coplanar Surfaces", "Selects all surfaces adjacent and coplanar with the selected surfaces", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift, EKeys::C) );
|
|
UI_COMMAND( SurfSelectAllAdjacentWalls, "Select All Adjacent Wall Surfaces", "Selects all adjacent upright surfaces", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift, EKeys::W) );
|
|
UI_COMMAND( SurfSelectAllAdjacentFloors, "Select All Adjacent Floor Surfaces", "Selects all adjacent floor sufaces(ones with normals pointing up)", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift, EKeys::U) );
|
|
UI_COMMAND( SurfSelectAllAdjacentSlants, "Select All Adjacent Slant Surfaces", "Selects all adjacent slant surfaces (surfaces that are not walls, floors, or ceilings according to their normals) to the currently selected surfaces.", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift, EKeys::Y) );
|
|
UI_COMMAND( SurfSelectReverse, "Invert Surface Selection", "Inverts the current surface selection", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift, EKeys::Q) );
|
|
UI_COMMAND( SurfSelectMemorize, "Memorize Surface Selection", "Stores the current surface selection in memory", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift, EKeys::M) );
|
|
UI_COMMAND( SurfSelectRecall, "Recall Surface Selection", "Replace the current selection with the selection saved in memory", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift, EKeys::R) );
|
|
UI_COMMAND( SurfSelectOr, "Surface Selection OR", "Replace the current selection with only the surfaces which are both currently selected and contained within the saved selection in memory", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift, EKeys::O) );
|
|
UI_COMMAND( SurfSelectAnd, "Surface Selection AND", "Add the selection of surfaces saved in memory to the current selection", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift, EKeys::A) );
|
|
UI_COMMAND( SurfSelectXor, "Surace Selection XOR", " Replace the current selection with only the surfaces that are not in both the current selection and the selection saved in memory", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Shift, EKeys::X) );
|
|
UI_COMMAND( SurfUnalign, "Align Surface Default", "Default surface alignmment", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SurfAlignPlanarAuto, "Align Surface Planar", "Planar surface alignment", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SurfAlignPlanarWall, "Align Surface Planar Wall", "Planar wall surface alignment", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SurfAlignPlanarFloor, "Align Surface Planar Floor", "Planar floor surface alignment", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SurfAlignBox, "Align Surface Box", "Box surface alignment", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( SurfAlignFit, "Align Surface Fit", "Best fit surface alignment", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( ApplyMaterialToSurface, "Apply Material to Surface Selection", "Applies the selected material to the selected surfaces", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( CreateBoundingBoxVolume, "Create Bounding Box Blocking Volume From Mesh", "Create a bounding box blocking volume from the static mesh", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( CreateHeavyConvexVolume, "Heavy Convex Blocking Volume From Mesh", "Creates a heavy convex blocing volume from the static mesh", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( CreateNormalConvexVolume, "Normal Convex Blocking Volume From Mesh", "Creates a normal convex blocking volume from the static mesh", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( CreateLightConvexVolume, "Light Convex Blocking Volume From Mesh", "Creates a light convex blocking volume from the static mesh", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( CreateRoughConvexVolume, "Rought Convex Blocking Volume From Mesh", "Creates a rough convex blocking volume from the static mesh", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( SaveBrushAsCollision, "Save Collision from Builder Brush", "Creates a collision primitive on the selected static meshes based on the shape of the builder brush", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( KeepSimulationChanges, "Keep Simulation Changes", "Saves the changes made to this actor in Simulate mode to the actor's default state.", EUserInterfaceActionType::Button, FInputGesture( EKeys::K ) );
|
|
|
|
UI_COMMAND( MakeActorLevelCurrent, "Make Selected Actor's Level Current", "Makes the selected actors level the current level", EUserInterfaceActionType::Button, FInputGesture( EKeys::M ) );
|
|
UI_COMMAND( MoveSelectedToCurrentLevel, "Move Selection to Current Level", "Moves the selected actors to the current level", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Control, EKeys::M ) );
|
|
UI_COMMAND( FindLevelsInLevelBrowser, "Find Levels in Level Browser", "Finds the selected actors level in the level browser", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( AddLevelsToSelection, "Add Levels to Selection", "Adds the selected actors levels to the current level browser selection", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( RemoveLevelsFromSelection, "Remove Levels from Selection", "Removes the selected actors levels from the current level browser selection", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( FindActorInLevelScript, "Find in Level Blueprint", "Finds any references to the selected actor in its level's blueprint", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( WorldProperties, "World Properties", "Displays the world properties", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( OpenContentBrowser, "Open Content Browser", "Opens the Content Browser", EUserInterfaceActionType::Button, FInputGesture(EModifierKey::Control|EModifierKey::Shift, EKeys::F) );
|
|
UI_COMMAND( OpenMarketplace, "Open Marketplace", "Opens the Marketplace", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( AddMatinee, "Add Matinee", "Creates a new matinee actor to edit", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( EditMatinee, "Edit Matinee", "Selects a Matinee to edit", EUserInterfaceActionType::Button, FInputGesture() );
|
|
|
|
UI_COMMAND( OpenLevelBlueprint, "Open Level Blueprint", "Edit the Level Blueprint for the current level", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( OpenGameModeBlueprint, "Open/Create Game Mode Blueprint", "Opens or create the active GameMode blueprint", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( OpenGameStateBlueprint, "Open/Create Game State Blueprint", "Open or create the GameState blueprint and auto assign it to the active GameMode", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( OpenDefaultPawnBlueprint, "Open/Create Default Pawn Blueprint", "Open or create the Pawn blueprint and auto assign it to the active GameMode", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( OpenHUDBlueprint, "Open/Create HUD Blueprint", "Open or create the HUD blueprint and auto assign it to the active GameMode", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( OpenPlayerControllerBlueprint, "Open/Create Player Controller Blueprint", "Open or create the Player Controller blueprint and auto assign it to the active GameMode", EUserInterfaceActionType::Button, FInputGesture() );
|
|
UI_COMMAND( CreateClassBlueprint, "New Class Blueprint...", "Create a new Class Blueprint", EUserInterfaceActionType::Button, FInputGesture());
|
|
|
|
UI_COMMAND( ShowTransformWidget, "Show Transform Widget", "Toggles the visibility of the transform widgets", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( AllowTranslucentSelection, "Allow Translucent Selection", "Allows translucent objects to be selected", EUserInterfaceActionType::ToggleButton, FInputGesture(EKeys::T) );
|
|
UI_COMMAND( AllowGroupSelection, "Allow Group Selection", "Allows actor groups to be selected", EUserInterfaceActionType::ToggleButton, FInputGesture(EModifierKey::Control|EModifierKey::Shift, EKeys::G) );
|
|
UI_COMMAND( StrictBoxSelect, "Strict Box Selection", "When enabled an object must be entirely encompassed by the selection box when marquee box selecting", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( DrawBrushMarkerPolys, "Draw Brush Marker Polys", "Draws semi-transparent polygons around a brush when selected", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( OnlyLoadVisibleInPIE, "Only Load Visible Levels in Game Preview", "If enabled, when game preview starts, only visible levels will be loaded", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( ToggleSocketSnapping, "Enable Socket Snapping", "Enables or disables snapping to sockets", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( ToggleParticleSystemLOD, "Enable Particle System LOD Switching", "If enabled particle systems will use distance LOD switching in perspective viewports", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( ToggleFreezeParticleSimulation, "Freeze Particle Simulation", "If enabled particle systems will freeze their simulation state", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( ToggleParticleSystemHelpers, "Toggle Particle System Helpers", "Toggles showing particle system helper widgets in viewports", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( ToggleLODViewLocking, "Enable LOD View Locking", "If enabled viewports of the same type will use the same LOD", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( LevelStreamingVolumePrevis, "Enable Automatic Level Streaming", "If enabled, the viewport will stream in levels automatically when the camera is moved", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( EnableActorSnap, "Enable Actor Snapping", "If enabled, actors will snap to the location of other actors when they are within distance", EUserInterfaceActionType::ToggleButton, FInputGesture(EModifierKey::Control|EModifierKey::Shift, EKeys::K) );
|
|
UI_COMMAND( EnableVertexSnap, "Enable Vertex Snapping","If enabled, actors will snap to the location of the nearest vertex on another actor in the direction of movement", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
UI_COMMAND( ToggleHideViewportUI, "Hide Viewport UI", "Toggles hidden viewport UI mode. Hides all overlaid viewport UI widgets", EUserInterfaceActionType::ToggleButton, FInputGesture() );
|
|
|
|
//if (FParse::Param( FCommandLine::Get(), TEXT( "editortoolbox" ) ))
|
|
//{
|
|
// UI_COMMAND( BspMode, "Enable Bsp Mode", "Enables BSP mode", EUserInterfaceActionType::ToggleButton, FInputGesture( EModifierKey::Shift, EKeys::One ) );
|
|
// UI_COMMAND( MeshPaintMode, "Enable Mesh Paint Mode", "Enables mesh paint mode", EUserInterfaceActionType::ToggleButton, FInputGesture( EModifierKey::Shift, EKeys::Two ) );
|
|
// UI_COMMAND( LandscapeMode, "Enable Landscape Mode", "Enables landscape editing", EUserInterfaceActionType::ToggleButton, FInputGesture( EModifierKey::Shift, EKeys::Three ) );
|
|
// UI_COMMAND( FoliageMode, "Enable Foliage Mode", "Enables foliage editing", EUserInterfaceActionType::ToggleButton, FInputGesture( EModifierKey::Shift, EKeys::Four ) );
|
|
//}
|
|
|
|
UI_COMMAND( ShowSelectedDetails, "Show Actor Details", "Opens a details panel for the selected actors", EUserInterfaceActionType::Button, FInputGesture( EKeys::F4 ) );
|
|
|
|
UI_COMMAND( RecompileShaders, "Recompile Changed Shaders", "Recompiles shaders which are out of date", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Shift|EModifierKey::Control, EKeys::Period ) );
|
|
UI_COMMAND( ProfileGPU, "Profile GPU", "Profiles the GPU for the next frame and opens a window with profiled data", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Shift|EModifierKey::Control, EKeys::Comma ) );
|
|
|
|
UI_COMMAND( ResetAllParticleSystems, "Reset All Particle Systems", "Resets all particle system emitters (removes all active particles and restarts them)", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Shift, EKeys::Slash ) );
|
|
UI_COMMAND( ResetSelectedParticleSystem, "Resets Selected Particle Systems" , "Resets selected particle system emitters (removes all active particles and restarts them)", EUserInterfaceActionType::Button, FInputGesture( EKeys::Slash ) );
|
|
|
|
UI_COMMAND( SelectActorsInLayers, "Select all actors in selected actor's layers", "Selects all actors belonging to the layers of the currently selected actors", EUserInterfaceActionType::Button, FInputGesture( EModifierKey::Control, EKeys::L ) );
|
|
|
|
UI_COMMAND( FocusAllViewportsToSelection, "Focus Selected Actors in All Viewports", "Moves the camera in front of the selected actors in all open viewports", EUserInterfaceActionType::Button, FInputGesture( EKeys::F, EModifierKey::Shift ) );
|
|
|
|
UI_COMMAND( MaterialQualityLevel_Low, "Low", "Sets material quality in the scene to low.", EUserInterfaceActionType::RadioButton, FInputGesture() );
|
|
UI_COMMAND( MaterialQualityLevel_High, "High", "Sets material quality in the scene to high.", EUserInterfaceActionType::RadioButton, FInputGesture() );
|
|
|
|
for (int32 i = 0; i < ERHIFeatureLevel::Num; ++i)
|
|
{
|
|
FName Name;
|
|
GetFeatureLevelName((ERHIFeatureLevel::Type)i, Name);
|
|
|
|
FeatureLevelPreview[i] =
|
|
FUICommandInfoDecl(
|
|
this->AsShared(),
|
|
Name,
|
|
//FText::Format(NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreview", "Preview scenes using feature level {0}"), TEXT("Thing")),
|
|
FText::FromName(Name),
|
|
FText::Format(NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewTooltip", "Preview scenes using feature level {0}"), FText::FromName(Name)))
|
|
.UserInterfaceType(EUserInterfaceActionType::Button)
|
|
.DefaultGesture(FInputGesture());
|
|
}
|
|
}
|
|
|
|
PRAGMA_ENABLE_OPTIMIZATION
|
|
|
|
#undef LOCTEXT_NAMESPACE
|