Files
UnrealEngineUWP/Engine/Source/Runtime/Projects/Private/ModuleDescriptor.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

427 lines
12 KiB
C++

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#include "ProjectsPrivatePCH.h"
#define LOCTEXT_NAMESPACE "ModuleDescriptor"
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" );
case PostEngineInit:
return TEXT( "PostEngineInit" );
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 RuntimeAndProgram:
return TEXT("RuntimeAndProgram");
case Developer:
return TEXT( "Developer" );
case Editor:
return TEXT( "Editor" );
case EditorNoCommandlet:
return TEXT( "EditorNoCommandlet" );
case Program:
return TEXT("Program");
case ServerOnly:
return TEXT("ServerOnly");
default:
ensureMsgf( false, TEXT( "Unrecognized EModuleType value: %i" ), Value );
return NULL;
}
}
FModuleDescriptor::FModuleDescriptor(const FName InName, EHostType::Type InType, ELoadingPhase::Type InLoadingPhase)
: Name(InName)
, Type(InType)
, LoadingPhase(InLoadingPhase)
{
}
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());
}
}
// 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());
}
}
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();
}
if (AdditionalDependencies.Num() > 0)
{
Writer.WriteArrayStart(TEXT("AdditionalDependencies"));
for (int Idx = 0; Idx < AdditionalDependencies.Num(); Idx++)
{
Writer.WriteValue(AdditionalDependencies[Idx]);
}
Writer.WriteArrayEnd();
}
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();
}
}
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:
#if IS_PROGRAM
return false;
#else
return true;
#endif
case EHostType::RuntimeAndProgram:
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;
case EHostType::ServerOnly:
return !FPlatformProperties::IsClientOnly();
}
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::RuntimeAndProgram:
#if (WITH_ENGINE || WITH_PLUGIN_SUPPORT)
return true;
#endif
break;
case EHostType::Runtime:
#if (WITH_ENGINE || WITH_PLUGIN_SUPPORT) && !IS_PROGRAM
return true;
#endif
break;
case EHostType::RuntimeNoCommandlet:
#if (WITH_ENGINE || WITH_PLUGIN_SUPPORT) && !IS_PROGRAM
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;
case EHostType::ServerOnly:
return !FPlatformProperties::IsClientOnly();
}
return false;
}
void FModuleDescriptor::LoadModulesForPhase(ELoadingPhase::Type LoadingPhase, const TArray<FModuleDescriptor>& Modules, TMap<FName, EModuleLoadResult>& ModuleLoadErrors)
{
FScopedSlowTask SlowTask(Modules.Num());
for(int Idx = 0; Idx < Modules.Num(); Idx++)
{
SlowTask.EnterProgressFrame(1);
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);
}
}
}
}
}
bool FModuleDescriptor::CheckModuleCompatibility(const TArray<FModuleDescriptor>& Modules, bool bGameModules, TArray<FString>& OutIncompatibleFiles)
{
bool bResult = true;
for(int Idx = 0; Idx < Modules.Num(); Idx++)
{
const FModuleDescriptor &Module = Modules[Idx];
if (Module.IsCompiledInCurrentConfiguration() && !FModuleManager::Get().IsModuleUpToDate(Module.Name))
{
OutIncompatibleFiles.Add(FModuleManager::GetCleanModuleFilename(Module.Name, bGameModules));
bResult = false;
}
}
return bResult;
}
#undef LOCTEXT_NAMESPACE