找回密码
 立即注册
查看: 449|回复: 0

Unreal4源码拆解-UnrealBuildTool功能流程解析 ...

[复制链接]
发表于 2021-12-4 15:27 | 显示全部楼层 |阅读模式
Unreal4源码拆解-UnrealBuildTool功能流程解析-PluginDescriptor

引擎版本4.27

4.2x功能不会差太多

功能漫谈

主要功能


  • PluginDescriptor类,如其命名,插件描述信息
  • 功能上大致是以JSON的方式读取和更新 .uplugin文件 。
  • 具体设计上类内变量名和JSON中项名相同。
  • 注意:可读可写
.uplugin文件

首先.uplugin文件文件是JSON文件,在每个插件的主文件夹中描述插件信息的文件。举例: Engine\Plugins\2D\Paper2D\Paper2D.uplugin
{
    "FileVersion" : 3,
    "Version" : 1,
    "VersionName" : "1.0",
    "FriendlyName" : "Paper2D",
    "Description" : "Paper2D adds tools and assets to help create 2D games including animated sprite assets, tilesets (experimental), 2D level editing tools, and more.",
    "Category" : "2D",
    "CreatedBy" : "Epic Games, Inc.",
    "CreatedByURL" : "http://epicgames.com",
    "DocsURL" : "",
    "MarketplaceURL" : "",
    "SupportURL" : "",
    "EnabledByDefault" : true,
    "CanContainContent" : true,
    "IsBetaVersion" : false,
    "Installed" : false,
    "Modules" :
    [
        {
            "Name" : "Paper2D",
            "Type" : "Runtime",
            "LoadingPhase" : "PreDefault"
        },
        {
            "Name" : "Paper2DEditor",
            "Type" : "Editor",
            "LoadingPhase" : "Default"
        },
        {
            "Name" : "PaperSpriteSheetImporter",
            "Type" : "Editor",
            "LoadingPhase" : "Default"
        },
        {
            "Name" : "PaperTiledImporter",
            "Type" : "Editor",
            "LoadingPhase" : "Default"
        },
        {
            "Name" : "SmartSnapping",
            "Type" : "Editor",
            "LoadingPhase" : "PostEngineInit"
        }
    ]
}注意:此文章主要给接下来的UBT主流程做铺垫   
注意:以后每更新变量的功能便会更新此文章
注意:插件以后有机会可以做专门的专栏
主要函数功能

public PluginDescriptor(JsonObject RawObject)


  • 构造方法 传入JSON对象,解析每一个条目并设置到同名变量中
public static PluginDescriptor FromFile(FileReference FileName)


  • 静态方法 传入文件,新建并且返回一个PluginDescriptor对象
public void Write(JsonWriter Writer)


  • 普通方法 更新信息到Json中
public bool SupportsTargetPlatform(UnrealTargetPlatform Platform)


  • 普通方法 输入目标平台信息,看看插件自己支不支持。
  • 结果:如果插件支持平台没有配或者配了且支持该平台,返回True。
源代码

// Copyright Epic Games, Inc. All Rights Reserved.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using Tools.DotNETCommon;

namespace UnrealBuildTool
{
    /// <summary>
    /// The version format for .uplugin files. This rarely changes now; plugin descriptors should maintain backwards compatibility automatically.
    /// </summary>
    public enum PluginDescriptorVersion
    {
        /// <summary>
        /// Invalid
        /// </summary>
        Invalid = 0,

        /// <summary>
        /// Initial version
        /// </summary>
        Initial = 1,

        /// <summary>
        /// Adding SampleNameHash
        /// </summary>
        NameHash = 2,

        /// <summary>
        /// Unifying plugin/project files (since abandoned, but backwards compatibility maintained)
        /// </summary>
        ProjectPluginUnification = 3,

        /// <summary>
        /// This needs to be the last line, so we can calculate the value of Latest below
        /// </summary>
        LatestPlusOne,

        /// <summary>
        /// The latest plugin descriptor version
        /// </summary>
        Latest = LatestPlusOne - 1
    }

    /// <summary>
    /// In-memory representation of a .uplugin file
    /// </summary>
    public class PluginDescriptor
    {
        /// <summary>
        /// Descriptor version number
        /// </summary>
        public int FileVersion;

        /// <summary>
        /// Version number for the plugin.  The version number must increase with every version of the plugin, so that the system
        /// can determine whether one version of a plugin is newer than another, or to enforce other requirements.  This version
        /// number is not displayed in front-facing UI.  Use the VersionName for that.
        /// </summary>
        public int Version;

