2014-03-14 14:13:41 -04:00
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
# include "ProjectsPrivatePCH.h"
DEFINE_LOG_CATEGORY_STATIC ( LogProjectManager , Log , All ) ;
# define LOCTEXT_NAMESPACE "ProjectManager"
FProjectManager : : FProjectManager ( )
{
2014-06-27 15:23:15 -04:00
bRestartRequired = false ;
}
const FProjectDescriptor * FProjectManager : : GetCurrentProject ( ) const
{
return CurrentProject . Get ( ) ;
2014-03-14 14:13:41 -04:00
}
bool FProjectManager : : LoadProjectFile ( const FString & InProjectFile )
{
2014-06-27 08:41:46 -04:00
// Try to load the descriptor
2014-03-14 14:13:41 -04:00
FText FailureReason ;
2014-06-27 08:41:46 -04:00
TSharedPtr < FProjectDescriptor > Descriptor = MakeShareable ( new FProjectDescriptor ( ) ) ;
if ( Descriptor - > Load ( InProjectFile , FailureReason ) )
2014-03-14 14:13:41 -04:00
{
2014-06-27 08:41:46 -04:00
// Create the project
2014-06-27 15:23:15 -04:00
CurrentProject = Descriptor ;
2014-05-13 18:23:53 -04:00
return true ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 18:40:57 -04:00
# if PLATFORM_IOS
FString UpdatedMessage = FString : : Printf ( TEXT ( " %s \n %s " ) , * FailureReason . ToString ( ) , TEXT ( " For troubleshooting, please go to https://docs.unrealengine.com/latest/INT/Platforms/iOS/GettingStarted/index.html " ) ) ;
FailureReason = FText : : FromString ( UpdatedMessage ) ;
# endif
2014-03-14 14:13:41 -04:00
UE_LOG ( LogProjectManager , Error , TEXT ( " %s " ) , * FailureReason . ToString ( ) ) ;
FMessageDialog : : Open ( EAppMsgType : : Ok , FailureReason ) ;
2014-04-23 18:40:57 -04:00
2014-03-14 14:13:41 -04:00
return false ;
}
bool FProjectManager : : LoadModulesForProject ( const ELoadingPhase : : Type LoadingPhase )
{
DECLARE_SCOPE_CYCLE_COUNTER ( TEXT ( " Loading Game Modules " ) , STAT_GameModule , STATGROUP_LoadTime ) ;
bool bSuccess = true ;
2014-06-27 15:23:15 -04:00
if ( CurrentProject . IsValid ( ) )
2014-03-14 14:13:41 -04:00
{
2014-06-18 19:23:34 -04:00
TMap < FName , EModuleLoadResult > ModuleLoadFailures ;
2014-06-27 15:23:15 -04:00
FModuleDescriptor : : LoadModulesForPhase ( LoadingPhase , CurrentProject - > Modules , ModuleLoadFailures ) ;
2014-03-14 14:13:41 -04:00
if ( ModuleLoadFailures . Num ( ) > 0 )
{
FText FailureMessage ;
for ( auto FailureIt = ModuleLoadFailures . CreateConstIterator ( ) ; FailureIt ; + + FailureIt )
{
2014-06-18 19:23:34 -04:00
const EModuleLoadResult FailureReason = FailureIt . Value ( ) ;
2014-03-14 14:13:41 -04:00
2014-06-18 19:23:34 -04:00
if ( FailureReason ! = EModuleLoadResult : : Success )
2014-03-14 14:13:41 -04:00
{
const FText TextModuleName = FText : : FromName ( FailureIt . Key ( ) ) ;
2014-06-18 19:23:34 -04:00
if ( FailureReason = = EModuleLoadResult : : FileNotFound )
2014-03-14 14:13:41 -04:00
{
FailureMessage = FText : : Format ( LOCTEXT ( " PrimaryGameModuleNotFound " , " The game module '{0}' could not be found. Please ensure that this module exists and that it is compiled. " ) , TextModuleName ) ;
}
2014-06-18 19:23:34 -04:00
else if ( FailureReason = = EModuleLoadResult : : FileIncompatible )
2014-03-14 14:13:41 -04:00
{
FailureMessage = FText : : Format ( LOCTEXT ( " PrimaryGameModuleIncompatible " , " The game module '{0}' does not appear to be up to date. This may happen after updating the engine. Please recompile this module and try again. " ) , TextModuleName ) ;
}
2014-06-18 19:23:34 -04:00
else if ( FailureReason = = EModuleLoadResult : : FailedToInitialize )
2014-03-14 14:13:41 -04:00
{
FailureMessage = FText : : Format ( LOCTEXT ( " PrimaryGameModuleFailedToInitialize " , " The game module '{0}' could not be successfully initialized after it was loaded. " ) , TextModuleName ) ;
}
2014-06-18 19:23:34 -04:00
else if ( FailureReason = = EModuleLoadResult : : CouldNotBeLoadedByOS )
2014-03-14 14:13:41 -04:00
{
FailureMessage = FText : : Format ( LOCTEXT ( " PrimaryGameModuleCouldntBeLoaded " , " The game module '{0}' could not be loaded. There may be an operating system error or the module may not be properly set up. " ) , TextModuleName ) ;
}
else
{
ensure ( 0 ) ; // If this goes off, the error handling code should be updated for the new enum values!
FailureMessage = FText : : Format ( LOCTEXT ( " PrimaryGameModuleGenericLoadFailure " , " The game module '{0}' failed to load for an unspecified reason. Please report this error. " ) , TextModuleName ) ;
}
// Just report the first error
break ;
}
}
FMessageDialog : : Open ( EAppMsgType : : Ok , FailureMessage ) ;
bSuccess = false ;
}
}
return bSuccess ;
}
2014-04-30 10:48:13 -04:00
bool FProjectManager : : AreProjectModulesUpToDate ( )
{
2014-06-27 15:23:15 -04:00
return ! CurrentProject . IsValid ( ) | | FModuleDescriptor : : AreModulesUpToDate ( CurrentProject - > Modules ) ;
2014-04-30 10:48:13 -04:00
}
2014-03-14 14:13:41 -04:00
const FString & FProjectManager : : GetAutoLoadProjectFileName ( )
{
static FString RecentProjectFileName = FPaths : : Combine ( * FPaths : : GameAgnosticSavedDir ( ) , TEXT ( " AutoLoadProject.txt " ) ) ;
return RecentProjectFileName ;
}
const FString & FProjectManager : : NonStaticGetProjectFileExtension ( )
{
static FString GameProjectFileExtension ( TEXT ( " uproject " ) ) ;
return GameProjectFileExtension ;
}
2014-04-23 18:32:52 -04:00
bool FProjectManager : : GenerateNewProjectFile ( const FString & NewProjectFilename , const TArray < FString > & StartupModuleNames , const FString & EngineIdentifier , FText & OutFailReason )
2014-03-14 14:13:41 -04:00
{
2014-06-27 08:41:46 -04:00
FProjectDescriptor Descriptor ;
Descriptor . EngineAssociation = EngineIdentifier ;
2014-03-14 14:13:41 -04:00
2014-06-27 08:41:46 -04:00
for ( int32 Idx = 0 ; Idx < StartupModuleNames . Num ( ) ; Idx + + )
2014-03-14 14:13:41 -04:00
{
2014-06-27 08:41:46 -04:00
Descriptor . Modules . Add ( FModuleDescriptor ( * StartupModuleNames [ Idx ] ) ) ;
2014-03-14 14:13:41 -04:00
}
2014-06-27 08:41:46 -04:00
return Descriptor . Save ( NewProjectFilename , OutFailReason ) ;
2014-03-14 14:13:41 -04:00
}
bool FProjectManager : : SignSampleProject ( const FString & FilePath , const FString & Category , FText & OutFailReason )
{
2014-06-27 08:41:46 -04:00
FProjectDescriptor Descriptor ;
if ( ! Descriptor . Load ( FilePath , OutFailReason ) )
2014-03-14 14:13:41 -04:00
{
return false ;
}
2014-06-27 08:41:46 -04:00
Descriptor . Sign ( FilePath ) ;
Descriptor . Category = Category ;
return Descriptor . Save ( FilePath , OutFailReason ) ;
2014-03-14 14:13:41 -04:00
}
2014-05-13 18:23:53 -04:00
bool FProjectManager : : QueryStatusForProject ( const FString & FilePath , FProjectStatus & OutProjectStatus ) const
2014-03-14 14:13:41 -04:00
{
FText FailReason ;
2014-06-27 08:41:46 -04:00
FProjectDescriptor Descriptor ;
if ( ! Descriptor . Load ( FilePath , FailReason ) )
2014-03-14 14:13:41 -04:00
{
return false ;
}
2014-06-27 08:41:46 -04:00
QueryStatusForProjectImpl ( Descriptor , FilePath , OutProjectStatus ) ;
2014-05-29 17:37:19 -04:00
return true ;
}
bool FProjectManager : : QueryStatusForCurrentProject ( FProjectStatus & OutProjectStatus ) const
{
2014-06-27 15:23:15 -04:00
if ( ! CurrentProject . IsValid ( ) )
2014-05-29 17:37:19 -04:00
{
return false ;
}
2014-06-27 15:23:15 -04:00
QueryStatusForProjectImpl ( * CurrentProject , FPaths : : GetProjectFilePath ( ) , OutProjectStatus ) ;
2014-05-29 17:37:19 -04:00
return true ;
}
2014-06-27 08:41:46 -04:00
void FProjectManager : : QueryStatusForProjectImpl ( const FProjectDescriptor & ProjectInfo , const FString & FilePath , FProjectStatus & OutProjectStatus )
2014-05-29 17:37:19 -04:00
{
2014-06-27 08:41:46 -04:00
OutProjectStatus . Name = FPaths : : GetBaseFilename ( FilePath ) ;
2014-03-14 14:13:41 -04:00
OutProjectStatus . Description = ProjectInfo . Description ;
OutProjectStatus . Category = ProjectInfo . Category ;
2014-05-13 18:23:53 -04:00
OutProjectStatus . bCodeBasedProject = ProjectInfo . Modules . Num ( ) > 0 ;
2014-06-27 08:41:46 -04:00
OutProjectStatus . bSignedSampleProject = ProjectInfo . IsSigned ( FilePath ) ;
OutProjectStatus . bRequiresUpdate = ProjectInfo . FileVersion < EProjectDescriptorVersion : : Latest ;
2014-05-29 17:37:19 -04:00
OutProjectStatus . TargetPlatforms = ProjectInfo . TargetPlatforms ;
}
2014-03-14 14:13:41 -04:00
2014-05-29 17:37:19 -04:00
void FProjectManager : : UpdateSupportedTargetPlatformsForProject ( const FString & FilePath , const FName & InPlatformName , const bool bIsSupported )
{
2014-06-27 08:41:46 -04:00
FProjectDescriptor NewProject ;
2014-05-29 17:37:19 -04:00
FText FailReason ;
2014-06-27 08:41:46 -04:00
if ( ! NewProject . Load ( FilePath , FailReason ) )
2014-05-29 17:37:19 -04:00
{
return ;
}
2014-06-27 08:41:46 -04:00
if ( bIsSupported )
{
NewProject . TargetPlatforms . AddUnique ( InPlatformName ) ;
}
else
{
NewProject . TargetPlatforms . Remove ( InPlatformName ) ;
}
2014-05-29 17:37:19 -04:00
2014-06-27 08:41:46 -04:00
NewProject . Save ( FilePath , FailReason ) ;
2014-05-29 17:37:19 -04:00
// Call OnTargetPlatformsForCurrentProjectChangedEvent if this project is the same as the one we currently have loaded
const FString CurrentProjectPath = FPaths : : ConvertRelativePathToFull ( FPaths : : GetProjectFilePath ( ) ) ;
const FString InProjectPath = FPaths : : ConvertRelativePathToFull ( FilePath ) ;
if ( CurrentProjectPath = = InProjectPath )
{
OnTargetPlatformsForCurrentProjectChangedEvent . Broadcast ( ) ;
}
}
void FProjectManager : : UpdateSupportedTargetPlatformsForCurrentProject ( const FName & InPlatformName , const bool bIsSupported )
{
2014-06-27 15:23:15 -04:00
if ( ! CurrentProject . IsValid ( ) )
2014-05-29 17:37:19 -04:00
{
return ;
}
2014-06-27 15:23:15 -04:00
CurrentProject - > UpdateSupportedTargetPlatforms ( InPlatformName , bIsSupported ) ;
2014-05-29 17:37:19 -04:00
2014-06-27 08:41:46 -04:00
FText FailReason ;
2014-06-27 15:23:15 -04:00
CurrentProject - > Save ( FPaths : : GetProjectFilePath ( ) , FailReason ) ;
2014-05-29 17:37:19 -04:00
OnTargetPlatformsForCurrentProjectChangedEvent . Broadcast ( ) ;
2014-03-14 14:13:41 -04:00
}
2014-06-05 12:13:44 -04:00
void FProjectManager : : ClearSupportedTargetPlatformsForProject ( const FString & FilePath )
{
2014-06-27 08:41:46 -04:00
FProjectDescriptor Descriptor ;
2014-06-05 12:13:44 -04:00
FText FailReason ;
2014-06-27 08:41:46 -04:00
if ( ! Descriptor . Load ( FilePath , FailReason ) )
2014-06-05 12:13:44 -04:00
{
return ;
}
2014-06-27 08:41:46 -04:00
Descriptor . TargetPlatforms . Empty ( ) ;
Descriptor . Save ( FilePath , FailReason ) ;
2014-06-05 12:13:44 -04:00
// Call OnTargetPlatformsForCurrentProjectChangedEvent if this project is the same as the one we currently have loaded
const FString CurrentProjectPath = FPaths : : ConvertRelativePathToFull ( FPaths : : GetProjectFilePath ( ) ) ;
const FString InProjectPath = FPaths : : ConvertRelativePathToFull ( FilePath ) ;
if ( CurrentProjectPath = = InProjectPath )
{
OnTargetPlatformsForCurrentProjectChangedEvent . Broadcast ( ) ;
}
}
void FProjectManager : : ClearSupportedTargetPlatformsForCurrentProject ( )
{
2014-06-27 15:23:15 -04:00
if ( ! CurrentProject . IsValid ( ) )
2014-06-05 12:13:44 -04:00
{
return ;
}
2014-06-27 15:23:15 -04:00
CurrentProject - > TargetPlatforms . Empty ( ) ;
2014-06-05 12:13:44 -04:00
2014-06-27 08:41:46 -04:00
FText FailReason ;
2014-06-27 15:23:15 -04:00
CurrentProject - > Save ( FPaths : : GetProjectFilePath ( ) , FailReason ) ;
2014-06-05 12:13:44 -04:00
OnTargetPlatformsForCurrentProjectChangedEvent . Broadcast ( ) ;
}
2014-06-27 15:23:15 -04:00
void FProjectManager : : GetEnabledPlugins ( TArray < FString > & OutPluginNames ) const
{
// Get the default list of plugin names
GetDefaultEnabledPlugins ( OutPluginNames ) ;
// Modify that with the list of plugins in the project file
const FProjectDescriptor * Project = GetCurrentProject ( ) ;
if ( Project ! = NULL )
{
for ( const FPluginReferenceDescriptor & Plugin : Project - > Plugins )
{
if ( Plugin . IsEnabledForPlatform ( FPlatformMisc : : GetUBTPlatform ( ) ) )
{
OutPluginNames . AddUnique ( Plugin . Name ) ;
}
else
{
OutPluginNames . Remove ( Plugin . Name ) ;
}
}
}
}
2014-06-27 16:38:50 -04:00
bool FProjectManager : : IsNonDefaultPluginEnabled ( ) const
2014-06-27 15:23:15 -04:00
{
TArray < FString > EnabledPlugins ;
GetEnabledPlugins ( EnabledPlugins ) ;
2014-06-27 16:38:50 -04:00
for ( const FPluginStatus & Plugin : IPluginManager : : Get ( ) . QueryStatusForAllPlugins ( ) )
2014-06-27 15:23:15 -04:00
{
2014-06-27 16:38:50 -04:00
if ( ( ! Plugin . bIsBuiltIn | | ! Plugin . bIsEnabledByDefault ) & & EnabledPlugins . Contains ( Plugin . Name ) )
2014-06-27 15:23:15 -04:00
{
return true ;
}
}
2014-06-27 16:38:50 -04:00
2014-06-27 15:23:15 -04:00
return false ;
}
bool FProjectManager : : SetPluginEnabled ( const FString & PluginName , bool bEnabled , FText & OutFailReason )
{
// Don't go any further if there's no project loaded
if ( ! CurrentProject . IsValid ( ) )
{
OutFailReason = LOCTEXT ( " NoProjectLoaded " , " No project is currently loaded " ) ;
return false ;
}
// Find or create the index of any existing reference in the project descriptor
int PluginRefIdx = 0 ;
for ( ; ; PluginRefIdx + + )
{
if ( PluginRefIdx = = CurrentProject - > Plugins . Num ( ) )
{
PluginRefIdx = CurrentProject - > Plugins . Add ( FPluginReferenceDescriptor ( PluginName , bEnabled ) ) ;
break ;
}
else if ( CurrentProject - > Plugins [ PluginRefIdx ] . Name = = PluginName )
{
CurrentProject - > Plugins [ PluginRefIdx ] . bEnabled = bEnabled ;
break ;
}
}
// If the current plugin reference is the default, just remove it from the list
const FPluginReferenceDescriptor * PluginRef = & CurrentProject - > Plugins [ PluginRefIdx ] ;
if ( PluginRef - > WhitelistPlatforms . Num ( ) = = 0 & & PluginRef - > BlacklistPlatforms . Num ( ) = = 0 )
{
// Get the default list of enabled plugins
TArray < FString > DefaultEnabledPlugins ;
GetDefaultEnabledPlugins ( DefaultEnabledPlugins ) ;
// Check the enabled state is the same in that
if ( DefaultEnabledPlugins . Contains ( PluginName ) = = bEnabled )
{
CurrentProject - > Plugins . RemoveAt ( PluginRefIdx ) ;
PluginRefIdx = INDEX_NONE ;
}
}
// Try to save the project file
if ( ! CurrentProject - > Save ( * FPaths : : GetProjectFilePath ( ) , OutFailReason ) )
{
return false ;
}
// Flag that a restart is required and return
bRestartRequired = true ;
return true ;
}
bool FProjectManager : : IsRestartRequired ( ) const
{
return bRestartRequired ;
}
void FProjectManager : : GetDefaultEnabledPlugins ( TArray < FString > & OutPluginNames )
{
2014-06-27 16:38:50 -04:00
// Add all the game plugins and everything marked as enabled by default
2014-06-27 15:23:15 -04:00
TArray < FPluginStatus > PluginStatuses = IPluginManager : : Get ( ) . QueryStatusForAllPlugins ( ) ;
for ( const FPluginStatus & PluginStatus : PluginStatuses )
{
2014-06-27 16:38:50 -04:00
if ( PluginStatus . bIsEnabledByDefault | | ! PluginStatus . bIsBuiltIn )
2014-06-27 15:23:15 -04:00
{
OutPluginNames . AddUnique ( PluginStatus . Name ) ;
}
}
}
2014-03-14 14:13:41 -04:00
IProjectManager & IProjectManager : : Get ( )
{
// Single instance of manager, allocated on demand and destroyed on program exit.
static FProjectManager * ProjectManager = NULL ;
if ( ProjectManager = = NULL )
{
ProjectManager = new FProjectManager ( ) ;
}
return * ProjectManager ;
}
# undef LOCTEXT_NAMESPACE