2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-06-27 08:41:46 -04:00
# include "ProjectsPrivatePCH.h"
# include "PluginDescriptor.h"
# define LOCTEXT_NAMESPACE "PluginDescriptor"
2014-10-08 13:14:41 -04:00
FPluginDescriptor : : FPluginDescriptor ( )
: FileVersion ( EPluginDescriptorVersion : : Latest )
, Version ( 0 )
, bEnabledByDefault ( false )
, bCanContainContent ( false )
, bIsBetaVersion ( false )
2015-04-27 20:08:52 -04:00
, bInstalled ( false )
{
}
2014-10-08 13:14:41 -04:00
bool FPluginDescriptor : : Load ( const FString & FileName , FText & OutFailReason )
2014-06-27 08:41:46 -04:00
{
// Read the file to a string
FString FileContents ;
2014-10-08 13:14:41 -04:00
2014-06-27 08:41:46 -04:00
if ( ! FFileHelper : : LoadFileToString ( FileContents , * FileName ) )
{
2014-10-08 13:14:41 -04:00
OutFailReason = FText : : Format ( LOCTEXT ( " FailedToLoadDescriptorFile " , " Failed to open descriptor file '{0}' " ) , FText : : FromString ( FileName ) ) ;
2014-06-27 08:41:46 -04:00
return false ;
}
2015-04-26 09:18:08 -04:00
// Parse it as a plug-in descriptor
return Read ( FileContents , OutFailReason ) ;
}
bool FPluginDescriptor : : Read ( const FString & Text , FText & OutFailReason )
{
2014-06-27 08:41:46 -04:00
// Deserialize a JSON object from the string
2015-04-26 09:18:08 -04:00
TSharedPtr < FJsonObject > ObjectPtr ;
TSharedRef < TJsonReader < > > Reader = TJsonReaderFactory < > : : Create ( Text ) ;
if ( ! FJsonSerializer : : Deserialize ( Reader , ObjectPtr ) | | ! ObjectPtr . IsValid ( ) )
2014-06-27 08:41:46 -04:00
{
2014-10-08 13:14:41 -04:00
OutFailReason = FText : : Format ( LOCTEXT ( " FailedToReadDescriptorFile " , " Failed to read file. {0} " ) , FText : : FromString ( Reader - > GetErrorMessage ( ) ) ) ;
2014-06-27 08:41:46 -04:00
return false ;
}
2015-04-26 09:18:08 -04:00
FJsonObject & Object = * ObjectPtr . Get ( ) ;
2014-06-27 08:41:46 -04:00
// Read the file version
int32 FileVersionInt32 ;
2014-10-08 13:14:41 -04:00
2014-06-27 08:41:46 -04:00
if ( ! Object . TryGetNumberField ( TEXT ( " FileVersion " ) , FileVersionInt32 ) )
{
if ( ! Object . TryGetNumberField ( TEXT ( " PluginFileVersion " ) , FileVersionInt32 ) )
{
OutFailReason = LOCTEXT ( " InvalidProjectFileVersion " , " File does not have a valid 'FileVersion' number. " ) ;
return false ;
}
}
// Check that it's within range
2015-02-19 12:13:52 -05:00
EPluginDescriptorVersion : : Type PluginFileVersion = ( EPluginDescriptorVersion : : Type ) FileVersionInt32 ;
if ( ( PluginFileVersion < = EPluginDescriptorVersion : : Invalid ) | | ( PluginFileVersion > EPluginDescriptorVersion : : Latest ) )
2014-06-27 08:41:46 -04:00
{
2015-02-19 12:13:52 -05:00
FText ReadVersionText = FText : : FromString ( FString : : Printf ( TEXT ( " %d " ) , ( int32 ) PluginFileVersion ) ) ;
2014-10-08 13:14:41 -04:00
FText LatestVersionText = FText : : FromString ( FString : : Printf ( TEXT ( " %d " ) , ( int32 ) EPluginDescriptorVersion : : Latest ) ) ;
2014-06-27 08:41:46 -04:00
OutFailReason = FText : : Format ( LOCTEXT ( " ProjectFileVersionTooLarge " , " File appears to be in a newer version ({0}) of the file format that we can load (max version: {1}). " ) , ReadVersionText , LatestVersionText ) ;
return false ;
}
// Read the other fields
Object . TryGetNumberField ( TEXT ( " Version " ) , Version ) ;
Object . TryGetStringField ( TEXT ( " VersionName " ) , VersionName ) ;
Object . TryGetStringField ( TEXT ( " FriendlyName " ) , FriendlyName ) ;
Object . TryGetStringField ( TEXT ( " Description " ) , Description ) ;
2014-10-08 13:14:41 -04:00
if ( ! Object . TryGetStringField ( TEXT ( " Category " ) , Category ) )
2014-06-27 08:41:46 -04:00
{
// Category used to be called CategoryPath in .uplugin files
Object . TryGetStringField ( TEXT ( " CategoryPath " ) , Category ) ;
}
// Due to a difference in command line parsing between Windows and Mac, we shipped a few Mac samples containing
// a category name with escaped quotes. Remove them here to make sure we can list them in the right category.
2014-10-08 13:14:41 -04:00
if ( Category . Len ( ) > = 2 & & Category . StartsWith ( TEXT ( " \" " ) ) & & Category . EndsWith ( TEXT ( " \" " ) ) )
2014-06-27 08:41:46 -04:00
{
Category = Category . Mid ( 1 , Category . Len ( ) - 2 ) ;
}
Object . TryGetStringField ( TEXT ( " CreatedBy " ) , CreatedBy ) ;
Object . TryGetStringField ( TEXT ( " CreatedByURL " ) , CreatedByURL ) ;
2014-10-08 13:14:41 -04:00
Object . TryGetStringField ( TEXT ( " DocsURL " ) , DocsURL ) ;
2014-06-27 08:41:46 -04:00
2014-10-08 13:14:41 -04:00
if ( ! FModuleDescriptor : : ReadArray ( Object , TEXT ( " Modules " ) , Modules , OutFailReason ) )
2014-06-27 08:41:46 -04:00
{
return false ;
}
2014-06-27 16:38:50 -04:00
Object . TryGetBoolField ( TEXT ( " EnabledByDefault " ) , bEnabledByDefault ) ;
2014-06-27 08:41:46 -04:00
Object . TryGetBoolField ( TEXT ( " CanContainContent " ) , bCanContainContent ) ;
Object . TryGetBoolField ( TEXT ( " IsBetaVersion " ) , bIsBetaVersion ) ;
2015-04-27 20:08:52 -04:00
Object . TryGetBoolField ( TEXT ( " Installed " ) , bInstalled ) ;
2014-10-08 13:14:41 -04:00
2014-06-27 08:41:46 -04:00
return true ;
}
2015-04-26 09:18:08 -04:00
bool FPluginDescriptor : : Save ( const FString & FileName , FText & OutFailReason ) const
{
// Write the contents of the descriptor to a string. Make sure the writer is destroyed so that the contents are flushed to the string.
FString Text = ToString ( ) ;
if ( FFileHelper : : SaveStringToFile ( Text , * FileName ) )
{
return true ;
}
else
{
OutFailReason = FText : : Format ( LOCTEXT ( " FailedToWriteOutputFile " , " Failed to write output file '{0}'. Perhaps the file is Read-Only? " ) , FText : : FromString ( FileName ) ) ;
return false ;
}
}
FString FPluginDescriptor : : ToString ( ) const
{
FString Text ;
TSharedRef < TJsonWriter < > > WriterRef = TJsonWriterFactory < > : : Create ( & Text ) ;
TJsonWriter < > & Writer = WriterRef . Get ( ) ;
Writer . WriteObjectStart ( ) ;
Writer . WriteValue ( TEXT ( " FileVersion " ) , EProjectDescriptorVersion : : Latest ) ;
Writer . WriteValue ( TEXT ( " Version " ) , Version ) ;
Writer . WriteValue ( TEXT ( " VersionName " ) , VersionName ) ;
Writer . WriteValue ( TEXT ( " FriendlyName " ) , FriendlyName ) ;
Writer . WriteValue ( TEXT ( " Description " ) , Description ) ;
Writer . WriteValue ( TEXT ( " Category " ) , Category ) ;
Writer . WriteValue ( TEXT ( " CreatedBy " ) , CreatedBy ) ;
Writer . WriteValue ( TEXT ( " CreatedByURL " ) , CreatedByURL ) ;
Writer . WriteValue ( TEXT ( " DocsURL " ) , DocsURL ) ;
FModuleDescriptor : : WriteArray ( Writer , TEXT ( " Modules " ) , Modules ) ;
Writer . WriteValue ( TEXT ( " EnabledByDefault " ) , bEnabledByDefault ) ;
Writer . WriteValue ( TEXT ( " CanContainContent " ) , bCanContainContent ) ;
Writer . WriteValue ( TEXT ( " IsBetaVersion " ) , bIsBetaVersion ) ;
2015-04-27 20:08:52 -04:00
Writer . WriteValue ( TEXT ( " Installed " ) , bInstalled ) ;
2015-04-26 09:18:08 -04:00
Writer . WriteObjectEnd ( ) ;
Writer . Close ( ) ;
return Text ;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2014-06-27 15:23:15 -04:00
2014-10-08 13:14:41 -04:00
FPluginReferenceDescriptor : : FPluginReferenceDescriptor ( const FString & InName , bool bInEnabled )
2014-06-27 15:23:15 -04:00
: Name ( InName )
, bEnabled ( bInEnabled )
2014-10-08 13:14:41 -04:00
{ }
2014-06-27 15:23:15 -04:00
2014-10-08 13:14:41 -04:00
bool FPluginReferenceDescriptor : : IsEnabledForPlatform ( const FString & Platform ) const
2014-06-27 15:23:15 -04:00
{
// If it's not enabled at all, return false
if ( ! bEnabled )
{
return false ;
}
// If there is a list of whitelisted platforms, and this isn't one of them, return false
if ( WhitelistPlatforms . Num ( ) > 0 & & ! WhitelistPlatforms . Contains ( Platform ) )
{
return false ;
}
// If this platform is blacklisted, also return false
if ( BlacklistPlatforms . Contains ( Platform ) )
{
return false ;
}
return true ;
}
2014-10-08 13:14:41 -04:00
bool FPluginReferenceDescriptor : : Read ( const FJsonObject & Object , FText & OutFailReason )
2014-06-27 15:23:15 -04:00
{
// Get the name
if ( ! Object . TryGetStringField ( TEXT ( " Name " ) , Name ) )
{
OutFailReason = LOCTEXT ( " PluginReferenceWithoutName " , " Plugin references must have a 'Name' field " ) ;
return false ;
}
// Get the enabled field
if ( ! Object . TryGetBoolField ( TEXT ( " Enabled " ) , bEnabled ) )
{
OutFailReason = LOCTEXT ( " PluginReferenceWithoutEnabled " , " Plugin references must have an 'Enabled' field " ) ;
return false ;
}
2014-07-30 13:16:05 -04:00
// Read the description
Object . TryGetStringField ( TEXT ( " Description " ) , Description ) ;
2014-06-27 15:23:15 -04:00
// Get the platform lists
Object . TryGetStringArrayField ( TEXT ( " WhitelistPlatforms " ) , WhitelistPlatforms ) ;
Object . TryGetStringArrayField ( TEXT ( " BlacklistPlatforms " ) , BlacklistPlatforms ) ;
2014-10-08 13:14:41 -04:00
2014-06-27 15:23:15 -04:00
return true ;
}
2014-10-08 13:14:41 -04:00
bool FPluginReferenceDescriptor : : ReadArray ( const FJsonObject & Object , const TCHAR * Name , TArray < FPluginReferenceDescriptor > & OutPlugins , FText & OutFailReason )
2014-06-27 15:23:15 -04:00
{
const TArray < TSharedPtr < FJsonValue > > * Array ;
2014-10-08 13:14:41 -04:00
if ( Object . TryGetArrayField ( Name , Array ) )
2014-06-27 15:23:15 -04:00
{
2014-10-08 13:14:41 -04:00
for ( const TSharedPtr < FJsonValue > & Item : * Array )
2014-06-27 15:23:15 -04:00
{
2015-02-19 12:13:52 -05:00
const TSharedPtr < FJsonObject > * ObjectPtr ;
2014-10-08 13:14:41 -04:00
2015-02-19 12:13:52 -05:00
if ( Item . IsValid ( ) & & Item - > TryGetObject ( ObjectPtr ) )
2014-06-27 15:23:15 -04:00
{
FPluginReferenceDescriptor Plugin ;
2014-10-08 13:14:41 -04:00
2015-02-19 12:13:52 -05:00
if ( ! Plugin . Read ( * ObjectPtr - > Get ( ) , OutFailReason ) )
2014-06-27 15:23:15 -04:00
{
return false ;
}
2014-10-08 13:14:41 -04:00
2014-06-27 15:23:15 -04:00
OutPlugins . Add ( Plugin ) ;
}
}
}
2014-10-08 13:14:41 -04:00
2014-06-27 15:23:15 -04:00
return true ;
}
2014-10-08 13:14:41 -04:00
void FPluginReferenceDescriptor : : Write ( TJsonWriter < > & Writer ) const
2014-06-27 15:23:15 -04:00
{
Writer . WriteObjectStart ( ) ;
Writer . WriteValue ( TEXT ( " Name " ) , Name ) ;
Writer . WriteValue ( TEXT ( " Enabled " ) , bEnabled ) ;
2014-10-08 13:14:41 -04:00
2014-07-30 13:16:05 -04:00
if ( Description . Len ( ) > 0 )
{
Writer . WriteValue ( TEXT ( " Description " ) , Description ) ;
}
2014-10-08 13:14:41 -04:00
2014-06-27 15:23:15 -04:00
if ( WhitelistPlatforms . Num ( ) > 0 )
{
Writer . WriteArrayStart ( TEXT ( " WhitelistPlatforms " ) ) ;
2014-10-08 13:14:41 -04:00
for ( int Idx = 0 ; Idx < WhitelistPlatforms . Num ( ) ; Idx + + )
2014-06-27 15:23:15 -04:00
{
Writer . WriteValue ( WhitelistPlatforms [ Idx ] ) ;
}
2014-10-08 13:14:41 -04:00
2014-06-27 15:23:15 -04:00
Writer . WriteArrayEnd ( ) ;
}
2014-10-08 13:14:41 -04:00
2014-06-27 15:23:15 -04:00
if ( BlacklistPlatforms . Num ( ) > 0 )
{
Writer . WriteArrayStart ( TEXT ( " BlacklistPlatforms " ) ) ;
2014-10-08 13:14:41 -04:00
for ( int Idx = 0 ; Idx < BlacklistPlatforms . Num ( ) ; Idx + + )
2014-06-27 15:23:15 -04:00
{
Writer . WriteValue ( BlacklistPlatforms [ Idx ] ) ;
}
2014-10-08 13:14:41 -04:00
2014-06-27 15:23:15 -04:00
Writer . WriteArrayEnd ( ) ;
}
2014-10-08 13:14:41 -04:00
2014-06-27 15:23:15 -04:00
Writer . WriteObjectEnd ( ) ;
}
2014-10-08 13:14:41 -04:00
void FPluginReferenceDescriptor : : WriteArray ( TJsonWriter < > & Writer , const TCHAR * Name , const TArray < FPluginReferenceDescriptor > & Plugins )
2014-06-27 15:23:15 -04:00
{
2014-10-08 13:14:41 -04:00
if ( Plugins . Num ( ) > 0 )
2014-06-27 15:23:15 -04:00
{
Writer . WriteArrayStart ( Name ) ;
2014-10-08 13:14:41 -04:00
for ( int Idx = 0 ; Idx < Plugins . Num ( ) ; Idx + + )
2014-06-27 15:23:15 -04:00
{
Plugins [ Idx ] . Write ( Writer ) ;
}
2014-10-08 13:14:41 -04:00
2014-06-27 15:23:15 -04:00
Writer . WriteArrayEnd ( ) ;
}
}
2014-10-08 13:14:41 -04:00
2014-06-27 08:41:46 -04:00
# undef LOCTEXT_NAMESPACE