Files
UnrealEngineUWP/Engine/Source/Runtime/Projects/Private/PluginDescriptor.cpp
2015-04-27 20:08:52 -04:00

295 lines
8.5 KiB
C++

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#include "ProjectsPrivatePCH.h"
#include "PluginDescriptor.h"
#define LOCTEXT_NAMESPACE "PluginDescriptor"
FPluginDescriptor::FPluginDescriptor()
: FileVersion(EPluginDescriptorVersion::Latest)
, Version(0)
, bEnabledByDefault(false)
, bCanContainContent(false)
, bIsBetaVersion(false)
, bInstalled(false)
{
}
bool FPluginDescriptor::Load( const FString& FileName, FText& OutFailReason )
{
// Read the file to a string
FString FileContents;
if (!FFileHelper::LoadFileToString(FileContents, *FileName))
{
OutFailReason = FText::Format(LOCTEXT("FailedToLoadDescriptorFile", "Failed to open descriptor file '{0}'"), FText::FromString(FileName));
return false;
}
// Parse it as a plug-in descriptor
return Read(FileContents, OutFailReason);
}
bool FPluginDescriptor::Read(const FString& Text, FText& OutFailReason)
{
// Deserialize a JSON object from the string
TSharedPtr< FJsonObject > ObjectPtr;
TSharedRef< TJsonReader<> > Reader = TJsonReaderFactory<>::Create(Text);
if (!FJsonSerializer::Deserialize(Reader, ObjectPtr) || !ObjectPtr.IsValid() )
{
OutFailReason = FText::Format(LOCTEXT("FailedToReadDescriptorFile", "Failed to read file. {0}"), FText::FromString(Reader->GetErrorMessage()));
return false;
}
FJsonObject& Object = *ObjectPtr.Get();
// Read the file version
int32 FileVersionInt32;
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
EPluginDescriptorVersion::Type PluginFileVersion = (EPluginDescriptorVersion::Type)FileVersionInt32;
if ((PluginFileVersion <= EPluginDescriptorVersion::Invalid) || (PluginFileVersion > EPluginDescriptorVersion::Latest))
{
FText ReadVersionText = FText::FromString(FString::Printf(TEXT("%d"), (int32)PluginFileVersion));
FText LatestVersionText = FText::FromString(FString::Printf(TEXT("%d"), (int32)EPluginDescriptorVersion::Latest));
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);
if (!Object.TryGetStringField(TEXT("Category"), Category))
{
// 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.
if (Category.Len() >= 2 && Category.StartsWith(TEXT("\"")) && Category.EndsWith(TEXT("\"")))
{
Category = Category.Mid(1, Category.Len() - 2);
}
Object.TryGetStringField(TEXT("CreatedBy"), CreatedBy);
Object.TryGetStringField(TEXT("CreatedByURL"), CreatedByURL);
Object.TryGetStringField(TEXT("DocsURL"), DocsURL);
if (!FModuleDescriptor::ReadArray(Object, TEXT("Modules"), Modules, OutFailReason))
{
return false;
}
Object.TryGetBoolField(TEXT("EnabledByDefault"), bEnabledByDefault);
Object.TryGetBoolField(TEXT("CanContainContent"), bCanContainContent);
Object.TryGetBoolField(TEXT("IsBetaVersion"), bIsBetaVersion);
Object.TryGetBoolField(TEXT("Installed"), bInstalled);
return true;
}
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);
Writer.WriteValue(TEXT("Installed"), bInstalled);
Writer.WriteObjectEnd();
Writer.Close();
return Text;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FPluginReferenceDescriptor::FPluginReferenceDescriptor( const FString &InName, bool bInEnabled )
: Name(InName)
, bEnabled(bInEnabled)
{ }
bool FPluginReferenceDescriptor::IsEnabledForPlatform( const FString& Platform ) const
{
// 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;
}
bool FPluginReferenceDescriptor::Read( const FJsonObject& Object, FText& OutFailReason )
{
// 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;
}
// Read the description
Object.TryGetStringField(TEXT("Description"), Description);
// Get the platform lists
Object.TryGetStringArrayField(TEXT("WhitelistPlatforms"), WhitelistPlatforms);
Object.TryGetStringArrayField(TEXT("BlacklistPlatforms"), BlacklistPlatforms);
return true;
}
bool FPluginReferenceDescriptor::ReadArray( const FJsonObject& Object, const TCHAR* Name, TArray<FPluginReferenceDescriptor>& OutPlugins, FText& OutFailReason )
{
const TArray< TSharedPtr<FJsonValue> > *Array;
if (Object.TryGetArrayField(Name, Array))
{
for (const TSharedPtr<FJsonValue> &Item : *Array)
{
const TSharedPtr<FJsonObject> *ObjectPtr;
if (Item.IsValid() && Item->TryGetObject(ObjectPtr))
{
FPluginReferenceDescriptor Plugin;
if (!Plugin.Read(*ObjectPtr->Get(), OutFailReason))
{
return false;
}
OutPlugins.Add(Plugin);
}
}
}
return true;
}
void FPluginReferenceDescriptor::Write( TJsonWriter<>& Writer ) const
{
Writer.WriteObjectStart();
Writer.WriteValue(TEXT("Name"), Name);
Writer.WriteValue(TEXT("Enabled"), bEnabled);
if (Description.Len() > 0)
{
Writer.WriteValue(TEXT("Description"), Description);
}
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();
}
Writer.WriteObjectEnd();
}
void FPluginReferenceDescriptor::WriteArray( TJsonWriter<>& Writer, const TCHAR* Name, const TArray<FPluginReferenceDescriptor>& Plugins )
{
if( Plugins.Num() > 0)
{
Writer.WriteArrayStart(Name);
for (int Idx = 0; Idx < Plugins.Num(); Idx++)
{
Plugins[Idx].Write(Writer);
}
Writer.WriteArrayEnd();
}
}
#undef LOCTEXT_NAMESPACE