// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Diagnostics;
using System.Linq;
using EpicGames.Core;
using JsonExtensions;
namespace UnrealBuildTool
{
///
/// Representation of a reference to a plugin from a project file
///
[DebuggerDisplay("Name={Name}")]
public class PluginReferenceDescriptor
{
///
/// Name of the plugin
///
public string Name;
///
/// Whether it should be enabled by default
///
public bool bEnabled;
///
/// Whether this plugin is optional, and the game should silently ignore it not being present
///
public bool bOptional;
///
/// Whether this plugin should be activated, if it is a Game Feature Plugin
///
public bool bActivate;
///
/// Description of the plugin for users that do not have it installed.
///
public string? Description;
///
/// URL for this plugin on the marketplace, if the user doesn't have it installed.
///
public string? MarketplaceURL;
///
/// If enabled, list of platforms for which the plugin should be enabled (or all platforms if blank).
///
public string[]? PlatformAllowList;
///
/// If enabled, list of platforms for which the plugin should be disabled.
///
public string[]? PlatformDenyList;
///
/// If enabled, list of target configurations for which the plugin should be enabled (or all target configurations if blank).
///
public UnrealTargetConfiguration[]? TargetConfigurationAllowList;
///
/// If enabled, list of target configurations for which the plugin should be disabled.
///
public UnrealTargetConfiguration[]? TargetConfigurationDenyList;
///
/// If enabled, list of targets for which the plugin should be enabled (or all targets if blank).
///
public TargetType[]? TargetAllowList;
///
/// If enabled, list of targets for which the plugin should be disabled.
///
public TargetType[]? TargetDenyList;
///
/// The list of supported platforms for this plugin. This field is copied from the plugin descriptor, and supplements the user's allowed/denied platforms.
///
public string[]? SupportedTargetPlatforms;
///
/// When true, empty SupportedTargetPlatforms and PlatformAllowList are interpreted as 'no platforms' with the expectation that explicit platforms will be added in plugin platform extensions
///
public bool bHasExplicitPlatforms;
///
/// When set, specifies a specific version of the plugin that this references.
///
public int? RequestedVersion;
///
/// Constructor
///
/// Name of the plugin
/// The marketplace URL for plugins which are not installed
/// Whether the plugin is enabled
public PluginReferenceDescriptor(string InName, string? InMarketplaceURL, bool bInEnabled)
{
Name = InName;
MarketplaceURL = InMarketplaceURL;
bEnabled = bInEnabled;
}
///
/// Construct a PluginReferenceDescriptor from a Json object
///
/// The writer for output fields
public void Write(JsonWriter Writer)
{
Writer.WriteObjectStart();
Writer.WriteValue("Name", Name);
Writer.WriteValue("Enabled", bEnabled);
if (bEnabled && bOptional)
{
Writer.WriteValue("Optional", bOptional);
}
if (bEnabled && bActivate)
{
Writer.WriteValue("Activate", bActivate);
}
if (!String.IsNullOrEmpty(Description))
{
Writer.WriteValue("Description", Description);
}
if (!String.IsNullOrEmpty(MarketplaceURL))
{
Writer.WriteValue("MarketplaceURL", MarketplaceURL);
}
if (PlatformAllowList != null && PlatformAllowList.Length > 0)
{
Writer.WriteStringArrayField("PlatformAllowList", PlatformAllowList.Select(x => x.ToString()).ToArray());
}
if (PlatformDenyList != null && PlatformDenyList.Length > 0)
{
Writer.WriteStringArrayField("PlatformDenyList", PlatformDenyList.Select(x => x.ToString()).ToArray());
}
if (TargetConfigurationAllowList != null && TargetConfigurationAllowList.Length > 0)
{
Writer.WriteEnumArrayField("TargetConfigurationAllowList", TargetConfigurationAllowList);
}
if (TargetConfigurationDenyList != null && TargetConfigurationDenyList.Length > 0)
{
Writer.WriteEnumArrayField("TargetConfigurationDenyList", TargetConfigurationDenyList);
}
if (TargetAllowList != null && TargetAllowList.Length > 0)
{
Writer.WriteEnumArrayField("TargetAllowList", TargetAllowList);
}
if (TargetDenyList != null && TargetDenyList.Length > 0)
{
Writer.WriteEnumArrayField("TargetDenyList", TargetDenyList);
}
if (SupportedTargetPlatforms != null && SupportedTargetPlatforms.Length > 0)
{
Writer.WriteStringArrayField("SupportedTargetPlatforms", SupportedTargetPlatforms.Select(x => x.ToString()).ToArray());
}
if (bHasExplicitPlatforms)
{
Writer.WriteValue("HasExplicitPlatforms", bHasExplicitPlatforms);
}
if (bEnabled && RequestedVersion != null)
{
Writer.WriteValue("Version", RequestedVersion.Value);
}
Writer.WriteObjectEnd();
}
private JsonObject ToJsonObject()
{
JsonObject PluginReferenceObject = new JsonObject();
PluginReferenceObject.AddOrSetFieldValue("Name", Name);
PluginReferenceObject.AddOrSetFieldValue("Enabled", bEnabled);
if (bEnabled && bOptional)
{
PluginReferenceObject.AddOrSetFieldValue("Optional", bOptional);
}
if (bEnabled && bActivate)
{
PluginReferenceObject.AddOrSetFieldValue("Activate", bActivate);
}
if (!String.IsNullOrEmpty(Description))
{
PluginReferenceObject.AddOrSetFieldValue("Description", Description);
}
if (!String.IsNullOrEmpty(MarketplaceURL))
{
PluginReferenceObject.AddOrSetFieldValue("MarketplaceURL", MarketplaceURL);
}
if (PlatformAllowList != null && PlatformAllowList.Length > 0)
{
PluginReferenceObject.AddOrSetFieldValue("PlatformAllowList", PlatformAllowList.Select(x => x.ToString()).ToArray());
}
if (PlatformDenyList != null && PlatformDenyList.Length > 0)
{
PluginReferenceObject.AddOrSetFieldValue("PlatformDenyList", PlatformDenyList.Select(x => x.ToString()).ToArray());
}
if (TargetConfigurationAllowList != null && TargetConfigurationAllowList.Length > 0)
{
PluginReferenceObject.AddOrSetFieldValue("TargetConfigurationAllowList", TargetConfigurationAllowList);
}
if (TargetConfigurationDenyList != null && TargetConfigurationDenyList.Length > 0)
{
PluginReferenceObject.AddOrSetFieldValue("TargetConfigurationDenyList", TargetConfigurationDenyList);
}
if (TargetAllowList != null && TargetAllowList.Length > 0)
{
PluginReferenceObject.AddOrSetFieldValue("TargetAllowList", TargetAllowList);
}
if (TargetDenyList != null && TargetDenyList.Length > 0)
{
PluginReferenceObject.AddOrSetFieldValue("TargetDenyList", TargetDenyList);
}
if (SupportedTargetPlatforms != null && SupportedTargetPlatforms.Length > 0)
{
PluginReferenceObject.AddOrSetFieldValue("SupportedTargetPlatforms", SupportedTargetPlatforms.Select(x => x.ToString()).ToArray());
}
if (bHasExplicitPlatforms)
{
PluginReferenceObject.AddOrSetFieldValue("HasExplicitPlatforms", bHasExplicitPlatforms);
}
if (bEnabled && RequestedVersion != null)
{
PluginReferenceObject.AddOrSetFieldValue("Version", RequestedVersion.Value);
}
return PluginReferenceObject;
}
///
/// Write an array of module descriptors
///
/// The Json writer to output to
/// Name of the array
/// Array of plugins
public static void WriteArray(JsonWriter Writer, string Name, PluginReferenceDescriptor[]? Plugins)
{
if (Plugins != null && Plugins.Length > 0)
{
Writer.WriteArrayStart(Name);
foreach (PluginReferenceDescriptor Plugin in Plugins)
{
Plugin.Write(Writer);
}
Writer.WriteArrayEnd();
}
}
///
/// Updates the json object with an array of plugin descriptors.
///
/// The Json object to update.
/// Name of the array
/// Array of plugins
public static void UpdateJson(JsonObject InObject, string Name, PluginReferenceDescriptor[]? Plugins)
{
if (Plugins != null && Plugins.Length > 0)
{
JsonObject[] JsonObjects = Plugins.Select(X => X.ToJsonObject()).ToArray();
InObject.AddOrSetFieldValue(Name, JsonObjects);
}
}
///
/// Checks the given platform names array and logs a message about any that are not known. This may simply be due to not having the platform synced in Engine/Platforms/[PlatformName].
///
///
private void VerifyPlatformNames(string[]? PlatformNames)
{
if (PlatformNames != null)
{
foreach (string PlatformName in PlatformNames)
{
UnrealTargetPlatform Platform;
if (!UnrealTargetPlatform.TryParse(PlatformName, out Platform))
{
Log.TraceLogOnce("Ignoring unknown platform '{0}' (referenced via a project's plugin descriptor for '{1}')", PlatformName, Name);
}
}
}
}
///
/// Construct a PluginReferenceDescriptor from a Json object
///
/// The Json object containing a plugin reference descriptor
/// New PluginReferenceDescriptor object
public static PluginReferenceDescriptor FromJsonObject(JsonObject RawObject)
{
PluginReferenceDescriptor Descriptor = new PluginReferenceDescriptor(RawObject.GetStringField("Name"), null, RawObject.GetBoolField("Enabled"));
RawObject.TryGetBoolField("Optional", out Descriptor.bOptional);
RawObject.TryGetBoolField("Activate", out Descriptor.bActivate);
RawObject.TryGetStringField("Description", out Descriptor.Description);
RawObject.TryGetStringField("MarketplaceURL", out Descriptor.MarketplaceURL);
// Only parse platform information if enabled
if (Descriptor.bEnabled)
{
RawObject.TryGetStringArrayFieldWithDeprecatedFallback("PlatformAllowList", "WhitelistPlatforms", out Descriptor.PlatformAllowList);
RawObject.TryGetStringArrayFieldWithDeprecatedFallback("PlatformDenyList", "BlacklistPlatforms", out Descriptor.PlatformDenyList);
RawObject.TryGetEnumArrayFieldWithDeprecatedFallback("TargetConfigurationAllowList", "WhitelistTargetConfigurations", out Descriptor.TargetConfigurationAllowList);
RawObject.TryGetEnumArrayFieldWithDeprecatedFallback("TargetConfigurationDenyList", "BlacklistTargetConfigurations", out Descriptor.TargetConfigurationDenyList);
RawObject.TryGetEnumArrayFieldWithDeprecatedFallback("TargetAllowList", "WhitelistTargets", out Descriptor.TargetAllowList);
RawObject.TryGetEnumArrayFieldWithDeprecatedFallback("TargetDenyList", "BlacklistTargets", out Descriptor.TargetDenyList);
RawObject.TryGetStringArrayField("SupportedTargetPlatforms", out Descriptor.SupportedTargetPlatforms);
RawObject.TryGetBoolField("HasExplicitPlatforms", out Descriptor.bHasExplicitPlatforms);
int RequestedVersion = -1;
if (RawObject.TryGetIntegerField("Version", out RequestedVersion))
{
Descriptor.RequestedVersion = RequestedVersion;
}
Descriptor.VerifyPlatformNames(Descriptor.PlatformAllowList);
Descriptor.VerifyPlatformNames(Descriptor.PlatformDenyList);
Descriptor.VerifyPlatformNames(Descriptor.SupportedTargetPlatforms);
}
return Descriptor;
}
///
/// Determines if this reference enables the plugin for a given platform
///
/// The platform to check
/// True if the plugin should be enabled
public bool IsEnabledForPlatform(UnrealTargetPlatform Platform)
{
if (!bEnabled)
{
return false;
}
if (bHasExplicitPlatforms)
{
if (PlatformAllowList == null || !PlatformAllowList.Contains(Platform.ToString()))
{
return false;
}
}
else if (PlatformAllowList != null && PlatformAllowList.Length > 0 && !PlatformAllowList.Contains(Platform.ToString()))
{
return false;
}
if (PlatformDenyList != null && PlatformDenyList.Contains(Platform.ToString()))
{
return false;
}
return true;
}
///
/// Determines if this reference enables the plugin for a given target configuration
///
/// The target configuration to check
/// True if the plugin should be enabled
public bool IsEnabledForTargetConfiguration(UnrealTargetConfiguration TargetConfiguration)
{
if (!bEnabled)
{
return false;
}
if (TargetConfigurationAllowList != null && TargetConfigurationAllowList.Length > 0 && !TargetConfigurationAllowList.Contains(TargetConfiguration))
{
return false;
}
if (TargetConfigurationDenyList != null && TargetConfigurationDenyList.Contains(TargetConfiguration))
{
return false;
}
return true;
}
///
/// Determines if this reference enables the plugin for a given target
///
/// The target to check
/// True if the plugin should be enabled
public bool IsEnabledForTarget(TargetType Target)
{
if (!bEnabled)
{
return false;
}
if (TargetAllowList != null && TargetAllowList.Length > 0 && !TargetAllowList.Contains(Target))
{
return false;
}
if (TargetDenyList != null && TargetDenyList.Contains(Target))
{
return false;
}
return true;
}
///
/// Determines if this reference is valid for the given target platform.
///
/// The platform to check
/// True if the plugin for this target platform
public bool IsSupportedTargetPlatform(UnrealTargetPlatform Platform)
{
if (bHasExplicitPlatforms)
{
return SupportedTargetPlatforms != null && SupportedTargetPlatforms.Contains(Platform.ToString());
}
else
{
return SupportedTargetPlatforms == null || SupportedTargetPlatforms.Length == 0 || SupportedTargetPlatforms.Contains(Platform.ToString());
}
}
}
}