2014-04-23 18:32:52 -04:00
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
# include "DesktopPlatformPrivatePCH.h"
# include "DesktopPlatformBase.h"
2014-05-06 10:27:35 -04:00
# include "UProjectInfo.h"
2014-05-13 18:23:53 -04:00
# include "EngineVersion.h"
# include "ModuleManager.h"
2014-06-04 18:06:57 -04:00
# include "Runtime/Launch/Resources/Version.h"
2014-05-13 18:23:53 -04:00
# define LOCTEXT_NAMESPACE "DesktopPlatform"
2014-04-23 18:32:52 -04:00
2014-05-14 15:20:39 -04:00
FDesktopPlatformBase : : FDesktopPlatformBase ( )
{
LauncherInstallationTimestamp = FDateTime : : MinValue ( ) ;
}
2014-06-04 19:07:11 -04:00
FString FDesktopPlatformBase : : GetEngineDescription ( const FString & Identifier )
{
// Official release versions just have a version number
if ( IsStockEngineRelease ( Identifier ) )
{
return Identifier ;
}
// Otherwise get the path
FString RootDir ;
if ( ! GetEngineRootDirFromIdentifier ( Identifier , RootDir ) )
{
return FString ( ) ;
}
// Convert it to a platform directory
FString PlatformRootDir = RootDir ;
FPaths : : MakePlatformFilename ( PlatformRootDir ) ;
// Perforce build
if ( IsSourceDistribution ( RootDir ) )
{
return FString : : Printf ( TEXT ( " Source build at %s " ) , * PlatformRootDir ) ;
}
else
{
return FString : : Printf ( TEXT ( " Binary build at %s " ) , * PlatformRootDir ) ;
}
}
2014-04-23 18:32:52 -04:00
FString FDesktopPlatformBase : : GetCurrentEngineIdentifier ( )
{
2014-05-13 18:23:53 -04:00
if ( CurrentEngineIdentifier . Len ( ) = = 0 & & ! GetEngineIdentifierFromRootDir ( FPlatformMisc : : RootDir ( ) , CurrentEngineIdentifier ) )
{
CurrentEngineIdentifier . Empty ( ) ;
}
return CurrentEngineIdentifier ;
2014-04-23 18:32:52 -04:00
}
2014-04-23 18:46:48 -04:00
void FDesktopPlatformBase : : EnumerateLauncherEngineInstallations ( TMap < FString , FString > & OutInstallations )
{
2014-05-14 15:20:39 -04:00
// Cache the launcher install list if necessary
ReadLauncherInstallationList ( ) ;
// We've got a list of launcher installations. Filter it by the engine installations.
for ( TMap < FString , FString > : : TConstIterator Iter ( LauncherInstallationList ) ; Iter ; + + Iter )
2014-05-08 08:20:34 -04:00
{
2014-05-14 15:20:39 -04:00
FString AppName = Iter . Key ( ) ;
if ( AppName . RemoveFromStart ( TEXT ( " UE_ " ) , ESearchCase : : CaseSensitive ) )
2014-05-08 08:20:34 -04:00
{
2014-05-14 15:20:39 -04:00
OutInstallations . Add ( AppName , Iter . Value ( ) ) ;
2014-05-08 08:20:34 -04:00
}
}
2014-04-23 18:46:48 -04:00
}
2014-05-13 19:34:00 -04:00
void FDesktopPlatformBase : : EnumerateLauncherSampleInstallations ( TArray < FString > & OutInstallations )
{
2014-05-14 15:20:39 -04:00
// Cache the launcher install list if necessary
ReadLauncherInstallationList ( ) ;
// We've got a list of launcher installations. Filter it by the engine installations.
for ( TMap < FString , FString > : : TConstIterator Iter ( LauncherInstallationList ) ; Iter ; + + Iter )
2014-05-13 19:34:00 -04:00
{
2014-05-14 15:20:39 -04:00
FString AppName = Iter . Key ( ) ;
if ( ! AppName . StartsWith ( TEXT ( " UE_ " ) , ESearchCase : : CaseSensitive ) )
2014-05-13 19:34:00 -04:00
{
2014-05-14 15:20:39 -04:00
OutInstallations . Add ( Iter . Value ( ) ) ;
2014-05-13 19:34:00 -04:00
}
}
}
2014-06-04 18:06:57 -04:00
void FDesktopPlatformBase : : EnumerateLauncherSampleProjects ( TArray < FString > & OutFileNames )
{
// Enumerate all the sample installation directories
TArray < FString > LauncherSampleDirectories ;
EnumerateLauncherSampleInstallations ( LauncherSampleDirectories ) ;
// Find all the project files within them
for ( int32 Idx = 0 ; Idx < LauncherSampleDirectories . Num ( ) ; Idx + + )
{
TArray < FString > FileNames ;
IFileManager : : Get ( ) . FindFiles ( FileNames , * ( LauncherSampleDirectories [ Idx ] / TEXT ( " *.uproject " ) ) , true , false ) ;
OutFileNames . Append ( FileNames ) ;
}
}
2014-04-23 18:32:52 -04:00
bool FDesktopPlatformBase : : GetEngineRootDirFromIdentifier ( const FString & Identifier , FString & OutRootDir )
{
// Get all the installations
TMap < FString , FString > Installations ;
EnumerateEngineInstallations ( Installations ) ;
// Find the one with the right identifier
for ( TMap < FString , FString > : : TConstIterator Iter ( Installations ) ; Iter ; + + Iter )
{
if ( Iter - > Key = = Identifier )
{
OutRootDir = Iter - > Value ;
return true ;
}
}
return false ;
}
bool FDesktopPlatformBase : : GetEngineIdentifierFromRootDir ( const FString & RootDir , FString & OutIdentifier )
{
// Get all the installations
TMap < FString , FString > Installations ;
EnumerateEngineInstallations ( Installations ) ;
// Normalize the root directory
FString NormalizedRootDir = RootDir ;
FPaths : : NormalizeDirectoryName ( NormalizedRootDir ) ;
// Find the label for the given directory
for ( TMap < FString , FString > : : TConstIterator Iter ( Installations ) ; Iter ; + + Iter )
{
if ( Iter - > Value = = NormalizedRootDir )
{
OutIdentifier = Iter - > Key ;
return true ;
}
}
2014-05-06 10:27:35 -04:00
// Otherwise just try to add it
return RegisterEngineInstallation ( RootDir , OutIdentifier ) ;
2014-04-23 18:32:52 -04:00
}
2014-04-23 18:46:48 -04:00
bool FDesktopPlatformBase : : GetDefaultEngineIdentifier ( FString & OutId )
{
TMap < FString , FString > Installations ;
EnumerateEngineInstallations ( Installations ) ;
bool bRes = false ;
if ( Installations . Num ( ) > 0 )
{
// Default to the first install
TMap < FString , FString > : : TConstIterator Iter ( Installations ) ;
OutId = Iter . Key ( ) ;
+ + Iter ;
// Try to find the most preferred install
for ( ; Iter ; + + Iter )
{
if ( IsPreferredEngineIdentifier ( Iter . Key ( ) , OutId ) )
{
OutId = Iter . Key ( ) ;
}
}
}
return bRes ;
}
bool FDesktopPlatformBase : : GetDefaultEngineRootDir ( FString & OutDirName )
{
FString Identifier ;
return GetDefaultEngineIdentifier ( Identifier ) & & GetEngineRootDirFromIdentifier ( Identifier , OutDirName ) ;
}
bool FDesktopPlatformBase : : IsPreferredEngineIdentifier ( const FString & Identifier , const FString & OtherIdentifier )
{
int32 Version = ParseReleaseVersion ( Identifier ) ;
int32 OtherVersion = ParseReleaseVersion ( OtherIdentifier ) ;
if ( Version ! = OtherVersion )
{
return Version > OtherVersion ;
}
else
{
return Identifier > OtherIdentifier ;
}
}
2014-05-13 18:23:53 -04:00
bool FDesktopPlatformBase : : IsStockEngineRelease ( const FString & Identifier )
{
return Identifier . Len ( ) > 0 & & FChar : : IsDigit ( Identifier [ 0 ] ) ;
}
2014-04-23 18:46:48 -04:00
bool FDesktopPlatformBase : : IsSourceDistribution ( const FString & EngineRootDir )
{
// Check for the existence of a SourceBuild.txt file
2014-04-23 18:59:02 -04:00
FString SourceBuildPath = EngineRootDir / TEXT ( " Engine/Build/SourceDistribution.txt " ) ;
2014-04-23 18:46:48 -04:00
return ( IFileManager : : Get ( ) . FileSize ( * SourceBuildPath ) > = 0 ) ;
}
bool FDesktopPlatformBase : : IsPerforceBuild ( const FString & EngineRootDir )
{
// Check for the existence of a SourceBuild.txt file
2014-04-23 18:59:02 -04:00
FString PerforceBuildPath = EngineRootDir / TEXT ( " Engine/Build/PerforceBuild.txt " ) ;
2014-04-23 18:46:48 -04:00
return ( IFileManager : : Get ( ) . FileSize ( * PerforceBuildPath ) > = 0 ) ;
}
bool FDesktopPlatformBase : : IsValidRootDirectory ( const FString & RootDir )
{
2014-08-01 11:32:55 -04:00
// Check that there's an Engine\Binaries directory underneath the root
2014-04-23 18:46:48 -04:00
FString EngineBinariesDirName = RootDir / TEXT ( " Engine/Binaries " ) ;
FPaths : : NormalizeDirectoryName ( EngineBinariesDirName ) ;
2014-08-01 11:32:55 -04:00
if ( ! IFileManager : : Get ( ) . DirectoryExists ( * EngineBinariesDirName ) )
{
return false ;
}
// Also check there's an Engine\Build directory. This will filter out anything that has an engine-like directory structure but doesn't allow building code projects - like the launcher.
FString EngineBuildDirName = RootDir / TEXT ( " Engine/Build " ) ;
FPaths : : NormalizeDirectoryName ( EngineBuildDirName ) ;
if ( ! IFileManager : : Get ( ) . DirectoryExists ( * EngineBuildDirName ) )
{
return false ;
}
// Otherwise it's valid
return true ;
2014-04-23 18:46:48 -04:00
}
2014-05-06 10:27:35 -04:00
bool FDesktopPlatformBase : : SetEngineIdentifierForProject ( const FString & ProjectFileName , const FString & InIdentifier )
2014-04-23 18:46:48 -04:00
{
2014-05-06 10:27:35 -04:00
// Load the project file
2014-04-23 18:46:48 -04:00
TSharedPtr < FJsonObject > ProjectFile = LoadProjectFile ( ProjectFileName ) ;
if ( ! ProjectFile . IsValid ( ) )
{
return false ;
}
2014-05-06 10:27:35 -04:00
// Check if the project is a non-foreign project of the given engine installation. If so, blank the identifier
// string to allow portability between source control databases. GetEngineIdentifierForProject will translate
// the association back into a local identifier on other machines or syncs.
FString Identifier = InIdentifier ;
if ( Identifier . Len ( ) > 0 )
{
FString RootDir ;
if ( GetEngineRootDirFromIdentifier ( Identifier , RootDir ) )
{
2014-05-13 18:23:53 -04:00
const FUProjectDictionary & Dictionary = GetCachedProjectDictionary ( RootDir ) ;
2014-05-06 10:27:35 -04:00
if ( ! Dictionary . IsForeignProject ( ProjectFileName ) )
{
Identifier . Empty ( ) ;
}
}
}
// Set the association on the project and save it
2014-04-23 18:46:48 -04:00
ProjectFile - > SetStringField ( TEXT ( " EngineAssociation " ) , Identifier ) ;
return SaveProjectFile ( ProjectFileName , ProjectFile ) ;
}
bool FDesktopPlatformBase : : GetEngineIdentifierForProject ( const FString & ProjectFileName , FString & OutIdentifier )
{
2014-06-10 10:27:47 -04:00
OutIdentifier . Empty ( ) ;
2014-05-06 10:27:35 -04:00
// Load the project file
2014-04-23 18:46:48 -04:00
TSharedPtr < FJsonObject > ProjectFile = LoadProjectFile ( ProjectFileName ) ;
if ( ! ProjectFile . IsValid ( ) )
{
return false ;
}
2014-06-10 10:27:47 -04:00
// Try to read the identifier from it
TSharedPtr < FJsonValue > Value = ProjectFile - > TryGetField ( TEXT ( " EngineAssociation " ) ) ;
if ( Value . IsValid ( ) & & Value - > Type = = EJson : : String )
2014-05-06 10:27:35 -04:00
{
2014-06-10 10:27:47 -04:00
OutIdentifier = Value - > AsString ( ) ;
if ( OutIdentifier . Len ( ) > 0 )
{
return true ;
}
2014-05-06 10:27:35 -04:00
}
2014-05-15 13:07:56 -04:00
// Otherwise scan up through the directory hierarchy to find an installation
2014-05-06 10:27:35 -04:00
FString ParentDir = FPaths : : GetPath ( ProjectFileName ) ;
FPaths : : NormalizeDirectoryName ( ParentDir ) ;
2014-05-15 13:07:56 -04:00
// Keep going until we reach the root
2014-05-06 10:27:35 -04:00
int32 SeparatorIdx ;
while ( ParentDir . FindLastChar ( TEXT ( ' / ' ) , SeparatorIdx ) )
{
ParentDir . RemoveAt ( SeparatorIdx , ParentDir . Len ( ) - SeparatorIdx ) ;
2014-05-15 13:07:56 -04:00
if ( IsValidRootDirectory ( ParentDir ) & & GetEngineIdentifierFromRootDir ( ParentDir , OutIdentifier ) )
2014-05-06 10:27:35 -04:00
{
return true ;
}
}
2014-05-13 18:23:53 -04:00
// Otherwise check the engine version string for 4.0, in case this project existed before the engine association stuff went in
FString EngineVersionString = ProjectFile - > GetStringField ( TEXT ( " EngineVersion " ) ) ;
if ( EngineVersionString . Len ( ) > 0 )
{
FEngineVersion EngineVersion ;
if ( FEngineVersion : : Parse ( EngineVersionString , EngineVersion ) & & EngineVersion . IsPromotedBuild ( ) & & EngineVersion . ToString ( EVersionComponent : : Minor ) = = TEXT ( " 4.0 " ) )
{
OutIdentifier = TEXT ( " 4.0 " ) ;
return true ;
}
}
2014-05-06 10:27:35 -04:00
return false ;
2014-04-23 18:46:48 -04:00
}
2014-06-18 13:42:01 -04:00
bool FDesktopPlatformBase : : OpenProject ( const FString & ProjectFileName )
{
FPlatformProcess : : LaunchFileInDefaultExternalApplication ( * ProjectFileName ) ;
return true ;
}
2014-07-22 15:58:02 -04:00
bool FDesktopPlatformBase : : CleanGameProject ( const FString & ProjectDir , FString & OutFailPath , FFeedbackContext * Warn )
2014-05-14 19:11:30 -04:00
{
// Begin a task
Warn - > BeginSlowTask ( LOCTEXT ( " CleaningProject " , " Removing stale build products... " ) , true ) ;
// Enumerate all the files
TArray < FString > FileNames ;
2014-05-29 17:45:17 -04:00
TArray < FString > DirectoryNames ;
GetProjectBuildProducts ( ProjectDir , FileNames , DirectoryNames ) ;
2014-05-14 19:11:30 -04:00
// Remove all the files
for ( int32 Idx = 0 ; Idx < FileNames . Num ( ) ; Idx + + )
{
// Remove the file
if ( ! IFileManager : : Get ( ) . Delete ( * FileNames [ Idx ] ) )
{
2014-07-22 15:58:02 -04:00
OutFailPath = FileNames [ Idx ] ;
Warn - > EndSlowTask ( ) ;
2014-05-14 19:11:30 -04:00
return false ;
}
2014-05-29 17:45:17 -04:00
// Update the progress
Warn - > UpdateProgress ( Idx , FileNames . Num ( ) + DirectoryNames . Num ( ) ) ;
}
// Remove all the directories
for ( int32 Idx = 0 ; Idx < DirectoryNames . Num ( ) ; Idx + + )
{
// Remove the directory
if ( ! IFileManager : : Get ( ) . DeleteDirectory ( * DirectoryNames [ Idx ] , false , true ) )
2014-05-14 19:11:30 -04:00
{
2014-07-22 15:58:02 -04:00
OutFailPath = DirectoryNames [ Idx ] ;
Warn - > EndSlowTask ( ) ;
2014-05-29 17:45:17 -04:00
return false ;
2014-05-14 19:11:30 -04:00
}
// Update the progress
2014-05-29 17:45:17 -04:00
Warn - > UpdateProgress ( Idx + FileNames . Num ( ) , FileNames . Num ( ) + DirectoryNames . Num ( ) ) ;
2014-05-14 19:11:30 -04:00
}
// End the task
Warn - > EndSlowTask ( ) ;
return true ;
}
2014-05-13 18:23:53 -04:00
bool FDesktopPlatformBase : : CompileGameProject ( const FString & RootDir , const FString & ProjectFileName , FFeedbackContext * Warn )
{
// Get the target name
2014-07-10 13:00:35 -04:00
FString Arguments = FString : : Printf ( TEXT ( " %s %s %s " ) , * FPaths : : GetBaseFilename ( ProjectFileName ) , FModuleManager : : Get ( ) . GetUBTConfiguration ( ) , FPlatformMisc : : GetUBTPlatform ( ) ) ;
2014-05-13 18:23:53 -04:00
// Append the project name if it's a foreign project
if ( ! ProjectFileName . IsEmpty ( ) )
{
FUProjectDictionary ProjectDictionary ( RootDir ) ;
if ( ProjectDictionary . IsForeignProject ( ProjectFileName ) )
{
Arguments + = FString : : Printf ( TEXT ( " -project= \" %s \" " ) , * IFileManager : : Get ( ) . ConvertToAbsolutePathForExternalAppForRead ( * ProjectFileName ) ) ;
}
}
// Append the Rocket flag
if ( ! IsSourceDistribution ( RootDir ) )
{
Arguments + = TEXT ( " -rocket " ) ;
}
// Append any other options
Arguments + = " -editorrecompile -progress " ;
// Run UBT
return RunUnrealBuildTool ( LOCTEXT ( " CompilingProject " , " Compiling project... " ) , RootDir , Arguments , Warn ) ;
}
bool FDesktopPlatformBase : : GenerateProjectFiles ( const FString & RootDir , const FString & ProjectFileName , FFeedbackContext * Warn )
{
# if PLATFORM_MAC
FString Arguments = TEXT ( " -xcodeprojectfile " ) ;
2014-07-30 23:26:47 -04:00
# elif PLATFORM_LINUX
FString Arguments = TEXT ( " -makefile " ) ;
2014-05-13 18:23:53 -04:00
# else
FString Arguments = TEXT ( " -projectfiles " ) ;
# endif
// Build the arguments to pass to UBT
if ( ! ProjectFileName . IsEmpty ( ) )
{
// Figure out whether it's a foreign project
2014-05-14 14:53:19 -04:00
const FUProjectDictionary & ProjectDictionary = GetCachedProjectDictionary ( RootDir ) ;
2014-05-13 18:23:53 -04:00
if ( ProjectDictionary . IsForeignProject ( ProjectFileName ) )
{
Arguments + = FString : : Printf ( TEXT ( " -project= \" %s \" " ) , * IFileManager : : Get ( ) . ConvertToAbsolutePathForExternalAppForRead ( * ProjectFileName ) ) ;
2014-05-19 13:08:08 -04:00
// Always include game source
Arguments + = " -game " ;
2014-05-13 18:23:53 -04:00
2014-05-19 13:08:08 -04:00
// Determine whether or not to include engine source
if ( IsSourceDistribution ( RootDir ) )
{
Arguments + = " -engine " ;
}
else
{
Arguments + = " -rocket " ;
}
2014-05-13 18:23:53 -04:00
}
}
Arguments + = " -progress " ;
// Run UnrealBuildTool
Warn - > BeginSlowTask ( LOCTEXT ( " GeneratingProjectFiles " , " Generating project files... " ) , true , true ) ;
bool bRes = RunUnrealBuildTool ( LOCTEXT ( " GeneratingProjectFiles " , " Generating project files... " ) , RootDir , Arguments , Warn ) ;
Warn - > EndSlowTask ( ) ;
return bRes ;
}
2014-06-04 18:06:57 -04:00
FString FDesktopPlatformBase : : GetDefaultProjectCreationPath ( )
{
// My Documents
const FString DefaultProjectSubFolder = TEXT ( " Unreal Projects " ) ;
return FString ( FPlatformProcess : : UserDir ( ) ) + DefaultProjectSubFolder ;
}
2014-06-23 05:11:34 -04:00
FGuid FDesktopPlatformBase : : GetMachineId ( )
{
FGuid MachineId ;
FString MachineIdStr ;
// Check to see if we already have a valid machine ID to use
if ( ! FPlatformMisc : : GetStoredValue ( TEXT ( " Epic Games " ) , TEXT ( " Unreal Engine/Identifiers " ) , TEXT ( " MachineId " ) , MachineIdStr ) | | ! FGuid : : Parse ( MachineIdStr , MachineId ) )
{
// No valid machine ID, generate and save a new one
MachineId = FGuid : : NewGuid ( ) ;
MachineIdStr = MachineId . ToString ( EGuidFormats : : Digits ) ;
if ( ! FPlatformMisc : : SetStoredValue ( TEXT ( " Epic Games " ) , TEXT ( " Unreal Engine/Identifiers " ) , TEXT ( " MachineId " ) , MachineIdStr ) )
{
// Failed to persist the machine ID - reset it to zero to avoid returning a transient value
MachineId = FGuid ( ) ;
}
}
return MachineId ;
}
FString FDesktopPlatformBase : : GetEpicAccountId ( )
{
FString AccountId ;
FPlatformMisc : : GetStoredValue ( TEXT ( " Epic Games " ) , TEXT ( " Unreal Engine/Identifiers " ) , TEXT ( " AccountId " ) , AccountId ) ;
return AccountId ;
}
void FDesktopPlatformBase : : SetEpicAccountId ( const FString & AccountId )
{
FPlatformMisc : : SetStoredValue ( TEXT ( " Epic Games " ) , TEXT ( " Unreal Engine/Identifiers " ) , TEXT ( " AccountId " ) , AccountId ) ;
}
2014-05-14 15:20:39 -04:00
void FDesktopPlatformBase : : ReadLauncherInstallationList ( )
2014-05-08 08:20:34 -04:00
{
FString InstalledListFile = FString ( FPlatformProcess : : ApplicationSettingsDir ( ) ) / TEXT ( " UnrealEngineLauncher/LauncherInstalled.dat " ) ;
2014-05-14 15:20:39 -04:00
// If the file does not exist, manually check for the 4.0 or 4.1 manifest
FDateTime NewListTimestamp = IFileManager : : Get ( ) . GetTimeStamp ( * InstalledListFile ) ;
if ( NewListTimestamp = = FDateTime : : MinValue ( ) )
2014-05-08 08:20:34 -04:00
{
2014-05-14 15:20:39 -04:00
if ( LauncherInstallationList . Num ( ) = = 0 )
2014-05-08 08:20:34 -04:00
{
2014-05-14 15:20:39 -04:00
CheckForLauncherEngineInstallation ( TEXT ( " 40003 " ) , TEXT ( " UE_4.0 " ) , LauncherInstallationList ) ;
CheckForLauncherEngineInstallation ( TEXT ( " 1040003 " ) , TEXT ( " UE_4.1 " ) , LauncherInstallationList ) ;
}
}
else if ( NewListTimestamp ! = LauncherInstallationTimestamp )
{
// Read the installation manifest
FString InstalledText ;
if ( FFileHelper : : LoadFileToString ( InstalledText , * InstalledListFile ) )
{
// Deserialize the object
TSharedPtr < FJsonObject > RootObject ;
TSharedRef < TJsonReader < > > Reader = TJsonReaderFactory < > : : Create ( InstalledText ) ;
if ( FJsonSerializer : : Deserialize ( Reader , RootObject ) & & RootObject . IsValid ( ) )
{
// Parse the list of installations
TArray < TSharedPtr < FJsonValue > > InstallationList = RootObject - > GetArrayField ( TEXT ( " InstallationList " ) ) ;
for ( int32 Idx = 0 ; Idx < InstallationList . Num ( ) ; Idx + + )
{
TSharedPtr < FJsonObject > InstallationItem = InstallationList [ Idx ] - > AsObject ( ) ;
FString AppName = InstallationItem - > GetStringField ( TEXT ( " AppName " ) ) ;
FString InstallLocation = InstallationItem - > GetStringField ( TEXT ( " InstallLocation " ) ) ;
if ( AppName . Len ( ) > 0 & & InstallLocation . Len ( ) > 0 )
{
FPaths : : NormalizeDirectoryName ( InstallLocation ) ;
LauncherInstallationList . Add ( AppName , InstallLocation ) ;
}
}
}
LauncherInstallationTimestamp = NewListTimestamp ;
2014-05-08 08:20:34 -04:00
}
}
}
2014-04-23 18:46:48 -04:00
void FDesktopPlatformBase : : CheckForLauncherEngineInstallation ( const FString & AppId , const FString & Identifier , TMap < FString , FString > & OutInstallations )
{
FString ManifestText ;
FString ManifestFileName = FString ( FPlatformProcess : : ApplicationSettingsDir ( ) ) / FString : : Printf ( TEXT ( " UnrealEngineLauncher/Data/Manifests/%s.manifest " ) , * AppId ) ;
if ( FFileHelper : : LoadFileToString ( ManifestText , * ManifestFileName ) )
{
TSharedPtr < FJsonObject > RootObject ;
TSharedRef < TJsonReader < > > Reader = TJsonReaderFactory < > : : Create ( ManifestText ) ;
if ( FJsonSerializer : : Deserialize ( Reader , RootObject ) & & RootObject . IsValid ( ) )
{
TSharedPtr < FJsonObject > CustomFieldsObject = RootObject - > GetObjectField ( TEXT ( " CustomFields " ) ) ;
if ( CustomFieldsObject . IsValid ( ) )
{
FString InstallLocation = CustomFieldsObject - > GetStringField ( " InstallLocation " ) ;
if ( InstallLocation . Len ( ) > 0 )
{
OutInstallations . Add ( Identifier , InstallLocation ) ;
}
}
}
}
}
int32 FDesktopPlatformBase : : ParseReleaseVersion ( const FString & Version )
{
TCHAR * End ;
uint64 Major = FCString : : Strtoui64 ( * Version , & End , 10 ) ;
if ( Major > = MAX_int16 | | * ( End + + ) ! = ' . ' )
{
return INDEX_NONE ;
}
uint64 Minor = FCString : : Strtoui64 ( End , & End , 10 ) ;
if ( Minor > = MAX_int16 | | * End ! = 0 )
{
return INDEX_NONE ;
}
return ( Major < < 16 ) + Minor ;
}
TSharedPtr < FJsonObject > FDesktopPlatformBase : : LoadProjectFile ( const FString & FileName )
{
FString FileContents ;
if ( ! FFileHelper : : LoadFileToString ( FileContents , * FileName ) )
{
return TSharedPtr < FJsonObject > ( NULL ) ;
}
TSharedPtr < FJsonObject > JsonObject ;
TSharedRef < TJsonReader < > > Reader = TJsonReaderFactory < > : : Create ( FileContents ) ;
if ( ! FJsonSerializer : : Deserialize ( Reader , JsonObject ) | | ! JsonObject . IsValid ( ) )
{
return TSharedPtr < FJsonObject > ( NULL ) ;
}
return JsonObject ;
}
bool FDesktopPlatformBase : : SaveProjectFile ( const FString & FileName , TSharedPtr < FJsonObject > Object )
{
FString FileContents ;
TSharedRef < TJsonWriter < > > Writer = TJsonWriterFactory < > : : Create ( & FileContents ) ;
if ( ! FJsonSerializer : : Serialize ( Object . ToSharedRef ( ) , Writer ) )
{
return false ;
}
if ( ! FFileHelper : : SaveStringToFile ( FileContents , * FileName ) )
{
return false ;
}
return true ;
}
2014-05-13 18:23:53 -04:00
const FUProjectDictionary & FDesktopPlatformBase : : GetCachedProjectDictionary ( const FString & RootDir )
{
FString NormalizedRootDir = RootDir ;
FPaths : : NormalizeDirectoryName ( NormalizedRootDir ) ;
FUProjectDictionary * Dictionary = CachedProjectDictionaries . Find ( NormalizedRootDir ) ;
if ( Dictionary = = NULL )
{
Dictionary = & CachedProjectDictionaries . Add ( RootDir , FUProjectDictionary ( RootDir ) ) ;
}
return * Dictionary ;
}
2014-05-29 17:45:17 -04:00
void FDesktopPlatformBase : : GetProjectBuildProducts ( const FString & ProjectDir , TArray < FString > & OutFileNames , TArray < FString > & OutDirectoryNames )
2014-05-14 19:11:30 -04:00
{
FString NormalizedProjectDir = ProjectDir ;
FPaths : : NormalizeDirectoryName ( NormalizedProjectDir ) ;
// Find all the build roots
TArray < FString > BuildRootDirectories ;
BuildRootDirectories . Add ( NormalizedProjectDir ) ;
// Add all the plugin directories
TArray < FString > PluginFileNames ;
IFileManager : : Get ( ) . FindFilesRecursive ( PluginFileNames , * ( NormalizedProjectDir / TEXT ( " Plugins " ) ) , TEXT ( " *.uplugin " ) , true , false ) ;
for ( int32 Idx = 0 ; Idx < PluginFileNames . Num ( ) ; Idx + + )
{
BuildRootDirectories . Add ( FPaths : : GetPath ( PluginFileNames [ Idx ] ) ) ;
}
2014-05-29 17:45:17 -04:00
// Add all the intermediate directories
for ( int32 Idx = 0 ; Idx < BuildRootDirectories . Num ( ) ; Idx + + )
2014-05-14 19:11:30 -04:00
{
2014-05-29 17:45:17 -04:00
OutDirectoryNames . Add ( BuildRootDirectories [ Idx ] / TEXT ( " Intermediate " ) ) ;
2014-05-14 19:11:30 -04:00
}
2014-05-29 17:45:17 -04:00
// Add the files in the cleaned directories to the output list
for ( int32 Idx = 0 ; Idx < OutDirectoryNames . Num ( ) ; Idx + + )
2014-05-14 19:11:30 -04:00
{
2014-05-29 17:45:17 -04:00
IFileManager : : Get ( ) . FindFilesRecursive ( OutFileNames , * OutDirectoryNames [ Idx ] , TEXT ( " * " ) , true , false , false ) ;
2014-05-14 19:11:30 -04:00
}
}
2014-06-04 18:06:57 -04:00
bool FDesktopPlatformBase : : EnumerateProjectsKnownByEngine ( const FString & Identifier , bool bIncludeNativeProjects , TArray < FString > & OutProjectFileNames )
{
// Get the engine root directory
FString RootDir ;
if ( ! GetEngineRootDirFromIdentifier ( Identifier , RootDir ) )
{
return false ;
}
// Get the path to the game agnostic settings
FString UserDir ;
if ( IsStockEngineRelease ( Identifier ) )
{
UserDir = FPaths : : Combine ( FPlatformProcess : : UserSettingsDir ( ) , * FString ( EPIC_PRODUCT_IDENTIFIER ) , * Identifier ) ;
}
else
{
UserDir = FPaths : : Combine ( * RootDir , TEXT ( " Engine " ) ) ;
}
// Get the game agnostic config dir
FString GameAgnosticConfigDir = UserDir / TEXT ( " Saved/Config " ) / ANSI_TO_TCHAR ( FPlatformProperties : : PlatformName ( ) ) ;
// Find all the created project directories. Start with the default project creation path.
TArray < FString > SearchDirectories ;
SearchDirectories . AddUnique ( GetDefaultProjectCreationPath ( ) ) ;
// Load the config file
FConfigFile GameAgnosticConfig ;
FConfigCacheIni : : LoadExternalIniFile ( GameAgnosticConfig , TEXT ( " EditorGameAgnostic " ) , NULL , * GameAgnosticConfigDir , false ) ;
// Find the editor game-agnostic settings
FConfigSection * Section = GameAgnosticConfig . Find ( TEXT ( " /Script/UnrealEd.EditorGameAgnosticSettings " ) ) ;
if ( Section ! = NULL )
{
// Add in every path that the user has ever created a project file. This is to catch new projects showing up in the user's project folders
TArray < FString > AdditionalDirectories ;
Section - > MultiFind ( TEXT ( " CreatedProjectPaths " ) , AdditionalDirectories ) ;
for ( int Idx = 0 ; Idx < AdditionalDirectories . Num ( ) ; Idx + + )
{
FPaths : : NormalizeDirectoryName ( AdditionalDirectories [ Idx ] ) ;
SearchDirectories . AddUnique ( AdditionalDirectories [ Idx ] ) ;
}
// Also add in all the recently opened projects
TArray < FString > RecentlyOpenedFiles ;
Section - > MultiFind ( TEXT ( " RecentlyOpenedProjectFiles " ) , RecentlyOpenedFiles ) ;
for ( int Idx = 0 ; Idx < RecentlyOpenedFiles . Num ( ) ; Idx + + )
{
FPaths : : NormalizeFilename ( RecentlyOpenedFiles [ Idx ] ) ;
OutProjectFileNames . AddUnique ( RecentlyOpenedFiles [ Idx ] ) ;
}
}
// Find all the other projects that are in the search directories
for ( int Idx = 0 ; Idx < SearchDirectories . Num ( ) ; Idx + + )
{
TArray < FString > ProjectFolders ;
IFileManager : : Get ( ) . FindFiles ( ProjectFolders , * ( SearchDirectories [ Idx ] / TEXT ( " * " ) ) , false , true ) ;
for ( int32 FolderIdx = 0 ; FolderIdx < ProjectFolders . Num ( ) ; FolderIdx + + )
{
TArray < FString > ProjectFiles ;
2014-06-05 16:39:57 -04:00
IFileManager : : Get ( ) . FindFiles ( ProjectFiles , * ( SearchDirectories [ Idx ] / ProjectFolders [ FolderIdx ] / TEXT ( " *.uproject " ) ) , true , false ) ;
2014-06-04 18:06:57 -04:00
for ( int32 FileIdx = 0 ; FileIdx < ProjectFiles . Num ( ) ; FileIdx + + )
{
2014-06-05 16:39:57 -04:00
OutProjectFileNames . AddUnique ( SearchDirectories [ Idx ] / ProjectFolders [ FolderIdx ] / ProjectFiles [ FileIdx ] ) ;
2014-06-04 18:06:57 -04:00
}
}
}
// Find all the native projects, and either add or remove them from the list depending on whether we want native projects
const FUProjectDictionary & Dictionary = GetCachedProjectDictionary ( RootDir ) ;
if ( bIncludeNativeProjects )
{
TArray < FString > NativeProjectPaths = Dictionary . GetProjectPaths ( ) ;
for ( int Idx = 0 ; Idx < NativeProjectPaths . Num ( ) ; Idx + + )
{
if ( ! NativeProjectPaths [ Idx ] . Contains ( TEXT ( " /Templates/ " ) ) )
{
OutProjectFileNames . AddUnique ( NativeProjectPaths [ Idx ] ) ;
}
}
}
else
{
TArray < FString > NativeProjectPaths = Dictionary . GetProjectPaths ( ) ;
for ( int Idx = 0 ; Idx < NativeProjectPaths . Num ( ) ; Idx + + )
{
OutProjectFileNames . Remove ( NativeProjectPaths [ Idx ] ) ;
}
}
return true ;
}
2014-05-13 18:23:53 -04:00
# undef LOCTEXT_NAMESPACE