        /// <summary>
        /// Name of the version for this plugin.  This is the front-facing part of the version number.  It doesn't need to match
        /// the version number numerically, but should be updated when the version number is increased accordingly.
        /// </summary>
        public string VersionName;

        /// <summary>
        /// Friendly name of the plugin
        /// </summary>
        public string FriendlyName;

        /// <summary>
        /// Description of the plugin
        /// </summary>
        public string Description;

        /// <summary>
        /// The name of the category this plugin
        /// </summary>
        public string Category;

        /// <summary>
        /// The company or individual who created this plugin.  This is an optional field that may be displayed in the user interface.
        /// </summary>
        public string CreatedBy;

        /// <summary>
        /// Hyperlink URL string for the company or individual who created this plugin.  This is optional.
        /// </summary>
        public string CreatedByURL;

        /// <summary>
        /// Documentation URL string.
        /// </summary>
        public string DocsURL;

        /// <summary>
        /// Marketplace URL for this plugin. This URL will be embedded into projects that enable this plugin, so we can redirect to the marketplace if a user doesn't have it installed.
        /// </summary>
        public string MarketplaceURL;

        /// <summary>
        /// Support URL/email for this plugin.
        /// </summary>
        public string SupportURL;

        /// <summary>
        /// Sets the version of the engine that this plugin is compatible with.
        /// </summary>
        public string EngineVersion;

        /// <summary>4
        /// If true, this plugin from a platform extension extending another plugin */
        /// </summary>
        public bool bIsPluginExtension;

        /// <summary>
        /// List of platforms supported by this plugin. This list will be copied to any plugin reference from a project file, to allow filtering entire plugins from staged builds.
        /// </summary>
        public List<UnrealTargetPlatform> SupportedTargetPlatforms;

        /// <summary>
        /// List of programs supported by this plugin.
        /// </summary>
        public string[] SupportedPrograms;

        /// <summary>
        /// List of all modules associated with this plugin
        /// </summary>
        public List<ModuleDescriptor> Modules;

        /// <summary>
        /// List of all localization targets associated with this plugin
        /// </summary>
        public LocalizationTargetDescriptor[] LocalizationTargets;

        /// <summary>
        /// Whether this plugin should be enabled by default for all projects
        /// </summary>
        public Nullable<bool> bEnabledByDefault;

        /// <summary>
        /// Can this plugin contain content?
        /// </summary>
        public bool bCanContainContent;

        /// <summary>
        /// Marks the plugin as beta in the UI
        /// </summary>
        public bool bIsBetaVersion;

        /// <summary>
        /// Marks the plugin as experimental in the UI
        /// </summary>
        public bool bIsExperimentalVersion;

        /// <summary>
        /// Set for plugins which are installed
        /// </summary>
        public bool bInstalled;

        /// <summary>
        /// For plugins that are under a platform folder (eg. /PS4/), determines whether compiling the plugin requires the build platform and/or SDK to be available
        /// </summary>
        public bool bRequiresBuildPlatform;

        /// <summary>
        /// When true, this plugin's modules will not be loaded automatically nor will it's content be mounted automatically. It will load/mount when explicitly requested and LoadingPhases will be ignored
        /// </summary>
        public bool bExplicitlyLoaded;

        /// <summary>
        /// Set of pre-build steps to execute, keyed by host platform name.
        /// </summary>
        public CustomBuildSteps PreBuildSteps;

        /// <summary>
        /// Set of post-build steps to execute, keyed by host platform name.
        /// </summary>
        public CustomBuildSteps PostBuildSteps;

        /// <summary>
        /// Additional plugins that this plugin depends on
        /// </summary>
        public List<PluginReferenceDescriptor> Plugins;

        /// <summary>
        /// Private constructor. This object should not be created directly; read it from disk using FromFile() instead.
        /// </summary>
        private PluginDescriptor()
        {
            FileVersion = (int)PluginDescriptorVersion.Latest;
        }

