Files
UnrealEngineUWP/Engine/Source/Developer/DesktopPlatform/Private/Linux/DesktopPlatformLinux.cpp
Matthew Griffin 6c75b4032c Merging //UE4/Release-4.11 to //UE4/Main (up to CL#2835147)
==========================
MAJOR FEATURES + CHANGES
==========================

Change 2817214 on 2016/01/06 by mason.seay
	Adjusted Walkable Slope Override for mesh

	#jira UE-24473

Change 2817384 on 2016/01/06 by Michael.Schoell
	Crash fix when selecting a variable node for a variable that is not owned by a Blueprint.

	#jira UE-24958 - Crash when getting the sequence player in level blueprint

Change 2817438 on 2016/01/06 by Max.Chen

	Sequencer: Add option to specify position of material name from the movie scene capture interface. For example, MovieCapture_{material}_{width}x{height}.{frame} will create files like this: MovieCapture_FinalImage_1920x1080.0010.exr

	#rb Andrew.Rodham
	#jira UE-24926

Change 2817459 on 2016/01/06 by Marc.Audy

	 PR #1679: Move MinRespawnDelay to virtual method AController::GetMinRespawnDelay() (Contributed by bozaro)
	#jira UE-22309

Change 2817472 on 2016/01/06 by Ben.Marsh

	Always run UHT in unattended mode from UBT; we don't want it opening any dialogs. Match3 is currently missing a plugin, and it's causing builds to time out.

Change 2817473 on 2016/01/06 by Marc.Audy

	 PR #1644: Improve "SpawnActor failed because the spawned actor IsPendingKill" error message (Contributed by slonopotamus)
	#jira UE-21911

Change 2817533 on 2016/01/06 by Lauren.Ridge

	Fixing Match3 not compiling in Debug (removed two checks on TileLibrary)

	#jira UE-25004

Change 2817625 on 2016/01/06 by Taizyd.Korambayil

	#jira UE-19659 Reimported Template Animations with Proper Skeletons

Change 2817647 on 2016/01/06 by Lukasz.Furman

	replaced ensure during initialization of blackboard based behavior tree task with log warning
	#ue4
	#jira UE-24448
	#rb Mieszko.Zielinski

Change 2817648 on 2016/01/06 by Lukasz.Furman

	fixed broken rendering component of navmesh actor after delete-undo operation
	#ue4
	#jira UE-24446
	#rb Mieszko.Zielinski

Change 2817688 on 2016/01/06 by Taizyd.Korambayil

	#jira UE-22347 Fixed Message Warnings on Startup

Change 2817815 on 2016/01/06 by Jamie.Dale

	Multiple fixes when editing right-to-left text

	- Text is now shaped over the entire line to allow rich-text and selected text to be shaped correctly across block boundaries.
	- Text layout highlights are now able to correctly handle bi-directional and right-to-left text.
	- Text picking can now handle bi-directional and right-to-left text.
	- Text picking can now pick the individual characters that make up a ligature glyph.
	- The caret now draws on the logical (rather than visual) side of the glyph (to handle right-to-left text).
	- Glyph clusters (multiple glyphs produced from a single character) are now treated as a single logical glyph.
	- Optimized some of the FShapedGlyphSequence to allow an early out once they've found and processed the start and end glyphs.

	#jira UE-25013

Change 2817828 on 2016/01/06 by Nick.Darnell

	Editor - Fixing the OpenLauncher call to be take a structure to allow us to customize it more, and to properly handle the silent command the way we're planning to handle it in the launcher.

	#jira UE-24563

Change 2818052 on 2016/01/06 by Nick.Darnell

	Editor - Adding another application check for the launcher to catch the current app name on mac.

	#jira UE-24563

Change 2818149 on 2016/01/06 by Taizyd.Korambayil

	#jira UE-19097 Adjusted FirstPerson Pawn, so that Camera doesnt clip the Arm Mesh

