You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
3087 lines
125 KiB
C++
3087 lines
125 KiB
C++
// Copyright 1998-2015 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/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 "MRUFavoritesList.h"
|
|
#include "Editor/SceneOutliner/Private/SSocketChooser.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 "ISizeMapModule.h"
|
|
#include "Developer/MeshUtilities/Public/MeshUtilities.h"
|
|
#include "EditorClassUtils.h"
|
|
#include "ComponentEditorUtils.h"
|
|
|
|
#include "EditorActorFolders.h"
|
|
#include "ActorPickerMode.h"
|
|
#include "EngineBuildSettings.h"
|
|
#include "HotReloadInterface.h"
|
|
#include "ISourceControlModule.h"
|
|
#include "SourceControlWindows.h"
|
|
#include "NotificationManager.h"
|
|
#include "SNotificationList.h"
|
|
#include "Engine/Selection.h"
|
|
#include "EngineUtils.h"
|
|
#include "Engine/StaticMeshActor.h"
|
|
#include "Engine/Polys.h"
|
|
#include "Components/LightComponent.h"
|
|
#include "Engine/StaticMesh.h"
|
|
#include "Engine/Light.h"
|
|
#include "Animation/SkeletalMeshActor.h"
|
|
#include "Editor/Persona/Public/AnimationRecorder.h"
|
|
#include "Editor/KismetWidgets/Public/CreateBlueprintFromActorDialog.h"
|
|
|
|
DEFINE_LOG_CATEGORY_STATIC(LevelEditorActions, Log, All);
|
|
|
|
#define LOCTEXT_NAMESPACE "LevelEditorActions"
|
|
|
|
const FName HotReloadModule("HotReload");
|
|
|
|
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(FDocumentationSourceInfo(TEXT("help_menu")));
|
|
}
|
|
|
|
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() && !GLevelEditorModeTools().IsTracking();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenLevel()
|
|
{
|
|
FEditorFileUtils::LoadMap();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OpenLevel_CanExecute()
|
|
{
|
|
return FSlateApplication::Get().IsNormalExecution() && !GLevelEditorModeTools().IsTracking();
|
|
}
|
|
|
|
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 );
|
|
|
|
// Move the item to the head of the list
|
|
MRUFavoritesList->MoveFavoritesItemToHead( 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()
|
|
{
|
|
if( GetWorld() && GetWorld()->GetOutermost() )
|
|
{
|
|
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;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::CanSaveWorld()
|
|
{
|
|
return FSlateApplication::Get().IsNormalExecution() && (!GUnrealEd || !GUnrealEd->GetPackageAutoSaver().IsAutoSaving());
|
|
}
|
|
|
|
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 )
|
|
{
|
|
auto* Settings = GetMutableDefault<UEditorPerProjectUserSettings>();
|
|
Settings->MaterialQualityLevel = NewQualityLevel;
|
|
Settings->PostEditChange();
|
|
|
|
//Ensure the material quality cvar is also set.
|
|
static IConsoleVariable* MaterialQualityLevelVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.MaterialQualityLevel"));
|
|
MaterialQualityLevelVar->Set(NewQualityLevel, ECVF_SetByScalability);
|
|
|
|
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)
|
|
{
|
|
// Record this feature level as we want to use it for all subsequent level creation and loading
|
|
GEditor->DefaultWorldFeatureLevel = InPreviewFeatureLevel;
|
|
|
|
GetWorld()->ChangeFeatureLevel(InPreviewFeatureLevel);
|
|
|
|
// Update any currently running PIE sessions.
|
|
for (TObjectIterator<UWorld> It; It; ++It)
|
|
{
|
|
UWorld* ItWorld = *It;
|
|
if (ItWorld->WorldType == EWorldType::PIE)
|
|
{
|
|
ItWorld->ChangeFeatureLevel(InPreviewFeatureLevel);
|
|
}
|
|
}
|
|
|
|
GUnrealEd->RedrawAllViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsFeatureLevelPreviewChecked(ERHIFeatureLevel::Type InPreviewFeatureLevel)
|
|
{
|
|
return InPreviewFeatureLevel == GetWorld()->FeatureLevel;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ConfigureLightingBuildOptions( const FLightingBuildOptions& Options )
|
|
{
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildSelected"), Options.bOnlyBuildSelected, GEditorPerProjectIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildCurrentLevel"), Options.bOnlyBuildCurrentLevel, GEditorPerProjectIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildSelectedLevels"),Options.bOnlyBuildSelectedLevels, GEditorPerProjectIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildVisibility"), Options.bOnlyBuildVisibility, GEditorPerProjectIni );
|
|
}
|
|
|
|
|
|
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, GEditorPerProjectIni);
|
|
return bUseErrorColoring;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::LightingBuildOptions_UseErrorColoring_Toggled()
|
|
{
|
|
bool bUseErrorColoring = false;
|
|
GConfig->GetBool( TEXT("LightingBuildOptions"), TEXT("UseErrorColoring"), bUseErrorColoring, GEditorPerProjectIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("UseErrorColoring"), !bUseErrorColoring, GEditorPerProjectIni );
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::LightingBuildOptions_ShowLightingStats_IsChecked()
|
|
{
|
|
bool bShowLightingBuildInfo = false;
|
|
GConfig->GetBool(TEXT("LightingBuildOptions"), TEXT("ShowLightingBuildInfo"), bShowLightingBuildInfo, GEditorPerProjectIni);
|
|
return bShowLightingBuildInfo;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::LightingBuildOptions_ShowLightingStats_Toggled()
|
|
{
|
|
bool bShowLightingBuildInfo = false;
|
|
GConfig->GetBool( TEXT("LightingBuildOptions"), TEXT("ShowLightingBuildInfo"), bShowLightingBuildInfo, GEditorPerProjectIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("ShowLightingBuildInfo"), !bShowLightingBuildInfo, GEditorPerProjectIni );
|
|
}
|
|
|
|
|
|
|
|
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 );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::BuildLODsOnly_Execute()
|
|
{
|
|
// Build paths!
|
|
FEditorBuildUtils::EditorBuild(GetWorld(), EBuildOptions::BuildHierarchicalLOD);
|
|
|
|
if (BuildLighting_CanExecute())
|
|
{
|
|
BuildLightingOnly_Execute();
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsLightingQualityChecked( ELightingBuildQuality TestQuality )
|
|
{
|
|
int32 CurrentQualityLevel;
|
|
GConfig->GetInt(TEXT("LightingBuildOptions"), TEXT("QualityLevel"), CurrentQualityLevel, GEditorPerProjectIni);
|
|
return TestQuality == CurrentQualityLevel;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingQuality( ELightingBuildQuality NewQuality )
|
|
{
|
|
GConfig->SetInt(TEXT("LightingBuildOptions"), TEXT("QualityLevel"), (int32)NewQuality, GEditorPerProjectIni);
|
|
}
|
|
|
|
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( ECheckBoxState NewCheckedState )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.bStaticMeshes = ( NewCheckedState == ECheckBoxState::Checked );
|
|
}
|
|
|
|
ECheckBoxState FLevelEditorActionCallbacks::IsLightingResolutionStaticMeshesChecked()
|
|
{
|
|
return ( FLightmapResRatioAdjustSettings::Get().bStaticMeshes ? ECheckBoxState::Checked : ECheckBoxState::Unchecked );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionBSPSurfaces( ECheckBoxState NewCheckedState )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.bBSPSurfaces = ( NewCheckedState == ECheckBoxState::Checked );
|
|
}
|
|
|
|
ECheckBoxState FLevelEditorActionCallbacks::IsLightingResolutionBSPSurfacesChecked()
|
|
{
|
|
return ( FLightmapResRatioAdjustSettings::Get().bBSPSurfaces ? ECheckBoxState::Checked : ECheckBoxState::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()
|
|
{
|
|
IHotReloadInterface& HotReloadSupport = FModuleManager::LoadModuleChecked<IHotReloadInterface>(HotReloadModule);
|
|
// If there is at least one loaded game module, source code actions should be available.
|
|
return HotReloadSupport.IsAnyGameModuleLoaded();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::RecompileGameCode_Clicked()
|
|
{
|
|
// Don't allow a recompile while already compiling!
|
|
IHotReloadInterface& HotReloadSupport = FModuleManager::LoadModuleChecked<IHotReloadInterface>(HotReloadModule);
|
|
if( !HotReloadSupport.IsCurrentlyCompiling() )
|
|
{
|
|
// Don't wait -- we want compiling to happen asynchronously
|
|
const bool bWaitForCompletion = false;
|
|
HotReloadSupport.DoHotReloadFromEditor(bWaitForCompletion);
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Recompile_CanExecute()
|
|
{
|
|
// We're not able to recompile if a compile is already in progress!
|
|
|
|
IHotReloadInterface& HotReloadSupport = FModuleManager::LoadModuleChecked<IHotReloadInterface>(HotReloadModule);
|
|
return !HotReloadSupport.IsCurrentlyCompiling() && !(GEngineVersion.IsPromotedBuild() && FEngineBuildSettings::IsPerforceBuild());
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ConnectToSourceControl_Clicked()
|
|
{
|
|
// Show login window regardless of current status - its useful as a shortcut to change settings.
|
|
ISourceControlModule& SourceControlModule = ISourceControlModule::Get();
|
|
SourceControlModule.ShowLoginDialog(FSourceControlLoginClosed(), ELoginWindowMode::Modeless, EOnLoginWindowStartup::PreserveProvider);
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CheckOutModifiedFiles_CanExecute()
|
|
{
|
|
ISourceControlModule& SourceControlModule = ISourceControlModule::Get();
|
|
if (ISourceControlModule::Get().IsEnabled() &&
|
|
ISourceControlModule::Get().GetProvider().IsAvailable())
|
|
{
|
|
TArray<UPackage*> PackagesToSave;
|
|
FEditorFileUtils::GetDirtyWorldPackages(PackagesToSave);
|
|
FEditorFileUtils::GetDirtyContentPackages(PackagesToSave);
|
|
|
|
return PackagesToSave.Num() > 0;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::CheckOutModifiedFiles_Clicked()
|
|
{
|
|
TArray<UPackage*> PackagesToSave;
|
|
FEditorFileUtils::GetDirtyWorldPackages(PackagesToSave);
|
|
FEditorFileUtils::GetDirtyContentPackages(PackagesToSave);
|
|
|
|
const bool bCheckDirty = true;
|
|
const bool bPromptUserToSave = false;
|
|
FEditorFileUtils::PromptForCheckoutAndSave(PackagesToSave, bCheckDirty, bPromptUserToSave);
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::SubmitToSourceControl_CanExecute()
|
|
{
|
|
ISourceControlModule& SourceControlModule = ISourceControlModule::Get();
|
|
return ISourceControlModule::Get().IsEnabled() &&
|
|
ISourceControlModule::Get().GetProvider().IsAvailable() &&
|
|
FSourceControlWindows::CanChoosePackagesToCheckIn();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SubmitToSourceControl_Clicked()
|
|
{
|
|
FSourceControlWindows::ChoosePackagesToCheckIn();
|
|
}
|
|
|
|
|
|
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::GoToDocsForActor_Clicked()
|
|
{
|
|
const auto& SelectedActorInfo = AssetSelectionUtils::GetSelectedActorInfo();
|
|
if( SelectedActorInfo.SelectionClass != nullptr )
|
|
{
|
|
FString DocumentationLink = FEditorClassUtils::GetDocumentationLink(SelectedActorInfo.SelectionClass);
|
|
if (!DocumentationLink.IsEmpty())
|
|
{
|
|
IDocumentation::Get()->Open( DocumentationLink, FDocumentationSourceInfo(TEXT("rightclick_viewdoc")) );
|
|
}
|
|
}
|
|
}
|
|
|
|
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::ViewSizeMap_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());
|
|
}
|
|
}
|
|
|
|
ISizeMapModule::Get().InvokeSizeMapTab(ViewableObjects);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanViewSizeMap()
|
|
{
|
|
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;
|
|
const bool bIgnoreOtherAssetsIfBPReferenced = true;
|
|
GEditor->GetReferencedAssetsForEditorSelection( ReferencedAssets, bIgnoreOtherAssetsIfBPReferenced );
|
|
|
|
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);
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::GoHere_Clicked( const FVector* Point )
|
|
{
|
|
if( GCurrentLevelEditingViewportClient )
|
|
{
|
|
FVector ZoomToPoint;
|
|
if( !Point )
|
|
{
|
|
FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(
|
|
GCurrentLevelEditingViewportClient->Viewport,
|
|
GCurrentLevelEditingViewportClient->GetWorld()->Scene,
|
|
GCurrentLevelEditingViewportClient->EngineShowFlags)
|
|
.SetRealtimeUpdate(true));
|
|
|
|
|
|
FSceneView* SceneView = GCurrentLevelEditingViewportClient->CalcSceneView(&ViewFamily);
|
|
|
|
if(SceneView)
|
|
{
|
|
FIntPoint MousePosition;
|
|
FVector WorldOrigin;
|
|
FVector WorldDirection;
|
|
GCurrentLevelEditingViewportClient->Viewport->GetMousePos(MousePosition);
|
|
|
|
SceneView->DeprojectFVector2D(MousePosition, WorldOrigin, WorldDirection);
|
|
|
|
FHitResult HitResult;
|
|
|
|
static FName FocusOnPoint = FName(TEXT("FocusOnPoint"));
|
|
FCollisionQueryParams LineParams(FocusOnPoint, true);
|
|
|
|
if(GCurrentLevelEditingViewportClient->GetWorld()->LineTraceSingleByObjectType(HitResult, WorldOrigin, WorldOrigin + WorldDirection * HALF_WORLD_MAX, FCollisionObjectQueryParams(ECC_WorldStatic), LineParams))
|
|
{
|
|
ZoomToPoint = HitResult.ImpactPoint;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ZoomToPoint = *Point;
|
|
}
|
|
|
|
const float PushOutSize = 500;
|
|
FBox BoundingBox(ZoomToPoint-PushOutSize, ZoomToPoint+PushOutSize);
|
|
|
|
GCurrentLevelEditingViewportClient->FocusViewportOnBox(BoundingBox);
|
|
}
|
|
}
|
|
|
|
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();
|
|
|
|
// Make sure we're in actor placement mode
|
|
GLevelEditorModeTools().ActivateMode(FBuiltinEditorModes::EM_Placement);
|
|
|
|
TArray<UObject*> AssetsToPlace;
|
|
AssetsToPlace.Add(Object);
|
|
|
|
auto* PlacementMode = GLevelEditorModeTools().GetActiveModeTyped<IPlacementMode>(FBuiltinEditorModes::EM_Placement);
|
|
PlacementMode->StartPlacing(AssetsToPlace, ActorFactory);
|
|
}
|
|
else
|
|
{
|
|
FLevelEditorActionCallbacks::AddActor(ActorFactory, AssetData, NULL);
|
|
}
|
|
}
|
|
|
|
AActor* FLevelEditorActionCallbacks::AddActor( UActorFactory* ActorFactory, const FAssetData& AssetData, const FTransform* ActorTransform )
|
|
{
|
|
AActor* NewActor = GEditor->UseActorFactory( ActorFactory, AssetData, ActorTransform );
|
|
|
|
if ( NewActor != NULL && IPlacementModeModule::IsAvailable() )
|
|
{
|
|
IPlacementModeModule::Get().AddToRecentlyPlaced( AssetData.GetAsset(), ActorFactory );
|
|
}
|
|
|
|
return NewActor;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AddActorFromClass_Clicked( UClass* ActorClass )
|
|
{
|
|
FLevelEditorActionCallbacks::AddActorFromClass(ActorClass);
|
|
}
|
|
|
|
AActor* FLevelEditorActionCallbacks::AddActorFromClass( UClass* ActorClass )
|
|
{
|
|
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, nullptr );
|
|
|
|
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 );
|
|
|
|
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 );
|
|
}
|
|
else if ( ActorFactory->CanCreateActorFrom( NoAssetData, UnusedErrorMessage ) )
|
|
{
|
|
// Replace all selected actors with actors created from the specified factory
|
|
GEditor->ReplaceSelectedActors( ActorFactory, NoAssetData );
|
|
}
|
|
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;
|
|
GLevelEditorModeTools().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;
|
|
}
|
|
}
|
|
|
|
// If we can copy, we can duplicate
|
|
bool bCanCopy = false;
|
|
if (GEditor->GetSelectedComponentCount() > 0)
|
|
{
|
|
TArray<UActorComponent*> SelectedComponents;
|
|
for (FSelectionIterator It(GEditor->GetSelectedComponentIterator()); It; ++It)
|
|
{
|
|
SelectedComponents.Add(CastChecked<UActorComponent>(*It));
|
|
}
|
|
|
|
bCanCopy = FComponentEditorUtils::CanCopyComponents(SelectedComponents);
|
|
}
|
|
else
|
|
{
|
|
bCanCopy = GUnrealEd->CanCopySelectedActorsToClipboard(GetWorld());
|
|
}
|
|
|
|
return bCanCopy;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Delete_CanExecute()
|
|
{
|
|
TArray<FEdMode*> ActiveModes;
|
|
GLevelEditorModeTools().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;
|
|
}
|
|
}
|
|
|
|
bool bCanDelete = false;
|
|
if (GEditor->GetSelectedComponentCount() > 0)
|
|
{
|
|
TArray<UActorComponent*> SelectedComponents;
|
|
for (FSelectionIterator It(GEditor->GetSelectedComponentIterator()); It; ++It)
|
|
{
|
|
SelectedComponents.Add(CastChecked<UActorComponent>(*It));
|
|
}
|
|
|
|
bCanDelete = FComponentEditorUtils::CanDeleteComponents(SelectedComponents);
|
|
}
|
|
else
|
|
{
|
|
bCanDelete = GUnrealEd->CanDeleteSelectedActors(GetWorld(), true, false);
|
|
}
|
|
|
|
return bCanDelete;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::Rename_Execute()
|
|
{
|
|
UActorComponent* Component = Cast<UActorComponent>(*GEditor->GetSelectedComponentIterator());
|
|
if (Component)
|
|
{
|
|
GEditor->BroadcastLevelComponentRequestRename(Component);
|
|
}
|
|
else
|
|
{
|
|
AActor* Actor = Cast<AActor>(*GEditor->GetSelectedActorIterator());
|
|
if (Actor)
|
|
{
|
|
GEditor->BroadcastLevelActorRequestRename(Actor);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Rename_CanExecute()
|
|
{
|
|
bool bCanRename = false;
|
|
if (GEditor->GetSelectedComponentCount() == 1)
|
|
{
|
|
if (UActorComponent* ComponentToRename = GEditor->GetSelectedComponents()->GetTop<UActorComponent>())
|
|
{
|
|
// We can't edit non-instance components or the default scene root
|
|
bCanRename = ComponentToRename->CreationMethod == EComponentCreationMethod::Instance && ComponentToRename->GetFName() != USceneComponent::GetDefaultSceneRootVariableName();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bCanRename = GEditor->GetSelectedActorCount() == 1;
|
|
}
|
|
|
|
return bCanRename;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Cut_CanExecute()
|
|
{
|
|
TArray<FEdMode*> ActiveModes;
|
|
GLevelEditorModeTools().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;
|
|
}
|
|
}
|
|
|
|
bool bCanCut = false;
|
|
if (GEditor->GetSelectedComponentCount() > 0)
|
|
{
|
|
// Make sure the components can be copied and deleted
|
|
TArray<UActorComponent*> SelectedComponents;
|
|
for (FSelectionIterator It(GEditor->GetSelectedComponentIterator()); It; ++It)
|
|
{
|
|
SelectedComponents.Add(CastChecked<UActorComponent>(*It));
|
|
}
|
|
|
|
bCanCut = FComponentEditorUtils::CanCopyComponents(SelectedComponents) && FComponentEditorUtils::CanDeleteComponents(SelectedComponents);
|
|
}
|
|
else
|
|
{
|
|
// For actors, if we can copy, we can cut
|
|
bCanCut = GUnrealEd->CanCopySelectedActorsToClipboard(GetWorld());
|
|
}
|
|
|
|
return bCanCut;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Copy_CanExecute()
|
|
{
|
|
TArray<FEdMode*> ActiveModes;
|
|
GLevelEditorModeTools().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;
|
|
}
|
|
}
|
|
|
|
bool bCanCopy = false;
|
|
if (GEditor->GetSelectedComponentCount() > 0)
|
|
{
|
|
TArray<UActorComponent*> SelectedComponents;
|
|
for (FSelectionIterator It(GEditor->GetSelectedComponentIterator()); It; ++It)
|
|
{
|
|
SelectedComponents.Add(CastChecked<UActorComponent>(*It));
|
|
}
|
|
|
|
bCanCopy = FComponentEditorUtils::CanCopyComponents(SelectedComponents);
|
|
}
|
|
else
|
|
{
|
|
bCanCopy = GUnrealEd->CanCopySelectedActorsToClipboard(GetWorld());
|
|
}
|
|
|
|
return bCanCopy;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Paste_CanExecute()
|
|
{
|
|
TArray<FEdMode*> ActiveModes;
|
|
GLevelEditorModeTools().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;
|
|
}
|
|
}
|
|
|
|
bool bCanPaste = false;
|
|
if (GEditor->GetSelectedComponentCount() > 0)
|
|
{
|
|
check(GEditor->GetSelectedActorCount() == 1);
|
|
auto SelectedActor = CastChecked<AActor>(*GEditor->GetSelectedActorIterator());
|
|
bCanPaste = FComponentEditorUtils::CanPasteComponents(SelectedActor->GetRootComponent());
|
|
}
|
|
else
|
|
{
|
|
bCanPaste = GUnrealEd->CanPasteSelectedActorsFromClipboard(GetWorld());
|
|
}
|
|
|
|
return bCanPaste;
|
|
}
|
|
|
|
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::OnSelectComponentOwnerActor()
|
|
{
|
|
auto ComponentOwner = Cast<AActor>(*GEditor->GetSelectedActorIterator());
|
|
check(ComponentOwner);
|
|
|
|
GEditor->SelectNone(true, true, false);
|
|
GEditor->SelectActor(ComponentOwner, true, true, true);
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanSelectComponentOwnerActor()
|
|
{
|
|
return GEditor->GetSelectedComponentCount() > 0;
|
|
}
|
|
|
|
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( GLevelEditorModeTools().IsModeActive( FBuiltinEditorModes::EM_InterpEdit ) )
|
|
{
|
|
FEdModeInterpEdit* InterpEditMode = (FEdModeInterpEdit*)GLevelEditorModeTools().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()
|
|
{
|
|
GEditor->GetSelectedActors()->BeginBatchSelectOperation();
|
|
// Select all light actors.
|
|
for( TActorIterator<ALight> It(GetWorld()); It; ++It )
|
|
{
|
|
GUnrealEd->SelectActor( *It, true, false, false );
|
|
}
|
|
|
|
GEditor->GetSelectedActors()->EndBatchSelectOperation();
|
|
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectStationaryLightsExceedingOverlap()
|
|
{
|
|
GEditor->SelectNone( true, true );
|
|
for( FActorIterator It(GetWorld()); It; ++It )
|
|
{
|
|
AActor* Actor = *It;
|
|
|
|
TInlineComponentArray<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( GetWorld(), 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()
|
|
{
|
|
IMeshUtilities* MeshUtilities = FModuleManager::Get().LoadModulePtr<IMeshUtilities>("MeshUtilities");
|
|
|
|
if (MeshUtilities && MeshUtilities->GetMeshMergingInterface() != nullptr)
|
|
{
|
|
FSelectedActorInfo Info = AssetSelectionUtils::GetSelectedActorInfo();
|
|
return (Info.bHaveStaticMeshComponent || Info.bHaveLandscape);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::SaveAnimationFromSkeletalMeshComponent(AActor * EditorActor, AActor * SimActor, TArray<class USkeletalMeshComponent*> & OutEditorComponents)
|
|
{
|
|
// currently blueprint actors don't work because their property can't get copied over.
|
|
if (Cast<UBlueprintGeneratedClass>(EditorActor->GetClass()) != nullptr)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// find all skel components
|
|
TInlineComponentArray<class USkeletalMeshComponent *> SimSkelComponents;
|
|
SimActor->GetComponents<USkeletalMeshComponent>(SimSkelComponents);
|
|
|
|
if(SimSkelComponents.Num() > 0)
|
|
{
|
|
// see if simulating,
|
|
bool bSimulating = false;
|
|
for (auto & Comp : SimSkelComponents)
|
|
{
|
|
bSimulating |= (Comp->SkeletalMesh && Comp->SkeletalMesh->Skeleton && Comp->IsSimulatingPhysics());
|
|
}
|
|
|
|
// if any of them are legitimately simulating
|
|
if (bSimulating)
|
|
{
|
|
// ask users if you'd like to make an animation
|
|
FFormatNamedArguments Args;
|
|
Args.Add(TEXT("ActorName"), FText::FromString(GetNameSafe(EditorActor)));
|
|
FText AskQuestion = FText::Format(LOCTEXT("KeepSimulationChanges_AskSaveAnimation", "Would you like to save animations from simulation for {ActorName} actor"), Args);
|
|
if(EAppReturnType::Yes == FMessageDialog::Open(EAppMsgType::YesNo, AskQuestion))
|
|
{
|
|
for (auto & Comp : SimSkelComponents)
|
|
{
|
|
if (Comp->SkeletalMesh && Comp->SkeletalMesh->Skeleton && Comp->IsSimulatingPhysics())
|
|
{
|
|
// now record to animation
|
|
FAnimationRecorder Recorder;
|
|
if(Recorder.TriggerRecordAnimation(Comp))
|
|
{
|
|
class UAnimSequence * Sequence = Recorder.GetAnimationObject();
|
|
if(Sequence)
|
|
{
|
|
Recorder.StopRecord(false);
|
|
Comp->SetAnimationMode(EAnimationMode::AnimationSingleNode);
|
|
Comp->AnimationData.AnimToPlay = Sequence;
|
|
Comp->SetAnimation(Sequence);
|
|
Comp->SetSimulatePhysics(false);
|
|
|
|
// add the matching component to EditorCompoennts
|
|
class USkeletalMeshComponent * MatchingComponent = Cast<USkeletalMeshComponent>(EditorUtilities::FindMatchingComponentInstance(Comp, EditorActor));
|
|
if (MatchingComponent)
|
|
{
|
|
OutEditorComponents.Add(MatchingComponent);
|
|
}
|
|
else
|
|
{
|
|
UE_LOG( LevelEditorActions, Warning, TEXT("Matching component could not be found %s(%s)"), *GetNameSafe(Comp), *GetNameSafe(EditorActor) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
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" ) );
|
|
|
|
TArray<class USkeletalMeshComponent*> ComponentsToReinitialize;
|
|
|
|
for( auto ActorIt( GEditor->GetSelectedActorIterator() ); ActorIt; ++ActorIt )
|
|
{
|
|
auto* SimWorldActor = CastChecked<AActor>( *ActorIt );
|
|
|
|
// Find our counterpart actor
|
|
AActor* EditorWorldActor = EditorUtilities::GetEditorWorldCounterpartActor( SimWorldActor );
|
|
if( EditorWorldActor != NULL )
|
|
{
|
|
SaveAnimationFromSkeletalMeshComponent(EditorWorldActor, SimWorldActor, ComponentsToReinitialize);
|
|
|
|
// 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 |
|
|
EditorUtilities::ECopyOptions::FilterBlueprintReadOnly);
|
|
const int32 CopiedPropertyCount = EditorUtilities::CopyActorProperties( SimWorldActor, EditorWorldActor, CopyOptions );
|
|
|
|
if( CopiedPropertyCount > 0 )
|
|
{
|
|
++UpdatedActorCount;
|
|
TotalCopiedPropertyCount += CopiedPropertyCount;
|
|
|
|
if( FirstUpdatedActorLabel.IsEmpty() )
|
|
{
|
|
FirstUpdatedActorLabel = EditorWorldActor->GetActorLabel();
|
|
}
|
|
}
|
|
}
|
|
|
|
// need to reinitialize animation
|
|
for (auto MeshComp : ComponentsToReinitialize)
|
|
{
|
|
if(MeshComp->SkeletalMesh)
|
|
{
|
|
MeshComp->InitAnim(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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 Epic Games 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::CanSelectGameModeBlueprint()
|
|
{
|
|
bool bCheckOutNeeded = false;
|
|
|
|
FString ConfigFilePath = FPaths::ConvertRelativePathToFull(FString::Printf(TEXT("%sDefaultEngine.ini"), *FPaths::SourceConfigDir()));
|
|
if(ISourceControlModule::Get().IsEnabled())
|
|
{
|
|
// note: calling QueueStatusUpdate often does not spam status updates as an internal timer prevents this
|
|
//ISourceControlModule::Get().QueueStatusUpdate(ConfigFilePath);
|
|
|
|
ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider();
|
|
FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(ConfigFilePath, EStateCacheUsage::Use);
|
|
bCheckOutNeeded = SourceControlState.IsValid() && SourceControlState->CanCheckout();
|
|
}
|
|
else
|
|
{
|
|
bCheckOutNeeded = (FPaths::FileExists(ConfigFilePath) && IFileManager::Get().IsReadOnly(*ConfigFilePath));
|
|
}
|
|
return !bCheckOutNeeded;
|
|
}
|
|
|
|
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::CreateBlankBlueprintClass()
|
|
{
|
|
// Use the BlueprintFactory to allow the user to pick a parent class for the new Blueprint class
|
|
UBlueprintFactory* NewFactory = Cast<UBlueprintFactory>(NewObject<UFactory>(GetTransientPackage(), 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", "CreateBlankBlueprintClass_Title", "Create Blank Blueprint Class"), SelectedClass);
|
|
|
|
if( Blueprint )
|
|
{
|
|
// @todo Re-enable once world centric works
|
|
const bool bOpenWorldCentric = false;
|
|
FAssetEditorManager::Get().OpenEditorForAsset(
|
|
Blueprint,
|
|
bOpenWorldCentric ? EToolkitMode::WorldCentric : EToolkitMode::Standalone);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanHarvestSelectedActorsIntoBlueprintClass()
|
|
{
|
|
return GEditor->GetSelectedActorCount() > 0;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::HarvestSelectedActorsIntoBlueprintClass()
|
|
{
|
|
const bool bHarvest = true;
|
|
FCreateBlueprintFromActorDialog::OpenDialog(bHarvest);
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanSubclassSelectedActorIntoBlueprintClass()
|
|
{
|
|
return GEditor->GetSelectedActorCount() == 1;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SubclassSelectedActorIntoBlueprintClass()
|
|
{
|
|
const bool bHarvest = false;
|
|
FCreateBlueprintFromActorDialog::OpenDialog(bHarvest);
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::CheckOutProjectSettingsConfig( )
|
|
{
|
|
FString ConfigFilePath = FPaths::ConvertRelativePathToFull(FString::Printf(TEXT("%sDefaultEngine.ini"), *FPaths::SourceConfigDir()));
|
|
if(ISourceControlModule::Get().IsEnabled())
|
|
{
|
|
SourceControlHelpers::CheckOutFile(ConfigFilePath);
|
|
}
|
|
else
|
|
{
|
|
FPlatformFileManager::Get().GetPlatformFile().SetReadOnly(*ConfigFilePath, false);
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnShowOnlySelectedActors()
|
|
{
|
|
const FScopedTransaction Transaction( NSLOCTEXT( "LevelEditorCommands", "ShowOnlySelectedActors", "Show Only Selected Actors" ) );
|
|
GUnrealEd->edactUnhideSelected( GetWorld() );
|
|
GUnrealEd->edactHideUnselected( GetWorld() );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleTransformWidgetVisibility()
|
|
{
|
|
GLevelEditorModeTools().SetShowWidget( !GLevelEditorModeTools().GetShowWidget() );
|
|
GUnrealEd->RedrawAllViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnGetTransformWidgetVisibility()
|
|
{
|
|
return GLevelEditorModeTools().GetShowWidget();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnAllowTranslucentSelection()
|
|
{
|
|
auto* Settings = GetMutableDefault<UEditorPerProjectUserSettings>();
|
|
|
|
// Toggle 'allow select translucent'
|
|
Settings->bAllowSelectTranslucent = !Settings->bAllowSelectTranslucent;
|
|
Settings->PostEditChange();
|
|
|
|
// Need to refresh hit proxies as we changed what should be rendered into them
|
|
GUnrealEd->RedrawAllViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsAllowTranslucentSelectionEnabled()
|
|
{
|
|
return GetDefault<UEditorPerProjectUserSettings>()->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::OnToggleTransparentBoxSelect()
|
|
{
|
|
ULevelEditorViewportSettings* ViewportSettings = GetMutableDefault<ULevelEditorViewportSettings>();
|
|
ViewportSettings->bTransparentBoxSelection = !ViewportSettings->bTransparentBoxSelection;
|
|
ViewportSettings->PostEditChange();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsTransparentBoxSelectEnabled()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->bTransparentBoxSelection;
|
|
}
|
|
|
|
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, ECVF_SetByConsole);
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsParticleSimulationFrozen()
|
|
{
|
|
IConsoleManager& ConsoleManager = IConsoleManager::Get();
|
|
static const auto* CVar = ConsoleManager.FindTConsoleVariableDataInt(TEXT("FX.FreezeParticleSimulation"));
|
|
if (CVar)
|
|
{
|
|
return CVar->GetValueOnGameThread() != 0;
|
|
}
|
|
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;
|
|
}
|
|
|
|
FText FLevelEditorActionCallbacks::GetAudioVolumeToolTip()
|
|
{
|
|
if ( !GEditor->IsRealTimeAudioMuted() )
|
|
{
|
|
const float Volume = GEditor->GetRealTimeAudioVolume() * 100.0f;
|
|
return FText::AsNumber( FMath::RoundToInt(Volume) );
|
|
}
|
|
return NSLOCTEXT("UnrealEd", "Muted", "Muted" );
|
|
}
|
|
|
|
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::SnapObjectToView_Clicked()
|
|
{
|
|
for (FSelectionIterator It(GEditor->GetSelectedActorIterator()); It; ++It)
|
|
{
|
|
AActor* Actor = Cast<AActor>(*It);
|
|
FVector location = GCurrentLevelEditingViewportClient->GetViewLocation();
|
|
FRotator rotation = GCurrentLevelEditingViewportClient->GetViewRotation();
|
|
|
|
Actor->SetActorLocation(location);
|
|
Actor->SetActorRotation(rotation);
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
FText FLevelEditorActionCallbacks::GetActorSnapTooltip()
|
|
{
|
|
// If the setting is enabled, return the distance, otherwise say disabled
|
|
if ( FSnappingUtils::IsSnapToActorEnabled() )
|
|
{
|
|
static const FNumberFormattingOptions FormatOptions = FNumberFormattingOptions()
|
|
.SetMinimumFractionalDigits(2)
|
|
.SetMaximumFractionalDigits(2);
|
|
return FText::AsNumber( FSnappingUtils::GetActorSnapDistance(), &FormatOptions );
|
|
}
|
|
return NSLOCTEXT("UnrealEd", "Disabled", "Disabled" );
|
|
}
|
|
|
|
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()
|
|
{
|
|
GLevelEditorModeTools().SetHideViewportUI( !GLevelEditorModeTools().IsViewportUIHidden() );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsViewportUIHidden()
|
|
{
|
|
return GLevelEditorModeTools().IsViewportUIHidden();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsEditorModeActive( FEditorModeID EditorMode )
|
|
{
|
|
return GLevelEditorModeTools().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(), &FTransform::Identity ) );
|
|
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( !GLevelEditorModeTools().IsTracking() )
|
|
{
|
|
GLevelEditorModeTools().SetWidgetMode( WidgetMode );
|
|
GEditor->RedrawAllViewports();
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsWidgetModeActive( FWidget::EWidgetMode WidgetMode )
|
|
{
|
|
return GLevelEditorModeTools().GetWidgetMode() == WidgetMode;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanSetWidgetMode( FWidget::EWidgetMode WidgetMode )
|
|
{
|
|
return GLevelEditorModeTools().GetShowWidget() == true;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsTranslateRotateModeVisible()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->bAllowTranslateRotateZWidget;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetCoordinateSystem( ECoordSystem CoordinateSystem )
|
|
{
|
|
GLevelEditorModeTools().SetCoordSystem( CoordinateSystem );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsCoordinateSystemActive( ECoordSystem CoordinateSystem )
|
|
{
|
|
return GLevelEditorModeTools().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::SnapToFloor_Clicked( bool InAlign, bool InUseLineTrace, bool InUseBounds, bool InUsePivot )
|
|
{
|
|
const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "SnapActorsToFloor", "Snap Actors To Floor") );
|
|
SnapTo_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") );
|
|
SnapTo_Clicked( InAlign, InUseLineTrace, InUseBounds, InUsePivot, Actor );
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SnapTo_Clicked( const bool InAlign, const bool InUseLineTrace, const bool InUseBounds, const bool InUsePivot, AActor* InDestination )
|
|
{
|
|
// Fires ULevel::LevelDirtiedEvent when falling out of scope.
|
|
FScopedLevelDirtied LevelDirtyCallback;
|
|
|
|
bool bSnappedComponents = false;
|
|
if( GEditor->GetSelectedComponentCount() > 0 )
|
|
{
|
|
for(FSelectedEditableComponentIterator It(GEditor->GetSelectedEditableComponentIterator()); It; ++It)
|
|
{
|
|
USceneComponent* SceneComponent = Cast<USceneComponent>(*It);
|
|
if(SceneComponent)
|
|
{
|
|
SceneComponent->Modify();
|
|
AActor* ActorOwner = SceneComponent->GetOwner();
|
|
bSnappedComponents = true;
|
|
if(ActorOwner)
|
|
{
|
|
ActorOwner->Modify();
|
|
GEditor->SnapObjectTo(FActorOrComponent(SceneComponent), InAlign, InUseLineTrace, InUseBounds, InUsePivot, FActorOrComponent(InDestination));
|
|
ActorOwner->InvalidateLightingCache();
|
|
ActorOwner->UpdateComponentTransforms();
|
|
|
|
LevelDirtyCallback.Request();
|
|
}
|
|
}
|
|
}
|
|
|
|
USceneComponent* LastComp = GEditor->GetSelectedComponents()->GetBottom<USceneComponent>();
|
|
|
|
GEditor->SetPivot(LastComp->GetComponentLocation(), false, true);
|
|
}
|
|
|
|
if( !bSnappedComponents )
|
|
{
|
|
for(FSelectionIterator It(GEditor->GetSelectedActorIterator()); It; ++It)
|
|
{
|
|
AActor* Actor = Cast<AActor>(*It);
|
|
if(Actor)
|
|
{
|
|
Actor->Modify();
|
|
GEditor->SnapObjectTo(FActorOrComponent(Actor), InAlign, InUseLineTrace, InUseBounds, InUsePivot, FActorOrComponent(InDestination));
|
|
Actor->InvalidateLightingCache();
|
|
Actor->UpdateComponentTransforms();
|
|
|
|
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)->GetStaticMeshComponent();
|
|
}
|
|
|
|
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.InverseFast();
|
|
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 = NewObject<UModel>();
|
|
TempModel->Initialize(nullptr, 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, FInputChord( EKeys::F1 ) );
|
|
UI_COMMAND( BrowseAPIReference, "API Reference...", "Opens the API reference documentation", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BrowseViewportControls, "Viewport Controls...", "Opens the viewport controls cheat sheet", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( NewLevel, "New Level...", "Create a new level, or choose a level template to start from.", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Control, EKeys::N ) );
|
|
UI_COMMAND( OpenLevel, "Open Level...", "Loads an existing level", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Control, EKeys::O ) );
|
|
UI_COMMAND( Save, "Save", "Saves the current level to disk", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SaveAs, "Save As...", "Save the current level as...", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Shift|EModifierKey::Control, EKeys::S ) );
|
|
UI_COMMAND( SaveAllLevels, "Save All Levels", "Saves all unsaved levels to disk", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ToggleFavorite, "Toggle Favorite", "Sets whether the currently loaded level will appear in the list of favorite levels", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
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 )
|
|
.DefaultChord( FInputChord() );
|
|
OpenRecentFileCommands.Add( OpenRecentFile );
|
|
}
|
|
|
|
UI_COMMAND( Import, "Import...", "Imports objects and actors from a T3D format into the current level", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ExportAll, "Export All...", "Exports the entire level to a file on disk (multiple formats are supported.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ExportSelected, "Export Selected...", "Exports currently-selected objects to a file on disk (multiple formats are supported.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( Build, "Build All Levels", "Builds all levels (precomputes lighting data and visibility data, generates navigation networks and updates brush models.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BuildAndSubmitToSourceControl, "Build and Submit...", "Displays a window that allows you to build all levels and submit them to source control", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BuildLightingOnly, "Build Lighting", "Only precomputes lighting (all levels.)", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Control|EModifierKey::Shift, EKeys::Semicolon) );
|
|
UI_COMMAND( BuildReflectionCapturesOnly, "Update Reflection Captures", "Only updates Reflection Captures (all levels.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BuildLightingOnly_VisibilityOnly, "Precompute Static Visibility", "Only precomputes static visibility data (all levels.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( LightingBuildOptions_UseErrorColoring, "Use Error Coloring", "When enabled, errors during lighting precomputation will be baked as colors into light map data", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
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, FInputChord() );
|
|
UI_COMMAND( BuildGeometryOnly, "Build Geometry", "Only builds geometry (all levels.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BuildGeometryOnly_OnlyCurrentLevel, "Build Geometry (Current Level)", "Builds geometry, only for the current level", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BuildPathsOnly, "Build Paths", "Only builds paths (all levels.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BuildLODsOnly, "Build LODs", "Only builds LODs (all levels.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( LightingQuality_Production, "Production", "Sets precomputed lighting quality to highest possible quality (slowest computation time.)", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( LightingQuality_High, "High", "Sets precomputed lighting quality to high quality", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( LightingQuality_Medium, "Medium", "Sets precomputed lighting quality to medium quality", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( LightingQuality_Preview, "Preview", "Sets precomputed lighting quality to preview quality (fastest computation time.)", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( LightingDensity_RenderGrayscale, "Render Grayscale", "Renders the lightmap density.", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( LightingResolution_CurrentLevel, "Current Level", "Adjust only primitives in the current level.", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( LightingResolution_SelectedLevels, "Selected Levels", "Adjust only primitives in the selected levels.", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( LightingResolution_AllLoadedLevels, "All Loaded Levels", "Adjust primitives in all loaded levels.", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( LightingResolution_SelectedObjectsOnly, "Selected Objects Only", "Adjust only selected objects in the levels.", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( LightingStaticMeshInfo, "Lighting StaticMesh Info...", "Shows the lighting information for the StaticMeshes.", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SceneStats, "Open Scene Stats", "Opens the Scene Stats viewer", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( TextureStats, "Open Texture Stats", "Opens the Texture Stats viewer", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MapCheck, "Open Map Check", "Checks map for errors", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( RecompileGameCode, "Recompile Game Code", "Recompiles and reloads C++ code for game systems on the fly", EUserInterfaceActionType::Button, FInputChord( EKeys::P, EModifierKey::Alt | EModifierKey::Control | EModifierKey::Shift ) );
|
|
|
|
UI_COMMAND( EditAsset, "Edit Asset", "Edits the asset associated with the selected actor", EUserInterfaceActionType::Button, FInputChord( EKeys::E, EModifierKey::Control ) );
|
|
UI_COMMAND( EditAssetNoConfirmMultiple, "Edit Asset", "Edits the asset associated with the selected actor", EUserInterfaceActionType::Button, FInputChord( EKeys::E, EModifierKey::Control | EModifierKey::Shift ) );
|
|
|
|
UI_COMMAND( GoHere, "Go Here", "Moves the camera to the current mouse position", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( SnapCameraToObject, "Snap View to Object", "Snaps the view to the selected object", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SnapObjectToCamera, "Snap Object to View", "Snaps the selected object to the view", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
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, FInputChord() );
|
|
UI_COMMAND( GoToDocsForActor, "Go to Documentation for Actor", "Opens documentation for the Actor in the default web browser", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( PasteHere, "Paste Here", "Pastes the actor at the click location", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( SnapOriginToGrid, "Snap Origin to Grid", "Snaps the actor to the nearest grid location at its origin", EUserInterfaceActionType::Button, FInputChord( 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, FInputChord() );
|
|
UI_COMMAND( AlignOriginToGrid, "Align Origin to Grid", "Aligns the actor to the nearest grid location at its origin", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SnapToFloor, "Snap to Floor", "Snaps the actor or component to the floor below it", EUserInterfaceActionType::Button, FInputChord( EKeys::End ) );
|
|
UI_COMMAND( AlignToFloor, "Align to Floor", "Aligns the actor or component with the floor", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SnapPivotToFloor, "Snap Pivot to Floor", "Snaps the actor to the floor at its pivot point", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Alt, EKeys::End ) );
|
|
UI_COMMAND( AlignPivotToFloor, "Align Pivot to Floor", "Aligns the actor with the floor at its pivot point", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SnapBottomCenterBoundsToFloor, "Snap Bottom Center Bounds to Floor", "Snaps the actor to the floor at its bottom center bounds", EUserInterfaceActionType::Button, FInputChord( 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, FInputChord() );
|
|
UI_COMMAND( SnapOriginToActor, "Snap Origin to Actor", "SNaps the actor to another actor at its origin", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AlignOriginToActor, "Align Origin to Actor", "Aligns the actor to another actor at its origin", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SnapToActor, "Snap to Actor", "Snaps the actor to another actor", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AlignToActor, "Align to Actor", "Aligns the actor with another actor", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SnapPivotToActor, "Snap Pivot to Actor", "Snaps the actor to another actor at its pivot point", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AlignPivotToActor, "Align Pivot to Actor", "Aligns the actor with another actor at its pivot point", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SnapBottomCenterBoundsToActor, "Snap Bottom Center Bounds to Actor", "Snaps the actor to another actor at its bottom center bounds", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AlignBottomCenterBoundsToActor, "Align Bottom Center Bounds to Actor", "Aligns the actor with another actor at its bottom center bounds", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( DeltaTransformToActors, "Delta Transform", "Apply Delta Transform to selected actors", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MirrorActorX, "Mirror X", "Mirrors the actor along the X axis", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MirrorActorY, "Mirror Y", "Mirrors the actor along the Y axis", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MirrorActorZ, "Mirror Z", "Mirrors the actor along the Z axis", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( LockActorMovement, "Lock Actor Movement", "Locks the actor so it cannot be moved", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( DetachFromParent, "Detach", "Detach the actor from its parent", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AttachSelectedActors, "Attach Selected Actors", "Attach the selected actors to the last selected actor", EUserInterfaceActionType::Button, FInputChord(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, FInputChord(EModifierKey::Alt, EKeys::A) );
|
|
UI_COMMAND( CreateNewOutlinerFolder, "Create Folder", "Place the selected actors in a new folder", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( HoldToEnableVertexSnapping, "Hold to Enable Vertex Snapping", "When the key binding is pressed and held vertex snapping will be enabled", EUserInterfaceActionType::ToggleButton, FInputChord(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, FInputChord() );
|
|
UI_COMMAND( ResetPivot, "Reset Pivot", "Resets the pivot", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ResetPrePivot, "Reset Pre-Pivot", "Resets the pre-pivot", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MovePivotHere, "Move Here", "Moves the pivot to the clicked location", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MovePivotHereSnapped, "Move Here (Snapped)", "Moves the pivot to the nearest grid point to the clicked location", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MovePivotToCenter, "Center on Selection", "Centers the pivot to the middle of the selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( ConvertToAdditive, "Additive", "Converts the selected brushes to additive brushes", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ConvertToSubtractive, "Subtractive", "Converts the selected brushes to subtractive brushes", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( OrderFirst, "To First", "Changes the drawing order of the selected brushes so they are the first to draw", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( OrderLast, "To Last", "Changes the drawing order of the selected brushes so they are the last to draw", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( MakeSolid, "Solid", "Makes the selected brushes solid", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MakeSemiSolid, "Semi-Solid", "Makes the selected brushes semi-solid", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MakeNonSolid, "Non-Solid", "Makes the selected brushes non-solid", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( MergePolys, "Merge", "Merges multiple polygons on a brush face into as few as possible", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SeparatePolys, "Separate", "Reverses the effect of a previous merge", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
// 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 chord which is the same for both.
|
|
UI_COMMAND( GroupActors, "Group", "Groups the selected actors", EUserInterfaceActionType::Button, FInputChord( /*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, FInputChord( EKeys::G, EModifierKey::Control ) );
|
|
UI_COMMAND( UngroupActors, "Ungroup", "Ungroups the selected actors", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Shift, EKeys::G ) );
|
|
UI_COMMAND( AddActorsToGroup, "Add to Group", "Adds the selected actors to the selected group", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( RemoveActorsFromGroup, "Remove from Group", "Removes the selected actors from the selected groups", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( LockGroup, "Lock", "Locks the selected groups", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( UnlockGroup, "Unlock", "Unlocks the selected groups", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MergeActors, "Create Mesh Proxy...", "Harvest geometry from selected actors and merge them into single mesh", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MergeActorsByMaterials, "Merge Actors...", "Harvest geometry from selected actors and merge grouping them by materials", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
#if PLATFORM_MAC
|
|
UI_COMMAND( ShowAll, "Show All Actors", "Shows all actors", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Command, EKeys::H ) );
|
|
#else
|
|
UI_COMMAND( ShowAll, "Show All Actors", "Shows all actors", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Control, EKeys::H ) );
|
|
#endif
|
|
UI_COMMAND( ShowSelectedOnly, "Show Only Selected", "Shows only the selected actors", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ShowSelected, "Show Selected", "Shows the selected actors", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Shift, EKeys::H ) );
|
|
UI_COMMAND( HideSelected, "Hide Selected", "Hides the selected actors", EUserInterfaceActionType::Button, FInputChord( EKeys::H ) );
|
|
UI_COMMAND( ShowAllStartup, "Show All At Startup", "Shows all actors at startup", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ShowSelectedStartup, "Show Selected At Startup", "Shows selected actors at startup", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( HideSelectedStartup, "Hide Selected At Startup", "Hide selected actors at startup", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( CycleNavigationDataDrawn, "Cycle Navigation Data Drawn", "Cycles through navigation data (navmeshes for example) to draw one at a time", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Alt, EKeys::N ) );
|
|
|
|
UI_COMMAND( SelectNone, "Unselect All", "Unselects all actors", EUserInterfaceActionType::Button, FInputChord( EKeys::Escape ) ) ;
|
|
UI_COMMAND( InvertSelection, "Invert Selection", "Inverts the current selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( SelectAllActorsOfSameClass, "Select All Actors of Same Class", "Selects all the actors that have the same class", EUserInterfaceActionType::Button, FInputChord(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, FInputChord() );
|
|
UI_COMMAND( SelectComponentOwnerActor, "Select Component Owner", "Select the actor that owns the currently selected component(s)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectRelevantLights, "Select Relevant Lights", "Select all lights relevant to the current selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
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, FInputChord() );
|
|
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, FInputChord( 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, FInputChord() );
|
|
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, FInputChord() );
|
|
UI_COMMAND( SelectAllWithSameMaterial, "Select All With Same Material", "Selects all actors with the same material as the selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectMatchingEmitter, "Select All Matching Emitters", "Selects all emitters with the same particle system as the selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectAllLights, "Select All Lights", "Selects all lights", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectStationaryLightsExceedingOverlap, "Select Stationary Lights exceeding overlap", "Selects all stationary lights exceeding the overlap limit", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectAllAddditiveBrushes, "Select All Additive Brushes", "Selects all additive brushes", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectAllSubtractiveBrushes, "Select All Subtractive Brushes", "Selects all subtractive brushes", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectAllActorsControlledByMatinee, "Select Actors Used by This Matinee", "Selects all actors controlled by this Matinee", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( SelectAllSurfaces, "Select All Surfaces", "Selects all bsp surfaces", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::S) );
|
|
|
|
UI_COMMAND( SurfSelectAllMatchingBrush, "Select Matching Brush", "Selects the surfaces belonging to the same brush as the selected surfaces", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::B) );
|
|
UI_COMMAND( SurfSelectAllMatchingTexture, "Select Matching Material", "Selects all surfaces with the same material as the selected surfaces", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::T) );
|
|
UI_COMMAND( SurfSelectAllAdjacents, "Select All Adjacent Surfaces", "Selects all surfaces adjacent to the currently selected surfaces", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::J) );
|
|
UI_COMMAND( SurfSelectAllAdjacentCoplanars, "Select All Coplanar Surfaces", "Selects all surfaces adjacent and coplanar with the selected surfaces", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::C) );
|
|
UI_COMMAND( SurfSelectAllAdjacentWalls, "Select All Adjacent Wall Surfaces", "Selects all adjacent upright surfaces", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::W) );
|
|
UI_COMMAND( SurfSelectAllAdjacentFloors, "Select All Adjacent Floor Surfaces", "Selects all adjacent floor sufaces(ones with normals pointing up)", EUserInterfaceActionType::Button, FInputChord(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, FInputChord(EModifierKey::Shift, EKeys::Y) );
|
|
UI_COMMAND( SurfSelectReverse, "Invert Surface Selection", "Inverts the current surface selection", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::Q) );
|
|
UI_COMMAND( SurfSelectMemorize, "Memorize Surface Selection", "Stores the current surface selection in memory", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::M) );
|
|
UI_COMMAND( SurfSelectRecall, "Recall Surface Selection", "Replace the current selection with the selection saved in memory", EUserInterfaceActionType::Button, FInputChord(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, FInputChord(EModifierKey::Shift, EKeys::O) );
|
|
UI_COMMAND( SurfSelectAnd, "Surface Selection AND", "Add the selection of surfaces saved in memory to the current selection", EUserInterfaceActionType::Button, FInputChord(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, FInputChord(EModifierKey::Shift, EKeys::X) );
|
|
UI_COMMAND( SurfUnalign, "Align Surface Default", "Default surface alignment", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SurfAlignPlanarAuto, "Align Surface Planar", "Planar surface alignment", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SurfAlignPlanarWall, "Align Surface Planar Wall", "Planar wall surface alignment", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SurfAlignPlanarFloor, "Align Surface Planar Floor", "Planar floor surface alignment", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SurfAlignBox, "Align Surface Box", "Box surface alignment", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SurfAlignFit, "Align Surface Fit", "Best fit surface alignment", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ApplyMaterialToSurface, "Apply Material to Surface Selection", "Applies the selected material to the selected surfaces", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( CreateBoundingBoxVolume, "Create Bounding Box Blocking Volume From Mesh", "Create a bounding box blocking volume from the static mesh", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( CreateHeavyConvexVolume, "Heavy Convex Blocking Volume From Mesh", "Creates a heavy convex blocing volume from the static mesh", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( CreateNormalConvexVolume, "Normal Convex Blocking Volume From Mesh", "Creates a normal convex blocking volume from the static mesh", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( CreateLightConvexVolume, "Light Convex Blocking Volume From Mesh", "Creates a light convex blocking volume from the static mesh", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( CreateRoughConvexVolume, "Rought Convex Blocking Volume From Mesh", "Creates a rough convex blocking volume from the static mesh", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
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, FInputChord() );
|
|
|
|
UI_COMMAND( KeepSimulationChanges, "Keep Simulation Changes", "Saves the changes made to this actor in Simulate mode to the actor's default state.", EUserInterfaceActionType::Button, FInputChord( EKeys::K ) );
|
|
|
|
UI_COMMAND( MakeActorLevelCurrent, "Make Selected Actor's Level Current", "Makes the selected actors level the current level", EUserInterfaceActionType::Button, FInputChord( EKeys::M ) );
|
|
#if PLATFORM_MAC
|
|
UI_COMMAND( MoveSelectedToCurrentLevel, "Move Selection to Current Level", "Moves the selected actors to the current level", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Command, EKeys::M ) );
|
|
#else
|
|
UI_COMMAND( MoveSelectedToCurrentLevel, "Move Selection to Current Level", "Moves the selected actors to the current level", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Control, EKeys::M ) );
|
|
#endif
|
|
UI_COMMAND( FindLevelsInLevelBrowser, "Find Levels in Level Browser", "Finds the selected actors level in the level browser", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AddLevelsToSelection, "Add Levels to Selection", "Adds the selected actors levels to the current level browser selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( RemoveLevelsFromSelection, "Remove Levels from Selection", "Removes the selected actors levels from the current level browser selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( FindActorInLevelScript, "Find in Level Blueprint", "Finds any references to the selected actor in its level's blueprint", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( WorldProperties, "World Settings", "Displays the world settings", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( OpenContentBrowser, "Open Content Browser", "Opens the Content Browser", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Control|EModifierKey::Shift, EKeys::F) );
|
|
UI_COMMAND( OpenMarketplace, "Open Marketplace", "Opens the Marketplace", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AddMatinee, "Add Matinee", "Creates a new matinee actor to edit", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( EditMatinee, "Edit Matinee", "Selects a Matinee to edit", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( OpenLevelBlueprint, "Open Level Blueprint", "Edit the Level Blueprint for the current level", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( CheckOutProjectSettingsConfig, "Check Out", "Checks out the project settings config file so the game mode can be set.", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( CreateBlankBlueprintClass, "New Empty Blueprint Class...", "Create a new Blueprint Class", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ConvertSelectionToBlueprintViaHarvest, "Convert Selected Components to Blueprint Class...", "Replace all of the selected actors with a new Blueprint Class based on Actor that contains the components", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ConvertSelectionToBlueprintViaSubclass, "Convert Selected Actor to Blueprint Class...", "Replace the selected actor with a new Blueprint subclass based on the class of the selected Actor", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( ShowTransformWidget, "Show Transform Widget", "Toggles the visibility of the transform widgets", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( AllowTranslucentSelection, "Allow Translucent Selection", "Allows translucent objects to be selected", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::T) );
|
|
UI_COMMAND( AllowGroupSelection, "Allow Group Selection", "Allows actor groups to be selected", EUserInterfaceActionType::ToggleButton, FInputChord(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, FInputChord() );
|
|
UI_COMMAND( TransparentBoxSelect, "Box Select Occluded Objects", "When enabled, marquee box select operations will also select objects that are occluded by other objects.", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( DrawBrushMarkerPolys, "Draw Brush Polys", "Draws semi-transparent polygons around a brush when selected", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( OnlyLoadVisibleInPIE, "Only Load Visible Levels in Game Preview", "If enabled, when game preview starts, only visible levels will be loaded", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( ToggleSocketSnapping, "Enable Socket Snapping", "Enables or disables snapping to sockets", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( ToggleParticleSystemLOD, "Enable Particle System LOD Switching", "If enabled particle systems will use distance LOD switching in perspective viewports", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( ToggleFreezeParticleSimulation, "Freeze Particle Simulation", "If enabled particle systems will freeze their simulation state", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( ToggleParticleSystemHelpers, "Toggle Particle System Helpers", "Toggles showing particle system helper widgets in viewports", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( ToggleLODViewLocking, "Enable LOD View Locking", "If enabled viewports of the same type will use the same LOD", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( LevelStreamingVolumePrevis, "Enable Automatic Level Streaming", "If enabled, the viewport will stream in levels automatically when the camera is moved", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( EnableActorSnap, "Enable Actor Snapping", "If enabled, actors will snap to the location of other actors when they are within distance", EUserInterfaceActionType::ToggleButton, FInputChord(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, FInputChord() );
|
|
UI_COMMAND( ToggleHideViewportUI, "Hide Viewport UI", "Toggles hidden viewport UI mode. Hides all overlaid viewport UI widgets", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
|
|
//if (FParse::Param( FCommandLine::Get(), TEXT( "editortoolbox" ) ))
|
|
//{
|
|
// UI_COMMAND( BspMode, "Enable Bsp Mode", "Enables BSP mode", EUserInterfaceActionType::ToggleButton, FInputChord( EModifierKey::Shift, EKeys::One ) );
|
|
// UI_COMMAND( MeshPaintMode, "Enable Mesh Paint Mode", "Enables mesh paint mode", EUserInterfaceActionType::ToggleButton, FInputChord( EModifierKey::Shift, EKeys::Two ) );
|
|
// UI_COMMAND( LandscapeMode, "Enable Landscape Mode", "Enables landscape editing", EUserInterfaceActionType::ToggleButton, FInputChord( EModifierKey::Shift, EKeys::Three ) );
|
|
// UI_COMMAND( FoliageMode, "Enable Foliage Mode", "Enables foliage editing", EUserInterfaceActionType::ToggleButton, FInputChord( EModifierKey::Shift, EKeys::Four ) );
|
|
//}
|
|
|
|
UI_COMMAND( ShowSelectedDetails, "Show Actor Details", "Opens a details panel for the selected actors", EUserInterfaceActionType::Button, FInputChord( EKeys::F4 ) );
|
|
|
|
UI_COMMAND( RecompileShaders, "Recompile Changed Shaders", "Recompiles shaders which are out of date", EUserInterfaceActionType::Button, FInputChord( 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, FInputChord( 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, FInputChord( 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, FInputChord( 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, FInputChord( 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, FInputChord( EKeys::F, EModifierKey::Shift ) );
|
|
|
|
UI_COMMAND( MaterialQualityLevel_Low, "Low", "Sets material quality in the scene to low.", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( MaterialQualityLevel_High, "High", "Sets material quality in the scene to high.", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
|
|
UI_COMMAND( ConnectToSourceControl, "Connect to Source Control...", "Opens a dialog to connect to source control.", EUserInterfaceActionType::Button, FInputChord());
|
|
UI_COMMAND( ChangeSourceControlSettings, "Change Source Control Settings...", "Opens a dialog to change source control settings.", EUserInterfaceActionType::Button, FInputChord());
|
|
UI_COMMAND( CheckOutModifiedFiles, "Check Out Modified Files...", "Opens a dialog to check out any assets which have been modified.", EUserInterfaceActionType::Button, FInputChord());
|
|
UI_COMMAND( SubmitToSourceControl, "Submit to Source Control...", "Opens a dialog with check in options for content and levels.", EUserInterfaceActionType::Button, FInputChord());
|
|
|
|
static const FText FeatureLevelLabels[ERHIFeatureLevel::Num] =
|
|
{
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewType_ES2", "Mobile / HTML5"),
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewType_ES31", "High-End Mobile / Metal"),
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewType_SM4", "Shader Model 4"),
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewType_SM5", "Shader Model 5"),
|
|
};
|
|
|
|
static const FText FeatureLevelToolTips[ERHIFeatureLevel::Num] =
|
|
{
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewTooltip_ES2", "OpenGLES 2"),
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewTooltip_ES3", "OpenGLES 3.1, Metal"),
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewTooltip_SM4", "DirectX 10, OpenGL 3.3+"),
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewTooltip_SM5", "DirectX 11, OpenGL 4.3+, PS4, XB1"),
|
|
};
|
|
|
|
for (int32 i = 0; i < ERHIFeatureLevel::Num; ++i)
|
|
{
|
|
FName Name;
|
|
GetFeatureLevelName((ERHIFeatureLevel::Type)i, Name);
|
|
|
|
FeatureLevelPreview[i] =
|
|
FUICommandInfoDecl(
|
|
this->AsShared(),
|
|
Name,
|
|
FeatureLevelLabels[i],
|
|
FeatureLevelToolTips[i])
|
|
.UserInterfaceType(EUserInterfaceActionType::RadioButton)
|
|
.DefaultChord(FInputChord());
|
|
}
|
|
}
|
|
|
|
PRAGMA_ENABLE_OPTIMIZATION
|
|
|
|
#undef LOCTEXT_NAMESPACE
|