        /// <summary>
        /// Reads a plugin descriptor from a json object
        /// </summary>
        /// <param name="RawObject">The object to read from</param>
        /// <returns>New plugin descriptor</returns>
        public PluginDescriptor(JsonObject RawObject)
        {
            // Read the version
            if (!RawObject.TryGetIntegerField("FileVersion", out FileVersion))
            {
                if (!RawObject.TryGetIntegerField("PluginFileVersion", out FileVersion))
                {
                    throw new BuildException("Plugin descriptor does not contain a valid FileVersion entry");
                }
            }

            // Check it's not newer than the latest version we can parse
            if (FileVersion > (int)PluginDescriptorVersion.Latest)
            {
                throw new BuildException("Plugin descriptor appears to be in a newer version ({0}) of the file format that we can load (max version: {1}).", FileVersion, (int)PluginDescriptorVersion.Latest);
            }

            // Read the other fields
            RawObject.TryGetIntegerField("Version", out Version);
            RawObject.TryGetStringField("VersionName", out VersionName);
            RawObject.TryGetStringField("FriendlyName", out FriendlyName);
            RawObject.TryGetStringField("Description", out Description);

            if (!RawObject.TryGetStringField("Category", out Category))
            {
                // Category used to be called CategoryPath in .uplugin files
                RawObject.TryGetStringField("CategoryPath", out 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 != null && Category.Length >= 2 && Category.StartsWith("\"") && Category.EndsWith("\""))
            {
                Category = Category.Substring(1, Category.Length - 2);
            }

            RawObject.TryGetStringField("CreatedBy", out CreatedBy);
            RawObject.TryGetStringField("CreatedByURL", out CreatedByURL);
            RawObject.TryGetStringField("DocsURL", out DocsURL);
            RawObject.TryGetStringField("MarketplaceURL", out MarketplaceURL);
            RawObject.TryGetStringField("SupportURL", out SupportURL);
            RawObject.TryGetStringField("EngineVersion", out EngineVersion);
            RawObject.TryGetStringArrayField("SupportedPrograms", out SupportedPrograms);
            RawObject.TryGetBoolField("bIsPluginExtension", out bIsPluginExtension);

            string[] SupportedTargetPlatformNames;
            if (RawObject.TryGetStringArrayField("SupportedTargetPlatforms", out SupportedTargetPlatformNames))
            {
                SupportedTargetPlatforms = new List<UnrealTargetPlatform>();
                foreach (string TargetPlatformName in SupportedTargetPlatformNames)
                {
                    UnrealTargetPlatform Platform;
                    if (UnrealTargetPlatform.TryParse(TargetPlatformName, out Platform))
                    {
                        SupportedTargetPlatforms.Add(Platform);
                    }
                    else
                    {
                        Log.TraceWarning("Unknown platform {0} listed in plugin with FriendlyName {1}", TargetPlatformName, FriendlyName);
                    }
                }
            }

            JsonObject[] ModulesArray;
            if (RawObject.TryGetObjectArrayField("Modules", out ModulesArray))
            {
                Modules = Array.ConvertAll(ModulesArray, x => ModuleDescriptor.FromJsonObject(x)).ToList();
            }

            JsonObject[] LocalizationTargetsArray;
            if (RawObject.TryGetObjectArrayField("LocalizationTargets", out LocalizationTargetsArray))
            {
                LocalizationTargets = Array.ConvertAll(LocalizationTargetsArray, x => LocalizationTargetDescriptor.FromJsonObject(x));
            }

            bool bEnabledByDefaultValue;
            if(RawObject.TryGetBoolField("EnabledByDefault", out bEnabledByDefaultValue))
            {
                bEnabledByDefault = bEnabledByDefaultValue;
            }

            RawObject.TryGetBoolField("CanContainContent", out bCanContainContent);
            RawObject.TryGetBoolField("IsBetaVersion", out bIsBetaVersion);
            RawObject.TryGetBoolField("IsExperimentalVersion", out bIsExperimentalVersion);
            RawObject.TryGetBoolField("Installed", out bInstalled);

            bool bCanBeUsedWithUnrealHeaderTool;
            if(RawObject.TryGetBoolField("CanBeUsedWithUnrealHeaderTool", out bCanBeUsedWithUnrealHeaderTool) && bCanBeUsedWithUnrealHeaderTool)
            {
                Array.Resize(ref SupportedPrograms, (SupportedPrograms == null)? 1 : SupportedPrograms.Length + 1);
                SupportedPrograms[SupportedPrograms.Length - 1] = "UnrealHeaderTool";
            }

            RawObject.TryGetBoolField("RequiresBuildPlatform", out bRequiresBuildPlatform);
            RawObject.TryGetBoolField("ExplicitlyLoaded", out bExplicitlyLoaded);

            CustomBuildSteps.TryRead(RawObject, "PreBuildSteps", out PreBuildSteps);
            CustomBuildSteps.TryRead(RawObject, "PostBuildSteps", out PostBuildSteps);

            JsonObject[] PluginsArray;
            if(RawObject.TryGetObjectArrayField("Plugins", out PluginsArray))
            {
                Plugins = Array.ConvertAll(PluginsArray, x => PluginReferenceDescriptor.FromJsonObject(x)).ToList();
            }
        }

        /// <summary>
        /// Creates a plugin descriptor from a file on disk
        /// </summary>
        /// <param name="FileName">The filename to read</param>
        /// <returns>New plugin descriptor</returns>
        public static PluginDescriptor FromFile(FileReference FileName)
        {
            JsonObject RawObject = JsonObject.Read(FileName);
            try
            {
                PluginDescriptor Descriptor = new PluginDescriptor(RawObject);
                if (Descriptor.Modules != null)
                {
                    foreach (ModuleDescriptor Module in Descriptor.Modules)
                    {
                        Module.Validate(FileName);
                    }
                }
                return Descriptor;
            }
            catch (JsonParseException ParseException)
            {
                throw new JsonParseException("{0} (in {1})", ParseException.Message, FileName);
            }
        }

        /// <summary>
        /// Saves the descriptor to disk
        /// </summary>
        /// <param name="FileName">The filename to write to</param>
        public void Save(string FileName)
        {
            using (JsonWriter Writer = new JsonWriter(FileName))
            {
                Writer.WriteObjectStart();
                Write(Writer);
                Writer.WriteObjectEnd();
            }
        }

        /// <summary>
        /// Writes the plugin descriptor to an existing Json writer
        /// </summary>
        /// <param name="Writer">The writer to receive plugin data</param>
        public void Write(JsonWriter Writer)
        {
            Writer.WriteValue("FileVersion", (int)ProjectDescriptorVersion.Latest);
            Writer.WriteValue("Version", Version);
            Writer.WriteValue("VersionName", VersionName);
            Writer.WriteValue("FriendlyName", FriendlyName);
            Writer.WriteValue("Description", Description);
            Writer.WriteValue("Category", Category);
            Writer.WriteValue("CreatedBy", CreatedBy);
            Writer.WriteValue("CreatedByURL", CreatedByURL);
            Writer.WriteValue("DocsURL", DocsURL);
            Writer.WriteValue("MarketplaceURL", MarketplaceURL);
            Writer.WriteValue("SupportURL", SupportURL);
            if(!String.IsNullOrEmpty(EngineVersion))
            {
                Writer.WriteValue("EngineVersion", EngineVersion);
            }
            if(bEnabledByDefault.HasValue)
            {
                Writer.WriteValue("EnabledByDefault", bEnabledByDefault.Value);
            }
            Writer.WriteValue("CanContainContent", bCanContainContent);
            if (bIsBetaVersion)
            {
                Writer.WriteValue("IsBetaVersion", bIsBetaVersion);
            }
            if (bIsExperimentalVersion)
            {
                Writer.WriteValue("IsExperimentalVersion", bIsExperimentalVersion);
            }
            if (bInstalled)
            {
                Writer.WriteValue("Installed", bInstalled);
            }

            if(bRequiresBuildPlatform)
            {
                Writer.WriteValue("RequiresBuildPlatform", bRequiresBuildPlatform);
            }

            if (bExplicitlyLoaded)
            {
                Writer.WriteValue("ExplicitlyLoaded", bExplicitlyLoaded);
            }

            if(SupportedTargetPlatforms != null && SupportedTargetPlatforms.Count > 0)
            {
                Writer.WriteStringArrayField("SupportedTargetPlatforms", SupportedTargetPlatforms.Select<UnrealTargetPlatform, string>(x => x.ToString()).ToArray());
            }

            if (SupportedPrograms != null && SupportedPrograms.Length > 0)
            {
                Writer.WriteStringArrayField("SupportedPrograms", SupportedPrograms);
            }
            if (bIsPluginExtension)
            {
                Writer.WriteValue("bIsPluginExtension", bIsPluginExtension);
            }

            if (Modules != null && Modules.Count > 0)
            {
                ModuleDescriptor.WriteArray(Writer, "Modules", Modules.ToArray());
            }

            LocalizationTargetDescriptor.WriteArray(Writer, "LocalizationTargets", LocalizationTargets);

            if(PreBuildSteps != null)
            {
                PreBuildSteps.Write(Writer, "PreBuildSteps");
            }

            if(PostBuildSteps != null)
            {
                PostBuildSteps.Write(Writer, "PostBuildSteps");
            }

            if (Plugins != null && Plugins.Count > 0)
            {
                PluginReferenceDescriptor.WriteArray(Writer, "Plugins", Plugins.ToArray());
            }
        }

        /// <summary>
        /// Determines if this reference enables the plugin for a given platform
        /// </summary>
        /// <param name="Platform">The platform to check</param>
        /// <returns>True if the plugin should be enabled</returns>
        public bool SupportsTargetPlatform(UnrealTargetPlatform Platform)
        {
            return SupportedTargetPlatforms == null || SupportedTargetPlatforms.Count == 0 || SupportedTargetPlatforms.Contains(Platform);
        }
    }
}
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-12-23 12:13 , Processed in 0.096484 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表