Change 2818360 on 2016/01/06 by Chris.Babcock

	Fix reading from ini sections not cached after build system changes for 4.11
	#jira UE-25027
	#ue4
	#android

Change 2818369 on 2016/01/06 by Ryan.Vance

	#jira UE-24976
	Adding tessellation support to instanced stereo

Change 2818999 on 2016/01/07 by Robert.Manuszewski

	UHT will no longer try to load game-only plugins.

	#jira UE-25032

	- Changed module type RuntimeNoProgram to RuntimeAndProgram so that bu default Runtime plugin modules won't be loaded by programs
	- Added better error message when UHT's PreInit fails

Change 2819064 on 2016/01/07 by Richard.Hinckley

	#jira UE-24694
	Fixing array usage in 4.11 stream.

Change 2819067 on 2016/01/07 by Ori.Cohen

	When editor tries to spawn a physics asset we automatically load the needed skeletal mesh

	#rb Matt.K
	#JIRA UE-24165
2016-01-22 08:13:18 -05:00

463 lines
14 KiB
C++

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#include "DesktopPlatformPrivatePCH.h"
#include "LinuxApplication.h"
#include "FeedbackContextMarkup.h"
//#include "LinuxNativeFeedbackContext.h"
// custom dialogs
#if WITH_LINUX_NATIVE_DIALOGS
#include "UNativeDialogs.h"
#else
#include "SlateFileDialogs.h"
#endif // WITH_LINUX_NATIVE_DIALOGS
#include "SDL.h"
#define LOCTEXT_NAMESPACE "DesktopPlatform"
#define MAX_FILETYPES_STR 4096
#define MAX_FILENAME_STR 65536
FDesktopPlatformLinux::FDesktopPlatformLinux()
: FDesktopPlatformBase()
{
#if WITH_LINUX_NATIVE_DIALOGS
bool bLNDInit = ULinuxNativeDialogs_Initialize();
if (bLNDInit)
{
UE_LOG(LogDesktopPlatform, Log, TEXT("LinuxNativeDialogs have been successfully initialized."));
}
else
{
UE_LOG(LogDesktopPlatform, Warning, TEXT("DesktopPlatformLinux could not initialize LinuxNativeDialogs - it will not work properly."));
}
#else
UE_LOG(LogDesktopPlatform, Log, TEXT("DesktopPlatformLinux is not using LinuxNativeDialogs."));
#endif // WITH_LINUX_NATIVE_DIALOGS
}
FDesktopPlatformLinux::~FDesktopPlatformLinux()
{
#if WITH_LINUX_NATIVE_DIALOGS
ULinuxNativeDialogs_Shutdown();
#endif
}
bool FDesktopPlatformLinux::OpenFileDialog(const void* ParentWindowHandle, const FString& DialogTitle, const FString& DefaultPath, const FString& DefaultFile, const FString& FileTypes, uint32 Flags, TArray<FString>& OutFilenames, int32& OutFilterIndex)
{
#if WITH_LINUX_NATIVE_DIALOGS
return FileDialogShared(false, ParentWindowHandle, DialogTitle, DefaultPath, DefaultFile, FileTypes, Flags, OutFilenames, OutFilterIndex);
#else
if (!FModuleManager::Get().IsModuleLoaded("SlateFileDialogs"))
{
FModuleManager::Get().LoadModule("SlateFileDialogs");
}
ISlateFileDialogsModule *FileDialog = FModuleManager::GetModulePtr<ISlateFileDialogsModule>("SlateFileDialogs");
if (FileDialog)
{
return FileDialog->OpenFileDialog(ParentWindowHandle, DialogTitle, DefaultPath, DefaultFile, FileTypes, Flags, OutFilenames, OutFilterIndex);
}
return false;
#endif // WITH_LINUX_NATIVE_DIALOGS
}
bool FDesktopPlatformLinux::OpenFileDialog(const void* ParentWindowHandle, const FString& DialogTitle, const FString& DefaultPath, const FString& DefaultFile, const FString& FileTypes, uint32 Flags, TArray<FString>& OutFilenames)
{
#if WITH_LINUX_NATIVE_DIALOGS
int32 DummyFilterIndex;
return FileDialogShared(false, ParentWindowHandle, DialogTitle, DefaultPath, DefaultFile, FileTypes, Flags, OutFilenames, DummyFilterIndex);
#else
if (!FModuleManager::Get().IsModuleLoaded("SlateFileDialogs"))
{
FModuleManager::Get().LoadModule("SlateFileDialogs");
}
ISlateFileDialogsModule *FileDialog = FModuleManager::GetModulePtr<ISlateFileDialogsModule>("SlateFileDialogs");
if (FileDialog)
{
return FileDialog->OpenFileDialog(ParentWindowHandle, DialogTitle, DefaultPath, DefaultFile, FileTypes, Flags, OutFilenames);
}
return false;
#endif // WITH_LINUX_NATIVE_DIALOGS
}
bool FDesktopPlatformLinux::SaveFileDialog(const void* ParentWindowHandle, const FString& DialogTitle, const FString& DefaultPath, const FString& DefaultFile, const FString& FileTypes, uint32 Flags, TArray<FString>& OutFilenames)
{
#if WITH_LINUX_NATIVE_DIALOGS
int32 DummyFilterIndex = 0;
return FileDialogShared(true, ParentWindowHandle, DialogTitle, DefaultPath, DefaultFile, FileTypes, Flags, OutFilenames, DummyFilterIndex);
#else
if (!FModuleManager::Get().IsModuleLoaded("SlateFileDialogs"))
{
FModuleManager::Get().LoadModule("SlateFileDialogs");
}
ISlateFileDialogsModule *FileDialog = FModuleManager::GetModulePtr<ISlateFileDialogsModule>("SlateFileDialogs");
if (FileDialog)
{
return FileDialog->SaveFileDialog(ParentWindowHandle, DialogTitle, DefaultPath, DefaultFile, FileTypes, Flags, OutFilenames);
}
return false;
#endif // WITH_LINUX_NATIVE_DIALOGS
}
bool FDesktopPlatformLinux::OpenDirectoryDialog(const void* ParentWindowHandle, const FString& DialogTitle, const FString& DefaultPath, FString& OutFolderName)
{
#if WITH_LINUX_NATIVE_DIALOGS
bool bSuccess;
struct UFileDialogHints hints = DEFAULT_UFILEDIALOGHINTS;
LinuxApplication->SetCapture(NULL);
hints.Action = UFileDialogActionOpenDirectory;
hints.WindowTitle = TCHAR_TO_UTF8(*DialogTitle);
hints.InitialDirectory = TCHAR_TO_UTF8(*DefaultPath);
UFileDialog* dialog = UFileDialog_Create(&hints);
while(UFileDialog_ProcessEvents(dialog))
{
FPlatformMisc::PumpMessages(true); // pretend that we're the main loop
}
const UFileDialogResult* result = UFileDialog_Result(dialog);
if (result)
{
if (result->count == 1)
{
OutFolderName = UTF8_TO_TCHAR(result->selection[0]);
//OutFolderName = IFileManager::Get().ConvertToRelativePath(*OutFolderName); // @todo (amigo): converting to relative path ends up without ../...
FPaths::NormalizeFilename(OutFolderName);
bSuccess = true;
}
else
{
bSuccess = false;
}
// Todo like in Windows, normalize files here instead of above
}
else
{
bSuccess = false;
}
UFileDialog_Destroy(dialog);
return bSuccess;
#else
if (!FModuleManager::Get().IsModuleLoaded("SlateFileDialogs"))
{
FModuleManager::Get().LoadModule("SlateFileDialogs");
}
ISlateFileDialogsModule *FileDialog = FModuleManager::GetModulePtr<ISlateFileDialogsModule>("SlateFileDialogs");
if (FileDialog)
{
return FileDialog->OpenDirectoryDialog(ParentWindowHandle, DialogTitle, DefaultPath, OutFolderName);
}
return false;
#endif // WITH_LINUX_NATIVE_DIALOGS
}
bool FDesktopPlatformLinux::OpenFontDialog(const void* ParentWindowHandle, FString& OutFontName, float& OutHeight, EFontImportFlags& OutFlags)
{
unimplemented();
return false;
}
bool FDesktopPlatformLinux::CanOpenLauncher(bool Install)
{
// TODO: no launcher support at the moment
return false;
}
bool FDesktopPlatformLinux::OpenLauncher(const FOpenLauncherOptions& Options)
{
// TODO: support launcher for realz
return true;
}
bool FDesktopPlatformLinux::FileDialogShared(bool bSave, const void* ParentWindowHandle, const FString& DialogTitle, const FString& DefaultPath, const FString& DefaultFile, const FString& FileTypes, uint32 Flags, TArray<FString>& OutFilenames, int32& OutFilterIndex)
{
#if WITH_LINUX_NATIVE_DIALOGS
FString Filename;
bool bSuccess;
LinuxApplication->SetCapture(NULL);
UE_LOG(LogDesktopPlatform, Warning, TEXT("FileDialogShared DialogTitle: %s, DefaultPath: %s, DefaultFile: %s, FileTypes: %s, Flags: %d"),
*DialogTitle, *DefaultPath, *DefaultFile, *FileTypes, Flags);
struct UFileDialogHints hints = DEFAULT_UFILEDIALOGHINTS;
hints.WindowTitle = TCHAR_TO_UTF8(*DialogTitle);
FString AllExtensionsSpaceDelim; // a string like "*.cpp *.h *.c"
// The strings will come in pairs, formatted as follows: Pair1String1|Pair1String2|Pair2String1|Pair2String2
// where the second string in the pair is the extension(s)
TArray<FString> Filters;
FileTypes.ParseIntoArray(Filters, TEXT("|"), true);
for( int32 ExtensionIndex = 1; ExtensionIndex < Filters.Num(); ExtensionIndex += 2)
{
const FString& Extensions = Filters[ExtensionIndex];
TArray<FString> ExtensionsArray;
// Extension can be either *.jpg or *.jpg;*.png -> in the latter case split at ';'
int32 UnusedIndex;
if (Extensions.FindChar(TEXT(';'), UnusedIndex))
{
Extensions.ParseIntoArray(ExtensionsArray, TEXT(";"), true);
}
else
{
ExtensionsArray.Add(Extensions); // just a single extension
}
for (const FString& Extension : ExtensionsArray)
{
if (AllExtensionsSpaceDelim.Find(Extension, ESearchCase::CaseSensitive) == INDEX_NONE)
{
AllExtensionsSpaceDelim += Extension;
AllExtensionsSpaceDelim += TEXT(" ");
}
}
}
FString AllExtensionsLumpedTogether(TEXT("All applicable ("));
AllExtensionsLumpedTogether += AllExtensionsSpaceDelim;
AllExtensionsLumpedTogether += TEXT(")");
char FileTypesBuf[MAX_FILETYPES_STR * 2] = {0,};
FTCHARToUTF8_Convert::Convert(FileTypesBuf, sizeof(FileTypesBuf), *AllExtensionsLumpedTogether, AllExtensionsLumpedTogether.Len());
hints.NameFilter = FileTypesBuf;
char DefPathBuf[MAX_FILENAME_STR * 2] = {0,};
FTCHARToUTF8_Convert::Convert(DefPathBuf, sizeof(DefPathBuf), *DefaultPath, DefaultPath.Len());
hints.InitialDirectory = DefPathBuf;
char DefFileBuf[MAX_FILENAME_STR * 2] = {0,};
FTCHARToUTF8_Convert::Convert(DefFileBuf, sizeof(DefFileBuf), *DefaultFile, DefaultFile.Len());
hints.DefaultFile = DefFileBuf;
if (bSave)
{
hints.Action = UFileDialogActionSave;
}
else
{
hints.Action = UFileDialogActionOpen;
}
UFileDialog* dialog = UFileDialog_Create(&hints);
while(UFileDialog_ProcessEvents(dialog))
{
FPlatformMisc::PumpMessages(true); // pretend that we're the main loop
}
const UFileDialogResult* result = UFileDialog_Result(dialog);
if (result)
{
if (result->count > 1)
{
// Todo better handling of multi-selects
UE_LOG(LogDesktopPlatform, Warning, TEXT("FileDialogShared Selected Files: %d"), result->count);
for(int i = 0;i < result->count;++i) {
//Filename = FUTF8ToTCHAR(result->selection[i], MAX_FILENAME_STR).Get();
Filename = UTF8_TO_TCHAR(result->selection[i]);
//new(OutFilenames) FString(Filename);
OutFilenames.Add(Filename);
Filename = IFileManager::Get().ConvertToRelativePath(*Filename);
FPaths::NormalizeFilename(Filename);
//UE_LOG(LogDesktopPlatform, Warning, TEXT("FileDialogShared File: %s"), *Filename);
}
bSuccess = true;
}
else if (result->count == 1)
{
//Filename = FUTF8ToTCHAR(result->selection[0], MAX_FILENAME_STR).Get();
Filename = UTF8_TO_TCHAR(result->selection[0]);
//new(OutFilenames) FString(Filename);
OutFilenames.Add(Filename);
Filename = IFileManager::Get().ConvertToRelativePath(*Filename);
FPaths::NormalizeFilename(Filename);
//UE_LOG(LogDesktopPlatform, Warning, TEXT("FileDialogShared File: %s"), *Filename);
bSuccess = true;
}
else
{
bSuccess = false;
}
// Todo like in Windows, normalize files here instead of above
}
else
{
bSuccess = false;
}
UFileDialog_Destroy(dialog);
return bSuccess;
#else
return false;
#endif // WITH_LINUX_NATIVE_DIALOGS
}
bool FDesktopPlatformLinux::RegisterEngineInstallation(const FString &RootDir, FString &OutIdentifier)
{
bool bRes = false;
if (IsValidRootDirectory(RootDir))
{
FConfigFile ConfigFile;
FString ConfigPath = FString(FPlatformProcess::ApplicationSettingsDir()) / FString(TEXT("UnrealEngine")) / FString(TEXT("Install.ini"));
ConfigFile.Read(ConfigPath);
FConfigSection &Section = ConfigFile.FindOrAdd(TEXT("Installations"));
OutIdentifier = FGuid::NewGuid().ToString(EGuidFormats::DigitsWithHyphens);
Section.AddUnique(*OutIdentifier, RootDir);
ConfigFile.Dirty = true;
ConfigFile.Write(ConfigPath);
}
return bRes;
}
void FDesktopPlatformLinux::EnumerateEngineInstallations(TMap<FString, FString> &OutInstallations)
{
EnumerateLauncherEngineInstallations(OutInstallations);
FString UProjectPath = FString(FPlatformProcess::ApplicationSettingsDir()) / "Unreal.uproject";
FArchive* File = IFileManager::Get().CreateFileWriter(*UProjectPath, FILEWRITE_EvenIfReadOnly);
if (File)
{
File->Close();
delete File;
}
else
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Unable to write to Settings Directory", TCHAR_TO_UTF8(*UProjectPath), NULL);
}
FConfigFile ConfigFile;
FString ConfigPath = FString(FPlatformProcess::ApplicationSettingsDir()) / FString(TEXT("UnrealEngine")) / FString(TEXT("Install.ini"));
ConfigFile.Read(ConfigPath);
FConfigSection &Section = ConfigFile.FindOrAdd(TEXT("Installations"));
// @todo: currently we can enumerate only this installation
FString EngineDir = FPaths::EngineDir();
FString EngineId;
const FName* Key = Section.FindKey(EngineDir);
if (Key)
{
EngineId = Key->ToString();
}
else
{
if (!OutInstallations.FindKey(EngineDir))
{
EngineId = FGuid::NewGuid().ToString(EGuidFormats::DigitsWithHyphens);
Section.AddUnique(*EngineId, EngineDir);
ConfigFile.Dirty = true;
}
}
if (!EngineId.IsEmpty() && !OutInstallations.Find(EngineId))
{
OutInstallations.Add(EngineId, EngineDir);
}
ConfigFile.Write(ConfigPath);
IFileManager::Get().Delete(*UProjectPath);
}
bool FDesktopPlatformLinux::IsSourceDistribution(const FString &RootDir)
{
// Check for the existence of a GenerateProjectFiles.sh file. This allows compatibility with the GitHub 4.0 release.
FString GenerateProjectFilesPath = RootDir / TEXT("GenerateProjectFiles.sh");
if (IFileManager::Get().FileSize(*GenerateProjectFilesPath) >= 0)
{
return true;
}
// Otherwise use the default test
return FDesktopPlatformBase::IsSourceDistribution(RootDir);
}
bool FDesktopPlatformLinux::VerifyFileAssociations()
{
STUBBED("FDesktopPlatformLinux::VerifyFileAssociationsg");
return true; // for now we are associated
}
bool FDesktopPlatformLinux::UpdateFileAssociations()
{
//unimplemented();
STUBBED("FDesktopPlatformLinux::UpdateFileAssociations");
return false;
}
bool FDesktopPlatformLinux::OpenProject(const FString &ProjectFileName)
{
// Get the project filename in a native format
FString PlatformProjectFileName = ProjectFileName;
FPaths::MakePlatformFilename(PlatformProjectFileName);
STUBBED("FDesktopPlatformLinux::OpenProject");
return false;
}
bool FDesktopPlatformLinux::RunUnrealBuildTool(const FText& Description, const FString& RootDir, const FString& Arguments, FFeedbackContext* Warn)
{
// Get the path to UBT
FString UnrealBuildToolPath = RootDir / TEXT("Engine/Binaries/DotNET/UnrealBuildTool.exe");
if(IFileManager::Get().FileSize(*UnrealBuildToolPath) < 0)
{
Warn->Logf(ELogVerbosity::Error, TEXT("Couldn't find UnrealBuildTool at '%s'"), *UnrealBuildToolPath);
return false;
}
// Write the output
Warn->Logf(TEXT("Running %s %s"), *UnrealBuildToolPath, *Arguments);
// launch UBT with Mono
FString CmdLineParams = FString::Printf(TEXT("\"%s\" %s"), *UnrealBuildToolPath, *Arguments);
// Spawn it
int32 ExitCode = 0;
return FFeedbackContextMarkup::PipeProcessOutput(Description, TEXT("/usr/bin/mono"), CmdLineParams, Warn, &ExitCode) && ExitCode == 0;
}
bool FDesktopPlatformLinux::IsUnrealBuildToolRunning()
{
// For now assume that if mono application is running, we're running UBT
// @todo: we need to get the commandline for the mono process and check if UBT.exe is in there.
return FPlatformProcess::IsApplicationRunning(TEXT("mono"));
}
FFeedbackContext* FDesktopPlatformLinux::GetNativeFeedbackContext()
{
//unimplemented();
STUBBED("FDesktopPlatformLinux::GetNativeFeedbackContext");
return GWarn;
}
FString FDesktopPlatformLinux::GetUserTempPath()
{
return FString(FPlatformProcess::UserTempDir());
}
#undef LOCTEXT_NAMESPACE