2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-06-25 13:09:31 -04:00
# include "ProjectsPrivatePCH.h"
2014-06-27 08:41:46 -04:00
# define LOCTEXT_NAMESPACE "ModuleDescriptor"
2014-06-25 13:09:31 -04:00
ELoadingPhase : : Type ELoadingPhase : : FromString ( const TCHAR * String )
{
ELoadingPhase : : Type TestType = ( ELoadingPhase : : Type ) 0 ;
for ( ; TestType < ELoadingPhase : : Max ; TestType = ( ELoadingPhase : : Type ) ( TestType + 1 ) )
{
const TCHAR * TestString = ToString ( TestType ) ;
if ( FCString : : Stricmp ( String , TestString ) = = 0 )
{
break ;
}
}
return TestType ;
}
const TCHAR * ELoadingPhase : : ToString ( const ELoadingPhase : : Type Value )
{
switch ( Value )
{
case Default :
return TEXT ( " Default " ) ;
case PostDefault :
return TEXT ( " PostDefault " ) ;
case PreDefault :
return TEXT ( " PreDefault " ) ;
case PostConfigInit :
return TEXT ( " PostConfigInit " ) ;
case PreLoadingScreen :
return TEXT ( " PreLoadingScreen " ) ;
2014-07-10 21:04:34 -04:00
case PostEngineInit :
return TEXT ( " PostEngineInit " ) ;
2014-06-25 13:09:31 -04:00
default :
ensureMsgf ( false , TEXT ( " Unrecognized ELoadingPhase value: %i " ) , Value ) ;
return NULL ;
}
}
EHostType : : Type EHostType : : FromString ( const TCHAR * String )
{
EHostType : : Type TestType = ( EHostType : : Type ) 0 ;
for ( ; TestType < EHostType : : Max ; TestType = ( EHostType : : Type ) ( TestType + 1 ) )
{
const TCHAR * TestString = ToString ( TestType ) ;
if ( FCString : : Stricmp ( String , TestString ) = = 0 )
{
break ;
}
}
return TestType ;
}
const TCHAR * EHostType : : ToString ( const EHostType : : Type Value )
{
switch ( Value )
{
case Runtime :
return TEXT ( " Runtime " ) ;
case RuntimeNoCommandlet :
return TEXT ( " RuntimeNoCommandlet " ) ;
case Developer :
return TEXT ( " Developer " ) ;
case Editor :
return TEXT ( " Editor " ) ;
case EditorNoCommandlet :
return TEXT ( " EditorNoCommandlet " ) ;
case Program :
return TEXT ( " Program " ) ;
default :
ensureMsgf ( false , TEXT ( " Unrecognized EModuleType value: %i " ) , Value ) ;
return NULL ;
}
}
2014-06-27 08:41:46 -04:00
FModuleDescriptor : : FModuleDescriptor ( const FName InName , EHostType : : Type InType , ELoadingPhase : : Type InLoadingPhase )
: Name ( InName )
, Type ( InType )
, LoadingPhase ( InLoadingPhase )
2014-06-25 13:09:31 -04:00
{
}
bool FModuleDescriptor : : Read ( const FJsonObject & Object , FText & OutFailReason )
{
// Read the module name
TSharedPtr < FJsonValue > NameValue = Object . TryGetField ( TEXT ( " Name " ) ) ;
if ( ! NameValue . IsValid ( ) | | NameValue - > Type ! = EJson : : String )
{
OutFailReason = LOCTEXT ( " ModuleWithoutAName " , " Found a 'Module' entry with a missing 'Name' field " ) ;
return false ;
}
Name = FName ( * NameValue - > AsString ( ) ) ;
// Read the module type
TSharedPtr < FJsonValue > TypeValue = Object . TryGetField ( TEXT ( " Type " ) ) ;
if ( ! TypeValue . IsValid ( ) | | TypeValue - > Type ! = EJson : : String )
{
OutFailReason = FText : : Format ( LOCTEXT ( " ModuleWithoutAType " , " Found Module entry '{0}' with a missing 'Type' field " ) , FText : : FromName ( Name ) ) ;
return false ;
}
Type = EHostType : : FromString ( * TypeValue - > AsString ( ) ) ;
if ( Type = = EHostType : : Max )
{
OutFailReason = FText : : Format ( LOCTEXT ( " ModuleWithInvalidType " , " Module entry '{0}' specified an unrecognized module Type '{1}' " ) , FText : : FromName ( Name ) , FText : : FromString ( TypeValue - > AsString ( ) ) ) ;
return false ;
}
// Read the loading phase
TSharedPtr < FJsonValue > LoadingPhaseValue = Object . TryGetField ( TEXT ( " LoadingPhase " ) ) ;
if ( LoadingPhaseValue . IsValid ( ) & & LoadingPhaseValue - > Type = = EJson : : String )
{
LoadingPhase = ELoadingPhase : : FromString ( * LoadingPhaseValue - > AsString ( ) ) ;
if ( LoadingPhase = = ELoadingPhase : : Max )
{
OutFailReason = FText : : Format ( LOCTEXT ( " ModuleWithInvalidLoadingPhase " , " Module entry '{0}' specified an unrecognized module LoadingPhase '{1}' " ) , FText : : FromName ( Name ) , FText : : FromString ( LoadingPhaseValue - > AsString ( ) ) ) ;
return false ;
}
}
// Read the whitelisted platforms
TSharedPtr < FJsonValue > WhitelistPlatformsValue = Object . TryGetField ( TEXT ( " WhitelistPlatforms " ) ) ;
if ( WhitelistPlatformsValue . IsValid ( ) & & WhitelistPlatformsValue - > Type = = EJson : : Array )
{
const TArray < TSharedPtr < FJsonValue > > & PlatformsArray = WhitelistPlatformsValue - > AsArray ( ) ;
for ( int Idx = 0 ; Idx < PlatformsArray . Num ( ) ; Idx + + )
{
WhitelistPlatforms . Add ( PlatformsArray [ Idx ] - > AsString ( ) ) ;
}
}
// Read the blacklisted platforms
TSharedPtr < FJsonValue > BlacklistPlatformsValue = Object . TryGetField ( TEXT ( " BlacklistPlatforms " ) ) ;
if ( BlacklistPlatformsValue . IsValid ( ) & & BlacklistPlatformsValue - > Type = = EJson : : Array )
{
const TArray < TSharedPtr < FJsonValue > > & PlatformsArray = BlacklistPlatformsValue - > AsArray ( ) ;
for ( int Idx = 0 ; Idx < PlatformsArray . Num ( ) ; Idx + + )
{
BlacklistPlatforms . Add ( PlatformsArray [ Idx ] - > AsString ( ) ) ;
}
}
2015-03-17 09:34:18 -04:00
// Read the additional dependencies
TSharedPtr < FJsonValue > AdditionalDependenciesValue = Object . TryGetField ( TEXT ( " AdditionalDependencies " ) ) ;
if ( AdditionalDependenciesValue . IsValid ( ) & & AdditionalDependenciesValue - > Type = = EJson : : Array )
{
const TArray < TSharedPtr < FJsonValue > > & DepArray = AdditionalDependenciesValue - > AsArray ( ) ;
for ( int Idx = 0 ; Idx < DepArray . Num ( ) ; Idx + + )
{
AdditionalDependencies . Add ( DepArray [ Idx ] - > AsString ( ) ) ;
}
}
2014-06-25 13:09:31 -04:00
return true ;
}
bool FModuleDescriptor : : ReadArray ( const FJsonObject & Object , const TCHAR * Name , TArray < FModuleDescriptor > & OutModules , FText & OutFailReason )
{
bool bResult = true ;
TSharedPtr < FJsonValue > ModulesArrayValue = Object . TryGetField ( Name ) ;
if ( ModulesArrayValue . IsValid ( ) & & ModulesArrayValue - > Type = = EJson : : Array )
{
const TArray < TSharedPtr < FJsonValue > > & ModulesArray = ModulesArrayValue - > AsArray ( ) ;
for ( int Idx = 0 ; Idx < ModulesArray . Num ( ) ; Idx + + )
{
const TSharedPtr < FJsonValue > & ModuleValue = ModulesArray [ Idx ] ;
if ( ModuleValue . IsValid ( ) & & ModuleValue - > Type = = EJson : : Object )
{
FModuleDescriptor Descriptor ;
if ( Descriptor . Read ( * ModuleValue - > AsObject ( ) . Get ( ) , OutFailReason ) )
{
OutModules . Add ( Descriptor ) ;
}
else
{
bResult = false ;
}
}
else
{
OutFailReason = LOCTEXT ( " ModuleWithInvalidModulesArray " , " The 'Modules' array has invalid contents and was not able to be loaded. " ) ;
bResult = false ;
}
}
}
return bResult ;
}
void FModuleDescriptor : : Write ( TJsonWriter < > & Writer ) const
{
Writer . WriteObjectStart ( ) ;
Writer . WriteValue ( TEXT ( " Name " ) , Name . ToString ( ) ) ;
Writer . WriteValue ( TEXT ( " Type " ) , FString ( EHostType : : ToString ( Type ) ) ) ;
Writer . WriteValue ( TEXT ( " LoadingPhase " ) , FString ( ELoadingPhase : : ToString ( LoadingPhase ) ) ) ;
if ( WhitelistPlatforms . Num ( ) > 0 )
{
Writer . WriteArrayStart ( TEXT ( " WhitelistPlatforms " ) ) ;
for ( int Idx = 0 ; Idx < WhitelistPlatforms . Num ( ) ; Idx + + )
{
Writer . WriteValue ( WhitelistPlatforms [ Idx ] ) ;
}
Writer . WriteArrayEnd ( ) ;
}
if ( BlacklistPlatforms . Num ( ) > 0 )
{
Writer . WriteArrayStart ( TEXT ( " BlacklistPlatforms " ) ) ;
for ( int Idx = 0 ; Idx < BlacklistPlatforms . Num ( ) ; Idx + + )
{
Writer . WriteValue ( BlacklistPlatforms [ Idx ] ) ;
}
Writer . WriteArrayEnd ( ) ;
}
2015-03-17 09:34:18 -04:00
if ( AdditionalDependencies . Num ( ) > 0 )
{
Writer . WriteArrayStart ( TEXT ( " AdditionalDependencies " ) ) ;
for ( int Idx = 0 ; Idx < AdditionalDependencies . Num ( ) ; Idx + + )
{
Writer . WriteValue ( AdditionalDependencies [ Idx ] ) ;
}
Writer . WriteArrayEnd ( ) ;
}
2014-06-25 13:09:31 -04:00
Writer . WriteObjectEnd ( ) ;
}
void FModuleDescriptor : : WriteArray ( TJsonWriter < > & Writer , const TCHAR * Name , const TArray < FModuleDescriptor > & Modules )
{
if ( Modules . Num ( ) > 0 )
{
Writer . WriteArrayStart ( Name ) ;
for ( int Idx = 0 ; Idx < Modules . Num ( ) ; Idx + + )
{
Modules [ Idx ] . Write ( Writer ) ;
}
Writer . WriteArrayEnd ( ) ;
}
}
2014-06-27 08:41:46 -04:00
bool FModuleDescriptor : : IsCompiledInCurrentConfiguration ( ) const
{
// Cache the string for the current platform
static FString UBTPlatform ( FPlatformMisc : : GetUBTPlatform ( ) ) ;
// Check the platform is whitelisted
if ( WhitelistPlatforms . Num ( ) > 0 & & ! WhitelistPlatforms . Contains ( UBTPlatform ) )
{
return false ;
}
// Check the platform is not blacklisted
if ( BlacklistPlatforms . Num ( ) > 0 & & BlacklistPlatforms . Contains ( UBTPlatform ) )
{
return false ;
}
// Check the module is compatible with this target. This should match UEBuildTarget.ShouldIncludePluginModule in UBT
switch ( Type )
{
case EHostType : : Runtime :
case EHostType : : RuntimeNoCommandlet :
return true ;
case EHostType : : Developer :
# if WITH_UNREAL_DEVELOPER_TOOLS
return true ;
# endif
break ;
case EHostType : : Editor :
case EHostType : : EditorNoCommandlet :
# if WITH_EDITOR
return true ;
# endif
break ;
case EHostType : : Program :
# if IS_PROGRAM
return true ;
# endif
break ;
}
return false ;
}
bool FModuleDescriptor : : IsLoadedInCurrentConfiguration ( ) const
{
// Check that the module is built for this configuration
if ( ! IsCompiledInCurrentConfiguration ( ) )
{
return false ;
}
// Check that the runtime environment allows it to be loaded
switch ( Type )
{
case EHostType : : Runtime :
# if WITH_ENGINE || WITH_PLUGIN_SUPPORT
return true ;
# endif
break ;
case EHostType : : RuntimeNoCommandlet :
# if WITH_ENGINE || WITH_PLUGIN_SUPPORT
if ( ! IsRunningCommandlet ( ) ) return true ;
# endif
break ;
case EHostType : : Developer :
# if WITH_UNREAL_DEVELOPER_TOOLS
return true ;
# endif
break ;
case EHostType : : Editor :
# if WITH_EDITOR
if ( GIsEditor ) return true ;
# endif
break ;
case EHostType : : EditorNoCommandlet :
# if WITH_EDITOR
if ( GIsEditor & & ! IsRunningCommandlet ( ) ) return true ;
# endif
break ;
case EHostType : : Program :
# if WITH_PLUGIN_SUPPORT && IS_PROGRAM
return true ;
# endif
break ;
}
return false ;
}
void FModuleDescriptor : : LoadModulesForPhase ( ELoadingPhase : : Type LoadingPhase , const TArray < FModuleDescriptor > & Modules , TMap < FName , EModuleLoadResult > & ModuleLoadErrors )
{
2014-12-17 02:15:23 -05:00
FScopedSlowTask SlowTask ( Modules . Num ( ) ) ;
2014-06-27 08:41:46 -04:00
for ( int Idx = 0 ; Idx < Modules . Num ( ) ; Idx + + )
{
2014-12-17 02:15:23 -05:00
SlowTask . EnterProgressFrame ( 1 ) ;
2014-06-27 08:41:46 -04:00
const FModuleDescriptor & Descriptor = Modules [ Idx ] ;
// Don't need to do anything if this module is already loaded
if ( ! FModuleManager : : Get ( ) . IsModuleLoaded ( Descriptor . Name ) )
{
if ( LoadingPhase = = Descriptor . LoadingPhase & & Descriptor . IsLoadedInCurrentConfiguration ( ) )
{
// @todo plugin: DLL search problems. Plugins that statically depend on other modules within this plugin may not be found? Need to test this.
// NOTE: Loading this module may cause other modules to become loaded, both in the engine or game, or other modules
// that are part of this project or plugin. That's totally fine.
EModuleLoadResult FailureReason ;
const TSharedPtr < IModuleInterface > & ModuleInterface = FModuleManager : : Get ( ) . LoadModuleWithFailureReason ( Descriptor . Name , FailureReason ) ;
if ( ModuleInterface . IsValid ( ) )
{
// Module loaded OK (or was already loaded.)
}
else
{
// The module failed to load. Note this in the ModuleLoadErrors list.
ModuleLoadErrors . Add ( Descriptor . Name , FailureReason ) ;
}
}
}
}
}
2014-09-10 12:43:07 -04:00
bool FModuleDescriptor : : CheckModuleCompatbility ( const TArray < FModuleDescriptor > & Modules , bool bGameModules , TArray < FString > & OutIncompatibleFiles )
2014-06-27 08:41:46 -04:00
{
2014-09-10 12:43:07 -04:00
bool bResult = true ;
2014-06-27 08:41:46 -04:00
for ( int Idx = 0 ; Idx < Modules . Num ( ) ; Idx + + )
{
const FModuleDescriptor & Module = Modules [ Idx ] ;
if ( Module . IsCompiledInCurrentConfiguration ( ) & & ! FModuleManager : : Get ( ) . IsModuleUpToDate ( Module . Name ) )
{
2014-09-10 12:43:07 -04:00
OutIncompatibleFiles . Add ( FModuleManager : : GetCleanModuleFilename ( Module . Name , bGameModules ) ) ;
bResult = false ;
2014-06-27 08:41:46 -04:00
}
}
2014-09-10 12:43:07 -04:00
return bResult ;
2014-06-27 08:41:46 -04:00
}
2014-06-25 13:09:31 -04:00
# undef LOCTEXT_NAMESPACE