Browse Source

Change SerializeContextTools into a ToolsApplication so that it can correctly read in slice data:
- Uses ToolsApplication instead of ComponentApplication so that built-in Editor components are recognized and read in correctly
- Starts up all the DynamicModules immediately so that the System Components are activated, which registers asset handlers and allows asset references to serialize in correctly
- Adds a -specialization command-line flag to specify which project specialization to use (editor, game, etc)
- Removes the filter to ignore unknown classes since they should all now be "known"
- Adds a few gem autoload flags and a null thumbnail service so that Qt and Python systems can be skipped, as they aren't needed for the data conversions and would bring additional overhead and complications

mbalfour 4 years ago
parent
commit
b5e87d3601

+ 37 - 6
Code/Tools/SerializeContextTools/Application.cpp

@@ -16,12 +16,23 @@
 #include <AzCore/StringFunc/StringFunc.h>
 #include <AzCore/StringFunc/StringFunc.h>
 #include <AzCore/Utils/Utils.h>
 #include <AzCore/Utils/Utils.h>
 
 
+#include <AzToolsFramework/Thumbnails/ThumbnailerNullComponent.h>
+
 namespace AZ
 namespace AZ
 {
 {
+    // SerializeContextTools is a full ToolsApplication that will load a project's Gem DLLs and initialize the system components.
+    // This level of initialization is required to get all the serialization contexts and asset handlers registered, so that when
+    // data transformations take place, none of the data is dropped due to not being recognized.
+    // However, as a simplification, anything requiring Python or Qt is skipped during initialization:
+    // - The gem_autoload.serializecontexttools.setreg file disables autoload for QtForPython, EditorPythonBindings, and PythonAssetBuilder
+    // - The system component initialization below uses ThumbnailerNullComponent so that other components relying on a ThumbnailService
+    //   can still be started up, but the thumbnail service itself won't do anything.  The real ThumbnailerComponent uses Qt, which is why
+    //   it isn't used.
+
     namespace SerializeContextTools
     namespace SerializeContextTools
     {
     {
         Application::Application(int argc, char** argv)
         Application::Application(int argc, char** argv)
-            : AZ::ComponentApplication(argc, argv)
+            : AzToolsFramework::ToolsApplication(&argc, &argv)
         {
         {
             AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
             AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
             if (projectPath.empty())
             if (projectPath.empty())
@@ -51,14 +62,25 @@ namespace AZ
             else
             else
             {
             {
                 AZ::SettingsRegistryInterface::Specializations projectSpecializations{ projectName };
                 AZ::SettingsRegistryInterface::Specializations projectSpecializations{ projectName };
-                AZ::IO::PathView configFilenameStem = m_configFilePath.Stem();
-                if (AZ::StringFunc::Equal(configFilenameStem.Native(),  "Editor"))
+
+                // If a project specialization has been passed in via the command line, use it.
+                if (m_commandLine.HasSwitch("specialization"))
                 {
                 {
-                    projectSpecializations.Append("editor");
+                    AZStd::string specialization = m_commandLine.GetSwitchValue("specialization", 0);
+                    projectSpecializations.Append(specialization);
                 }
                 }
-                else if (AZ::StringFunc::Equal(configFilenameStem.Native(), "Game"))
+                // Otherwise, if a config file was passed in, auto-set the specialization based on the config file name.
+                else
                 {
                 {
-                    projectSpecializations.Append(projectName + "_GameLauncher");
+                    AZ::IO::PathView configFilenameStem = m_configFilePath.Stem();
+                    if (AZ::StringFunc::Equal(configFilenameStem.Native(), "Editor"))
+                    {
+                        projectSpecializations.Append("editor");
+                    }
+                    else if (AZ::StringFunc::Equal(configFilenameStem.Native(), "Game"))
+                    {
+                        projectSpecializations.Append(projectName + "_GameLauncher");
+                    }
                 }
                 }
 
 
                 // Used the project specializations to merge the build dependencies *.setreg files
                 // Used the project specializations to merge the build dependencies *.setreg files
@@ -78,5 +100,14 @@ namespace AZ
             AZ::ComponentApplication::SetSettingsRegistrySpecializations(specializations);
             AZ::ComponentApplication::SetSettingsRegistrySpecializations(specializations);
             specializations.Append("serializecontexttools");
             specializations.Append("serializecontexttools");
         }
         }
+
+        AZ::ComponentTypeList Application::GetRequiredSystemComponents() const
+        {
+            // Use all of the default system components, but also add in the ThumbnailerNullComponent so that components requiring
+            // a ThumbnailService can still be started up.
+            AZ::ComponentTypeList components = AzToolsFramework::ToolsApplication::GetRequiredSystemComponents();
+            components.emplace_back(azrtti_typeid<AzToolsFramework::Thumbnailer::ThumbnailerNullComponent>());
+            return components;
+        }
     } // namespace SerializeContextTools
     } // namespace SerializeContextTools
 } // namespace AZ
 } // namespace AZ

+ 3 - 2
Code/Tools/SerializeContextTools/Application.h

@@ -12,7 +12,7 @@
 
 
 #pragma once
 #pragma once
 
 
-#include <AzCore/Component/ComponentApplication.h>
+#include <AzToolsFramework/Application/ToolsApplication.h>
 #include <AzCore/IO/Path/Path.h>
 #include <AzCore/IO/Path/Path.h>
 
 
 namespace AZ
 namespace AZ
@@ -20,13 +20,14 @@ namespace AZ
     namespace SerializeContextTools
     namespace SerializeContextTools
     {
     {
         class Application final
         class Application final
-            : public AZ::ComponentApplication
+            : public AzToolsFramework::ToolsApplication
         {
         {
         public:
         public:
             Application(int argc, char** argv);
             Application(int argc, char** argv);
             ~Application() override = default;
             ~Application() override = default;
             
             
             const char* GetConfigFilePath() const;
             const char* GetConfigFilePath() const;
+            AZ::ComponentTypeList GetRequiredSystemComponents() const override;
 
 
         protected:
         protected:
             void SetSettingsRegistrySpecializations(AZ::SettingsRegistryInterface::Specializations& specializations) override;
             void SetSettingsRegistrySpecializations(AZ::SettingsRegistryInterface::Specializations& specializations) override;

+ 2 - 0
Code/Tools/SerializeContextTools/CMakeLists.txt

@@ -29,4 +29,6 @@ ly_add_target(
     BUILD_DEPENDENCIES
     BUILD_DEPENDENCIES
         PRIVATE
         PRIVATE
             AZ::AzCore
             AZ::AzCore
+            AZ::AzFramework
+            AZ::AzToolsFramework
 )
 )

+ 0 - 1
Code/Tools/SerializeContextTools/Utilities.cpp

@@ -236,7 +236,6 @@ namespace AZ::SerializeContextTools
         AZ::IO::MemoryStream stream(data.data(), fileLength);
         AZ::IO::MemoryStream stream(data.data(), fileLength);
 
 
         ObjectStream::FilterDescriptor filter;
         ObjectStream::FilterDescriptor filter;
-        filter.m_flags = ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES;
         // Never load dependencies. That's another file that would need to be processed
         // Never load dependencies. That's another file that would need to be processed
         // separately from this one.
         // separately from this one.
         filter.m_assetCB = AZ::Data::AssetFilterNoAssetLoading;
         filter.m_assetCB = AZ::Data::AssetFilterNoAssetLoading;

+ 2 - 5
Code/Tools/SerializeContextTools/main.cpp

@@ -23,6 +23,7 @@ void PrintHelp()
     AZ_Printf("Help", "Serialize Context Tool\n");
     AZ_Printf("Help", "Serialize Context Tool\n");
     AZ_Printf("Help", "  <action> [-config] <action arguments>*\n");
     AZ_Printf("Help", "  <action> [-config] <action arguments>*\n");
     AZ_Printf("Help", "  [opt] -config=<path>: optional path to application's config file. Default is 'config/editor.xml'.\n");
     AZ_Printf("Help", "  [opt] -config=<path>: optional path to application's config file. Default is 'config/editor.xml'.\n");
+    AZ_Printf("Help", "  [opt] -specialization=<prefix>: optional Registry project specialization, such as 'editor' or 'game'.  Default is none. \n");
     AZ_Printf("Help", "\n");
     AZ_Printf("Help", "\n");
     AZ_Printf("Help", "  'help': Print this help\n");
     AZ_Printf("Help", "  'help': Print this help\n");
     AZ_Printf("Help", "    example: 'help'\n");
     AZ_Printf("Help", "    example: 'help'\n");
@@ -81,11 +82,7 @@ int main(int argc, char** argv)
     bool result = false;
     bool result = false;
     Application application(argc, argv);
     Application application(argc, argv);
     AZ::ComponentApplication::StartupParameters startupParameters;
     AZ::ComponentApplication::StartupParameters startupParameters;
-    startupParameters.m_loadDynamicModules = false;
-    application.Create({}, startupParameters);
-    // Load the DynamicModules after the Application starts to prevent Gem System Components
-    // from activating
-    application.LoadDynamicModules();
+    application.Start({}, startupParameters);
 
 
     const AZ::CommandLine* commandLine = application.GetAzCommandLine();
     const AZ::CommandLine* commandLine = application.GetAzCommandLine();
     if (commandLine->GetNumMiscValues() < 1)
     if (commandLine->GetNumMiscValues() < 1)

+ 15 - 0
Registry/gem_autoload.serializecontexttools.setreg

@@ -0,0 +1,15 @@
+{
+  "Amazon": {
+    "Gems": {
+      "QtForPython.Editor": {
+        "AutoLoad": false
+      },
+      "EditorPythonBindings.Editor": {
+        "AutoLoad": false
+      },
+      "PythonAssetBuilder.Editor": {
+        "AutoLoad": false
+      }
+    }
+  }
+}